Browse Source

initial implementation of pitch bending

master
Peter Cai 1 year ago
parent
commit
e64e4c19e8
  1. 12
      gen_pitch_table.py
  2. 6
      main.cpp
  3. 15
      motor_control.cpp
  4. 4
      motor_control.h

12
gen_pitch_table.py

@ -52,4 +52,16 @@ for i in range(start_pitch, end_pitch):
period = int(period / 2)
print(" " + str(period) + "ul,\t// " + name)
print("};")
print("")
print("// scale factors for bend values from 0 to 255")
print("// We don't support the full 16385 levels of MIDI bend")
print("// MIDI bend values have to be converted first to the nearest supported one")
print("constexpr float midi_pitch_bend_scale[256] = {")
for i in range(0, 256):
factor = pow(2, (8192 - i * 64) / 49152)
print(" " + str(factor) + "f,\t// " + str(i))
print("};")

6
main.cpp

@ -53,6 +53,11 @@ void midi_note_off(uint8_t channel, uint8_t note, uint8_t velocity) {
motors[channel - 1].TickOff();
}
void midi_pitch_bend(uint8_t channel, int bend) {
ASSERT_CHANNEL();
motors[channel - 1].TickPitchBend(bend);
}
int main() {
// Arduino library initialization
// Needed for some functions to work (like micros)
@ -76,6 +81,7 @@ int main() {
// Set up MIDI callbacks
MIDI.setHandleNoteOn(midi_note_on);
MIDI.setHandleNoteOff(midi_note_off);
MIDI.setHandlePitchBend(midi_pitch_bend);
unsigned long cur_micros;
unsigned long cur_half_micros;

15
motor_control.cpp

@ -4,7 +4,8 @@
MotorControl::MotorControl(int pin_dir, int pin_step) :
pin_dir(pin_dir), pin_step(pin_step),
last_tick_half_micros(0), tick_period_half_micros(0)
last_tick_half_micros(0), tick_period_half_micros(0),
tick_period_orig_half_micros(0)
{
// No actual constructor logic -- initialization is in Init()
}
@ -19,6 +20,7 @@ void MotorControl::Init() {
void MotorControl::TickOn(unsigned long period_half_micros) {
tick_period_half_micros = period_half_micros;
tick_period_orig_half_micros = period_half_micros;
// Force the next tick to happen
last_tick_half_micros = 0;
}
@ -32,8 +34,19 @@ void MotorControl::TickAtPitch(unsigned int midi_pitch) {
TickOn(midi_pitch_period[midi_pitch - midi_pitch_offset]);
}
void MotorControl::TickPitchBend(int bend) {
if (bend < 0 || bend >= 16384) return;
if (tick_period_orig_half_micros == 0) return;
// Scale the MIDI bend value down to 0 - 255
bend = bend / 64;
tick_period_half_micros = (unsigned long) (((float) tick_period_orig_half_micros) * midi_pitch_bend_scale[bend]);
}
void MotorControl::TickOff() {
tick_period_half_micros = 0;
tick_period_orig_half_micros = 0;
}
void MotorControl::Tick(unsigned long cur_half_micros) {

4
motor_control.h

@ -8,6 +8,8 @@ class MotorControl {
unsigned long last_tick_half_micros;
// Interval of motor ticking; 0 to disable the motor
unsigned long tick_period_half_micros;
// Original period of motor ticking (without applying bend)
unsigned long tick_period_orig_half_micros;
void DoTick();
public:
@ -19,6 +21,8 @@ class MotorControl {
void TickOn(unsigned long period_half_micros);
// Set the motor to tick with a given MIDI pitch
void TickAtPitch(unsigned int midi_pitch);
// Set the pitch bend
void TickPitchBend(int bend);
// Turn off the motor
void TickOff();
// Perform a tick if necessary

Loading…
Cancel
Save