' ****************************************************************************** ' * Aeio_master.bas * ' * Fundamental Robot Control Firmware * ' * with MIDI-Input * ' * for Amicus compiler on 18F25K20 microchip controller * ' * or the Proton+ Compiler on any 18F2xxx controller * ' * master controller for the robot * ' * Godfried-Willem Raes * ' ****************************************************************************** ' board description: ' midi in x-lat to commands for the 12 dsPIC boards driving the strings on aieo ' 12-LED's are used to display active strings. ' 2 PWM outputs are used for lights. '31.08.2010: Midi-output implementation, without output buffer. ' test midi-out hardware: o.k. on testboard. ' NoteOff implemented. ' NoteOn implementation halfway. ' Hammers implemented ' Dampers to be done. '01.09.2010: searching a solution for the unisons... ' easiest would be to have different channels for different voices... ' First version of the platonic overtone mapper ready, using lookup tables ' Proton+ compiler installed and updated to version 3.5.0.6 '02.09.2010: First test run with test prg. in GMT ' scrambled midi out data... ' apparently we cannot have any math in HRSOut commands... '03.09.2010: still bugs in the midi output... '06.06.2010: Implementing a real output buffer may become necessary. '07.06.2010: CC23 implementation changed. ' bug in noteoff's: we are sending noteoff for note 0 ... ' CC100-CC111 added for flageolet playing ' considering to activate the velo system such that we can start the notes ' with an accent above the setting of CC7 ' With the tuning set to 52-63, we get the fundamentals from our strings ' only good with the multiplier set to 2 ' Upgrade of the dsPIC's is urgently required now. '08.09.2010: Strange behaviour: as long as the PICkit is connected the firmware runs perfectly ' but as soon as we disconnect it, it ceases to work. '09.09.2010: Problem solved: due to the layout of the Amicus test board. Connecting grounds and ' placing a 100n cap over the 5V pins cured the problem. Nothing wrong with the software. '10.09.2010: This is Version 1.0 of the Aeio firmware. Tested o.k. Compiles both with Amicus as with Proton+ compiler. ' CC3[] and CC4[] array deleted and replaced by CC3 and CC4 as system vars. '11.09.2010: Now adapted to new dsPIC firmware. '12.09.2010: Lookup's extended. '13.09.2010: Bug with fine pitch corrections killed. Range extended up to note 127. ' Tune[] array deleted and replaced with Tune system var. Version 1.1 now '14.09.2010: Scientific lookup edited. (full of mistakes for now...) '15.09.2010: Further improvements.Bug in switching off of very high notes requiring transposition of the ' basenote solved. Keypressure now implemented. This be Version 1.2 '16.09.2010: HRSIn coding improved. All waits removed. Version 1.3 '17.09.2010: Version 1.3 flashed in Aeio (after M&M concert!) '19.09.2010: Version 1.4 flashed in Aeio, with changes in startup and lights implementation. '23.09.2010: Version 1.5, With first KL. lookup. Kristof working on more lookups for tuning. ' Flashed 23.09.2010. Device = 18F25K20 $define _Proton '$define _Amicus Optimiser_Level = 3 ' Full optimisation Declare Dead_Code_Remove = On '/Off Declare Icd_Req = 1 ' to allow ICD programming and PICkit2 ' params: On or Off, or True or False, or 1, 0 ' note that the ICD uses pins RB5, RB6, RB7 Declare Create_Coff = 1 ' generate a .COF file for the debugger in MPLAB Declare Xtal = 64 ' 16MHz Xtal * 4 PLL ' check datasheet for 18F2520 or 2525 for maximumn clock! May not go that fast. ' configuration: ' Disable Watchdog timer and specify an HS oscillator etc: ' This config block is essential as we erased the original bootsector on tne Amicus boards... Config_Start Debug = OFF ' Background debugger disabled; RB6/RB7 configured as I/O XINST = OFF ' Instruction set extension mode disabled (only required for improved float support] STVREN = OFF ' Reset on stack overflow/underflow disabled WDTEN = OFF ' WatchDog Timer disabled (control is placed on SWDTEN bit) FCMEN = On ' was Off, changed by gwr. ' Fail-Safe Clock Monitor disabled - makes no apparent difference FOSC = HSPLL ' HS oscillator, PLL enabled and under software control. 4x x-tal frequency IESO = OFF ' Two-Speed Start-up disabled WDTPS = 128 ' Watchdog oscillator prescaler 1:128 BOREN = SBORDIS ' was off, changed to on by gwr ' off= Brown-out Reset disabled in hardware and software BORV = 27 ' 18 = VBOR set to 1.8 V nominal - to be changed for 5V devices *********************** MCLRE = On ' MCLR pin enabled, RE3 input pin disabled HFOFST = On ' was Off ' The clock is held off until the HF-INTOSC is stable. LPT1OSC = On ' Timer1 operates in standard power mode PBADEN = OFF ' PORTB<4:0> pins are configured as digital I/O on Reset CCP2MX = PORTC ' CCP2 input/output is multiplexed with RC1 LVP = OFF ' Single-Supply ICSP disabled 'changing this makes no difference... CP0 = OFF ' Block 0 (000800-001FFFh) not code-protected CP1 = OFF ' Block 1 (002000-003FFFh) not code-protected CPB = OFF ' Boot block (000000-0007FFh) not code-protected CPD = OFF ' Data EEPROM not code-protected WRT0 = OFF ' Block 0 (000800-001FFFh) not write-protected WRT1 = OFF ' Block 1 (002000-003FFFh) not write-protected WRTB = OFF ' Boot block (000000-0007FFh) not write-protected WRTC = OFF ' Config registers (300000-3000FFh) not write-protected WRTD = OFF ' Data EEPROM not write-protected EBTR0 = OFF ' Block 0 (000800-001FFFh) not protected from table reads ' executed in other blocks EBTR1 = OFF ' Block 1 (002000-003FFFh) not protected from table reads ' executed in other blocks EBTRB = OFF ' Boot block (000000-0007FFh) not protected from reads ' executed in other blocks Config_End 'constant def 'initialisations for the midi input parser: Symbol Midichannel = 1 ' Aeio_Channel Symbol NoteOff_Status = 128 + Midichannel ' 2 bytes follow Symbol NoteOn_Status = 144 + Midichannel Symbol Keypres_Status = 160 + Midichannel Symbol Control_Status = 176 + Midichannel Symbol ProgChange_Status = 192 + Midichannel ' 1 byte message Symbol Aftertouch_Status = 208 + Midichannel ' 1 byte follows Symbol Pitchbend_Status = 224 + Midichannel ' lsb msb follow ' Setup the USART Declare Hserial_Baud = 31250 ' Set baud rate for the USART to MIDI specs. Declare Hserial_TXSTA = 0x24 ' instead of the normal 0x20 - ?? 0x24 ' Declare Hserial_Clear = On ' should clear on errors. Bytes get lost of course... This must be 31250 for MIDI ' Create variables Dim Cntl As TMR0L.Word 'this is the trick to read both TMR0L and TMR0H ? YES 'it makes Cntl the low word of cnt Dim Bytein As Byte System ' midi byte read from buffer Dim StBit As Bytein.7 ' highest bit of ByteIn Dim i As Byte System ' general purpose counter Dim j As Byte System Dim k As Byte System ' general purpose variable Dim z As Byte System ' midi variables Dim statusbyte As Byte System Dim noteUit As Byte System ' note off + release value Dim release As Byte System Dim noteAan As Byte System ' note on + release value Dim velo As Byte System Dim notePres As Byte System ' note pressure + pressure value Dim pres As Byte System Dim Ctrl As Byte System ' continuous controller + value Dim value As Byte System Dim prog As Byte System ' program change + program-byte Dim aft As Byte System ' channel aftertouch Dim pblsb As Byte System ' pitch bend lsb Dim pbmsb As Byte System ' pitch bend msb Dim veltim As Dword System ' 32 bit velo Dim VelFlags As Word System ' bits 0 - 15 used as flags for active velo-timers Dim VelFlags0 As VelFlags.Byte0 ' alias for bits 0-7 Dim VelFlags1 As VelFlags.Byte1 ' bits 8-15 Dim UseString As Byte System ' var. to pass the string to be used for the requested note [0-11] Dim CC3 As Byte System Dim CC4 As Byte System Dim CC7 As Byte System ' received value for volume controller Dim CC64 As Byte System ' sustain switch Dim CC65 As Byte System ' noteoff with release enable controller Dim CC66 As Byte System ' global on/off switch Dim Lut As Word System ' the compiler does not allow aLUT[n].Highbyte etc... Dim LutSnaar As Lut.HighByte 'the low nibble of the highbyte holds the string to use (0-11) 'the high nibble can be used for transpositions Dim LutMulti As Lut.LowByte 'the lowbyte holds the multiplier setting required (1-64) Dim Tune As Byte System Dim BaseNote As Byte System 'for transposition required in the upper octave Dim st As Byte System Dim b1 As Byte System Dim b2 As Byte System Dim lim As Byte System 'sofar, 66 system var's used. ' Dim KPFlags As Dword System ' used as flags for active key pressure modulation ' only 96 bytes available in system RAM!!! '----------------------------------------------------------------------------------------- ' Load the USART Interrupt handler And buffer read subroutines into memory 'Include "Irq_Handler.inc" ' irq handler for UART and Timer0 interrupt Include "Aeio_Irq.inc" ' our own version Include "Timers.inc" ' required for velo support with timed pulses. 'declare and dimension all scalars: Dim HammerIndex[128] As Byte ' 24-35 Dim LightIndex[7] As Byte ' 1-6 Dim SnaarX[12] As Byte ' if SnaarX[x] = 0 then the string is free ' else: SnaarX[x] = multiplier-value used for playing ' multiplier = CC22 Dim SnaarNote[12] As Byte ' indicates what note the string is sounding ' set to 255 if no note is sounding on that string Dim OldTune[12] As Byte ' last set value for string fine tuning with CC24 Dim cc3Old[12] As Byte ' pwm setting for cc3 Dim cc4Old[12] As Byte ' pwm setting for cc4 Dim CC20[12] As Byte ' basic tuning for the strings Dim CC23[12] As Byte ' drive symmetry controller Dim CC69[12] As Byte ' on/off flags for the string drivers Dim OldVelo[12] As Byte ' to check whether or not cc3 and cc4 have to be recalculated. Dim Multi[12] As Byte ' multiplier values for flageolets used with CC100-CC111 Dim pLUT[92] As Word ' shifted 36. 0-91 for notes 36 to 127 Dim aLUT[92] As Word ' alternative way of playing the note in the index ' HighByte, lownibble = snaarnummer , highnibble transposition ' Lowbyte = multiplier Dim pKOR[92] As Byte ' pitch correction to adapt to inharmonicity Dim aKOR[92] As Byte ' now 36 - 127, dsPIC 11.09.2010 ' Mapping defines for midi-events on pin outputs: ' There are only 16 pins free: RB0-5, RC0, RC3-5, RA0-RA5 ' mapping for our special Aeio-parser board (06.09.2010) $define Note0 PORTB.0 ' Led light for string 36 $define Note1 PORTB.1 ' Led light for string 37 $define Note2 PORTB.2 ' 38 $define Note3 PORTB.3 ' 39 $define Note4 PORTB.4 ' 40 ' RB5, RB6, RB7 used for ICD $define Note5 PORTB.5 ' 41 ' RB5 is also used by the ICD... $define Note6 PORTA.5 ' 42 $define Note7 PORTA.4 ' 43 $define Note8 PORTA.3 ' 44 $define Note9 PORTA.2 ' 45 $define NoteA PORTA.1 ' 46 $define NoteB PORTA.0 ' 47 $define NoteC PORTC.0 ' light - mosfet - noot 1 $define NoteD PORTC.3 ' light - mosfet - noot 2 $define NoteE PORTC.4 ' blue debug LED {Left, upper) - noot 3 $define NoteF PORTC.5 ' blue debug LED (Right, lowest) - noot 4 ' configure the output pins: TRISA = %01000000 'bits set to 0 are output, 1 = input TRISB = %11100000 TRISC = %11000000 'RC1 en RC2 zijn pwm outputs and must be set to output 'RC6 en RC7 zijn USART I/O and must be set to input 'make sure we initialize those pins to 0 on start up: (test LED's will be ON if pulled up to +3V) Low Note0 Low Note1 Low Note2 Low Note3 Low Note4 Low Note5 Low Note6 Low Note7 Low Note8 Low Note9 Low NoteA Low NoteB Low NoteC 'light Low NoteD 'light Low NoteE 'blue led Low NoteF 'blue led 'after reset the pwm outputs should be off also: [ to be used for lights] 'Low RC1 'this one is low by default after reset - Proton+ does not find it... 'Low RC2 'this one is high by default after reset! Low PORTC.1 'this works for the Proton compiler. Low PORTC.2 '----------------------------------------------------------------------------------------- ' Main program loop starts here ' GoTo Start_2 Start_0: GoSub Lookup_Plato_Pitch ' pitch mapping on overtones GoTo MAIN Start_1: GoSub Lookup_Science_Pitch GoTo MAIN Start_2: GoSub Lookup_Empiric GoTo MAIN Start_3: GoSub Lookup_EQ MAIN: DelayMS 100 ' wait for stability - also, because the dsPIC's have to start up on a ' cold boot Init_Usart_Interrupt ' Initiate the USART serial buffer interrupt ' this procedure is in the include file Clear_Serial_Buffer ' Clear the serial buffer and reset its pointers ' in the include as well ' following only required for pulse outputs: ' Note that we can only use timer0 since the other timers ' are used by the PWM subsystem ' Configure Timer0 for: ' Clear TMR0L and TMR0H registers ' Interrupt on Timer0 overflow ' 16-bit operation ' Internal clock source 64MHz ' 1:256 Prescaler : thus 64MHz / 256 = 250kHz Opentimer0 (Timer_INT_On & T0_16BIT & T0_SOURCE_INT & T0_PS_1_256) ' Setup the High priorities for the interrupts GoSub Init_Aeio ' send all required initialisation to aeio 'GoSub Lookup_Plato_Pitch ' pitch mapping on overtones GoSub Init_Veloscales ' load lookup for the veloscalings for each output ' also resets all velo counters ' vellsb[x] = 0xFFFF ' velmsb[x] = 0x7FFF 0x7FFF because dwords are signed! ' sofar not used in aeio. All set to 0 High NoteF ' indicate we are ready for startup (blue LED) ' start the main program loop: While 1 = 1 ' Create an infinite loop Bytein = HRSIn ' Read data from the serial buffer, with timeout ' timeout values set to bare minimum. ' Here we can start the midi parser. Midi_Parse: If Bytein > ProgChange_Status Then ' was Pitchbend_Status Then , but here this is not implemented. If Bytein > 253 Then '254 = midiclock, 255= reset 'midiclock can interrupt all other msg's... '255 had to be intercepted since thats what we 'get when no new byte flows in (?) GoTo Midi_Parse_End 'throw away... Else Clear statusbyte 'reset the status byte GoTo Midi_Parse_End 'throw away End If EndIf If StBit =1 Then 'should be faster than If Bytein > 127 Then 'status byte received, bit 7 is set Clear statusbyte 'if on another channel, the statusbyte needs a reset Select Bytein 'eqv to Select case ByteIn Case NoteOff_Status statusbyte = Bytein noteUit = 255 'reset value. Cannot be 0 !!! release = 255 '0 is a valid midi note! Case NoteOn_Status statusbyte = Bytein noteAan = 255 velo = 255 Case Keypres_Status statusbyte = Bytein notePres = 255 pres = 255 Case Control_Status statusbyte = Bytein Ctrl = 255 value = 255 Case ProgChange_Status statusbyte = Bytein prog = 255 ' Case Aftertouch_Status ' statusbyte = Bytein ' aft = 255 ' Case Pitchbend_Status ' statusbyte = Bytein ' pblsb = 255 ' pbmsb = 255 End Select Else 'midi byte is 7 bits Select statusbyte Case 0 'not a message for this channel GoTo Midi_Parse_End 'disregard Case NoteOff_Status If noteUit = 255 Then noteUit = Bytein Else release = Bytein 'message complete, so we can do the action... 'the hammers do not need a note off, so we disregard them here. 'lights may have to be handled here though. 'problem: how to discriminate unison notes? Select noteUit Case > 35 'If noteUit < 108 Then 'higher notes have a transposition! GoSub Aeio_NoteOff 'noteUit is passed to the proc. noteUit = 255 GoTo Midi_Parse_End 'EndIf Case < 7 On LightIndex[noteUit] GoSub NOC, NOD, NOE, NOF, YELO1, YELO2 noteUit = 255 GoTo Midi_Parse_End End Select noteUit = 255 'reset EndIf GoTo Midi_Parse_End Case NoteOn_Status If noteAan = 255 Then noteAan = Bytein Else velo = Bytein If velo = 0 Then 'here we have to lookup which string was playing the note... 'only then we can release the string and give it free. 'handle dampers If noteAan > 35 Then 'If noteAan < 108 Then noteUit = noteAan release = velo GoSub Aeio_NoteOff noteUit = 255 'EndIf Else If noteAan < 7 Then On LightIndex[noteAan] GoSub NOC, NOD, NOE, NOF, YELO1, YELO2 EndIf noteAan = 255 'reset !!! GoTo Midi_Parse_End 'jump out EndIf Select noteAan Case < 24 If noteAan < 7 Then On LightIndex[noteAan] GoSub NAC, NAD, NAE, NAF, YELA1, YELA2 'niks - on the dsPIC's the dampers are triggered on the note-offs noteAan = 255 GoTo Midi_Parse_End 'seems required... Case < 36 'beaters: - mapped on notes 24-35 - this should work already. On HammerIndex[noteAan] GoSub N24,N25,N26,N27, N28, N29, N30, N31, N32, N33, N34, N35 noteAan = 255 GoTo Midi_Parse_End 'seems required... Case < 127 'we use lookuptable here: for notes 36 to 127 i = noteAan - 36 'apply the offset If pLUT[i] > 0 Then 'check whether the string can play the note Lut = pLUT[i] UseString = LutSnaar & 0x0F 'pLUT.Highbyte[i] 'pLUT[i].Highbyte - syntax error!!! 'Lutsnaar is an alias for the highbyte of Lut 'we need only the low nibble of this highbyte, hence 'the mask If SnaarX[UseString] = 0 Then 'if the string is free SnaarX[UseString] = LutMulti 'pLUT[i].LowByte BaseNote = LutSnaar >> 4 'high nibble 'LutMulti is an alias for the lowbyte of Lut 'SnaarNote[UseString] = noteAan done in play procedure 'Check for pitch correction entry in the lookup: Tune = pKOR[i] Else If aLUT[i] > 0 Then Lut = aLUT[i] 'if it could be played on another string UseString = LutSnaar & 0x0F 'aLUT[i].Highbyte If SnaarX[UseString] = 0 Then 'if the string is free SnaarX[UseString] = LutMulti 'aLUT(i).Lowbyte 'SnaarNote[Usestring] = noteAan BaseNote = LutSnaar >> 4 'pitch correction entry: Tune = aKOR[i] Else noteAan = 255 'cannot be played GoTo Midi_Parse_End EndIf Else noteAan = 255 GoTo Midi_Parse_End 'note cannot be played End If EndIf EndIf Case Else noteAan = 255 GoTo Midi_Parse_End End Select If UseString < 12 Then GoSub Aeio_Play_Note '>=12 should never happen... noteAan = 255 'reset EndIf GoTo Midi_Parse_End Case Keypres_Status 'must be implemented on aeio!!! If notePres = 255 Then notePres = Bytein Else pres = Bytein GoSub KeyPres EndIf GoTo Midi_Parse_End Case Control_Status If Ctrl = 255 Then Ctrl = Bytein Else value = Bytein GoSub Controller EndIf GoTo Midi_Parse_End Case ProgChange_Status If prog = 255 Then 'single byte message prog = Bytein 'weak coding... GoSub ProgChange 'Goto ProgChange EndIf ' GoTo Midi_Parse_End ' Case Aftertouch_Status ' 'not to be implemented on Aeio ' If aft = 255 Then 'single byte message ' aft = Bytein ' GoSub Aftertouch ' EndIf ' Case Pitchbend_Status 'two bytes message ' If pblsb = 255 Then ' pblsb = Bytein ' Else ' pbmsb = Bytein ' GoSub Pitchbend ' End If End Select EndIf Midi_Parse_End: 'jump out of parser label ' here we check the velo counters and compare them with the cnt value ' new construction using the Velflags dword variable: ' If VelFlags > 0 Then 'if any bit is set here, there is a velo timer running ' Cnt.LowWord = Cntl 'read counter ' For i = 0 To 15 ' If GetBit VelFlags, i = 1 Then 'check which counter is active ' veltim.Word1 = velmsb[i] ' veltim.Word0 = vellsb[i] ' If Cnt >= veltim Then '32 bit compare ' On i GoSub PE0,PE1,PE2,PE3,PE4,PE5,PE6,PE7,PE8,PE9,PEA,PEB,PEC,PED,PEE, PEF ' EndIf ' EndIf ' Next i ' EndIf Wend 'end of the main loop '------------------------------------------------------------------------------------ 'here we write the code for what has to happen on reception of midi commands: 'midi action procedures: ------------------------------------------------------------ Aeio_NoteOff: 'if two strings are sounding a same note, we will run into a problem here. 'as coded now, always the first note encountered in SnaarNote[] will be released. For k = 0 To 11 If noteUit = SnaarNote[k] Then Break 'jump out of the loop Next 'what if the note is never found??? If k < 12 Then st = 128 + k If noteUit < 115 Then HRSOut st, 36, release 'release only if we implement it on the dsPic's 'the dsPIC's take the largest of CC65 and release 'to calculate the damping time. Else st = 176 + k HRSOut st, 123, 0 'in this case we send an all notes off command. EndIf SnaarNote[k] = 255 'give the string free for other notes: SnaarX[k] = 0 'set multiplier to 0, string is free. 'do the LED's: On k GoSub NO0, NO1, NO2,NO3,NO4,NO5,NO6, NO7, NO8, NO9, NOA, NOB 'check sustain flag: if off, we should send the commands to the dampers ' Aeio Version 1.1: This is now handled by the dsPICs EndIf noteUit = 255 'reset Return Aeio_Play_Note: ' called on midinoteON command ' UseString is known, the multiplier is in SnaarX[UseString] ' usestring is 0-11, number of the string. 'Usestring = Usestring min 11 'for debug!!! 'following can be left out, to save some time... If CC69[UseString] = 0 Then 'make sure the ebow for that string is enabled... st = 176 + UseString HRSOut st, 69, 64 'switch ON of it was off CC69[UseString] = 64 EndIf '---------------------- 'HRSOut 144+ UseString , 36, velo ' velo not implemented here in dsPIC 'HRSOut 176+ UseString, 22, SnaarX[UseString] 'send multiplier 'try sending as one chunk: st = 144 + UseString 'this is the note-on command. b1 = 176 + UseString b2 = SnaarX[UseString] 'multiplier - CC22 'HRSOut st , 36, velo, (176+ UseString), 22, SnaarX[UseString] If BaseNote = 0 Then HRSOut st,36,velo,b1,22,b2 'always note 36, always send multiplier. 'note that the value for velo is irrelevant here, since nothing with it is done by the dsPIC Else Select BaseNote ' values 1-7 transpose the base note an octave up [ implemented only 1-4 ] ' values 8-15 transpoee the base note octaves down [ implemented only 8-9 ] ' this will not be possible, since the dsPICs start at note 36, below this we have hammers... Case 1 HRSOut st,48,velo,b1,22,b2 'always note 48, always send multiplier. Case 2 HRSOut st,60,velo,b1,22,b2 'always note 60, always send multiplier. Case 3 HRSOut st,72,velo,b1,22,b2 'always note 72, always send multiplier. Case 4 HRSOut st, 84, velo, b1, 22, b2 ' CASE 8 ' HRSOut st,24,velo,b1,22,b2 'always note 24, always send multiplier. ' CASE 9 ' HRSOut st,12,velo,b1,22,b2 'always note 12, always send multiplier. End Select End If If Tune <> OldTune[UseString] Then 'tune is read from lookup also!!! st = 176 + UseString HRSOut st, 24, Tune 'send fine tuning if required . controller 24 OldTune[UseString] = Tune 'Tune[UseString] EndIf ' If velo <> OldVelo[UseString] Then ' ' velo control: - now symmetric PWM: ' ' calculate the required CC3 - cc4 settings form velo ' ' following tested ok in GMT, but should be recoded for integer math. ' ' CC3[0]= 64 * (velo/127) 'gaan op de PIC nooit echt naar 0 ' ' CC4[0]= (127- 64) * (velo/127) '64 gives us 12.5% duty cycle ' HRSOut (176+ UseString), 3, CC3[UseString] ' HRSOut (176+ usestring), 4, CC4[UseString] ' OldVelo[0] = velo ' EndIf ' ' calculation of the required settings for cc3 and cc4: [ first version] ' x = velo + CC7 'range becomes 0-254 ' k = x >> 1 'divide by 2, so now back to 0-126 ' 'apply symmetry controller cc23: ' 'when cc23 = 64 the drive will be symmetric ' 'when cc23 = 127 , cc3 will become 0 ' 'when cc23 = 0 , cc4 will become 0 ' CC3[UseString] = 127 - CC23[UseString] ' if cc23 = 64, cc3 will be 63 ' ' if cc23 = 127, cc3 will be 0 ' ' if cc23 = 0, cc3 will be 127 ' CC4[UseString] = 127 - CC3[UseString] ' if cc23 = 64, cc4 will be 64 ' ' if cc23 = 127, cc4 will be 127 ' ' if cc23 = 0, cc4 will be 0 ' 'cc3[UseString] = CC3[Usestring] * k 'not possible since cc3 is only a byte... ' 'cc4[Usestring] = CC4[usestring] * k ' 'quick and dirty: ' CC3[UseString] = CC3[UseString] Min k ' CC4[UseString] = CC4[UseString] Min k ' ' first version END '---------------------------------------------------------------------------- ' 'alternative code, whereby CC7 is the upperlimits for the values for CC3 and cc4 ' 'note that here, both coils can be at maximum drive. ' CC3[UseString] = CC7 ' CC4[UseString] = CC7 ' if CC23[Usestring] >= 64 then ' x = CC23[UseString] - 64 '0-63 ' if CC7 > x then ' CC3[Usestring] = CC3[Usestring] - x 'when CC23=64, and CC7= 127, CC3 will be 127 ' else 'when CC23=127, and CC7=127, CC3 will be 63 ' CC3 = 0 ' endif ' else ' x = CC23[UseString] '0-63 ' if CC7>= x then ' CC4[UseString] = CC4[UseString] - x ' else ' CC4 = 0 ' endif ' endif ' 'and now limit to the velo setting: ' CC3[Usestring] = CC3[Usestring] min velo ' CC4[UseString] = CC4[UseString] Min velo ' '-------------------------------------- 'new attempt: [07.09.2010] lim = CC7 Min velo 'set the limit to the smallest of both k = CC23[UseString] << 1 'x 2 gives us 0-254 range z = 254 - k 'complimentary value CC3 = k Min lim 'CC3[UseString] = k Min lim CC4 = z Min lim 'CC4[UseString] = z Min lim OldVelo[UseString] = velo 'Uitsturing: If CC3 <> cc3Old[UseString] Then st = 176 + UseString HRSOut st, 3, CC3 cc3Old[UseString] = CC3 EndIf If CC4 <> cc4Old[UseString] Then st = 176 + UseString HRSOut st, 4, CC4 cc4Old[UseString] = CC4 End If SnaarNote[UseString] = noteAan 'required to be able to switch it off 'to finish: light the LED to indicate to the user which string is active: On UseString GoSub NA0, NA1, NA2, NA3, NA4, NA5, NA6, NA7, NA8, NA9, NAA, NAB noteAan = 255 'reset Return 'NOTE-OFF procedures, called with the On idx Gosub... construction: 'In Aeio this only controls the LED display on the parser PC board. NO0: Low Note0 'Clear VelFlags0.0 'if we want to do something with the release value, if set, it should be implemented here. Return NO1: Low Note1 'Clear VelFlags0.1 Return NO2: Low Note2 'Clear VelFlags0.2 Return NO3: Low Note3 'Clear VelFlags0.3 Return NO4: Low Note4 'Clear VelFlags0.4 Return NO5: Low Note5 'Clear VelFlags0.5 Return NO6: Low Note6 'Clear VelFlags0.6 Return NO7: Low Note7 'Clear VelFlags0.7 Return NO8: Low Note8 'Clear VelFlags1.0 Return NO9: Low Note9 'Clear VelFlags1.1 Return NOA: Low NoteA 'Clear VelFlags1.2 Return NOB: Low NoteB 'Clear VelFlags1.3 Return NOC: Low NoteC 'light 1 Return NOD: Low NoteD 'light 2 Return NOE: Low NoteE 'light 3 Return NOF: Low NoteF 'light 4 Return YELO1: 'yellow light 1 (note 5) Low PORTC.1 Return YELO2: 'yellow light 2 (note 6) Low PORTC.2 Return '-------------------------------------- 'here we have all 16 note-ON procedures: 'in Aeio, this only switches on the LED's indicating string busyness. 'we need only 12 procs. NA0: ' called with On idx Gosub from the main loop. High Note0 'this should always happen... Return NA1: High Note1 Return NA2: High Note2 Return NA3: High Note3 Return NA4: High Note4 Return NA5: High Note5 Return NA6: High Note6 Return NA7: High Note7 Return NA8: High Note8 Return NA9: High Note9 Return NAA: High NoteA Return NAB: High NoteB Return NAC: High NoteC 'lite 1 Return NAD: High NoteD 'lite2 Return NAE: High NoteE 'lite3 Return NAF: High NoteF 'lite4 Return YELA1: High PORTC.1 'lite5 Return YELA2: High PORTC.2 'lite6 Return KeyPres: 'the note to which the pressure should be applied is passed in NotePres, the value in Pres 'modulate the loudness of playing notes. 'first attempt: 'we have to find the string playing the note for which the volume has to be modulated: For i = 0 To 11 If notePres = SnaarNote[i] Then Break 'jump out of the loop Next If i > 11 Then Return 'error ' i contains now the string number (0-11) If SnaarX[i] > 0 Then 'check whether the string is still playing... lim = CC7 Min pres 'set the limit to the smallest of both k = CC23[i] << 1 'x 2 gives us 0-254 range z = 254 - k 'complimentary value CC3 = k Min lim CC4 = z Min lim 'Uitsturing: If CC3 <> cc3Old[i] Then st = 176 + i HRSOut st, 3, CC3 cc3Old[i] = CC3 EndIf If CC4 <> cc4Old[i] Then st = 176 + i HRSOut st, 4, CC4 cc4Old[i] = CC4 End If EndIf notePres = 255 Return ProgChange: 'used for changing the pitch lookup tables. 'prog. changes should not be send fast!!! ' to be implemented prog. changes: ' 0 = platonic overtone series (does not sound very well) [religionszwang] ' 1 = scientific overtone series, with inharmonicity correction for optimum resonance ' pitches will be out of tune [Scientia vincere tenebras] ' 2 = empirical overtone series, measured out by Kristof Lauwers [earthbound] ' 3 = optimum equal temperament scale tuning [pragmaticism] ' IF prog.0 = 0 THEN 'bit 0 sets the lookup table to use ' GOSUB Lookup_Plato_Pitch ' ELSE ' GOSUB Lookup_Science_Pitch ' END IF On prog GoSub Lookup_Plato_Pitch, Lookup_Plato_Pitch, Lookup_Science_Pitch, Lookup_Empiric, Lookup_EQ 'try this instead: ' On prog goto Start_0, Start_0, Start_1, Start_2, Start_3 ' Goto Midi_Parse_End ' in case a non existing prog. change was received. ' Select prog ' Case 1 '0 ' Goto Start_0 ' 'GoSub Lookup_Plato_Pitch ' Case 2 '1 ' Goto Start_1 ' 'GoSub Lookup_Science_Pitch ' Case 3 '2 ' Goto Start_2 ' 'GoSub Lookup_Empiric ' Case 4 '3 ' Goto Start_3 ' 'GoSub Lookup_EQ ' End Select prog = 255 'this is not realy required Return Pitchbend: 'only implemented on dsPIC based robots, but not on Aeio pblsb = 255 Return 'Aftertouch: ' 'this is the channel aftertouch, affecting all notes ' 'not to be implemented in Aeio ' aft = 255 'not mandatory 'Return Controller: Select Ctrl '19.09.2010: Although the following works nicely, we remmed it out for the yellow 'led lights we use do not work with PWM poser supply. (they are ac types with regulation) ' Case 5 ' 'we can use one of the 2 hardware pwm's here: ' HPWM 0, value + value, 3906 'uses CCP1 (=RC2) output. 3906 is the minimum frequency here. ' ' duty cycle range is 0-255, hence the value + value ' 'this works fine. ' 'lights!!! ' GoTo Ctrl_Parse_End ' Case 6 ' 'we can use the second hardware pwm: ' HPWM 1, value + value, 3906 'uses CCP2 (-RC1) output ' 'lights!!! ' GoTo Ctrl_Parse_End Case 7 'master volume controller, sets max. energy to ebows. (ceil for velo) CC7 = value 'modulate the loudness of playing notes. 'first attempt: [ this contradicts the use of velo as a pulse exciter or course...] For i = 0 To 11 If SnaarX[i] > 0 Then 'check whether the string is playing... lim = CC7 Min OldVelo[i] 'set the limit to the smallest of both k = CC23[i] << 1 'x 2 gives us 0-254 range z = 254 - k 'complimentary value CC3 = k Min lim CC4 = z Min lim 'Uitsturing: If CC3 <> cc3Old[i] Then st = 176 + i HRSOut st, 3, CC3 cc3Old[i] = CC3 EndIf If CC4 <> cc4Old[i] Then st = 176 + i HRSOut st, 4, CC4 cc4Old[i] = CC4 End If EndIf Next i GoTo Ctrl_Parse_End Case 23 'this controller sets the symmetry for all the ebow drivers 'on start-up the values are preset to 64 'changes of this controller will only affect the next note playing! For i = 0 To 11 CC23[i] = value 'to set the values individually we need 12 separate controllers Next i GoTo Ctrl_Parse_End Case 30 To 41 CC23[Ctrl - 30] = value 'separate controllers for each string 'a change of these controllers should be applied whilst a note is playing. 'to be done. GoTo Ctrl_Parse_End Case 50 To 61 'can be used to shift the basic tuning of čach string 'or in fact, any interval, if users know what they are doing... CC20[Ctrl - 50] = value st = 176 + (Ctrl - 50) HRSOut st, 20, value GoTo Ctrl_Parse_End Case 64 'sustain on/off If value = 0 Then CC64 = 0 'damping is used Else CC64 = 64 'no damping after notes EndIf 'if sustain is > 0 we disable the dampers 'if sustain is = 0 we enable the dampers For k = 0 To 11 st = 176 + k HRSOut st, 64, CC64 Next k GoTo Ctrl_Parse_End Case 65 'enable or disable note-off with release 'if note off with release is not used, this controller is used 'to control the duration of the damping after a note off. 'This will only work if CC64 = 0 of course. CC65 = value For k = 0 To 11 st = 176 + k HRSOut st, 65, CC65 Next k GoTo Ctrl_Parse_End Case 66 'on/off for robot If value = 0 Then GoSub AllNotesOff ' HPWM 0, 0 , 3906 ' HPWM 1, 0, 3906 Else For k = 0 To 11 st = 176 + k HRSOut st, 69, 64 'ebows enabled. CC69[k] = 64 Next k EndIf GoTo Ctrl_Parse_End Case 80 To 91 'can be used to fine tune the basic frequency 'OldTune[Ctrl - 80] = value st = 176 + (Ctrl - 80) HRSOut st, 24, value 'the dsPICs use CC24 for fine tuning 'now bipolar. 2 cent resolution, mid position = 64 'means no tuning change. OldTune[Ctrl-80] = value 'so it will be reset when the next note is played again! GoTo Ctrl_Parse_End Case 100 To 111 'can be used to manually set the multiplier value for a sounding note k = Ctrl - 100 'string number If SnaarX[k] > 0 Then 'the string must be playing!!! If value > 0 Then If value < 65 Then Multi[k] = value 'must be 1-64 st = 176 + k HRSOut st, 22, value 'CC22 is the multiplier controller SnaarX[k] = value 'could be dangerous. GoTo Ctrl_Parse_End EndIf EndIf EndIf GoTo Ctrl_Parse_End Case 123 'all notes off GoSub AllNotesOff End Select Ctrl_Parse_End: Ctrl = 255 'mandatory reset Return AllNotesOff: ' send as a single chunk: ' could it be that this also resets the tuning with CC20??? ' HRSOut 176, 69,0 , 177, 69, 0, 178, 69, 0 , 179, 69, 0, 180, 69, 0, 181, 69,0, 182, 69, 0, 183, 69, 0, 184, 69, 0, 185, 69, 0, 186, 69, 0, 187, 69, 0 HRSOut 176, 123,0 , 177, 123, 0, 178, 123, 0 , 179, 123, 0, 180, 123, 0, 181, 123,0, 182, 123, 0, 183, 123, 0, 184, 123, 0, 185, 123, 0, 186, 123, 0, 187, 123, 0 Low Note0 Low Note1 Low Note2 Low Note3 Low Note4 Low Note5 Low Note6 Low Note7 Low Note8 Low Note9 Low NoteA Low NoteB ' not notes Low NoteC Low NoteD Low NoteE Low NoteF Low PORTC.1 Low PORTC.2 Clear VelFlags For k = 0 To 11 SnaarX[k] = 0 'make all strings free ' CC69[k] = 0 'not required SnaarNote[k] = 255 Next k Return Init_Veloscales: 'to be edited for each application 'to implement: if a zero value is written, we can configure that note for on/off only. 'since the timer lowword overflows at ca. 1.1Hz, the clock ticks go at 72kHz '1 timeunit must now be 13.8 microseconds '1 to 127 would then be a range of 13.8 microseconds to 1.7ms 'value 100 gives than 1.38ms to 176ms 'value 50 gives 690us to 88ms 'In theory, a unit ought to be 4 microseconds... 'with the implementation now, the maximum value should be 512. ' VeloScale[0] = 0'00 ' value 100 gives 400us to 50.8 ms range for velo's ' VeloScale[1] = 0'0 ' VeloScale[2] = 0 ' VeloScale[3] = 0 ' VeloScale[4] = 0 ' VeloScale[5] = 0 ' VeloScale[6] = 0 ' VeloScale[7] = 0 ' VeloScale[8] = 0 ' VeloScale[9] = 0 ' VeloScale[10] = 0 ' VeloScale[11] = 0 'velopulsing not implemented for the strings. ' 'it could be done, by sending max. power to the bows during the attack ' VeloScale[12] = 50 ' VeloScale[13] = 50 ' VeloScale[14] = 50 ' VeloScale[15] = 50 LightIndex[0] = 255 LightIndex[1] = 0 'lampjes - noot 1 LightIndex[2] = 1 LightIndex[3] = 2 LightIndex[4] = 3 LightIndex[5] = 4 LightIndex[6] = 5 For i = 0 To 127 HammerIndex[i] = 255 Next i For i = 24 To 35 HammerIndex[i] = i - 24 'these notes are hammers Next i Clear VelFlags 'no velo timer active on start up 'not implemented notes will have a zero in Notes[x] Return Init_Aeio: 'this will take about 144 ms For k = 0 To 11 st = 176 + k 'HRSOut st, 69, 64 'on/off controller CC69[k] = 64 'switch all strings ON CC23[k] = 64 'set bow symmetry drive controllers to 50/50 'this controller should not be sent to the dsPICs ' b2 = 52 + k 'HRSOut st, 20, b2, 22, 1 'set tuning right for 36-47 - CC20 'since it sounds better an octave higher, we changed this to: b2 = 64 + k 'it should be 64 + k, to get the tuning right for notes 36 ... CC20[k] = b2 'basic tuning 'updated 11.09.2010 in the dsPICS 'set flag. multiplier to 1 - CC22 OldTune[k] = 64 'HRSOut st, 24, 0 'set fine tune to center - CC24 cc3Old[k] = 64 'HRSOut st, 3, 64 '12.5% PWM A - CC3 cc4Old[k] = 64 'HRSOut st , 4, 64 '12.5% PWM B - CC4 SnaarX[k] = 0 'make string free for use ' sending all in one chunk: (midi running mode) HRSOut st, 69, 64, 20, b2, 22, 1, 24, 64, 3, 64 , 4, 64 DelayMS 6 CC64 = 0 '0 = enable the damper mechanism (sustain = OFF) CC65 = 15 'release value for the damping. 'should also be send to the dsPIC's on init!!! 'with value 127, the damper will stay against the string as long as 'the string is not playing. 'with value 126 it will release after some 2 seconds HRSOut st, 64, CC64, 65, CC65 DelayMS 4 Next k CC3 = 64 CC4 = 64 CC7 = 64 'default volume (not yet individualized) Return ' midi commands for the hammer=exciters: - this works fine. N24: HRSOut 144, 24, velo 'send pulse command to the excitation hammers string0 Return N25: HRSOut 145, 24, velo Return N26: HRSOut 146, 24, velo Return N27: HRSOut 147, 24, velo Return N28: HRSOut 148, 24, velo Return N29: HRSOut 149, 24, velo Return N30: HRSOut 150,24, velo Return N31: HRSOut 151, 24, velo Return N32: HRSOut 152, 24, velo Return N33: HRSOut 153, 24, velo Return N34: HRSOut 154, 24, velo Return N35: HRSOut 155, 24, velo Return Lookup_Plato_Pitch: 'alternate lookups according to physical reality to be worked out. 'selection of lookups can happen with program change commands 'offset 36 !!! 'pLUT[0] = 0-91 for notes 36 to 127 For k = 0 To 91 pKOR[k] = 64 'default to no pitch correction, or center value for CC24 aKOR[k] = 64 Next For k = 0 To 18 : aLUT[k] = 0 : Next pLUT[0] = 0x0001 'highbyte = string number, lowbyte= multiplier pLUT[1] = 0x0101 pLUT[2] = 0x0201 pLUT[3] = 0x0301 pLUT[4] = 0x0401 pLUT[5] = 0x0501 pLUT[6] = 0x0601 pLUT[7] = 0x0701 pLUT[8] = 0x0801 pLUT[9] = 0x0901 pLUT[10] = 0x0A01 pLUT[11] = 0x0B01 pLUT[12] = 0x0002 'note 48 pLUT[13] = 0x0102 pLUT[14] = 0x0202 'note 50 pLUT[15] = 0x0302 '51 pLUT[16] = 0x0402 '52 pLUT[17] = 0x0502 '53 pLUT[18] = 0x0602 '54 pLUT[19] = 0x0702 '55 first note that can be played two ways aLUT[19] = 0x0003 pLUT[20] = 0x0802 : aLUT[20] = 0x0103 pLUT[21] = 0x0902 : aLUT[21] = 0x0203 pLUT[22] = 0x0A02 : aLUT[22] = 0x0303 pLUT[23] = 0x0B02 : aLUT[23] = 0x0403 pLUT[24] = 0x0004 : aLUT[24] = 0x0503 'note 60 pLUT[25] = 0x0104 : aLUT[25] = 0x0603 pLUT[26] = 0x0204 : aLUT[26] = 0x0703 pLUT[27] = 0x0304 : aLUT[27] = 0x0803 pLUT[28] = 0x0404 : aLUT[28] = 0x0903 pLUT[29] = 0x0504 : aLUT[29] = 0x0A03 pLUT[30] = 0x0604 : aLUT[30] = 0x0B03 'note 66 pLUT[31] = 0x0704 : aLUT[31] = 0x0006 pLUT[32] = 0x0804 : aLUT[32] = 0x0106 'note 68 pLUT[33] = 0x0904 : aLUT[33] = 0x0206 pLUT[34] = 0x0A04 : aLUT[34] = 0x0306 'note 70 pLUT[35] = 0x0B04 : aLUT[35] = 0x0406 pLUT[36] = 0x0008 : aLUT[36] = 0x0506 'note 72 pLUT[37] = 0x0108 : aLUT[37] = 0x0606 pLUT[38] = 0x0208 : aLUT[38] = 0x0706 pLUT[39] = 0x0308 : aLUT[39] = 0x0806 pLUT[40] = 0x0408 : aLUT[40] = 0x0906 'note 76 pLUT[41] = 0x0508 : aLUT[41] = 0x0A06 pLUT[42] = 0x0608 : aLUT[42] = 0x0B06 pLUT[43] = 0x0708 : aLUT[43] = 0x000C 'note 79 pLUT[44] = 0x0808 : aLUT[44] = 0x010C pLUT[45] = 0x0908 : aLUT[45] = 0x020C '81 pLUT[46] = 0x0A08 : aLUT[46] = 0x030C '82 pLUT[47] = 0x0B08 : aLUT[47] = 0x040C pLUT[48] = 0x0010 : aLUT[48] = 0x050C '84 pLUT[49] = 0x0110 : aLUT[49] = 0x060C pLUT[50] = 0x0210 : aLUT[50] = 0x070C pLUT[51] = 0x0310 : aLUT[51] = 0x080C pLUT[52] = 0x0410 : aLUT[52] = 0x090C pLUT[53] = 0x0510 : aLUT[53] = 0x0A0C '89 pLUT[54] = 0x0610 : aLUT[54] = 0x0B0C pLUT[55] = 0x0710 : aLUT[55] = 0x0018 '91 - multiplier = 24 = 0x18 pLUT[56] = 0x0810 : aLUT[56] = 0x0118 pLUT[57] = 0x0910 : aLUT[57] = 0x0218 pLUT[58] = 0x0A10 : aLUT[58] = 0x0318 pLUT[59] = 0x0B10 : aLUT[59] = 0x0418 '95 pLUT[60] = 0x0020 : aLUT[60] = 0x0518 '0x20 = 32,the max. value for the multiplier now pLUT[61] = 0x0120 : aLUT[61] = 0x0618 pLUT[62] = 0x0220 : aLUT[62] = 0x0718 pLUT[63] = 0x0320 : aLUT[63] = 0x0818 '99 pLUT[64] = 0x0420 : aLUT[64] = 0x0918 '100 pLUT[65] = 0x0520 : aLUT[65] = 0x0A18 pLUT[66] = 0x0620 : aLUT[66] = 0x0B18 '102 pLUT[67] = 0x0720 : aLUT[67] = 0x0030 ' exceeding multiplier 32 !!!0x0530 (x48 required) pLUT[68] = 0x0820 : aLUT[68] = 0x0130 'to be checked with new ds firmware pLUT[69] = 0x0920 : aLUT[69] = 0x0230 pLUT[70] = 0x0A20 : aLUT[70] = 0x0330 '106 pLUT[71] = 0x0B20 : aLUT[71] = 0x0430 '107 - highest possible note in dsPIC version 1 pLUT[72] = 0x0040 : aLUT[72] = 0x0530 pLUT[73] = 0x0140 : aLUT[73] = 0x0630 pLUT[74] = 0x0240 : aLUT[74] = 0x0730 pLUT[75] = 0x0340 : aLUT[75] = 0x0830 pLUT[76] = 0x0440 : aLUT[76] = 0x0930 '112 pLUT[77] = 0x0540 : aLUT[77] = 0x0A30 pLUT[78] = 0x0640 : aLUT[78] = 0x0B30 '114 pLUT[79] = 0x0740 : aLUT[79] = 0x1030 '115 alut with fundamental an octave up (high nibble = 1) pLUT[80] = 0x0840 : aLUT[80] = 0x1130 pLUT[81] = 0x0940 : aLUT[81] = 0x1230 pLUT[82] = 0x0A40 : aLUT[82] = 0x1330 pLUT[83] = 0x0B40 : aLUT[83] = 0x1430 '119 'for the range up to 127 we have to tune the fundamental an octave up. 'so, we set the highest nibble to 1 pLUT[84] = 0x1040 : aLUT[84] = 0x1530 '120 pLUT[85] = 0x1140 : aLUT[85] = 0x1630 pLUT[86] = 0x1240 : aLUT[86] = 0x1730 pLUT[87] = 0x1340 : aLUT[87] = 0x1830 '123 pLUT[88] = 0x1440 : aLUT[88] = 0x1930 pLUT[89] = 0x1540 : aLUT[89] = 0x1A30 pLUT[90] = 0x1640 : aLUT[90] = 0x1B30 '126 pLUT[91] = 0x1740 : aLUT[91] = 0x2030 '127 - this is the absolute upper limit for Midi 'note: to implement an octave upwards, we use the high nibble of the pLUT[] values ' to get the string we have to mask out the high nibble with AND 0x0F ' to get the new fundamental tuning we mask with 0xF0 Return Lookup_Science_Pitch: 'This is the loopup table after mathematical analysis based on the 2nd degree equation 'pLUT[0] = 0-91 for notes 36 to 127 For k = 0 To 91 pKOR[k] = 64 'default to no correction or CC24 in central position aKOR[k] = 64 Next For k = 0 To 18 aLUT[k] = 0 Next pLUT[0] = 0x0001 : pKOR[0] = 64 'pLUT: highbyte, lownibble = string number, lowbyte= multiplier (cc22) ' highbyte, highnibble = basenote transposition: ' 1 = octave up, 2= 2 octaves up, 3= 3 octaves up ' 8 = octave down, 9 = 2 octaves down. 'pKOR: pitch correction required (64 = no correction), range 0-127 pLUT[1] = 0x0101 : pKOR[1] = 64 pLUT[2] = 0x0201 : pKOR[2] = 64 pLUT[3] = 0x0301 : pKOR[3] = 64 pLUT[4] = 0x0401 : pKOR[4] = 64 pLUT[5] = 0x0501 : pKOR[5] = 64 pLUT[6] = 0x0601 : pKOR[6] = 64 pLUT[7] = 0x0701 : pKOR[7] = 64 pLUT[8] = 0x0801 : pKOR[8] = 64 pLUT[9] = 0x0901 : pKOR[9] = 64 pLUT[10] = 0x0A01 : pKOR[10] = 64 pLUT[11] = 0x0B01 : pKOR[11] = 64 pLUT[12] = 0x0002 : pKOR[12] = 62 '48 x pLUT[13] = 0x0102 : pKOR[13] = 64 '49 x pLUT[14] = 0x0202 : pKOR[14] = 64 '50 x pLUT[15] = 0x0302 : pKOR[15] = 60 '51 x pLUT[16] = 0x0402 : pKOR[16] = 65 '52 x pLUT[17] = 0x0502 : pKOR[17] = 67 '53 x pLUT[18] = 0x0602 : pKOR[18] = 66 '54 x pLUT[19] = 0x0702 : pKOR[19] = 63 : aLUT[19] = 0x0003 : aKOR[19] = 66 '55 x x pLUT[20] = 0x0802 : pKOR[20] = 66 : aLUT[20] = 0x0103 : aKOR[20] = 70 '56 x x pLUT[21] = 0x0902 : pKOR[21] = 65 : aLUT[21] = 0x0203 : aKOR[21] = 70 '57 x x pLUT[22] = 0x0A02 : pKOR[22] = 71 : aLUT[22] = 0x0303 : aKOR[22] = 67 '58 x x pLUT[23] = 0x0B02 : pKOR[23] = 73 : aLUT[23] = 0x0403 : aKOR[23] = 73 '59 x x pLUT[24] = 0x0004 : pKOR[24] = 65 : aLUT[24] = 0x0503 : aKOR[24] = 76 '60 x x pLUT[25] = 0x0104 : pKOR[25] = 76 : aLUT[25] = 0x0603 : aKOR[25] = 76 '61 x x pLUT[26] = 0x0204 : pKOR[26] = 78 : aLUT[26] = 0x0703 : aKOR[26] = 74 '62 x x pLUT[27] = 0x0304 : pKOR[27] = 75 : aLUT[27] = 0 : aKOR[27] = 64 '63 x pLUT[28] = 0x0404 : pKOR[28] = 83 : aLUT[28] = 0 : aKOR[28] = 64 '64 x pLUT[29] = 0x0504 : pKOR[29] = 85 : aLUT[29] = 0 : aKOR[29] = 64 '65 x pLUT[30] = 0x0604 : pKOR[30] = 88 : aLUT[30] = 0 : aKOR[30] = 64 '66 x pLUT[31] = 0x0704 : pKOR[31] = 86 : aLUT[31] = 0 : aKOR[31] = 64 '67 x pLUT[32] = 0x0804 : pKOR[32] = 92 : aLUT[32] = 0 : aKOR[32] = 64 '68 x pLUT[33] = 0x0904 : pKOR[33] = 93 : aLUT[33] = 0 : aKOR[33] = 64 '69 x pLUT[34] = 0x0007 : pKOR[34] = 85 : aLUT[34] = 0 : aKOR[34] = 64 '70 x pLUT[35] = 0x0A04 : pKOR[35] = 44 : aLUT[35] = 0x0605 : aKOR[35] = 45 '71 x x pLUT[36] = 0x0B04 : pKOR[36] = 59 : aLUT[36] = 0 : aKOR[36] = 59 '72 x pLUT[37] = 0x0506 : pKOR[37] = 65 : aLUT[37] = 0x0008 : aKOR[37] = 63 '73 x x pLUT[38] = 0x0905 : pKOR[38] = 66 : aLUT[38] = 0x0606 : aKOR[38] = 70 '74 x x pLUT[39] = 0x0A05 : pKOR[39] = 69 : aLUT[39] = 0x0009 : aKOR[39] = 78 '75 x x pLUT[40] = 0x0507 : pKOR[40] = 67 : aLUT[40] = 0x0906 : aKOR[40] = 64 '76 x pLUT[41] = 0x0508 : pKOR[41] = 64 : aLUT[41] = 0x0A06 : aKOR[41] = 64 pLUT[42] = 0x0608 : pKOR[42] = 64 : aLUT[42] = 0x0B06 : aKOR[42] = 64 pLUT[43] = 0x0708 : pKOR[43] = 64 : aLUT[43] = 0x000C : aKOR[43] = 64 'note 79 pLUT[44] = 0x0409 : pKOR[44] = 64 : aLUT[44] = 0x010C : aKOR[44] = 64 '80 x pLUT[45] = 0x0708 : pKOR[45] = 68 : aLUT[45] = 0x030A : aKOR[45] = 60 '81 x x pLUT[46] = 0x0A07 : pKOR[46] = 65 : aLUT[46] = 0x030C : aKOR[46] = 64 '82 x pLUT[47] = 0x000D : pKOR[47] = 60 : aLUT[47] = 0x030B : aKOR[47] = 63 '83 x x pLUT[48] = 0x0010 : pKOR[48] = 64 : aLUT[48] = 0x050C : aKOR[48] = 64 '84 pLUT[49] = 0x0809 : pKOR[49] = 63 : aLUT[49] = 0x030C : aKOR[49] = 60 '85 x x pLUT[50] = 0x0710 : pKOR[50] = 64 : aLUT[50] = 0x070C : aKOR[50] = 64 '86 x pLUT[51] = 0x0310 : pKOR[51] = 64 : aLUT[51] = 0x080C : aKOR[51] = 64 pLUT[52] = 0x0410 : pKOR[52] = 64 : aLUT[52] = 0x090C : aKOR[52] = 64 pLUT[53] = 0x0011 : pKOR[53] = 63 : aLUT[53] = 0x060C : aKOR[53] = 64 '89 x x kan ook op snaar 1 pLUT[54] = 0x040E : pKOR[54] = 61 : aLUT[54] = 0x030F : aKOR[54] = 70 '90 x x pLUT[55] = 0x060D : pKOR[55] = 61 : aLUT[55] = 0x0018 : aKOR[55] = 64 '91 x pLUT[56] = 0x0810 : pKOR[56] = 64 : aLUT[56] = 0x0118 : aKOR[56] = 64 pLUT[57] = 0x050F : pKOR[57] = 68 : aLUT[57] = 0x0014 : aKOR[57] = 64 '93 x x pLUT[58] = 0x0A10 : pKOR[58] = 64 : aLUT[58] = 0x0318 : aKOR[58] = 64 pLUT[59] = 0x0B10 : pKOR[59] = 64 : aLUT[59] = 0x0418 : aKOR[59] = 64 '95 pLUT[60] = 0x070F : pKOR[60] = 60 : aLUT[60] = 0x0313 : aKOR[60] = 67 '96 x x kan ook op snaar 2 pLUT[61] = 0x0116 : pKOR[61] = 64 : aLUT[61] = 0x0618 : aKOR[61] = 64 '97 x pLUT[62] = 0x0117 : pKOR[62] = 73 : aLUT[62] = 0x0718 : aKOR[62] = 64 '98 x pLUT[63] = 0x0418 : pKOR[63] = 68 : aLUT[63] = 0x0818 : aKOR[63] = 64 '99 x x pLUT[64] = 0x0316 : pKOR[64] = 64 : aLUT[64] = 0x0018 : aKOR[64] = 60 '100 x x pLUT[65] = 0x001B : pKOR[65] = 62 : aLUT[65] = 0x0910 : aKOR[65] = 63 '101 x x kan op snaar 0 en 9 x x 'ook op 8 en 2 pLUT[66] = 0x0515 : pKOR[66] = 66 : aLUT[66] = 0x0219 : aKOR[66] = 65 '102 x x pLUT[67] = 0x0417 : pKOR[67] = 62 : aLUT[67] = 0x021A : aKOR[67] = 71 '103 x x pLUT[68] = 0x0813 : pKOR[68] = 65 : aLUT[68] = 0x001E : aKOR[68] = 60 '104 x x pLUT[69] = 0x0616 : pKOR[69] = 63 : aLUT[69] = 0x0230 : aKOR[69] = 64 '105 x pLUT[70] = 0x0A20 : pKOR[70] = 64 : aLUT[70] = 0x0330 : aKOR[70] = 64 '106 x pLUT[71] = 0x0815 : pKOR[71] = 62 : aLUT[71] = 0x0519 : aKOR[71] = 67 '107 x x pLUT[72] = 0x0040 : pKOR[72] = 64 : aLUT[72] = 0x0530 : aKOR[72] = 64 '108 pLUT[73] = 0x031E : pKOR[73] = 61 : aLUT[73] = 0x0630 : aKOR[73] = 64 '109 x pLUT[74] = 0x0916 : pKOR[74] = 74 : aLUT[74] = 0x061A : aKOR[74] = 60 '110 x x kan ook op snaar 3 pLUT[75] = 0x0818 : pKOR[75] = 64 : aLUT[75] = 0x061B : aKOR[75] = 65 '111 x x pLUT[76] = 0x0440 : pKOR[76] = 64 : aLUT[76] = 0x061C : aKOR[76] = 72 '112 - x pLUT[77] = 0x0540 : pKOR[77] = 64 : aLUT[77] = 0x0A30 : aKOR[77] = 64 pLUT[78] = 0x0919 : pKOR[78] = 69 : aLUT[78] = 0x0B30 : aKOR[78] = 64 '114 x pLUT[79] = 0x0B17 : pKOR[79] = 66 : aLUT[79] = 0x1030 : aKOR[79] = 64 '115 pLUT[80] = 0x071E : pKOR[80] = 64 : aLUT[80] = 0x1130 : aKOR[80] = 64 '116 x pLUT[81] = 0x0A1C : pKOR[81] = 66 : aLUT[81] = 0x071F : aKOR[81] = 65 '117 x x pLUT[82] = 0x081E : pKOR[82] = 64 : aLUT[82] = 0x0720 : aKOR[82] = 65 '118 x x pLUT[83] = 0x0B40 : pKOR[83] = 59 : aLUT[83] = 0x1430 : aKOR[83] = 64 '119 x 'for the range up to 127 we may have to tune the fundamental an octave up. pLUT[84] = 0x0B4D : pKOR[84] = 71 : aLUT[84] = 0x1530 : aKOR[84] = 64 '120 pLUT[85] = 0x1140 : pKOR[85] = 64 : aLUT[85] = 0x1630 : aKOR[85] = 64 pLUT[86] = 0x0920 : pKOR[86] = 59 : aLUT[86] = 0x1730 : aKOR[86] = 64 '122 x pLUT[87] = 0x1340 : pKOR[87] = 64 : aLUT[87] = 0x1830 : aKOR[87] = 64 '123 pLUT[88] = 0x1440 : pKOR[88] = 64 : aLUT[88] = 0x1930 : aKOR[88] = 64 pLUT[89] = 0x1540 : pKOR[89] = 64 : aLUT[89] = 0x1A30 : aKOR[89] = 64 pLUT[90] = 0x1640 : pKOR[90] = 64 : aLUT[90] = 0x1B30 : aKOR[90] = 64 '126 pLUT[91] = 0x1740 : pKOR[91] = 64 : aLUT[91] = 0x2030 : aKOR[91] = 64 '127 - this is the absolute upper limit. ' add here pKor and aKOR , with the values for the frequency corrector to apply Return Lookup_Empiric: ' data filled in after empirical measurement by Kristof Lauwers ' lookup table for Aeio based on empirical data ' overtones that are too weak as well as pitches deviating more then 25 cent of the wanted pitch are discarded ' (which means a lot of notes can only be played in one way - we might consider using a bigger tolerance) ' from note 95 (pLUT[59]) on we use theoretical values, as our measurements didn't go that high ' (and pitches that high generally don't sound good anymore) ' ' pLUT[0] = 0-91 for notes 36 to 127 For k = 0 To 91 pKOR[k] = 64 'default to no correction or CC24 in central position aKOR[k] = 64 aLUT[k] = 0 'delete previous entries if we do prog.change. pLUT[k] = 0 Next pLUT[0] = 0x0001 : pKOR[0] = 64 pLUT[1] = 0x0101 : pKOR[1] = 64 pLUT[2] = 0x0201 : pKOR[2] = 64 pLUT[3] = 0x0301 : pKOR[3] = 64 pLUT[4] = 0x0401 : pKOR[4] = 64 pLUT[5] = 0x0501 : pKOR[5] = 64 pLUT[6] = 0x0601 : pKOR[6] = 64 pLUT[7] = 0x0701 : pKOR[7] = 64 pLUT[8] = 0x0801 : pKOR[8] = 64 pLUT[9] = 0x0901 : pKOR[9] = 64 pLUT[10] = 0x0A01 : pKOR[10] = 64 pLUT[11] = 0x0B01 : pKOR[11] = 64 pLUT[12] = 0x0002 : pKOR[12] = 66 ' 48 - actual pitches 48.04 pLUT[13] = 0x0102 : pKOR[13] = 68 ' 49 - actual pitches 49.08 pLUT[14] = 0x0202 : pKOR[14] = 63 ' 50 - actual pitches 49.98 pLUT[15] = 0x0302 : pKOR[15] = 67 ' 51 - actual pitches 51.06 pLUT[16] = 0x0402 : pKOR[16] = 30 ' 52 - actual pitches 51.32 pLUT[17] = 0x0502 : pKOR[17] = 54 ' 53 - actual pitches 52.8 pLUT[18] = 0x0602 : pKOR[18] = 49 ' 54 - actual pitches 53.7 pLUT[19] = 0x0702 : pKOR[19] = 66 : aLUT[19] = 0x0003 : aKOR[19] = 72 ' 55 - actual pitches 55.04 55.1796 pLUT[20] = 0x0802 : pKOR[20] = 62 : aLUT[20] = 0x0103 : aKOR[20] = 74 ' 56 - actual pitches 55.96 56.2196 pLUT[21] = 0x0902 : pKOR[21] = 60 ' 57 - actual pitches 56.92 pLUT[22] = 0x0A02 : pKOR[22] = 66 : aLUT[22] = 0x0303 : aKOR[22] = 53 ' 58 - actual pitches 58.04 57.7996 pLUT[23] = 0x0B02 : pKOR[23] = 72 ' 59 - actual pitches 59.16 pLUT[24] = 0x0503 : pKOR[24] = 69 : aLUT[24] = 0x0004 : aKOR[24] = 71 ' 60 - actual pitches 60.1196 60.14 pLUT[25] = 0x0104 : pKOR[25] = 76 ' 61 - actual pitches 61.24 pLUT[26] = 0x0703 : pKOR[26] = 75 ' 62 - actual pitches 62.2396 pLUT[27] = 0x0803 : pKOR[27] = 64 : aLUT[27] = 0x0304 : aKOR[27] = 68 ' 63 - actual pitches 63.0196 63.08 pLUT[28] = 0x0903 : pKOR[28] = 60 : aLUT[28] = 0x0005 : aKOR[28] = 78 ' 64 - actual pitches 63.9395 64.1431 pLUT[29] = 0x0105 : pKOR[29] = 74 ' 65 - actual pitches 65.0631 pLUT[30] = 0x0B03 : pKOR[30] = 66 : aLUT[30] = 0x0604 : aKOR[30] = 76 ' 66 - actual pitches 66.0595 66.24 pLUT[31] = 0x0305 : pKOR[31] = 72 ' 67 - actual pitches 67.0231 pLUT[32] = 0x0804 : pKOR[32] = 74 ' 68 - actual pitches 68.2 pLUT[33] = 0x0206 : pKOR[33] = 55 ' 69 - actual pitches 68.8395 pLUT[34] = 0x0605 : pKOR[34] = 82 ' 70 - actual pitches 70.2231 pLUT[35] = 0x0406 : pKOR[35] = 71 ' 71 - actual pitches 71.1596 pLUT[36] = 0x0008 : pKOR[36] = 70 ' 72 - actual pitches 72.12 pLUT[37] = 0x0108 : pKOR[37] = 58 : aLUT[37] = 0x0009 : aKOR[37] = 21 ' 73 - actual pitches 72.88 73.1791 pLUT[38] = 0x0407 : pKOR[38] = 86 ' 74 - actual pitches 74.1283 pLUT[39] = 0x0806 : pKOR[39] = 52 ' 75 - actual pitches 74.7795 pLUT[40] = 0x0508 : pKOR[40] = 9 : aLUT[40] = 0x0308 : aKOR[40] = 107 ' 76 - actual pitches 75.9 75.86 pLUT[41] = 0x0408 : pKOR[41] = 113 : aLUT[41] = 0x020A : aKOR[41] = 33 ' 77 - actual pitches 76.98 77.2431 pLUT[42] = 0x0A06 : pKOR[42] = 92 ' 78 - actual pitches 77.5795 pLUT[43] = 0x040A : pKOR[43] = 27 : aLUT[43] = 0x020B : aKOR[43] = 46 ' 79 - actual pitches 79.1231 79.1532 pLUT[44] = 0x0B07 : pKOR[44] = 32 ' 80 - actual pitches 80.0483 pLUT[45] = 0x050A : pKOR[45] = 70 : aLUT[45] = 0x020C : aKOR[45] = 68 ' 81 - actual pitches 80.9831 81.0995 pLUT[46] = 0x040C : pKOR[46] = 13 : aLUT[46] = 0x040B : aKOR[46] = 85 ' 82 - actual pitches 81.9996 81.9332 pLUT[47] = 0x0B08 : pKOR[47] = 63 : aLUT[47] = 0x080A : aKOR[47] = 19 ' 83 - actual pitches 82.98 82.9631 pLUT[48] = 0x0110 : pKOR[48] = 26 : aLUT[48] = 0x010F : aKOR[48] = 82 ' 84 - actual pitches 84.24 84.2427 pLUT[49] = 0x0210 : pKOR[49] = 10 : aLUT[49] = 0x020F : aKOR[49] = 65 ' 85 - actual pitches 84.92 84.9027 pLUT[50] = 0x040F : pKOR[50] = 19 : aLUT[50] = 0x040E : aKOR[50] = 75 ' 86 - actual pitches 85.9827 85.9083 pLUT[51] = 0x060D : pKOR[51] = 86 ' 87 - actual pitches 86.8453 pLUT[52] = 0x0311 : pKOR[52] = 52 ' 88 - actual pitches 87.8096 pLUT[53] = 0x0B0C : pKOR[53] = 9 : aLUT[53] = 0x0B0B : aKOR[53] = 84 ' 89 - actual pitches 88.9195 88.9132 pLUT[54] = 0x0A0D : pKOR[54] = 45 ' 90 - actual pitches 90.0253 pLUT[55] = 0x0611 : pKOR[55] = 63 ' 91 - actual pitches 91.0296 pLUT[56] = 0x0A0F : pKOR[56] = 28 : aLUT[56] = 0x0A0E : aKOR[56] = 88 ' 92 - actual pitches 92.1627 92.1683 pLUT[57] = 0x0911 : pKOR[57] = 10 : aLUT[57] = 0x0910 : aKOR[57] = 66 ' 93 - actual pitches 92.9696 93.04 pLUT[58] = 0x0B10 : pKOR[58] = 7 : aLUT[58] = 0x0B0F : aKOR[58] = 58 ' 94 - actual pitches 93.86 93.7627 '!!! from here on theoretical mapping is used.. pLUT[59] = 0x0B10 : pKOR[59] = 64 : aLUT[59] = 0x0418 : aKOR[59] = 64 '95 pLUT[60] = 0x070F : pKOR[60] = 60 : aLUT[60] = 0x0313 : aKOR[60] = 67 '96 x x kan ook op snaar 2 pLUT[61] = 0x0116 : pKOR[61] = 64 : aLUT[61] = 0x0618 : aKOR[61] = 64 '97 x pLUT[62] = 0x0117 : pKOR[62] = 73 : aLUT[62] = 0x0718 : aKOR[62] = 64 '98 x pLUT[63] = 0x0418 : pKOR[63] = 68 : aLUT[63] = 0x0818 : aKOR[63] = 64 '99 x x pLUT[64] = 0x0316 : pKOR[64] = 64 : aLUT[64] = 0x0018 : aKOR[64] = 60 '100 x x pLUT[65] = 0x001B : pKOR[65] = 62 : aLUT[65] = 0x0910 : aKOR[65] = 63 '101 x x kan op snaar 0 en 9 x x 'ook op 8 en 2 pLUT[66] = 0x0515 : pKOR[66] = 66 : aLUT[66] = 0x0219 : aKOR[66] = 65 '102 x x pLUT[67] = 0x0417 : pKOR[67] = 62 : aLUT[67] = 0x021A : aKOR[67] = 71 '103 x x pLUT[68] = 0x0813 : pKOR[68] = 65 : aLUT[68] = 0x001E : aKOR[68] = 60 '104 x x pLUT[69] = 0x0616 : pKOR[69] = 63 : aLUT[69] = 0x0230 : aKOR[69] = 64 '105 x pLUT[70] = 0x0A20 : pKOR[70] = 64 : aLUT[70] = 0x0330 : aKOR[70] = 64 '106 x pLUT[71] = 0x0815 : pKOR[71] = 62 : aLUT[71] = 0x0519 : aKOR[71] = 67 '107 x x pLUT[72] = 0x0040 : pKOR[72] = 64 : aLUT[72] = 0x0530 : aKOR[72] = 64 '108 pLUT[73] = 0x031E : pKOR[73] = 61 : aLUT[73] = 0x0630 : aKOR[73] = 64 '109 x pLUT[74] = 0x0916 : pKOR[74] = 74 : aLUT[74] = 0x061A : aKOR[74] = 60 '110 x x kan ook op snaar 3 pLUT[75] = 0x0818 : pKOR[75] = 64 : aLUT[75] = 0x061B : aKOR[75] = 65 '111 x x pLUT[76] = 0x0440 : pKOR[76] = 64 : aLUT[76] = 0x061C : aKOR[76] = 72 '112 - x pLUT[77] = 0x0540 : pKOR[77] = 64 : aLUT[77] = 0x0A30 : aKOR[77] = 64 pLUT[78] = 0x0919 : pKOR[78] = 69 : aLUT[78] = 0x0B30 : aKOR[78] = 64 '114 x pLUT[79] = 0x0B17 : pKOR[79] = 66 : aLUT[79] = 0x1030 : aKOR[79] = 64 '115 pLUT[80] = 0x071E : pKOR[80] = 64 : aLUT[80] = 0x1130 : aKOR[80] = 64 '116 x pLUT[81] = 0x0A1C : pKOR[81] = 66 : aLUT[81] = 0x071F : aKOR[81] = 65 '117 x x pLUT[82] = 0x081E : pKOR[82] = 64 : aLUT[82] = 0x0720 : aKOR[82] = 65 '118 x x pLUT[83] = 0x0B40 : pKOR[83] = 59 : aLUT[83] = 0x1430 : aKOR[83] = 64 '119 x 'for the range up to 127 we may have to tune the fundamental an octave up. pLUT[84] = 0x0B4D : pKOR[84] = 71 : aLUT[84] = 0x1530 : aKOR[84] = 64 '120 pLUT[85] = 0x1140 : pKOR[85] = 64 : aLUT[85] = 0x1630 : aKOR[85] = 64 pLUT[86] = 0x0920 : pKOR[86] = 59 : aLUT[86] = 0x1730 : aKOR[86] = 64 '122 x pLUT[87] = 0x1340 : pKOR[87] = 64 : aLUT[87] = 0x1830 : aKOR[87] = 64 '123 pLUT[88] = 0x1440 : pKOR[88] = 64 : aLUT[88] = 0x1930 : aKOR[88] = 64 pLUT[89] = 0x1540 : pKOR[89] = 64 : aLUT[89] = 0x1A30 : aKOR[89] = 64 pLUT[90] = 0x1640 : pKOR[90] = 64 : aLUT[90] = 0x1B30 : aKOR[90] = 64 '126 pLUT[91] = 0x1740 : pKOR[91] = 64 : aLUT[91] = 0x2030 : aKOR[91] = 64 '127 - this is the absolute upper limit. Return Lookup_EQ: 'This is the loopup table for best possible equal temperament playing 'to be done!!! 'pLUT[0] = 0-91 for notes 36 to 127 For k = 0 To 91 pKOR[k] = 64 'default to no correction or CC24 in central position aKOR[k] = 64 Next For k = 0 To 18 aLUT[k] = 0 ' aKOR[k] = 64 Next pLUT[0] = 0x0001 : pKOR[0] = 64 'pLUT: highbyte, lownibble = string number, lowbyte= multiplier (cc22) ' highbyte, highnibble = basenote transposition: ' 1 = octave up, 2= 2 octaves up, 3= 3 octaves up ' 8 = octave down, 9 = 2 octaves down. 'pKOR: pitch correction required (64 = no correction), range 0-127 pLUT[1] = 0x0101 : pKOR[1] = 64 pLUT[2] = 0x0201 : pKOR[2] = 64 pLUT[3] = 0x0301 : pKOR[3] = 64 pLUT[4] = 0x0401 : pKOR[4] = 64 pLUT[5] = 0x0501 : pKOR[5] = 64 pLUT[6] = 0x0601 : pKOR[6] = 64 pLUT[7] = 0x0701 : pKOR[7] = 64 pLUT[8] = 0x0801 : pKOR[8] = 64 pLUT[9] = 0x0901 : pKOR[9] = 64 pLUT[10] = 0x0A01 : pKOR[10] = 64 pLUT[11] = 0x0B01 : pKOR[11] = 64 pLUT[12] = 0x0002 : pKOR[12] = 62 '48 x pLUT[13] = 0x0102 : pKOR[13] = 64 '49 x pLUT[14] = 0x0202 : pKOR[14] = 64 '50 x pLUT[15] = 0x0302 : pKOR[15] = 60 '51 x pLUT[16] = 0x0402 : pKOR[16] = 65 '52 x pLUT[17] = 0x0502 : pKOR[17] = 67 '53 x pLUT[18] = 0x0602 : pKOR[18] = 66 '54 x pLUT[19] = 0x0702 : pKOR[19] = 63 : aLUT[19] = 0x0003 : aKOR[19] = 66 '55 x x pLUT[20] = 0x0802 : pKOR[20] = 66 : aLUT[20] = 0x0103 : aKOR[20] = 70 '56 x x pLUT[21] = 0x0902 : pKOR[21] = 65 : aLUT[21] = 0x0203 : aKOR[21] = 70 '57 x x pLUT[22] = 0x0A02 : pKOR[22] = 71 : aLUT[22] = 0x0303 : aKOR[22] = 67 '58 x x pLUT[23] = 0x0B02 : pKOR[23] = 73 : aLUT[23] = 0x0403 : aKOR[23] = 73 '59 x x pLUT[24] = 0x0004 : pKOR[24] = 65 : aLUT[24] = 0x0503 : aKOR[24] = 76 '60 x x pLUT[25] = 0x0104 : pKOR[25] = 76 : aLUT[25] = 0x0603 : aKOR[25] = 76 '61 x x pLUT[26] = 0x0204 : pKOR[26] = 78 : aLUT[26] = 0x0703 : aKOR[26] = 74 '62 x x pLUT[27] = 0x0304 : pKOR[27] = 75 : aLUT[27] = 0 : aKOR[27] = 64 '63 x pLUT[28] = 0x0404 : pKOR[28] = 83 : aLUT[28] = 0 : aKOR[28] = 64 '64 x pLUT[29] = 0x0504 : pKOR[29] = 85 : aLUT[29] = 0 : aKOR[29] = 64 '65 x pLUT[30] = 0x0604 : pKOR[30] = 88 : aLUT[30] = 0 : aKOR[30] = 64 '66 x pLUT[31] = 0x0704 : pKOR[31] = 86 : aLUT[31] = 0 : aKOR[31] = 64 '67 x pLUT[32] = 0x0804 : pKOR[32] = 92 : aLUT[32] = 0 : aKOR[32] = 64 '68 x pLUT[33] = 0x0904 : pKOR[33] = 93 : aLUT[33] = 0 : aKOR[33] = 64 '69 x pLUT[34] = 0x0007 : pKOR[34] = 85 : aLUT[34] = 0 : aKOR[34] = 64 '70 x pLUT[35] = 0x0A04 : pKOR[35] = 44 : aLUT[35] = 0x0605 : aKOR[35] = 45 '71 x x pLUT[36] = 0x0B04 : pKOR[36] = 59 : aLUT[36] = 0 : aKOR[36] = 59 '72 x pLUT[37] = 0x0506 : pKOR[37] = 65 : aLUT[37] = 0x0008 : aKOR[37] = 63 '73 x x pLUT[38] = 0x0905 : pKOR[38] = 66 : aLUT[38] = 0x0606 : aKOR[38] = 70 '74 x x pLUT[39] = 0x0A05 : pKOR[39] = 69 : aLUT[39] = 0x0009 : aKOR[39] = 78 '75 x x pLUT[40] = 0x0507 : pKOR[40] = 67 : aLUT[40] = 0x0906 : aKOR[40] = 64 '76 x pLUT[41] = 0x0508 : pKOR[41] = 64 : aLUT[41] = 0x0A06 : aKOR[41] = 64 pLUT[42] = 0x0608 : pKOR[42] = 64 : aLUT[42] = 0x0B06 : aKOR[42] = 64 pLUT[43] = 0x0708 : pKOR[43] = 64 : aLUT[43] = 0x000C : aKOR[43] = 64 'note 79 pLUT[44] = 0x0409 : pKOR[44] = 64 : aLUT[44] = 0x010C : aKOR[44] = 64 '80 x pLUT[45] = 0x0708 : pKOR[45] = 68 : aLUT[45] = 0x030A : aKOR[45] = 60 '81 x x pLUT[46] = 0x0A07 : pKOR[46] = 65 : aLUT[46] = 0x030C : aKOR[46] = 64 '82 x pLUT[47] = 0x000D : pKOR[47] = 60 : aLUT[47] = 0x030B : aKOR[47] = 63 '83 x x pLUT[48] = 0x0010 : pKOR[48] = 64 : aLUT[48] = 0x050C : aKOR[48] = 64 '84 pLUT[49] = 0x0809 : pKOR[49] = 63 : aLUT[49] = 0x030C : aKOR[49] = 60 '85 x x pLUT[50] = 0x0710 : pKOR[50] = 64 : aLUT[50] = 0x070C : aKOR[50] = 64 '86 x pLUT[51] = 0x0310 : pKOR[51] = 64 : aLUT[51] = 0x080C : aKOR[51] = 64 pLUT[52] = 0x0410 : pKOR[52] = 64 : aLUT[52] = 0x090C : aKOR[52] = 64 pLUT[53] = 0x0011 : pKOR[53] = 63 : aLUT[53] = 0x060C : aKOR[53] = 64 '89 x x kan ook op snaar 1 pLUT[54] = 0x040E : pKOR[54] = 61 : aLUT[54] = 0x030F : aKOR[54] = 70 '90 x x pLUT[55] = 0x060D : pKOR[55] = 61 : aLUT[55] = 0x0018 : aKOR[55] = 64 '91 x pLUT[56] = 0x0810 : pKOR[56] = 64 : aLUT[56] = 0x0118 : aKOR[56] = 64 pLUT[57] = 0x050F : pKOR[57] = 68 : aLUT[57] = 0x0014 : aKOR[57] = 64 '93 x x pLUT[58] = 0x0A10 : pKOR[58] = 64 : aLUT[58] = 0x0318 : aKOR[58] = 64 pLUT[59] = 0x0B10 : pKOR[59] = 64 : aLUT[59] = 0x0418 : aKOR[59] = 64 '95 pLUT[60] = 0x070F : pKOR[60] = 60 : aLUT[60] = 0x0313 : aKOR[60] = 67 '96 x x kan ook op snaar 2 pLUT[61] = 0x0116 : pKOR[61] = 64 : aLUT[61] = 0x0618 : aKOR[61] = 64 '97 x pLUT[62] = 0x0117 : pKOR[62] = 73 : aLUT[62] = 0x0718 : aKOR[62] = 64 '98 x pLUT[63] = 0x0418 : pKOR[63] = 68 : aLUT[63] = 0x0818 : aKOR[63] = 64 '99 x x pLUT[64] = 0x0316 : pKOR[64] = 64 : aLUT[64] = 0x0018 : aKOR[64] = 60 '100 x x pLUT[65] = 0x001B : pKOR[65] = 62 : aLUT[65] = 0x0910 : aKOR[65] = 63 '101 x x kan op snaar 0 en 9 x x 'ook op 8 en 2 pLUT[66] = 0x0515 : pKOR[66] = 66 : aLUT[66] = 0x0219 : aKOR[66] = 65 '102 x x pLUT[67] = 0x0417 : pKOR[67] = 62 : aLUT[67] = 0x021A : aKOR[67] = 71 '103 x x pLUT[68] = 0x0813 : pKOR[68] = 65 : aLUT[68] = 0x001E : aKOR[68] = 60 '104 x x pLUT[69] = 0x0616 : pKOR[69] = 63 : aLUT[69] = 0x0230 : aKOR[69] = 64 '105 x pLUT[70] = 0x0A20 : pKOR[70] = 64 : aLUT[70] = 0x0330 : aKOR[70] = 64 '106 x pLUT[71] = 0x0815 : pKOR[71] = 62 : aLUT[71] = 0x0519 : aKOR[71] = 67 '107 x x pLUT[72] = 0x0040 : pKOR[72] = 64 : aLUT[72] = 0x0530 : aKOR[72] = 64 '108 pLUT[73] = 0x031E : pKOR[73] = 61 : aLUT[73] = 0x0630 : aKOR[73] = 64 '109 x pLUT[74] = 0x0916 : pKOR[74] = 74 : aLUT[74] = 0x061A : aKOR[74] = 60 '110 x x kan ook op snaar 3 pLUT[75] = 0x0818 : pKOR[75] = 64 : aLUT[75] = 0x061B : aKOR[75] = 65 '111 x x pLUT[76] = 0x0440 : pKOR[76] = 64 : aLUT[76] = 0x061C : aKOR[76] = 72 '112 - x pLUT[77] = 0x0540 : pKOR[77] = 64 : aLUT[77] = 0x0A30 : aKOR[77] = 64 pLUT[78] = 0x0919 : pKOR[78] = 69 : aLUT[78] = 0x0B30 : aKOR[78] = 64 '114 x pLUT[79] = 0x0B17 : pKOR[79] = 66 : aLUT[79] = 0x1030 : aKOR[79] = 64 '115 pLUT[80] = 0x071E : pKOR[80] = 64 : aLUT[80] = 0x1130 : aKOR[80] = 64 '116 x pLUT[81] = 0x0A1C : pKOR[81] = 66 : aLUT[81] = 0x071F : aKOR[81] = 65 '117 x x pLUT[82] = 0x081E : pKOR[82] = 64 : aLUT[82] = 0x0720 : aKOR[82] = 65 '118 x x pLUT[83] = 0x0B40 : pKOR[83] = 59 : aLUT[83] = 0x1430 : aKOR[83] = 64 '119 x 'for the range up to 127 we may have to tune the fundamental an octave up. pLUT[84] = 0x0B4D : pKOR[84] = 71 : aLUT[84] = 0x1530 : aKOR[84] = 64 '120 pLUT[85] = 0x1140 : pKOR[85] = 64 : aLUT[85] = 0x1630 : aKOR[85] = 64 pLUT[86] = 0x0920 : pKOR[86] = 59 : aLUT[86] = 0x1730 : aKOR[86] = 64 '122 x pLUT[87] = 0x1340 : pKOR[87] = 64 : aLUT[87] = 0x1830 : aKOR[87] = 64 '123 pLUT[88] = 0x1440 : pKOR[88] = 64 : aLUT[88] = 0x1930 : aKOR[88] = 64 pLUT[89] = 0x1540 : pKOR[89] = 64 : aLUT[89] = 0x1A30 : aKOR[89] = 64 pLUT[90] = 0x1640 : pKOR[90] = 64 : aLUT[90] = 0x1B30 : aKOR[90] = 64 '126 pLUT[91] = 0x1740 : pKOR[91] = 64 : aLUT[91] = 0x2030 : aKOR[91] = 64 '127 - this is the absolute upper limit. Return '[EOF]