@@ -1213,88 +1213,98 @@ def tick(self):
12131213 # reset waves are always low; the clock's stop() function handles triggering them
12141214 out_volts = 0.0
12151215 else :
1216- if self .wave_counter % 2 == 0 :
1217- # first half of the swing; if swing < 50% this is short, otherwise long
1218- swing_amt = self .swing .value / 100.0
1219- else :
1220- # second half of the swing; if swing < 50% this is long, otherwise short
1221- swing_amt = (100 - self .swing .value ) / 100.0
1222- ticks_per_note = round (2 * MasterClock .PPQN / self .real_clock_mod * swing_amt )
1223- if ticks_per_note == 0 :
1224- # we're swinging SO HARD that one beat is squashed out of existence!
1225- # move immediately to the other beat
1226- self .e_position = self .e_position + 1
1227- if self .e_position >= len (self .e_pattern ):
1228- self .e_position = 0
1229- ticks_per_note = round (2 * MasterClock .PPQN / self .real_clock_mod )
1230-
1231- e_step = self .e_pattern [self .e_position ]
1232- wave_position = self .clock .elapsed_pulses % ticks_per_note
1233- # are we starting a new repeat of the pattern?
1234- rising_edge = (wave_position == int (self .phase .value * ticks_per_note / 100.0 )) and e_step
1235- # determine if we should skip this sample playback
1236- if rising_edge :
1237- self .skip_this_step = random .randint (0 , 100 ) < self .skip .value
1238- self .wave_counter += 1
1239-
1240- wave_sample = int (e_step ) * int (not self .skip_this_step )
1241- if self .wave_shape .value == WAVE_RANDOM :
1242- if rising_edge and not self .skip_this_step :
1243- wave_sample = random .random () * (self .amplitude .value / 100.0 ) + (self .width .value / 100.0 )
1244- else :
1245- wave_sample = self .previous_wave_sample
1246- elif self .wave_shape .value == WAVE_AIN :
1247- if rising_edge and not self .skip_this_step :
1248- wave_sample = CV_INS ["AIN" ].percent () * self .amplitude .value / 100.0
1249- else :
1250- wave_sample = self .previous_wave_sample
1251- elif self .wave_shape .value == WAVE_KNOB :
1252- if rising_edge and not self .skip_this_step :
1253- wave_sample = CV_INS ["KNOB" ].percent () * self .amplitude .value / 100.0
1254- else :
1255- wave_sample = self .previous_wave_sample
1256- elif self .wave_shape .value == WAVE_SQUARE :
1257- wave_sample = wave_sample * self .square_wave (wave_position , ticks_per_note ) * (self .amplitude .value / 100.0 )
1258- elif self .wave_shape .value == WAVE_TRIANGLE :
1259- wave_sample = wave_sample * self .triangle_wave (wave_position , ticks_per_note ) * (self .amplitude .value / 100.0 )
1260- elif self .wave_shape .value == WAVE_SIN :
1261- wave_sample = wave_sample * self .sine_wave (wave_position , ticks_per_note ) * (self .amplitude .value / 100.0 )
1262- elif self .wave_shape .value == WAVE_ADSR :
1263- wave_sample = wave_sample * self .adsr_wave (wave_position , ticks_per_note ) * (self .amplitude .value / 100.0 )
1264- elif self .wave_shape .value == WAVE_TURING :
1265- wave_sample = self .turing_wave (wave_position , ticks_per_note ) * (self .amplitude .value / 100.0 )
1266- else :
1267- wave_sample = 0.0
1268-
1269- self .previous_wave_sample = wave_sample
1270- out_volts = wave_sample * MAX_OUTPUT_VOLTAGE
1271-
1272- if self .quantizer .mapped_value is not None :
1273- (out_volts , note ) = self .quantizer .mapped_value .quantize (out_volts , self .root .value )
1274-
1275- if wave_position == ticks_per_note - 1 :
1276- if self .next_e_pattern :
1277- # if we just finished a waveform and we have a new euclidean pattern, start it
1278- # this will always line up with the current beat, but may be rotated relative to
1279- # other patterns currently playing.
1280- # rather than do a lot of math, treat this as a feature that if you change patterns
1281- # while playing, the new pattern starts right away instead of waiting for for the
1282- # end of (a potentially long, slow) pattern to finish
1283- self .e_position = 0
1284- self .e_pattern = self .next_e_pattern
1285- self .next_e_pattern = None
1286- else :
1287- # if we've reached end of the euclidean pattern start it again
1288- self .e_position = self .e_position + 1
1289- if self .e_position >= len (self .e_pattern ):
1290- self .e_position = 0
1216+ out_volts = self .wave_gen ()
12911217
12921218 # If the clock modifier was changed, apply the new value now
12931219 if self .clock_mod_dirty :
12941220 self .change_clock_mod ()
12951221
12961222 self .out_volts = out_volts
12971223
1224+ @micropython .native
1225+ def wave_gen (self ):
1226+ """Calculates the output voltage for the output channel.
1227+
1228+ @return The desired output voltage to be applied
1229+ """
1230+ if self .wave_counter % 2 == 0 :
1231+ # first half of the swing; if swing < 50% this is short, otherwise long
1232+ swing_amt = self .swing .value / 100.0
1233+ else :
1234+ # second half of the swing; if swing < 50% this is long, otherwise short
1235+ swing_amt = (100 - self .swing .value ) / 100.0
1236+ ticks_per_note = round (2 * MasterClock .PPQN / self .real_clock_mod * swing_amt )
1237+ if ticks_per_note == 0 :
1238+ # we're swinging SO HARD that one beat is squashed out of existence!
1239+ # move immediately to the other beat
1240+ self .e_position = self .e_position + 1
1241+ if self .e_position >= len (self .e_pattern ):
1242+ self .e_position = 0
1243+ ticks_per_note = round (2 * MasterClock .PPQN / self .real_clock_mod )
1244+
1245+ e_step = self .e_pattern [self .e_position ]
1246+ wave_position = self .clock .elapsed_pulses % ticks_per_note
1247+ # are we starting a new repeat of the pattern?
1248+ rising_edge = (wave_position == int (self .phase .value * ticks_per_note / 100.0 )) and e_step
1249+ # determine if we should skip this sample playback
1250+ if rising_edge :
1251+ self .skip_this_step = random .randint (0 , 100 ) < self .skip .value
1252+ self .wave_counter += 1
1253+
1254+ wave_sample = int (e_step ) * int (not self .skip_this_step )
1255+ if self .wave_shape .value == WAVE_RANDOM :
1256+ if rising_edge and not self .skip_this_step :
1257+ wave_sample = random .random () * (self .amplitude .value / 100.0 ) + (self .width .value / 100.0 )
1258+ else :
1259+ wave_sample = self .previous_wave_sample
1260+ elif self .wave_shape .value == WAVE_AIN :
1261+ if rising_edge and not self .skip_this_step :
1262+ wave_sample = CV_INS ["AIN" ].percent () * self .amplitude .value / 100.0
1263+ else :
1264+ wave_sample = self .previous_wave_sample
1265+ elif self .wave_shape .value == WAVE_KNOB :
1266+ if rising_edge and not self .skip_this_step :
1267+ wave_sample = CV_INS ["KNOB" ].percent () * self .amplitude .value / 100.0
1268+ else :
1269+ wave_sample = self .previous_wave_sample
1270+ elif self .wave_shape .value == WAVE_SQUARE :
1271+ wave_sample = wave_sample * self .square_wave (wave_position , ticks_per_note ) * (self .amplitude .value / 100.0 )
1272+ elif self .wave_shape .value == WAVE_TRIANGLE :
1273+ wave_sample = wave_sample * self .triangle_wave (wave_position , ticks_per_note ) * (self .amplitude .value / 100.0 )
1274+ elif self .wave_shape .value == WAVE_SIN :
1275+ wave_sample = wave_sample * self .sine_wave (wave_position , ticks_per_note ) * (self .amplitude .value / 100.0 )
1276+ elif self .wave_shape .value == WAVE_ADSR :
1277+ wave_sample = wave_sample * self .adsr_wave (wave_position , ticks_per_note ) * (self .amplitude .value / 100.0 )
1278+ elif self .wave_shape .value == WAVE_TURING :
1279+ wave_sample = self .turing_wave (wave_position , ticks_per_note ) * (self .amplitude .value / 100.0 )
1280+ else :
1281+ wave_sample = 0.0
1282+
1283+ self .previous_wave_sample = wave_sample
1284+ out_volts = wave_sample * MAX_OUTPUT_VOLTAGE
1285+
1286+ if self .quantizer .mapped_value is not None :
1287+ (out_volts , note ) = self .quantizer .mapped_value .quantize (out_volts , self .root .value )
1288+
1289+ if wave_position == ticks_per_note - 1 :
1290+ if self .next_e_pattern :
1291+ # if we just finished a waveform and we have a new euclidean pattern, start it
1292+ # this will always line up with the current beat, but may be rotated relative to
1293+ # other patterns currently playing.
1294+ # rather than do a lot of math, treat this as a feature that if you change patterns
1295+ # while playing, the new pattern starts right away instead of waiting for for the
1296+ # end of (a potentially long, slow) pattern to finish
1297+ self .e_position = 0
1298+ self .e_pattern = self .next_e_pattern
1299+ self .next_e_pattern = None
1300+ else :
1301+ # if we've reached end of the euclidean pattern start it again
1302+ self .e_position = self .e_position + 1
1303+ if self .e_position >= len (self .e_pattern ):
1304+ self .e_position = 0
1305+
1306+ return out_volts
1307+
12981308 @micropython .native
12991309 def apply (self ):
13001310 """Apply the calculated voltage to the output channel
0 commit comments