Skip to content

Commit

Permalink
Move pitch bend logic into main MIDI module
Browse files Browse the repository at this point in the history
  • Loading branch information
rhargreaves committed Jul 25, 2024
1 parent 171eca8 commit df6d865
Show file tree
Hide file tree
Showing 11 changed files with 72 additions and 100 deletions.
25 changes: 16 additions & 9 deletions src/midi.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,17 @@ typedef struct MidiChannel {
typedef enum MappingMode { MappingMode_Static, MappingMode_Dynamic, MappingMode_Auto } MappingMode;

static const VTable PSG_VTable = { midi_psg_note_on, midi_psg_note_off, midi_psg_channel_volume,
midi_psg_pitch_bend, midi_psg_program, midi_psg_all_notes_off, midi_psg_pan, midi_psg_pitch };
midi_psg_program, midi_psg_all_notes_off, midi_psg_pan, midi_psg_pitch };

static const VTable FM_VTable = { midi_fm_note_on, midi_fm_note_off, midi_fm_channel_volume,
midi_fm_pitch_bend, midi_fm_program, midi_fm_all_notes_off, midi_fm_pan, midi_fm_pitch };
midi_fm_program, midi_fm_all_notes_off, midi_fm_pan, midi_fm_pitch };

static const VTable SpecialMode_VTable
= { midi_fm_sm_note_on, midi_fm_sm_note_off, midi_fm_sm_channel_volume, midi_fm_sm_pitch_bend,
midi_fm_sm_program, midi_fm_sm_all_notes_off, midi_fm_sm_pan, midi_fm_sm_pitch };
= { midi_fm_sm_note_on, midi_fm_sm_note_off, midi_fm_sm_channel_volume, midi_fm_sm_program,
midi_fm_sm_all_notes_off, midi_fm_sm_pan, midi_fm_sm_pitch };

static const VTable DAC_VTable = { midi_dac_note_on, midi_dac_note_off, midi_dac_channel_volume,
midi_dac_pitch_bend, midi_dac_program, midi_dac_all_notes_off, midi_dac_pan, midi_dac_pitch };
midi_dac_program, midi_dac_all_notes_off, midi_dac_pan, midi_dac_pitch };

static const u8** defaultEnvelopes;
static const FmChannel** defaultPresets;
Expand Down Expand Up @@ -333,7 +333,9 @@ static void updatePan(MidiChannel* midiChannel, DeviceChannel* devChan)
static void updatePitchBend(MidiChannel* midiChannel, DeviceChannel* devChan)
{
if (devChan->pitchBend != midiChannel->pitchBend) {
devChan->ops->pitchBend(devChan->number, midiChannel->pitchBend);
PitchCents pc
= midi_effectivePitchCents(devChan->pitch, devChan->cents, midiChannel->pitchBend);
devChan->ops->pitch(devChan->number, pc.pitch, pc.cents);
devChan->pitchBend = midiChannel->pitchBend;
}
}
Expand Down Expand Up @@ -407,8 +409,12 @@ void midi_note_on(u8 chan, u8 pitch, u8 velocity)
}

devChan->midiChannel = chan;
devChan->noteOn = true;
devChan->cents = 0;
devChan->pitch = pitch;
updateDeviceChannelFromAssociatedMidiChannel(devChan);
devChanNoteOn(devChan, pitch, velocity);
PitchCents pc = midi_effectivePitchCents(devChan->pitch, devChan->cents, devChan->pitchBend);
devChan->ops->noteOn(devChan->number, pc.pitch, pc.cents, velocity);
}

void midi_note_off(u8 chan, u8 pitch)
Expand Down Expand Up @@ -438,7 +444,8 @@ static void devChanNoteOn(DeviceChannel* devChan, u8 pitch, u8 velocity)
devChan->noteOn = true;
devChan->cents = 0;
devChan->pitch = pitch;
devChan->ops->noteOn(devChan->number, pitch, velocity);
PitchCents pc = midi_effectivePitchCents(devChan->pitch, devChan->cents, devChan->pitchBend);
devChan->ops->noteOn(devChan->number, pc.pitch, pc.cents, velocity);
}

static void devChanNoteOff(DeviceChannel* devChan, u8 pitch)
Expand Down Expand Up @@ -959,7 +966,7 @@ void midi_tick(void)
processPortamento();
}

PitchCents midi_effectivePitchCents(u8 pitch, u8 cents, u16 pitchBend)
PitchCents midi_effectivePitchCents(u8 pitch, s8 cents, u16 pitchBend)
{
s16 newPitch = pitch + ((pitchBend - MIDI_PITCH_BEND_CENTRE) / 0x1000);
s16 newCents = cents + (((pitchBend - MIDI_PITCH_BEND_CENTRE) % 0x1000) / 41);
Expand Down
9 changes: 4 additions & 5 deletions src/midi.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,13 @@
#define SYSEX_COMMAND_WRITE_YM2612_REG_PART_1 0x09

typedef struct VTable {
void (*noteOn)(u8 chan, u8 pitch, u8 velocity);
void (*noteOn)(u8 chan, u8 pitch, s8 cents, u8 velocity);
void (*noteOff)(u8 chan, u8 pitch);
void (*channelVolume)(u8 chan, u8 volume);
void (*pitchBend)(u8 chan, u16 bend);
void (*program)(u8 chan, u8 program);
void (*allNotesOff)(u8 chan);
void (*pan)(u8 chan, u8 pan);
void (*pitch)(u8 chan, u8 pitch, u8 cents);
void (*pitch)(u8 chan, u8 pitch, s8 cents);
} VTable;

typedef struct DeviceChannel {
Expand All @@ -146,7 +145,7 @@ typedef struct DeviceChannel {

typedef struct PitchCents {
u8 pitch;
u8 cents;
s8 cents;
} PitchCents;

void midi_init(const FmChannel** defaultPresets, const PercussionPreset** defaultPercussionPresets,
Expand All @@ -162,4 +161,4 @@ DeviceChannel* midi_channel_mappings(void);
void midi_remap_channel(u8 midiChannel, u8 deviceChannel);
void midi_reset(void);
void midi_tick(void);
PitchCents midi_effectivePitchCents(u8 pitch, u8 cents, u16 pitchBend);
PitchCents midi_effectivePitchCents(u8 pitch, s8 cents, u16 pitchBend);
8 changes: 2 additions & 6 deletions src/midi_dac.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,12 @@
#include "snd/sound.h"
#include "snd/pcm/snd_pcm.h"

void midi_dac_note_on(u8 chan, u8 pitch, u8 velocity)
void midi_dac_note_on(u8 chan, u8 pitch, s8 cents, u8 velocity)
{
const PcmSample* sample = percussionPcmSample[0];
SND_PCM_startPlay(sample->data, sample->length, sample->rate, SOUND_PAN_CENTER, 0);
}

void midi_dac_pitch_bend(u8 chan, u16 bend)
{
}

void midi_dac_reset(void)
{
}
Expand All @@ -37,6 +33,6 @@ void midi_dac_all_notes_off(u8 chan)
{
}

void midi_dac_pitch(u8 chan, u8 pitch, u8 cents)
void midi_dac_pitch(u8 chan, u8 pitch, s8 cents)
{
}
5 changes: 2 additions & 3 deletions src/midi_dac.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
#pragma once
#include "types.h"

void midi_dac_note_on(u8 chan, u8 pitch, u8 velocity);
void midi_dac_pitch_bend(u8 chan, u16 bend);
void midi_dac_note_on(u8 chan, u8 pitch, s8 cents, u8 velocity);
void midi_dac_reset(void);
void midi_dac_note_off(u8 chan, u8 pitch);
void midi_dac_channel_volume(u8 chan, u8 volume);
void midi_dac_pan(u8 chan, u8 pan);
void midi_dac_program(u8 chan, u8 program);
void midi_dac_all_notes_off(u8 chan);
void midi_dac_pitch(u8 chan, u8 pitch, u8 cents);
void midi_dac_pitch(u8 chan, u8 pitch, s8 cents);
25 changes: 7 additions & 18 deletions src/midi_fm.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ static const u16 FREQS[] = { 607, // B

typedef struct MidiFmChannel {
u8 pitch;
u8 cents;
u16 pitchBend;
s8 cents;
u8 volume;
u8 velocity;
u8 pan;
Expand Down Expand Up @@ -46,13 +45,12 @@ void midi_fm_reset(void)
fmChan->velocity = MAX_MIDI_VOLUME;
fmChan->pan = 0;
fmChan->percussive = false;
fmChan->pitchBend = DEFAULT_MIDI_PITCH_BEND;
fmChan->cents = 0;
}
synth_init(presets[0]);
}

u16 midi_fm_pitchCentsToFreqNum(u8 pitch, u8 cents)
u16 midi_fm_pitchCentsToFreqNum(u8 pitch, s8 cents)
{
u16 freq = lookupFreqNum(pitch, 0);
u16 nextFreq = lookupFreqNum(pitch, 1);
Expand All @@ -62,12 +60,11 @@ u16 midi_fm_pitchCentsToFreqNum(u8 pitch, u8 cents)
static void setSynthPitch(u8 chan)
{
MidiFmChannel* fmChan = &fmChannels[chan];
PitchCents pc = midi_effectivePitchCents(fmChan->pitch, fmChan->cents, fmChan->pitchBend);
synth_pitch(
chan, midi_fm_pitchToOctave(pc.pitch), midi_fm_pitchCentsToFreqNum(pc.pitch, pc.cents));
synth_pitch(chan, midi_fm_pitchToOctave(fmChan->pitch),
midi_fm_pitchCentsToFreqNum(fmChan->pitch, fmChan->cents));
}

void midi_fm_note_on(u8 chan, u8 pitch, u8 velocity)
void midi_fm_note_on(u8 chan, u8 pitch, s8 cents, u8 velocity)
{
if (pitchIsOutOfRange(pitch)) {
return;
Expand All @@ -81,7 +78,7 @@ void midi_fm_note_on(u8 chan, u8 pitch, u8 velocity)
fmChan->velocity = velocity;
synth_volume(chan, effectiveVolume(fmChan));
fmChan->pitch = pitch;
fmChan->cents = 0;
fmChan->cents = cents;

setSynthPitch(chan);
synth_noteOn(chan);
Expand All @@ -100,14 +97,6 @@ void midi_fm_channel_volume(u8 chan, u8 volume)
synth_volume(chan, effectiveVolume(fmChan));
}

void midi_fm_pitch_bend(u8 chan, u16 bend)
{
MidiFmChannel* fmChan = &fmChannels[chan];
fmChan->pitchBend = bend;

setSynthPitch(chan);
}

void midi_fm_program(u8 chan, u8 program)
{
const FmChannel* data = presets[program];
Expand Down Expand Up @@ -164,7 +153,7 @@ static u8 effectiveVolume(MidiFmChannel* fmChan)
return (fmChan->volume * fmChan->velocity) / 0x7F;
}

void midi_fm_pitch(u8 chan, u8 pitch, u8 cents)
void midi_fm_pitch(u8 chan, u8 pitch, s8 cents)
{
MidiFmChannel* fmChan = &fmChannels[chan];
fmChan->pitch = pitch;
Expand Down
7 changes: 3 additions & 4 deletions src/midi_fm.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@ typedef struct PercussionPreset {
void midi_fm_init(
const FmChannel** defaultPresets, const PercussionPreset** defaultPercussionPresets);
void midi_fm_reset(void);
void midi_fm_note_on(u8 chan, u8 pitch, u8 velocity);
void midi_fm_note_on(u8 chan, u8 pitch, s8 cents, u8 velocity);
void midi_fm_note_off(u8 chan, u8 pitch);
void midi_fm_channel_volume(u8 chan, u8 volume);
void midi_fm_pan(u8 chan, u8 pan);
void midi_fm_pitch_bend(u8 chan, u16 bend);
void midi_fm_program(u8 chan, u8 program);
void midi_fm_all_notes_off(u8 chan);
void midi_fm_percussive(u8 chan, bool enabled);
u8 midi_fm_pitchToOctave(u8 pitch);
void midi_fm_pitch(u8 chan, u8 pitch, u8 cents);
u16 midi_fm_pitchCentsToFreqNum(u8 pitch, u8 cents);
void midi_fm_pitch(u8 chan, u8 pitch, s8 cents);
u16 midi_fm_pitchCentsToFreqNum(u8 pitch, s8 cents);
26 changes: 11 additions & 15 deletions src/midi_fm_sm.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,38 @@

typedef struct SpecialModeOperator {
u8 pitch;
u16 pitchBend;
s8 cents;
} SpecialModeOperator;

static SpecialModeOperator smOperators[SM_OP_LEN];

void midi_fm_sm_note_on(u8 op, u8 pitch, u8 velocity)
void midi_fm_sm_note_on(u8 op, u8 pitch, s8 cents, u8 velocity)
{
SpecialModeOperator* smOp = &smOperators[op];
smOp->pitch = pitch;
PitchCents pc = midi_effectivePitchCents(smOp->pitch, 0, smOp->pitchBend);
smOp->cents = cents;

synth_specialModePitch(
op, midi_fm_pitchToOctave(pc.pitch), midi_fm_pitchCentsToFreqNum(pc.pitch, pc.cents));
synth_specialModePitch(op, midi_fm_pitchToOctave(smOp->pitch),
midi_fm_pitchCentsToFreqNum(smOp->pitch, smOp->cents));
synth_specialModeVolume(op, velocity);
}

void midi_fm_sm_pitch_bend(u8 op, u16 bend)
void midi_fm_sm_pitch(u8 op, u8 pitch, s8 cents)
{
SpecialModeOperator* smOp = &smOperators[op];
smOp->pitchBend = bend;
PitchCents pc = midi_effectivePitchCents(smOp->pitch, 0, smOp->pitchBend);
smOp->pitch = pitch;
smOp->cents = cents;

synth_specialModePitch(
op, midi_fm_pitchToOctave(pc.pitch), midi_fm_pitchCentsToFreqNum(pc.pitch, pc.cents));
synth_specialModePitch(op, midi_fm_pitchToOctave(smOp->pitch),
midi_fm_pitchCentsToFreqNum(smOp->pitch, smOp->cents));
}

void midi_fm_sm_reset(void)
{
for (u8 op = 0; op < SM_OP_LEN; op++) {
SpecialModeOperator* smOp = &smOperators[op];
smOp->pitch = 0;
smOp->pitchBend = DEFAULT_MIDI_PITCH_BEND;
smOp->cents = 0;
}
}

Expand All @@ -61,7 +61,3 @@ void midi_fm_sm_program(u8 chan, u8 program)
void midi_fm_sm_all_notes_off(u8 chan)
{
}

void midi_fm_sm_pitch(u8 chan, u8 pitch, u8 cents)
{
}
5 changes: 2 additions & 3 deletions src/midi_fm_sm.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
#include "synth.h"
#include "types.h"

void midi_fm_sm_note_on(u8 chan, u8 pitch, u8 velocity);
void midi_fm_sm_pitch_bend(u8 chan, u16 bend);
void midi_fm_sm_note_on(u8 chan, u8 pitch, s8 cents, u8 velocity);
void midi_fm_sm_reset(void);
void midi_fm_sm_pitch(u8 chan, u8 pitch, u8 cents);
void midi_fm_sm_pitch(u8 chan, u8 pitch, s8 cents);

// no-ops
void midi_fm_sm_note_off(u8 chan, u8 pitch);
Expand Down
Loading

0 comments on commit df6d865

Please sign in to comment.