Week 10 First prototype reflection and Future work

Tianyi Liu - Sun 17 May 2020, 7:30 pm
Modified: Sun 17 May 2020, 7:31 pm

First Prototype Reflection

Code Review

The code could be divided into 3 parts, codes in Arduino IDE, code to receive data from Arduino, and code to convert and play out as music.

The code in the Arduino UNO is just a simple could to print out the serials data of the FSR.

To output the music notes and chords, it's essential to define music note as a Class in the program:


noteDict = {}               #create a dictionary for music notes

Notes = ["c2","c2s","d2","d2s","e2","f2","f2s","g2","g2s","a2","a2s","b2","c3","c3s","d3","d3s","e3","f3","f3s","g3","g3s","a3","a3s","b3","c4","c4s","d4","d4s","e4","f4","f4s","g4","g4s","a4","a4s","b4","c5"]

startpoint = 48

for i in Notes:

    noteDict[i] = startpoint

    startpoint += 1

The midi signal is formed by several numbers, each music notes was matched with a certain integer, we have middle C(C3) match with 60, and we could easily know the other numbers.

Create class for music notes and chords´╝Ü


class Note():                   # A class of the music notes

    

    def __init__(self, notename):

        self._notename = notename

    def get_note_number(self):

        return noteDict[self._notename]

    def play_notes(self, duration, velocity):

        return [self.get_note_number(), duration, velocity]

        

for i in Notes:             # create instance for each note

    locals()[i] = Note(i)

class Chord():              # A class of chords, which is fromed by a list of notes

    def __init__(self,notes):

        self.notes = notes

        self.base = notes[0]

    

    def note_included(self, note):

        included = False

        for i in self.notes:

            if i.get_note_number() == note.get_note_number():

                included = True

        return included

    

    def get_notes(self):

        return self.notes

# Pre defined common chords

chord_C = Chord([c2,g2,e3])

chord_Cmaj7 = Chord([c2,e2,g2,b2])

chord_D7 = Chord([d2,a2,c3])

chord_Dm7 = Chord([d2,f2,a2,c3])

chord_E7 = Chord([e2,g2s,b2,d3])

chord_F = Chord([f2,c3,f3])

chord_G = Chord([g2,b2,d3])

chord_Am = Chord([a2,c3,e3])

chord_Bdim = Chord([b2,d3,f3])

chord_Em = Chord([e2,g2,b2])

Use rtmidi to send virtual signal to music software.


class Player():

    '''A Class of the music player'''

    def __init__(self):

        self.midiout = rtmidi.MidiOut()

        self.available_ports = self.midiout.get_ports()

        #print(available_ports)

        if self.available_ports:

            self.midiout.open_port(0)

        else:

            self.midiout.open_virtual_port("My virtual output")

    def play_note_start(self,note, velocity):               #Start to send a midi signal that start a music note

        self.midiout.send_message([0x90, note.get_note_number(),velocity])

    def play_note_end(self, note):

        self.midiout.send_message([0x80, note.get_note_number(),0])

    def play_chordnote(self, target, duration, velocity):           

        # [(c3,chord_C)]

        if type(target) !=tuple:

            self.note = target

            # play single note

            self.play_note_start(self.note, velocity)

            time.sleep(duration*0.8)

            self.play_note_end(self.note)

            time.sleep(duration*0.2)

        else:

            #play chord and note

            self.note = target[0]

            self.chord = target[1]

            self.play_note_start(self.note,velocity)

            interval = (len(self.chord.get_notes())-1)*0.1

            for i in self.chord.get_notes():

                self.play_note_start(i,velocity*0.7)

                time.sleep(duration*0.05)

            time.sleep(duration*(0.8-interval))

            self.play_note_end(self.note)

            time.sleep(duration*0.2)

            for i in self.chord.get_notes():

                self.play_note_end(i)

    def close(self):

        del self.midiout

A music note played with midi is based on following parameters, the certain note that is going to be played, velocity of the note, and duration. The duration is actualy not a independent parameter, the whole signal if formed by Start message and End message, the start message define the time start to play the note and the end will stop it.

Converting data into Drum Beats is based on following code:

when the read data is larger than 500, the program start to send a start message of a drum beats and if it drop under 500 send a message to stop it.


while 1:

    data = server.readline()                

    result = convertData(data)

    print(hit,result)               # Read data from Arduino UNO

    if result>500:

        if hit == False:

            if hit_count%2 == 1:

                player1.play_note_start(e2,100)

            else:

                player1.play_note_start(f2,100)

            hit = True

            hit_count += 1

            continue

    elif result < 500:

        if hit == True:

            if hit_count%2 == 1:

                player1.play_note_end(e2)

            else:

                player1.play_note_end(f2)

            hit = False

            continue

    else:

        continue

Code used to play chords progression:

We pre defined some chords progressions for testing, it should be able for user to change it.


Chords_Kanon = [chord_C, chord_G, chord_Am, chord_Em, chord_F, chord_C, chord_F, chord_G]

Chords_Blues = [chord_Cmaj7, chord_Dm7, chord_E7, chord_F, chord_G, chord_Am, chord_Bdim, chord_Cmaj7]


while 1:

    data = server.readline()

    result = convertData(data)

    last_chord = Chords_Kanon[hit_count%8-1]

    this_chord = Chords_Kanon[hit_count%8]

    print(hit,result)

    if result ==0:

        if hit == True:

            player1.play_chords_end(this_chord)

            hit = False

            hit_count += 1

    else:

        if hit == False:

            player1.play_chords_start(this_chord,int(result/6))

            hit = True

        else:

            player1.play_chords_end(this_chord)

            player1.play_chords_start(this_chord, int(result/6))

player1.close()

server.close

The velocity of the chords is based on the pressure use placed on the sensor. Each time the system detect a "Press" action, it will change the chord to play.

This Week

This week we were planning for our final prototype, we are going to combine our work together for the exhibition. Our final prototype will be an installation in a much larger scale than teh current one, so we will need some more materials.

We discussed the form our prototype will be. There should be a structure to contain all the sensors and wires inside, and should be stable enough to allow our user to stand on. It should be like a "Box", the FSR sensor placed on the top of the surface, and LED lights on the bottom side. The top surface should be transparent to allow the light comes out. So we considered Acrylic Board. Also it should be structed on its edge and corner a little bit higher than the ground to allow sensors and wires stuff.

Future plan

For the comming weeks, the focus of the work will be deciding "how we are going to allow our user to switch between different types of exercising". We could have a switch for our user to switch themselves, we could also have the system to detect it automactically, however there are still things need to be considered.

If we have system detect it automatically: there will be a lot of code work, and I am not sure whether we could carry it out, it may involve some work concern machine learning...

If we have our user to select themselves:We need to find a way to allow our user select the type of exercise, we don't have buttons, switch nor remote or touch screen, so it might be related with the sensor, but we still need some user research to support our idea.