Document the different filter types, and combine some split lines
[openal-soft.git] / Alc / midi / soft.c
blob7102ff7a6133ef111ca6bb1d2ca8e2112fe14e00
2 #include "config.h"
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <limits.h>
9 #include "alMain.h"
10 #include "alError.h"
11 #include "evtqueue.h"
12 #include "alu.h"
14 #include "midi/base.h"
17 typedef struct SSynth {
18 DERIVE_FROM_TYPE(MidiSynth);
19 } SSynth;
21 static void SSynth_mixSamples(SSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]);
23 static void SSynth_Construct(SSynth *self, ALCdevice *device);
24 static void SSynth_Destruct(SSynth *self);
25 static DECLARE_FORWARD3(SSynth, MidiSynth, ALenum, selectSoundfonts, ALCcontext*, ALsizei, const ALuint*)
26 static DECLARE_FORWARD1(SSynth, MidiSynth, void, setGain, ALfloat)
27 static DECLARE_FORWARD(SSynth, MidiSynth, void, stop)
28 static DECLARE_FORWARD(SSynth, MidiSynth, void, reset)
29 static void SSynth_update(SSynth *self, ALCdevice *device);
30 static void SSynth_process(SSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]);
31 DECLARE_DEFAULT_ALLOCATORS(SSynth)
32 DEFINE_MIDISYNTH_VTABLE(SSynth);
35 static void SSynth_Construct(SSynth *self, ALCdevice *device)
37 MidiSynth_Construct(STATIC_CAST(MidiSynth, self), device);
38 SET_VTABLE2(SSynth, MidiSynth, self);
41 static void SSynth_Destruct(SSynth* UNUSED(self))
46 static void SSynth_update(SSynth* UNUSED(self), ALCdevice* UNUSED(device))
51 static void SSynth_mixSamples(SSynth* UNUSED(self), ALuint UNUSED(SamplesToDo), ALfloat (*restrict DryBuffer)[BUFFERSIZE])
53 (void)DryBuffer;
57 static void SSynth_processQueue(SSynth *self, ALuint64 time)
59 EvtQueue *queue = &STATIC_CAST(MidiSynth, self)->EventQueue;
61 while(queue->pos < queue->size && queue->events[queue->pos].time <= time)
62 queue->pos++;
65 static void SSynth_process(SSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE])
67 MidiSynth *synth = STATIC_CAST(MidiSynth, self);
68 ALenum state = synth->State;
69 ALuint64 curtime;
70 ALuint total = 0;
72 if(state == AL_INITIAL)
73 return;
74 if(state != AL_PLAYING)
76 SSynth_mixSamples(self, SamplesToDo, DryBuffer);
77 return;
80 curtime = MidiSynth_getTime(synth);
81 while(total < SamplesToDo)
83 ALuint64 time, diff;
84 ALint tonext;
86 time = MidiSynth_getNextEvtTime(synth);
87 diff = maxu64(time, curtime) - curtime;
88 if(diff >= MIDI_CLOCK_RES || time == UINT64_MAX)
90 /* If there's no pending event, or if it's more than 1 second
91 * away, do as many samples as we can. */
92 tonext = INT_MAX;
94 else
96 /* Figure out how many samples until the next event. */
97 tonext = (ALint)((diff*synth->SampleRate + (MIDI_CLOCK_RES-1)) / MIDI_CLOCK_RES);
98 tonext -= total;
99 /* For efficiency reasons, try to mix a multiple of 64 samples
100 * (~1ms @ 44.1khz) before processing the next event. */
101 tonext = (tonext+63) & ~63;
104 if(tonext > 0)
106 ALuint todo = mini(tonext, SamplesToDo-total);
107 SSynth_mixSamples(self, todo, DryBuffer);
108 total += todo;
109 tonext -= todo;
111 if(total < SamplesToDo && tonext <= 0)
112 SSynth_processQueue(self, time);
115 synth->SamplesDone += SamplesToDo;
116 synth->ClockBase += (synth->SamplesDone/synth->SampleRate) * MIDI_CLOCK_RES;
117 synth->SamplesDone %= synth->SampleRate;
121 MidiSynth *SSynth_create(ALCdevice *device)
123 SSynth *synth;
125 /* This option is temporary. Once this synth is in a more usable state, a
126 * more generic selector should be used. */
127 if(!GetConfigValueBool("midi", "internal-synth", 0))
129 TRACE("Not using internal MIDI synth\n");
130 return NULL;
133 synth = SSynth_New(sizeof(*synth));
134 if(!synth)
136 ERR("Failed to allocate SSynth\n");
137 return NULL;
139 SSynth_Construct(synth, device);
140 return STATIC_CAST(MidiSynth, synth);