summaryrefslogtreecommitdiff
path: root/src/revolution/homebuttonLib/sound/synctrl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/revolution/homebuttonLib/sound/synctrl.cpp')
-rw-r--r--src/revolution/homebuttonLib/sound/synctrl.cpp309
1 files changed, 309 insertions, 0 deletions
diff --git a/src/revolution/homebuttonLib/sound/synctrl.cpp b/src/revolution/homebuttonLib/sound/synctrl.cpp
new file mode 100644
index 0000000000..a683e5528b
--- /dev/null
+++ b/src/revolution/homebuttonLib/sound/synctrl.cpp
@@ -0,0 +1,309 @@
+#include "synprivate.h"
+
+
+#include <revolution/types.h>
+
+#include "mix.h"
+
+// #include <revolution/ax.h>
+// #include <revolution/os.h>
+// #include <revolution/os/OSInterrupt.h>
+
+
+
+// MidiChannelVoiceMessage
+#define MIDI_MESSAGE_CHANNEL_VOICE_NOTE_OFF 8
+#define MIDI_MESSAGE_CHANNEL_VOICE_NOTE_ON 9
+#define MIDI_MESSAGE_CHANNEL_VOICE_CONTROL_CHANGE 11
+#define MIDI_MESSAGE_CHANNEL_VOICE_PROGRAM_CHANGE 12
+
+// MidiChannelControl
+#define MIDI_CC_CHANNEL_VOLUME 7
+#define MIDI_CC_PAN 10
+#define MIDI_CC_EXPRESSION 11
+#define MIDI_CC_REVERB_SEND_LEVEL 91
+#define MIDI_CC_TREMOLO_DEPTH 92
+
+
+static void __HBMSYNProgramChange(HBMSYNSYNTH *synth, u8 midiChannel,
+ u8 program);
+
+static void __HBMSYNResetController(HBMSYNSYNTH *synth, u8 midiChannel);
+
+static void __HBMSYNNoteOff(HBMSYNSYNTH *synth, u8 midiChannel, u8 keyNum);
+static void __HBMSYNNoteOn(HBMSYNSYNTH *synth, u8 midiChannel, u8 keyNum,
+ u8 keyVel);
+static void __HBMSYNMidiIn(HBMSYNSYNTH *synth, u8 *input);
+
+
+// .data
+
+// Why is this here anyways if its only use is in another file
+f32 __HBMSYNn128[128] = // x/128, rounded to 5 decimal places
+{
+ 0.0f, 0.007813f, 0.015625f, 0.023438f,
+ 0.03125f, 0.039063f, 0.046875f, 0.054688f,
+ 0.0625f, 0.070313f, 0.078125f, 0.085938f,
+ 0.09375f, 0.101563f, 0.109375f, 0.117188f,
+ 0.125f, 0.132813f, 0.140625f, 0.148438f,
+ 0.15625f, 0.164063f, 0.171875f, 0.179688f,
+ 0.1875f, 0.195313f, 0.203125f, 0.210938f,
+ 0.21875f, 0.226563f, 0.234375f, 0.242188f,
+ 0.25f, 0.257813f, 0.265625f, 0.273438f,
+ 0.28125f, 0.289063f, 0.296875f, 0.304688f,
+ 0.3125f, 0.320313f, 0.328125f, 0.335938f,
+ 0.34375f, 0.351563f, 0.359375f, 0.367188f,
+ 0.375f, 0.382813f, 0.390625f, 0.398438f,
+ 0.40625f, 0.414063f, 0.421875f, 0.429688f,
+ 0.4375f, 0.445313f, 0.453125f, 0.460938f,
+ 0.46875f, 0.476563f, 0.484375f, 0.492188f,
+ 0.5f, 0.507813f, 0.515625f, 0.523438f,
+ 0.53125f, 0.539063f, 0.546875f, 0.554688f,
+ 0.5625f, 0.570313f, 0.578125f, 0.585938f,
+ 0.59375f, 0.601563f, 0.609375f, 0.617188f,
+ 0.625f, 0.632813f, 0.640625f, 0.648438f,
+ 0.65625f, 0.664063f, 0.671875f, 0.679688f,
+ 0.6875f, 0.695313f, 0.703125f, 0.710938f,
+ 0.71875f, 0.726563f, 0.734375f, 0.742188f,
+ 0.75f, 0.757813f, 0.765625f, 0.773438f,
+ 0.78125f, 0.789063f, 0.796875f, 0.804688f,
+ 0.8125f, 0.820313f, 0.828125f, 0.835938f,
+ 0.84375f, 0.851563f, 0.859375f, 0.867188f,
+ 0.875f, 0.882813f, 0.890625f, 0.898438f,
+ 0.90625f, 0.914063f, 0.921875f, 0.929688f,
+ 0.9375f, 0.945313f, 0.953125f, 0.960938f,
+ 0.96875f, 0.976563f, 0.984375f, 0.992188f
+};
+
+
+static void __HBMSYNProgramChange(HBMSYNSYNTH *synth, u8 midiChannel,
+ u8 program)
+{
+ ASSERTLINE(54, synth);
+ ASSERTLINE(55, midiChannel < 16);
+ ASSERTLINE(56, program < 128);
+
+ synth->inst[midiChannel] = &synth->melodicInst[program];
+}
+
+void __HBMSYNSetController(HBMSYNSYNTH *synth, u8 midiChannel, u8 function,
+ u8 value)
+{
+ ASSERTLINE(67, synth);
+ ASSERTLINE(68, midiChannel < 16);
+ ASSERTLINE(69, function < 128);
+ ASSERTLINE(70, value < 128);
+
+ switch (function)
+ {
+ case MIDI_CC_CHANNEL_VOLUME:
+ synth->volAttn[midiChannel] = __HBMSYNVolumeAttenuation[value];
+ break;
+
+ case MIDI_CC_PAN:
+ synth->pan[midiChannel] = value;
+ break;
+
+ case MIDI_CC_REVERB_SEND_LEVEL:
+ synth->auxAAttn[midiChannel] = __HBMSYNVolumeAttenuation[value];
+ break;
+
+ default: // the rest aren't supported
+ break;
+ }
+}
+
+static void __HBMSYNResetController(HBMSYNSYNTH *synth, u8 midiChannel)
+{
+ ASSERTLINE(102, synth);
+ ASSERTLINE(103, midiChannel < 16);
+
+ __HBMSYNSetController(synth, midiChannel, MIDI_CC_CHANNEL_VOLUME, 100);
+ __HBMSYNSetController(synth, midiChannel, MIDI_CC_PAN, 64);
+ __HBMSYNSetController(synth, midiChannel, MIDI_CC_EXPRESSION, 127);
+ __HBMSYNSetController(synth, midiChannel, MIDI_CC_REVERB_SEND_LEVEL, 0);
+ __HBMSYNSetController(synth, midiChannel, MIDI_CC_TREMOLO_DEPTH, 0);
+}
+
+void __HBMSYNResetAllControllers(HBMSYNSYNTH *synth)
+{
+ u8 midiChannel;
+
+ ASSERTLINE(121, synth);
+
+ for (midiChannel = 0; midiChannel < HBMSYN_NUM_MIDI_CHANNELS; ++midiChannel)
+ {
+ __HBMSYNProgramChange(synth, midiChannel, 0);
+ __HBMSYNResetController(synth, midiChannel);
+ }
+}
+
+static void __HBMSYNNoteOff(HBMSYNSYNTH *synth, u8 midiChannel, u8 keyNum)
+{
+ HBMSYNVOICE *voice;
+
+ ASSERTLINE(138, synth);
+ ASSERTLINE(139, midiChannel < 16);
+ ASSERTLINE(140, keyNum < 128);
+
+ voice = synth->voice[midiChannel][keyNum];
+
+ if (voice)
+ {
+ __HBMSYNSetVoiceToRelease(voice);
+ synth->voice[midiChannel][keyNum] = NULL;
+ }
+}
+
+static void __HBMSYNNoteOn(HBMSYNSYNTH *synth, u8 midiChannel, u8 keyNum,
+ u8 keyVel)
+{
+ ASSERTLINE(162, synth);
+ ASSERTLINE(163, midiChannel < 16);
+ ASSERTLINE(164, keyNum < 128);
+ ASSERTLINE(165, keyVel < 128);
+
+ if (keyVel)
+ {
+ AXVPB *axvpb;
+
+ if (synth->voice[midiChannel][keyNum])
+ {
+ __HBMSYNSetVoiceToRelease(synth->voice[midiChannel][keyNum]);
+ synth->voice[midiChannel][keyNum] = NULL;
+ }
+
+ axvpb = AXAcquireVoice(AX_PRIORITY_MAX, &__HBMSYNClearVoiceReferences,
+ (u32)synth);
+
+ if (axvpb)
+ {
+ int index = HBMAllocIndex(axvpb->index);
+
+ if (index >= 0)
+ {
+ HBMSYNVOICE *voice = __HBMSYNVoice + index;
+
+ voice->axvpb = axvpb;
+ voice->synth = synth;
+ voice->midiChannel = midiChannel;
+ voice->keyNum = keyNum;
+ voice->keyVel = keyVel;
+
+ if (__HBMSYNGetWavetableData(voice))
+ {
+ synth->voice[midiChannel][keyNum] = voice;
+ ++synth->notes;
+
+ __HBMSYNSetupPitch(voice);
+ __HBMSYNSetupVolume(voice);
+ __HBMSYNSetupPan(voice);
+ __HBMSYNSetupVolumeEnvelope(voice);
+
+ HBMMIXInitChannel(axvpb, __HBMSYNGetVoiceInput(voice),
+ synth->auxAAttn[midiChannel] >> 16,
+ synth->pan[midiChannel],
+ __HBMSYNGetVoiceFader(voice));
+
+ __HBMSYNSetupSample(voice);
+ __HBMSYNSetupSrc(voice);
+
+ axvpb->pb.state = 1;
+ axvpb->sync |= AX_VPB_SYNC_FLAG_STATE;
+ }
+ else
+ {
+ voice->synth = NULL;
+
+ HBMMIXReleaseChannel(axvpb);
+ HBMFreeIndex(index);
+ AXFreeVoice(axvpb);
+ }
+ }
+ else
+ {
+ AXFreeVoice(axvpb);
+ }
+ }
+ }
+ else
+ {
+ __HBMSYNNoteOff(synth, midiChannel, keyNum);
+ }
+}
+
+static void __HBMSYNMidiIn(HBMSYNSYNTH *synth, u8 *input)
+{
+ u8 *ch;
+ u8 midiFunction;
+ u8 midiChannel;
+ u8 _2ndByte;
+ u8 _3rdByte;
+
+ ASSERTLINE(275, synth);
+ ASSERTLINE(276, input);
+
+ ch = input;
+
+ midiFunction = *ch >> 4;
+ midiChannel = *ch & 0x0f;
+ ++ch;
+
+ _2ndByte = *ch;
+ ++ch;
+
+ switch (midiFunction)
+ {
+ case MIDI_MESSAGE_CHANNEL_VOICE_NOTE_OFF:
+ __HBMSYNNoteOff(synth, midiChannel, _2ndByte);
+ break;
+
+ case MIDI_MESSAGE_CHANNEL_VOICE_NOTE_ON:
+ _3rdByte = *ch;
+ __HBMSYNNoteOn(synth, midiChannel, _2ndByte, _3rdByte);
+ break;
+
+ case MIDI_MESSAGE_CHANNEL_VOICE_CONTROL_CHANGE:
+ _3rdByte = *ch;
+ __HBMSYNSetController(synth, midiChannel, _2ndByte, _3rdByte);
+ break;
+
+ case MIDI_MESSAGE_CHANNEL_VOICE_PROGRAM_CHANGE:
+ __HBMSYNProgramChange(synth, midiChannel, _2ndByte);
+ break;
+
+ default: // the rest aren't supported
+ break;
+ }
+}
+
+void __HBMSYNRunInputBufferEvents(HBMSYNSYNTH *synth)
+{
+ u8 (*input)[3];
+
+ for (input = synth->input; synth->inputCounter; --synth->inputCounter)
+ {
+ __HBMSYNMidiIn(synth, *input);
+
+ ++input;
+ }
+
+ synth->inputPosition = *synth->input;
+}
+
+BOOL __HBMSYNGetWavetableData(HBMSYNVOICE *voice)
+{
+ HBMSYNSYNTH *synth = voice->synth;
+ u32 regionIndex = synth->inst[voice->midiChannel]->keyRegion[voice->keyNum];
+
+ // TODO: a define, maybe?
+ if (regionIndex == 0xffff)
+ return FALSE;
+
+ voice->region = synth->region + regionIndex;
+ voice->art = synth->art + voice->region->articulationIndex;
+ voice->sample = synth->sample + voice->region->sampleIndex;
+ voice->adpcm = synth->adpcm + voice->sample->adpcmIndex;
+
+ return TRUE;
+}