From 370160c6241abe29265e6e9fb851d571aab8d10e Mon Sep 17 00:00:00 2001 From: grm Date: Sun, 2 Mar 2025 16:45:10 +0200 Subject: smol improvements on midi --- src/midi.c | 227 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 128 insertions(+), 99 deletions(-) (limited to 'src/midi.c') diff --git a/src/midi.c b/src/midi.c index 2ba97d6..8597100 100644 --- a/src/midi.c +++ b/src/midi.c @@ -6,99 +6,132 @@ #include #include +void midi_pitch_bend(synth_t *synth, int channel, int value) { + (void)channel; + + float pitch; + float semitones = 2; + if (value == 0) { + pitch = 1; + } else if (value > 0) { + pitch = 1 + ((float)value / 8191) * semitones * pow(2.0, 1.0 / 12.0) / 12; + } else { + pitch = 1 + ((float)value / 8192) * semitones * pow(2.0, 1.0 / 12.0) / 12; + } + synth->cc_pitch.target = pitch; + /* cc_step(synth->cc_pitch, 1); */ +} + +void midi_cc(synth_t *synth, int channel, int controller, int value) { + (void)channel; + + int x = value < 64 ? 1 : -1; + switch (controller) { + case 0: + cc_step(&synth->cc_adsr_a, x); + //synth->adsr.a = synth->adsr.a + (x * 0.01); + //synth->freq_offset = synth->freq_offset + (x*5); + //cc_step(&synth->cc_cutoff, x); + break; + case 1: + cc_step(&synth->cc_adsr_d, x); + //synth->adsr.d = synth->adsr.d + (x * 0.01); + break; + case 2: + cc_step(&synth->cc_adsr_s, x); + //synth->adsr.s = synth->adsr.s + (x * 0.01); + break; + case 3: + cc_step(&synth->cc_adsr_r, x); + //synth->adsr.r = synth->adsr.r + (x * 0.01); + break; + case 4: + cc_step(&synth->cc_cutoff, x); + //synth->cutoff = synth->cutoff + (x * (10 * log10(synth->cutoff))); + break; + case 5: + cc_step(&synth->cc_resonance, x); + break; + case 6: + //cc_step(&synth->cc_pitch, x); + cc_step(&synth->cc_lfo_freq, x); + //synth->lfo.freq = synth->lfo.freq + (x * 0.1); + break; + case 7: + //cc_reset(&synth->cc_pitch); + cc_step(&synth->cc_lfo_amp, x); + //synth->lfo.amp = synth->lfo.amp + (x * 0.002); + break; + case 8: + //cc_reset(&synth->cc_pitch); + synth->wvt_pos = value; + //synth->lfo.amp = synth->lfo.amp + (x * 0.002); + break; + case 28: + if (synth->geni > 0) synth->geni--; + break; + case 29: + if (synth->geni < 6) synth->geni++; + break; + default: + break; + } +} + +void midi_note_off(synth_t *synth, int channel, int note, int velocity) { + (void)channel; + (void)velocity; + + synth->midi_note[note].noteOff = Pa_GetStreamTime(synth->stream); + synth->midi_note[note].noteOffSample = synth->midi_note[note].elapsed; +} + +void midi_note_on(synth_t *synth, int channel, int note, int velocity) { + int flag = 1; + + synth->midi_note[note].freq = notes[note % 12][(note / 12) % 8]; + synth->midi_note[note].channel = channel; + synth->midi_note[note].noteOn = Pa_GetStreamTime(synth->stream); + synth->midi_note[note].noteOff = 0; + synth->midi_note[note].velocity = (float)velocity / 127.0; + synth->midi_note[note].elapsed = 0; + synth->midi_note[note].active = 1; + for (int i = 0; i < synth->midi_active_n; i++) { + if (synth->midi_active[i] == &synth->midi_note[note]) { + flag = 0; + } + } + if (flag) { + synth->midi_active[synth->midi_active_n++] = &synth->midi_note[note]; + } + synth->active = 1; + +} + void midi_decode(uint32_t msg, synth_t * synth) { - // printf("MIDI message: 0x%X\n", msg); + //printf("MIDI message: 0x%X\n", msg); uint8_t status = msg; uint8_t data1 = (msg >> 8) & 0xFF; uint8_t data2 = (msg >> 16) & 0xFF; uint8_t channel = (status & 0x0F) + 1; // convert to human uint8_t message = status >> 4; - int flag = 1; - switch (message) { case 0x08: printf("Note Off: channel=%d, note=%d, velocity=%d\n", channel, data1, data2); - synth->midi_note[data1].noteOff = Pa_GetStreamTime(synth->stream); - synth->midi_note[data1].noteOffSample = synth->midi_note[data1].elapsed; + midi_note_off(synth, channel, data1, data2); break; case 0x09: printf("Note On: channel=%d, note=%d, velocity=%d\n", channel, data1, data2); - //synth->midi_note[i].n = -1; - synth->midi_note[data1].freq = notes[data1 % 12][(data1 / 12) % 8]; - synth->midi_note[data1].channel = channel; - synth->midi_note[data1].noteOn = Pa_GetStreamTime(synth->stream); - synth->midi_note[data1].noteOff = 0; - synth->midi_note[data1].velocity = (float)data2 / 127.0; - synth->midi_note[data1].elapsed = 0; - synth->midi_note[data1].active = 1; - for (int i = 0; i < synth->midi_active_n; i++) { - if (synth->midi_active[i] == &synth->midi_note[data1]) { - flag = 0; - } - } - if (flag) { - synth->midi_active[synth->midi_active_n++] = &synth->midi_note[data1]; - } - synth->active = 1; + midi_note_on(synth, channel, data1, data2); break; case 0x0A: printf("Aftertouch: channel=%d, note=%d, pressure=%d\n", channel, data1, data2); break; case 0x0B: - printf("Control Change: channel=%d, controller=%d, value=%d\n", channel, data1, data2); - int x = data2 < 64 ? 1 : -1; - int val; - switch (data1) { - case 0: - cc_step(&synth->cc_adsr_a, x); - //synth->adsr.a = synth->adsr.a + (x * 0.01); - //synth->freq_offset = synth->freq_offset + (x*5); - //cc_step(&synth->cc_cutoff, x); - break; - case 1: - cc_step(&synth->cc_adsr_d, x); - //synth->adsr.d = synth->adsr.d + (x * 0.01); - break; - case 2: - cc_step(&synth->cc_adsr_s, x); - //synth->adsr.s = synth->adsr.s + (x * 0.01); - break; - case 3: - cc_step(&synth->cc_adsr_r, x); - //synth->adsr.r = synth->adsr.r + (x * 0.01); - break; - case 4: - cc_step(&synth->cc_cutoff, x); - //synth->cutoff = synth->cutoff + (x * (10 * log10(synth->cutoff))); - break; - case 5: - cc_step(&synth->cc_resonance, x); - break; - case 6: - //cc_step(&synth->cc_pitch, x); - cc_step(&synth->cc_lfo_freq, x); - //synth->lfo.freq = synth->lfo.freq + (x * 0.1); - break; - case 7: - //cc_reset(&synth->cc_pitch); - cc_step(&synth->cc_lfo_amp, x); - //synth->lfo.amp = synth->lfo.amp + (x * 0.002); - break; - case 8: - //cc_reset(&synth->cc_pitch); - synth->wvt_pos = data2; - //synth->lfo.amp = synth->lfo.amp + (x * 0.002); - break; - case 28: - if (synth->geni > 0) synth->geni--; - break; - case 29: - if (synth->geni < 6) synth->geni++; - break; - default: - break; - } + printf("Control Change: channel=%d, controller=%d, value=%d\n", channel, + data1, data2); + midi_cc(synth, channel, data1, data2); break; case 0x0C: printf("Program Change: channel=%d, program=%d\n", channel, data1); @@ -107,19 +140,8 @@ void midi_decode(uint32_t msg, synth_t * synth) { printf("Channel Pressure: channel=%d, pressure=%d\n", channel, data1); break; case 0x0E: - val = ((data2 << 7) | data1) - 8192; - printf("Pitch Bend: channel=%d, value=%d\n", channel, val); - float pitch; - float semitones = 2; - if (val == 0) { - pitch = 1; - } else if (val > 0) { - pitch = 1 + ((float)val / 8191) * semitones * pow(2.0, 1.0 / 12.0) / 12; - } else { - pitch = 1 + ((float)val / 8192) * semitones * pow(2.0, 1.0 / 12.0) / 12; - } - synth->cc_pitch.target = pitch; - /* cc_step(synth->cc_pitch, 1); */ + printf("Pitch Bend: channel=%d, value=%d\n", channel, ((data2 << 7) | data1) - 8192); + midi_pitch_bend(synth, channel, ((data2 << 7) | data1) - 8192); break; default: printf("Unknown MIDI message\n"); @@ -136,7 +158,7 @@ midiCallback(PtTimestamp timestamp, void *userData) { if (!m->stream) return; if (!enable) return; - // if (!Pm_Poll(m->stream)) return; + //if (!Pm_Poll(m->stream)) return; PmEvent buf; int e = Pm_Read(m->stream, &buf, 1); @@ -157,7 +179,10 @@ init_midi(midi_t *m, synth_t *synth) m->stream = NULL; m->synth = synth; - Pm_Initialize(); + PmError err = Pm_Initialize(); + if (err != pmNoError) { + fprintf(stdout, "Pm Error: %s\n", Pm_GetErrorText(err)); + } //printf("midi devs: %d\n", Pm_CountDevices()); const PmDeviceInfo *info; @@ -167,20 +192,24 @@ init_midi(midi_t *m, synth_t *synth) if (!info->input) { continue; } - //printf("%d: %s [input: %d output: %d opened: %d is_virt:%d] (interf: %s) -- %d\n", i, info->name, info->input, info->output, info->opened, info->is_virtual, info->interf, Pm_GetDefaultInputDeviceID()); - if (!strcmp(synth->midi_device.name, info->name) && !info->input) break; + printf("%d: %s [input: %d output: %d opened: %d is_virt:%d] (interface: %s)\n", i, info->name, info->input, info->output, info->opened, info->is_virtual, info->interf); + if (0 == strcmp(synth->midi_device.name, info->name)) + break; } printf("Selected device: %s [input: %d output: %d opened: %d is_virt:%d] (interf: %s)\n", info->name, info->input, info->output, info->opened, info->is_virtual, info->interf); Pt_Start(1, midiCallback, m); - Pm_OpenInput(&(m->stream), - i, //Pm_GetDefaultInputDeviceID(), - NULL, - 128, - NULL, - NULL); + err = Pm_OpenInput(&(m->stream), + i, //Pm_GetDefaultInputDeviceID(), + NULL, + 128, + NULL, + NULL); + if (err != pmNoError) { + fprintf(stdout, "Pm Error: %s\n", Pm_GetErrorText(err)); + } enable = 1; } @@ -219,7 +248,7 @@ get_midi_devices() strcat(ret, ";"); } ret[strlen(ret) - 1] = '\0'; - + return ret; } -- cgit v1.2.3