-
Project Log 10/6/2018
10/06/2018 at 08:30 • 0 commentsProject Log 10/6/2018
===================
Here is a block diagram of the Synchronia♥Duet:
The CPU (ATMEGA2560) has 4 Serial I/O Ports. Comm1 is connected to the PC via USB. Comm2 Input is connected to the MELODY KEYBOARD while Comm2 Output shuttles DATA to the MIDI Out Port. Comm3 i/o communicates with the Harmony Keyboard, an Adafruit HELLA Untztrument.
-
PSEUDOCODE For Synchronia♥Duet Firmware
10/05/2018 at 14:09 • 0 commentsThe Following is a pseudocode listing of the Synchronia-Duet Firmware. It can be readily adapted to any compiler. PSEUDOCODE ========== '---------------------------- ' Synchronia--Duet 0.0.7 ' (C)2018 Thomas R. Mahanna '---------------------------- 'CONFIGURE HARDWARE I/O (ATMEGA2560 in the Case of the Prototype) 'Configure Communication Open Serial1 For Binary As #0 'Serial Connection to PC Open Serial2 For Binary As #1 'MIDI Out / QUNexus In Open Serial3 For Binary As #2 'UNZTRUMENT I/O 'DIMESION VARIABLES 'Serial Input Variables Dim SerialInbyte As Byte Dim SerialFlag As Bit Dim QuNexusInbyte As Byte Dim QuNexusFlag As Bit Dim UntzInbyte As Byte Dim UntzFlag As Bit 'MIDI Variables Dim MIDICh as byte Dim Timbre as Byte Dim Status As Byte Dim Data1 As Byte Dim Data2 As Byte Dim StrumDelay As Byte Dim ChordArray(4) as Byte Dim ScaleArray(5) as Byte Dim Vel as Byte Dim Pedal as bit Dim Notes(5) as Byte 'Main Variables Dim I As Byte Dim ChordType As Byte Dim OldChord As Byte Dim Root As Byte Dim OldRoot As Byte Dim OldChordButton As Byte Dim OldRootButton As Byte Dim ButtonHold As Bit Dim Offset as Byte Dim Temp as byte 'DEFINE IRQ HANDLERS On Serial1 PCSerial_isr On Serial2 Qunexus_isr On Serial3 Untz_isr 'ENABLE INTERRUPTS Enable IRQ0 Enable IRQ1 Enable IRQ2 Enable Global Interrupts 'DEFINE / DECLARE SUBROUTINES Declare Sub Midiout(byval Ch As Byte , Byval Note As Byte , Byval Vel As Byte) Declare Sub Midipatch(byval Ch As Byte , Byval Patch As Byte) Declare Sub Mastervolume(byval Vol As Byte) Declare Sub Allnotesoff Declare Sub ProcessUntzButton 'MAIN ' Entering Main Loop For I = 0 To 15 SerialOut #2 , I 'All Chord Buttons Off Waitms 1 Next For I = 76 To 79 SerialOut #2 , I Waitms 1 Next For I = 92 To 95 SerialOut #2 , I Waitms 1 Next For I = 108 To 111 SerialOut #2 , I 'All Trellis Root Buttons Off Waitms 1 Next Chordtype = 0 SerialOut #2 , 140 OldChordButton = 12 Root = 0 SerialOut #2 , 204 OldRootButton = 76 Offset = 48 'Octave 4 * 12 Call ProcessUntzButton MIDICh = 1 'Set MIDI Output Channel Timbre = 0 'GM Piano [0] Vel = 96 'Velocity StrumDelay = 40 'Spread Between Notes (mS) Pedal = 1 'Pedal off SerialOut #1 , &HB0 SerialOut #1 , &H7B SerialOut #1 , &H00 'All Notes Off SerialOut #1 , 176 SerialOut #1 , 7 SerialOut #1 , 64 'Set Volume to 96 Call Mastervolume(64) 'Set Volume to 96 Call Midipatch(midich , Timbre) 'Change MIDI Intrument Timbre Do '// PROCESS UNTZTRUMENT If UntzFlag = 1 Then Select Case UntzInbyte '// Button Release Case 12 ButtonHold = 0 Case 13 ButtonHold = 0 Case 14 ButtonHold = 0 Case 15 ButtonHold = 0 Case 16 to 127 If Pedal = 0 then Call MIDIOut(MIDICh , ChordArray(1) , 0) Call MIDIOut(MIDICh , ChordArray(2) , 0) Call MIDIOut(MIDICh , ChordArray(3) , 0) Call MIDIOut(MIDICh , ChordArray(4) , 0) End If '// Chord Selection Case 140 Chordtype = 0 'Major SerialOut #2 , OldChordButton 'Turn old chordtype button off SerialOut #2 , UntzInbyte 'Turn new chordtype button on If UntzInbyte > 127 Then OldChordButton = UntzInbyte - 128 Else OldChordButton = UntzInbyte End If Buttonhold = 1 Call ProcessUntzButton Case 141 Chordtype = 1 'Minor SerialOut #2 , OldChordButton 'Turn old chordtype button off SerialOut #2 , UntzInbyte 'Turn new chordtype button on If UntzInbyte > 127 Then OldChordButton = UntzInbyte - 128 Else OldChordButton = UntzInbyte End If Buttonhold = 1 Case 142 Chordtype = 2 'Sus4 SerialOut #2 , OldChordButton 'Turn old chordtype button off SerialOut #2 , UntzInbyte 'Turn new chordtype button on If UntzInbyte > 127 Then OldChordButton = UntzInbyte - 128 Else OldChordButton = UntzInbyte End If Buttonhold = 1 Case 143 Chordtype = 3 'Dom7 SerialOut #2 , OldChordButton 'Turn old chordtype button off SerialOut #2 , UntzInbyte 'Turn new chordtype button on If UntzInbyte > 127 Then OldChordButton = UntzInbyte - 128 Else OldChordButton = UntzInbyte End If Buttonhold = 1 '// Root Selection Case 204 SerialOut #2 , OldRootButton 'Turn old root button off SerialOut #2 , UntzInbyte 'Turn new root button on Root = 0 'Root C Call ProcessUntzButton If ButtonHold = 1 Then Call MIDIOut(MIDICh , ChordArray(1) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(2) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(3) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(4) , Vel) waitms StrumDelay End If If UntzInbyte > 127 Then OldRootButton = UntzInbyte - 128 Else OldRootButton = UntzInbyte End If Case 205 SerialOut #2 , OldRootButton 'Turn old root button off SerialOut #2 , UntzInbyte 'Turn new root button on Root = 1 'Root C# Call ProcessUntzButton If ButtonHold = 1 Then Call MIDIOut(MIDICh , ChordArray(1) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(2) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(3) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(4) , Vel) waitms StrumDelay End If If UntzInbyte > 127 Then OldRootButton = UntzInbyte - 128 Else OldRootButton = UntzInbyte End If Case 206 SerialOut #2 , OldRootButton 'Turn old root button off SerialOut #2 , UntzInbyte 'Turn new root button on Root = 2 'Root D Call ProcessUntzButton If ButtonHold = 1 Then Call MIDIOut(MIDICh , ChordArray(1) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(2) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(3) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(4) , Vel) waitms StrumDelay End If If UntzInbyte > 127 Then OldRootButton = UntzInbyte - 128 Else OldRootButton = UntzInbyte End If Case 207 SerialOut #2 , OldRootButton 'Turn old root button off SerialOut #2 , UntzInbyte 'Turn new root button on Root = 3 'Root D# Call ProcessUntzButton If ButtonHold = 1 Then Call MIDIOut(MIDICh , ChordArray(1) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(2) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(3) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(4) , Vel) waitms StrumDelay End If If UntzInbyte > 127 Then OldRootButton = UntzInbyte - 128 Else OldRootButton = UntzInbyte End If Case 220 SerialOut #2 , OldRootButton 'Turn old root button off SerialOut #2 , UntzInbyte 'Turn new root button on Root = 4 'Root E Call ProcessUntzButton If ButtonHold = 1 Then Call MIDIOut(MIDICh , ChordArray(1) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(2) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(3) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(4) , Vel) waitms StrumDelay End If If UntzInbyte > 127 Then OldRootButton = UntzInbyte - 128 Else OldRootButton = UntzInbyte End If Case 221 SerialOut #2 , OldRootButton 'Turn old root button off SerialOut #2 , UntzInbyte 'Turn new root button on Root = 5 'Root F Call ProcessUntzButton If ButtonHold = 1 Then Call MIDIOut(MIDICh , ChordArray(1) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(2) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(3) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(4) , Vel) waitms StrumDelay End If If UntzInbyte > 127 Then OldRootButton = UntzInbyte - 128 Else OldRootButton = UntzInbyte End If Case 222 SerialOut #2 , OldRootButton 'Turn old root button off SerialOut #2 , UntzInbyte 'Turn new root button on Root = 6 'Root F# Call ProcessUntzButton If ButtonHold = 1 Then Call MIDIOut(MIDICh , ChordArray(1) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(2) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(3) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(4) , Vel) waitms StrumDelay End If If UntzInbyte > 127 Then OldRootButton = UntzInbyte - 128 Else OldRootButton = UntzInbyte End If Case 223 SerialOut #2 , OldRootButton 'Turn old root button off SerialOut #2 , UntzInbyte 'Turn new root button on Root = 7 'Root G Call ProcessUntzButton If ButtonHold = 1 Then Call MIDIOut(MIDICh , ChordArray(1) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(2) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(3) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(4) , Vel) waitms StrumDelay End If If UntzInbyte > 127 Then OldRootButton = UntzInbyte - 128 Else OldRootButton = UntzInbyte End If 'Print "Root = G" Case 236 SerialOut #2 , OldRootButton 'Turn old root button off SerialOut #2 , UntzInbyte 'Turn new root button on Root = 8 'Root G# Call ProcessUntzButton If ButtonHold = 1 Then Call MIDIOut(MIDICh , ChordArray(1) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(2) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(3) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(4) , Vel) waitms StrumDelay End If If UntzInbyte > 127 Then OldRootButton = UntzInbyte - 128 Else OldRootButton = UntzInbyte End If Case 237 SerialOut #2 , OldRootButton 'Turn old root button off SerialOut #2 , UntzInbyte 'Turn new root button on Root = 9 'Root A Call ProcessUntzButton If ButtonHold = 1 Then Call MIDIOut(MIDICh , ChordArray(1) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(2) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(3) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(4) , Vel) waitms StrumDelay End If If UntzInbyte > 127 Then OldRootButton = UntzInbyte - 128 Else OldRootButton = UntzInbyte End If Case 238 SerialOut #2 , OldRootButton 'Turn old root button off SerialOut #2 , UntzInbyte 'Turn new root button on Root = 10 'Root A# Call ProcessUntzButton If ButtonHold = 1 Then Call MIDIOut(MIDICh , ChordArray(1) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(2) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(3) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(4) , Vel) waitms StrumDelay End If If UntzInbyte > 127 Then OldRootButton = UntzInbyte - 128 Else OldRootButton = UntzInbyte End If Case 239 SerialOut #2 , OldRootButton 'Turn old root button off SerialOut #2 , UntzInbyte 'Turn new root button on Root = 11 'Root B Call ProcessUntzButton If ButtonHold = 1 Then Call MIDIOut(MIDICh , ChordArray(1) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(2) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(3) , Vel) waitms StrumDelay Call MIDIOut(MIDICh , ChordArray(4) , Vel) waitms StrumDelay End If If UntzInbyte > 127 Then OldRootButton = UntzInbyte - 128 Else OldRootButton = UntzInbyte End If End Select UntzFlag = 0 End If '// PROCESS QUNEXUS If QuNexusFlag = 1 Then If Data2 > 0 then Select Case Data1 '// Process White Keys Case 48 Temp = ChordArray(1) - 12 Case 50 Temp = ChordArray(2) - 12 Case 52 Temp = ChordArray(3) - 12 Case 53 Temp = ChordArray(4) - 12 Case 55 Temp = ChordArray(1) Case 57 Temp = ChordArray(2) Case 59 Temp = ChordArray(3) Case 60 Temp = ChordArray(4) Case 62 Temp = ChordArray(1) + 12 Case 64 Temp = ChordArray(2) + 12 Case 65 Temp = ChordArray(3) + 12 Case 67 Temp = ChordArray(4) + 12 Case 69 Temp = ChordArray(1) + 24 Case 71 Temp = ChordArray(2) + 24 Case 72 Temp = ChordArray(3) + 24 '// Process Blue Keys Case 49 Temp = ScaleArray(1) Case 51 Temp = ScaleArray(2) Case 54 Temp = ScaleArray(3) Case 56 Temp = ScaleArray(4) Case 58 Temp = ScaleArray(5) Case 61 Temp = ScaleArray(1) + 12 Case 63 Temp = ScaleArray(2) + 12 Case 66 Temp = ScaleArray(3) + 12 Case 68 Temp = ScaleArray(4) + 12 Case 70 Temp = ScaleArray(5) + 12 End Select Call MidiOut(MIDICh , Temp , Vel) Else If Pedal = 0 Then Select Case Data1 '// Process White Keys Case 48 Temp = ChordArray(1) - 12 Case 50 Temp = ChordArray(2) - 12 Case 52 Temp = ChordArray(3) - 12 Case 53 Temp = ChordArray(4) - 12 Case 55 Temp = ChordArray(1) Case 57 Temp = ChordArray(2) Case 59 Temp = ChordArray(3) Case 60 Temp = ChordArray(4) Case 62 Temp = ChordArray(1) + 12 Case 64 Temp = ChordArray(2) + 12 Case 65 Temp = ChordArray(3) + 12 Case 67 Temp = ChordArray(4) + 12 Case 69 Temp = ChordArray(1) + 24 Case 71 Temp = ChordArray(2) + 24 Case 72 Temp = ChordArray(3) + 24 '// Process Blue Keys Case 49 Temp = ScaleArray(1) Case 51 Temp = ScaleArray(2) Case 54 Temp = ScaleArray(3) Case 56 Temp = ScaleArray(4) Case 58 Temp = ScaleArray(5) Case 61 Temp = ScaleArray(1) + 12 Case 63 Temp = ScaleArray(2) + 12 Case 66 Temp = ScaleArray(3) + 12 Case 68 Temp = ScaleArray(4) + 12 Case 70 Temp = ScaleArray(5) + 12 End Select Call MidiOut(MIDICh , Temp , 0) End If End If QuNexusFlag = 0 End If Loop Sub MIDIOut(Byval Ch As Byte , Byval Note As Byte , Byval Vel As Byte) Ch = &H8F + Ch SerialOut #1 , Ch SerialOut #1 , Note SerialOut #1 , Vel End Sub Sub MIDIPatch(byval Ch As Byte , Byval Patch As Byte) Ch = &HBF + Ch SerialOut #1 , Ch SerialOut #1 , Patch End Sub Sub MasterVolume(byval Vol As Byte) SerialOut #1 , 176 SerialOut #1 , 7 SerialOut #1 , Vol End Sub Sub AllNotesOff SerialOut #1 , &HB0 SerialOut #1 , &H7B SerialOut #1 , &H00 'All Notes Off End Sub Sub ProcessUntzButton ChordArray(1) = Root + Offset ScaleArray(1) = Root + Offset Select Case ChordType Case 0 ' Major ChordArray(2) = ChordArray(1) + 7 ChordArray(3) = ChordArray(1) + 16 ChordArray(4) = ChordArray(1) + 24 ScaleArray(2) = ScaleArray(1) + 2 ScaleArray(3) = ScaleArray(1) + 4 ScaleArray(4) = ScaleArray(1) + 7 ScaleArray(5) = ScaleArray(1) + 9 Case 1 ' Minor ChordArray(2) = ChordArray(1) + 7 ChordArray(3) = ChordArray(1) + 15 ChordArray(4) = ChordArray(1) + 24 ScaleArray(2) = ScaleArray(1) + 3 ScaleArray(3) = ScaleArray(1) + 5 ScaleArray(4) = ScaleArray(1) + 7 ScaleArray(5) = ScaleArray(1) + 10 Case 2 ' Sus4 ChordArray(2) = ChordArray(1) + 7 ChordArray(3) = ChordArray(1) + 17 ChordArray(4) = ChordArray(1) + 24 ScaleArray(2) = ScaleArray(1) + 2 ScaleArray(3) = ScaleArray(1) + 5 ScaleArray(4) = ScaleArray(1) + 7 ScaleArray(5) = ScaleArray(1) + 9 Case 3 ' Dom7 ChordArray(2) = ChordArray(1) + 7 ChordArray(3) = ChordArray(1) + 16 ChordArray(4) = ChordArray(1) + 22 ScaleArray(2) = ScaleArray(1) + 2 ScaleArray(3) = ScaleArray(1) + 4 ScaleArray(4) = ScaleArray(1) + 7 ScaleArray(5) = ScaleArray(1) + 10 End Select End Sub PCSerial_isr: SerialInbyte = Udr SerialFlag = 1 Return QuNexus_ISR: QuNexusInbyte = UDR1 Select Case QuNexusInbyte Case &H80 to &H9F 'Note On / Off Status = QuNexusInbyte Data1 = &HFF Data2 = &HFF Case 0 To 127 'Data If Status > 0 Then If Data1 = &HFF Then Data1 = QuNexusInbyte Else Data2 = QuNexusInbyte QuNexusFlag = 1 End If End If End Select Return Untz_isr: UntzInbyte = Udr2 UntzFlag = 1 Return
-
Project Log 10/4/2018
10/05/2018 at 12:06 • 0 comments-
Project Log 10/4/2018
==================
Here is a chart of the layout of the Synchronia♥Duet Harmony Keyboard:
Holding down the M key sets the keyboard for Major Chords, m for Minor Chords, etc. The left hand would press the M, m, S4, D7 (up for higher octave) and the right hand would select the Root note from the bottom row (C - B) and the Inversion on the Y-Axis. Holding down the M, m, S4, D7 would actually sound the chord, so press and release the M, m, S4, D7 if you just want to choose it without playing it.
The Melody Keyboard layout:
in the case that a C Major chord (Root Inversion) was selected, would be mapped as above. The lower keys would sound four cotaves of the open chord notes and the upper keys would sound two octaves of the associated minor pentatonic scale for soloing.
-
Project Log 10/3/2018
a day ago • 0 commentsProject Log 10/3/2018
==================
I've been really busy lately and almost forgot about this project. Thanks to Stephen Tranovich for reminding me to update it.
The Synchronia♥Duet is my attempt at solving the problem of creating a musical instrument that utilizes the unique talents of two instrumentalists, playing in concert. It achieves it's end by uniting two keyboards in a 3D Matrix (Harmony / Melody / Time) with the Harmony Keyboardist choosing the musical space in which the melody keyboardist is playing.
In the video example, the Harmony Keyboardist is playing a simple repeating I / iii / IV / iii ( C / D# / F / D#) chord progression. The software reads the Harmony Keyboard and, depending on the whether the Harmony Keyboardist is holding down the <Chord Type> selctor key, strums the chord. The Melody Keyboard is dynamically remapped (with the lower keys representing the selected chord notes (C E G, D# G A#, F A C, etc) in multiple octaves and the upper keys representing two octaves of the associated Minor Pentatonic Scale A C D E G, C D# F G A#, D F G A C).
-
-
Project Log 10/3/2018
10/05/2018 at 12:05 • 0 commentsProject Log 10/3/2018
==================
I've been really busy lately and almost forgot about this project. Thanks to Stephen Tranovich for reminding me to update it.
The Synchronia♥Duet is my attempt at solving the problem of creating a musical instrument that utilizes the unique talents of two instrumentalists, playing in concert. It achieves it's end by uniting two keyboards in a 3D Matrix (Harmony / Melody / Time) with the Harmony Keyboardist choosing the musical space in which the melody keyboardist is playing.
In the video example, the Harmony Keyboardist is playing a simple repeating I / iii / IV / iii ( C / D# / F / D#) chord progression. The software reads the Harmony Keyboard and, depending on the whether the Harmony Keyboardist is holding down the <Chord Type> selctor key, strums the chord. The Melody Keyboard is dynamically remapped (with the lower keys representing the selected chord notes (C E G, D# G A#, F A C, etc) in multiple octaves and the upper keys representing two octaves of the associated Minor Pentatonic Scale A C D E G, C D# F G A#, D F G A C).
Share