aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/midi/base.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2014-02-02 02:39:56 -0800
committerChris Robinson <[email protected]>2014-02-02 02:39:56 -0800
commit7c4339c195e29b17c8f76e6fbe9c8ee1b4f7b9b8 (patch)
tree728e3298bff7d7612ee6d7fcd88a2049d343d763 /Alc/midi/base.c
parent755f161fc58aec0b541c7783ed716bd5c861a615 (diff)
Rework MIDI clock timing
It's best to avoid using doubles in the mixer since the FPU's set to single- precision mode. The new clock timing is similar to the device clock timing, and should hopefully be less prone to drift caused by fp rounding errors.
Diffstat (limited to 'Alc/midi/base.c')
-rw-r--r--Alc/midi/base.c69
1 files changed, 15 insertions, 54 deletions
diff --git a/Alc/midi/base.c b/Alc/midi/base.c
index 249bc2a8..1850a6c6 100644
--- a/Alc/midi/base.c
+++ b/Alc/midi/base.c
@@ -16,9 +16,6 @@
#include "alu.h"
-/* Nanosecond resolution */
-#define TICKS_PER_SECOND (1000000000)
-
/* MIDI events */
#define SYSEX_EVENT (0xF0)
@@ -129,12 +126,9 @@ void MidiSynth_Construct(MidiSynth *self, ALCdevice *device)
self->Gain = 1.0f;
self->State = AL_INITIAL;
- self->LastEvtTime = 0;
- self->NextEvtTime = UINT64_MAX;
- self->SamplesSinceLast = 0.0;
- self->SamplesToNext = 0.0;
-
- self->SamplesPerTick = (ALdouble)device->Frequency / TICKS_PER_SECOND;
+ self->ClockBase = 0;
+ self->SamplesDone = 0;
+ self->SampleRate = device->Frequency;
}
void MidiSynth_Destruct(MidiSynth *self)
@@ -195,29 +189,22 @@ void MidiSynth_stop(MidiSynth *self)
{
ResetEvtQueue(&self->EventQueue);
- self->LastEvtTime = 0;
- self->NextEvtTime = UINT64_MAX;
- self->SamplesSinceLast = 0.0;
- self->SamplesToNext = 0.0;
+ self->ClockBase = 0;
+ self->SamplesDone = 0;
}
extern inline void MidiSynth_reset(MidiSynth *self);
-
-ALuint64 MidiSynth_getTime(const MidiSynth *self)
-{
- ALuint64 time = self->LastEvtTime + (self->SamplesSinceLast/self->SamplesPerTick);
- return clampu64(time, self->LastEvtTime, self->NextEvtTime);
-}
-
+extern inline ALuint64 MidiSynth_getTime(const MidiSynth *self);
extern inline ALuint64 MidiSynth_getNextEvtTime(const MidiSynth *self);
-void MidiSynth_setSampleRate(MidiSynth *self, ALdouble srate)
+void MidiSynth_setSampleRate(MidiSynth *self, ALuint srate)
{
- ALdouble sampletickrate = srate / TICKS_PER_SECOND;
-
- self->SamplesSinceLast = self->SamplesSinceLast * sampletickrate / self->SamplesPerTick;
- self->SamplesToNext = self->SamplesToNext * sampletickrate / self->SamplesPerTick;
- self->SamplesPerTick = sampletickrate;
+ if(self->SampleRate != srate)
+ {
+ self->ClockBase += self->SamplesDone * MIDI_CLOCK_RES / self->SampleRate;
+ self->SamplesDone = 0;
+ self->SampleRate = srate;
+ }
}
extern inline void MidiSynth_update(MidiSynth *self, ALCdevice *device);
@@ -225,25 +212,11 @@ extern inline void MidiSynth_update(MidiSynth *self, ALCdevice *device);
ALenum MidiSynth_insertEvent(MidiSynth *self, ALuint64 time, ALuint event, ALsizei param1, ALsizei param2)
{
MidiEvent entry;
- ALenum err;
-
entry.time = time;
entry.event = event;
entry.param.val[0] = param1;
entry.param.val[1] = param2;
-
- err = InsertEvtQueue(&self->EventQueue, &entry);
- if(err != AL_NO_ERROR) return err;
-
- if(entry.time < self->NextEvtTime)
- {
- self->NextEvtTime = entry.time;
-
- self->SamplesToNext = (self->NextEvtTime - self->LastEvtTime) * self->SamplesPerTick;
- self->SamplesToNext -= self->SamplesSinceLast;
- }
-
- return AL_NO_ERROR;
+ return InsertEvtQueue(&self->EventQueue, &entry);
}
ALenum MidiSynth_insertSysExEvent(MidiSynth *self, ALuint64 time, const ALbyte *data, ALsizei size)
@@ -261,18 +234,6 @@ ALenum MidiSynth_insertSysExEvent(MidiSynth *self, ALuint64 time, const ALbyte *
err = InsertEvtQueue(&self->EventQueue, &entry);
if(err != AL_NO_ERROR)
- {
free(entry.param.sysex.data);
- return err;
- }
-
- if(entry.time < self->NextEvtTime)
- {
- self->NextEvtTime = entry.time;
-
- self->SamplesToNext = (self->NextEvtTime - self->LastEvtTime) * self->SamplesPerTick;
- self->SamplesToNext -= self->SamplesSinceLast;
- }
-
- return AL_NO_ERROR;
+ return err;
}