ref: 563d83b675bf201bf1df5e626b81f9ddb568c8b7
parent: 5a7a5402f74361dee7f2c6109eb46b83b4d17c16
parent: 4f4cfd902dcdf93e9db6043ddb080dd20b471c3d
author: Simon Howard <fraggle+github@gmail.com>
date: Tue Oct 28 18:31:53 EDT 2014
Merge pull request #468 from khokh2001/opl-fix4 Fix voice allocation when there are no more free voices. This fixes a long-standing (but minor) discrepancy between the OPL code and the DMX library that was marked in the code with a TODO.
--- a/src/i_oplmusic.c
+++ b/src/i_oplmusic.c
@@ -364,6 +364,7 @@
static opl_voice_t *GetFreeVoice(void)
{
opl_voice_t *result;
+ opl_voice_t **rover;
// None available?
@@ -379,9 +380,16 @@
// Add to allocated list
- result->next = voice_alloced_list;
- voice_alloced_list = result;
+ rover = &voice_alloced_list;
+ while (*rover != NULL)
+ {
+ rover = &(*rover)->next;
+ }
+
+ *rover = result;
+ result->next = NULL;
+
return result;
}
@@ -636,22 +644,12 @@
}
}
-// Compare the priorities of channels, returning either -1, 0 or 1.
-
-static int CompareChannelPriorities(opl_channel_data_t *chan1,
- opl_channel_data_t *chan2)
-{
- // TODO ...
-
- return 1;
-}
-
// When all voices are in use, we must discard an existing voice to
// play a new note. Find and free an existing voice. The channel
// passed to the function is the channel for the new note to be
// played.
-static opl_voice_t *ReplaceExistingVoice(opl_channel_data_t *channel)
+static void ReplaceExistingVoice()
{
opl_voice_t *rover;
opl_voice_t *result;
@@ -664,51 +662,19 @@
// than higher-numbered channels, eg. MIDI channel 1 is never
// discarded for MIDI channel 2.
- result = NULL;
+ result = voice_alloced_list;
for (rover = voice_alloced_list; rover != NULL; rover = rover->next)
{
if (rover->current_instr_voice != 0
- || (rover->channel > channel
- && CompareChannelPriorities(channel, rover->channel) > 0))
+ || rover->channel >= result->channel)
{
result = rover;
- break;
}
}
- // If we didn't find a voice, find an existing voice being used to
- // play a note on the same channel, and use that.
-
- if (result == NULL)
- {
- for (rover = voice_alloced_list; rover != NULL; rover = rover->next)
- {
- if (rover->channel == channel)
- {
- result = rover;
- break;
- }
- }
- }
-
- // Still nothing found? Give up and just use the first voice in
- // the list.
-
- if (result == NULL)
- {
- result = voice_alloced_list;
- }
-
- // Stop playing this voice playing and release it back to the free
- // list.
-
VoiceKeyOff(result);
ReleaseVoice(result);
-
- // Re-allocate the voice again and return it.
-
- return GetFreeVoice();
}
@@ -822,21 +788,9 @@
voice = GetFreeVoice();
- // If there are no more voices left, we must decide what to do.
- // If this is the first voice of the instrument, free an existing
- // voice and use that. Otherwise, if this is the second voice,
- // it isn't as important; just discard it.
-
if (voice == NULL)
{
- if (instrument_voice == 0)
- {
- voice = ReplaceExistingVoice(channel);
- }
- else
- {
- return;
- }
+ return;
}
voice->channel = channel;
@@ -917,6 +871,11 @@
else
{
instrument = channel->instrument;
+ }
+
+ if (voice_free_list == NULL)
+ {
+ ReplaceExistingVoice();
}
// Find and program a voice for this instrument. If this