20 #define SYSEX_EVENT (0xF0)
23 void InitEvtQueue(EvtQueue
*queue
)
31 void ResetEvtQueue(EvtQueue
*queue
)
34 for(i
= 0;i
< queue
->size
;i
++)
36 if(queue
->events
[i
].event
== SYSEX_EVENT
)
38 free(queue
->events
[i
].param
.sysex
.data
);
39 queue
->events
[i
].param
.sysex
.data
= NULL
;
50 ALenum
InsertEvtQueue(EvtQueue
*queue
, const MidiEvent
*evt
)
54 if(queue
->maxsize
== queue
->size
)
58 /* Queue has some stale entries, remove them to make space for more
60 for(pos
= 0;pos
< queue
->pos
;pos
++)
62 if(queue
->events
[pos
].event
== SYSEX_EVENT
)
64 free(queue
->events
[pos
].param
.sysex
.data
);
65 queue
->events
[pos
].param
.sysex
.data
= NULL
;
68 memmove(&queue
->events
[0], &queue
->events
[queue
->pos
],
69 (queue
->size
-queue
->pos
)*sizeof(queue
->events
[0]));
70 queue
->size
-= queue
->pos
;
75 /* Queue is full, double the allocated space. */
79 newsize
= (queue
->maxsize
? (queue
->maxsize
<<1) : 16);
80 if(newsize
> queue
->maxsize
)
81 temp
= realloc(queue
->events
, newsize
* sizeof(queue
->events
[0]));
83 return AL_OUT_OF_MEMORY
;
86 queue
->maxsize
= newsize
;
93 ALsizei high
= queue
->size
- 1;
96 ALsizei mid
= pos
+ (high
-pos
)/2;
97 if(queue
->events
[mid
].time
< evt
->time
)
102 while(pos
< queue
->size
&& queue
->events
[pos
].time
<= evt
->time
)
105 if(pos
< queue
->size
)
106 memmove(&queue
->events
[pos
+1], &queue
->events
[pos
],
107 (queue
->size
-pos
)*sizeof(queue
->events
[0]));
110 queue
->events
[pos
] = *evt
;
117 void MidiSynth_Construct(MidiSynth
*self
, ALCdevice
*device
)
119 InitEvtQueue(&self
->EventQueue
);
121 RWLockInit(&self
->Lock
);
123 self
->Soundfonts
= NULL
;
124 self
->NumSoundfonts
= 0;
127 self
->State
= AL_INITIAL
;
130 self
->SamplesDone
= 0;
131 self
->SampleRate
= device
->Frequency
;
134 void MidiSynth_Destruct(MidiSynth
*self
)
138 for(i
= 0;i
< self
->NumSoundfonts
;i
++)
139 DecrementRef(&self
->Soundfonts
[i
]->ref
);
140 free(self
->Soundfonts
);
141 self
->Soundfonts
= NULL
;
142 self
->NumSoundfonts
= 0;
144 ResetEvtQueue(&self
->EventQueue
);
148 ALenum
MidiSynth_selectSoundfonts(MidiSynth
*self
, ALCcontext
*context
, ALsizei count
, const ALuint
*ids
)
150 ALCdevice
*device
= context
->Device
;
151 ALsoundfont
**sfonts
;
154 if(self
->State
!= AL_INITIAL
&& self
->State
!= AL_STOPPED
)
155 return AL_INVALID_OPERATION
;
157 sfonts
= calloc(1, count
* sizeof(sfonts
[0]));
158 if(!sfonts
) return AL_OUT_OF_MEMORY
;
160 for(i
= 0;i
< count
;i
++)
163 sfonts
[i
] = ALsoundfont_getDefSoundfont(context
);
164 else if(!(sfonts
[i
]=LookupSfont(device
, ids
[i
])))
167 return AL_INVALID_VALUE
;
171 for(i
= 0;i
< count
;i
++)
172 IncrementRef(&sfonts
[i
]->ref
);
173 sfonts
= ExchangePtr((XchgPtr
*)&self
->Soundfonts
, sfonts
);
174 count
= ExchangeInt(&self
->NumSoundfonts
, count
);
176 for(i
= 0;i
< count
;i
++)
177 DecrementRef(&sfonts
[i
]->ref
);
183 extern inline void MidiSynth_setGain(MidiSynth
*self
, ALfloat gain
);
184 extern inline ALfloat
MidiSynth_getGain(const MidiSynth
*self
);
185 extern inline void MidiSynth_setState(MidiSynth
*self
, ALenum state
);
186 extern inline ALenum
MidiSynth_getState(const MidiSynth
*self
);
188 void MidiSynth_stop(MidiSynth
*self
)
190 ResetEvtQueue(&self
->EventQueue
);
193 self
->SamplesDone
= 0;
196 extern inline void MidiSynth_reset(MidiSynth
*self
);
197 extern inline ALuint64
MidiSynth_getTime(const MidiSynth
*self
);
198 extern inline ALuint64
MidiSynth_getNextEvtTime(const MidiSynth
*self
);
200 void MidiSynth_setSampleRate(MidiSynth
*self
, ALuint srate
)
202 if(self
->SampleRate
!= srate
)
204 self
->ClockBase
+= self
->SamplesDone
* MIDI_CLOCK_RES
/ self
->SampleRate
;
205 self
->SamplesDone
= 0;
206 self
->SampleRate
= srate
;
210 extern inline void MidiSynth_update(MidiSynth
*self
, ALCdevice
*device
);
212 ALenum
MidiSynth_insertEvent(MidiSynth
*self
, ALuint64 time
, ALuint event
, ALsizei param1
, ALsizei param2
)
217 entry
.param
.val
[0] = param1
;
218 entry
.param
.val
[1] = param2
;
219 return InsertEvtQueue(&self
->EventQueue
, &entry
);
222 ALenum
MidiSynth_insertSysExEvent(MidiSynth
*self
, ALuint64 time
, const ALbyte
*data
, ALsizei size
)
228 entry
.event
= SYSEX_EVENT
;
229 entry
.param
.sysex
.size
= size
;
230 entry
.param
.sysex
.data
= malloc(size
);
231 if(!entry
.param
.sysex
.data
)
232 return AL_OUT_OF_MEMORY
;
233 memcpy(entry
.param
.sysex
.data
, data
, size
);
235 err
= InsertEvtQueue(&self
->EventQueue
, &entry
);
236 if(err
!= AL_NO_ERROR
)
237 free(entry
.param
.sysex
.data
);