summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSimon Howard2015-05-27 21:51:58 -0400
committerSimon Howard2015-05-27 21:51:58 -0400
commita09682d46edae813700eb693d0e5d5dccc652cd7 (patch)
tree858258b89d58f0cbd46f51a90a37dc0a1f6315cb /src
parent4f8f8a43e174f1e82dc0160c0ea96070e1cf6ef9 (diff)
parent270a249e5e1d15a17c2f7b91c7cf53e28d342229 (diff)
downloadchocolate-doom-a09682d46edae813700eb693d0e5d5dccc652cd7.tar.gz
chocolate-doom-a09682d46edae813700eb693d0e5d5dccc652cd7.tar.bz2
chocolate-doom-a09682d46edae813700eb693d0e5d5dccc652cd7.zip
Merge pull request #516 from khokh2001/oldopl
Older DMX's OPL voice allocation algorithm
Diffstat (limited to 'src')
-rw-r--r--src/doom/s_sound.c1
-rw-r--r--src/heretic/s_sound.c1
-rw-r--r--src/hexen/s_sound.c1
-rw-r--r--src/i_oplmusic.c158
-rw-r--r--src/i_sound.c6
-rw-r--r--src/i_sound.h7
-rw-r--r--src/strife/s_sound.c1
7 files changed, 157 insertions, 18 deletions
diff --git a/src/doom/s_sound.c b/src/doom/s_sound.c
index 5834650d..884e0c1a 100644
--- a/src/doom/s_sound.c
+++ b/src/doom/s_sound.c
@@ -115,6 +115,7 @@ void S_Init(int sfxVolume, int musicVolume)
{
int i;
+ I_SetOPLDriverVer(opl_v_new);
I_PrecacheSounds(S_sfx, NUMSFX);
S_SetSfxVolume(sfxVolume);
diff --git a/src/heretic/s_sound.c b/src/heretic/s_sound.c
index 09f2032d..988dc039 100644
--- a/src/heretic/s_sound.c
+++ b/src/heretic/s_sound.c
@@ -516,6 +516,7 @@ void S_UpdateSounds(mobj_t * listener)
void S_Init(void)
{
+ I_SetOPLDriverVer(opl_v_old);
soundCurve = Z_Malloc(MAX_SND_DIST, PU_STATIC, NULL);
if (snd_Channels > 8)
{
diff --git a/src/hexen/s_sound.c b/src/hexen/s_sound.c
index b5af53c7..60666566 100644
--- a/src/hexen/s_sound.c
+++ b/src/hexen/s_sound.c
@@ -787,6 +787,7 @@ void S_UpdateSounds(mobj_t * listener)
void S_Init(void)
{
+ I_SetOPLDriverVer(opl_v_old);
SoundCurve = W_CacheLumpName("SNDCURVE", PU_STATIC);
// SoundCurve = Z_Malloc(MAX_SND_DIST, PU_STATIC, NULL);
diff --git a/src/i_oplmusic.c b/src/i_oplmusic.c
index a5910056..2df361e5 100644
--- a/src/i_oplmusic.c
+++ b/src/i_oplmusic.c
@@ -143,6 +143,9 @@ struct opl_voice_s
// The current volume (register value) that has been set for this channel.
unsigned int reg_volume;
+ // Priority.
+ unsigned int priority;
+
// Next in linked list; a voice is always either in the
// free list or the allocated list.
opl_voice_t *next;
@@ -294,6 +297,7 @@ static const unsigned int volume_mapping_table[] = {
124, 124, 125, 125, 126, 126, 127, 127
};
+opl_driver_ver_t opl_drv_ver = opl_v_new;
static boolean music_initialized = false;
//static boolean musicpaused = false;
@@ -311,6 +315,7 @@ static char (*percussion_names)[32];
static opl_voice_t voices[OPL_NUM_VOICES];
static opl_voice_t *voice_free_list;
static opl_voice_t *voice_alloced_list;
+static int voice_alloced_num;
// Track data for playing tracks:
@@ -391,6 +396,8 @@ static opl_voice_t *GetFreeVoice(void)
*rover = result;
result->next = NULL;
+ voice_alloced_num++;
+
return result;
}
@@ -410,6 +417,7 @@ static void RemoveVoiceFromAllocedList(opl_voice_t *voice)
{
*rover = voice->next;
voice->next = NULL;
+ voice_alloced_num--;
break;
}
@@ -419,13 +427,20 @@ static void RemoveVoiceFromAllocedList(opl_voice_t *voice)
// Release a voice back to the freelist.
+static void VoiceKeyOff(opl_voice_t *voice);
+
static void ReleaseVoice(opl_voice_t *voice)
{
opl_voice_t **rover;
+ opl_voice_t *next;
+ boolean doublev;
voice->channel = NULL;
voice->note = 0;
+ doublev = voice->current_instr_voice != 0;
+ next = voice->next;
+
// Remove from alloced list.
RemoveVoiceFromAllocedList(voice);
@@ -441,6 +456,12 @@ static void ReleaseVoice(opl_voice_t *voice)
*rover = voice;
voice->next = NULL;
+
+ if (next != NULL && doublev && opl_drv_ver == opl_v_old)
+ {
+ VoiceKeyOff(next);
+ ReleaseVoice(next);
+ }
}
// Load data to the specified operator
@@ -511,6 +532,11 @@ static void SetVoiceInstrument(opl_voice_t *voice,
// Hack to force a volume update.
voice->reg_volume = 999;
+
+ // Calculate voice priority.
+
+ voice->priority = 0x0f - (data->carrier.attack >> 4)
+ + 0x0f - (data->carrier.sustain & 0x0f);
}
static void SetVoiceVolume(opl_voice_t *voice, unsigned int volume)
@@ -638,8 +664,9 @@ static opl_channel_data_t *TrackChannelForEvent(opl_track_data_t *track,
static void KeyOffEvent(opl_track_data_t *track, midi_event_t *event)
{
opl_channel_data_t *channel;
+ opl_voice_t *rover;
+ opl_voice_t *prev;
unsigned int key;
- unsigned int i;
/*
printf("note off: channel %i, %i, %i\n",
@@ -654,15 +681,31 @@ static void KeyOffEvent(opl_track_data_t *track, midi_event_t *event)
// Turn off voices being used to play this key.
// If it is a double voice instrument there will be two.
- for (i = 0; i < OPL_NUM_VOICES; ++i)
+ rover = voice_alloced_list;
+ prev = NULL;
+
+ while (rover!=NULL)
{
- if (voices[i].channel == channel && voices[i].key == key)
+ if (rover->channel == channel && rover->key == key)
{
- VoiceKeyOff(&voices[i]);
+ VoiceKeyOff(rover);
// Finished with this voice now.
- ReleaseVoice(&voices[i]);
+ ReleaseVoice(rover);
+ if (prev == NULL)
+ {
+ rover = voice_alloced_list;
+ }
+ else
+ {
+ rover = prev->next;
+ }
+ }
+ else
+ {
+ prev = rover;
+ rover = rover->next;
}
}
}
@@ -701,6 +744,39 @@ static void ReplaceExistingVoice(void)
ReleaseVoice(result);
}
+static void ReplaceExistingVoiceOld(opl_channel_data_t *channel)
+{
+ opl_voice_t *rover;
+ opl_voice_t *result;
+ opl_voice_t *roverend;
+ int i;
+ int priority;
+
+ result = voice_alloced_list;
+
+ roverend = voice_alloced_list;
+
+ for (i = 0; i < voice_alloced_num - 3; i++)
+ {
+ roverend = roverend->next;
+ }
+
+ priority = 0x8000;
+
+ for (rover = voice_alloced_list; rover != roverend; rover = rover->next)
+ {
+ if (rover->priority < priority
+ && rover->channel >= channel)
+ {
+ priority = rover->priority;
+ result = rover;
+ }
+ }
+
+ VoiceKeyOff(result);
+ ReleaseVoice(result);
+}
+
static unsigned int FrequencyForVoice(opl_voice_t *voice)
{
@@ -854,6 +930,7 @@ static void KeyOnEvent(opl_track_data_t *track, midi_event_t *event)
genmidi_instr_t *instrument;
opl_channel_data_t *channel;
unsigned int note, key, volume;
+ boolean doublev;
/*
printf("note on: channel %i, %i, %i\n",
@@ -896,20 +973,45 @@ static void KeyOnEvent(opl_track_data_t *track, midi_event_t *event)
{
instrument = channel->instrument;
}
+ doublev = (SHORT(instrument->flags) & GENMIDI_FLAG_2VOICE) != 0;
- if (voice_free_list == NULL)
+ if (opl_drv_ver == opl_v_old)
{
- ReplaceExistingVoice();
- }
+ if (voice_alloced_num == OPL_NUM_VOICES)
+ {
+ ReplaceExistingVoiceOld(channel);
+ }
+ if (voice_alloced_num == OPL_NUM_VOICES - 1 && doublev)
+ {
+ ReplaceExistingVoiceOld(channel);
+ }
- // Find and program a voice for this instrument. If this
- // is a double voice instrument, we must do this twice.
+ // Find and program a voice for this instrument. If this
+ // is a double voice instrument, we must do this twice.
- VoiceKeyOn(channel, instrument, 0, note, key, volume);
+ if (doublev)
+ {
+ VoiceKeyOn(channel, instrument, 1, note, key, volume);
+ }
- if ((SHORT(instrument->flags) & GENMIDI_FLAG_2VOICE) != 0)
+ VoiceKeyOn(channel, instrument, 0, note, key, volume);
+ }
+ else
{
- VoiceKeyOn(channel, instrument, 1, note, key, volume);
+ if (voice_free_list == NULL)
+ {
+ ReplaceExistingVoice();
+ }
+
+ // Find and program a voice for this instrument. If this
+ // is a double voice instrument, we must do this twice.
+
+ VoiceKeyOn(channel, instrument, 0, note, key, volume);
+
+ if (doublev)
+ {
+ VoiceKeyOn(channel, instrument, 1, note, key, volume);
+ }
}
}
@@ -948,14 +1050,34 @@ static void SetChannelVolume(opl_channel_data_t *channel, unsigned int volume)
// Handler for the MIDI_CONTROLLER_ALL_NOTES_OFF channel event.
static void AllNotesOff(opl_channel_data_t *channel, unsigned int param)
{
- unsigned int i;
+ opl_voice_t *rover;
+ opl_voice_t *prev;
- for (i = 0; i < OPL_NUM_VOICES; ++i)
+ rover = voice_alloced_list;
+ prev = NULL;
+
+ while (rover!=NULL)
{
- if (voices[i].channel == channel)
+ if (rover->channel == channel)
{
- VoiceKeyOff(&voices[i]);
- ReleaseVoice(&voices[i]);
+ VoiceKeyOff(rover);
+
+ // Finished with this voice now.
+
+ ReleaseVoice(rover);
+ if (prev == NULL)
+ {
+ rover = voice_alloced_list;
+ }
+ else
+ {
+ rover = prev->next;
+ }
+ }
+ else
+ {
+ prev = rover;
+ rover = rover->next;
}
}
}
diff --git a/src/i_sound.c b/src/i_sound.c
index e70b9bc7..6763fa37 100644
--- a/src/i_sound.c
+++ b/src/i_sound.c
@@ -66,6 +66,7 @@ extern music_module_t music_opl_module;
// For OPL module:
+extern opl_driver_ver_t opl_drv_ver;
extern int opl_io_port;
// For native music module:
@@ -472,3 +473,8 @@ void I_BindSoundVariables(void)
#endif
}
+void I_SetOPLDriverVer(opl_driver_ver_t ver)
+{
+ opl_drv_ver = ver;
+}
+
diff --git a/src/i_sound.h b/src/i_sound.h
index e429e960..a240c48b 100644
--- a/src/i_sound.h
+++ b/src/i_sound.h
@@ -234,5 +234,12 @@ extern char *snd_musiccmd;
void I_BindSoundVariables(void);
+typedef enum {
+ opl_v_old, // hexen heretic
+ opl_v_new // doom strife
+} opl_driver_ver_t;
+
+void I_SetOPLDriverVer(opl_driver_ver_t ver);
+
#endif
diff --git a/src/strife/s_sound.c b/src/strife/s_sound.c
index d22f84e4..3f010ea1 100644
--- a/src/strife/s_sound.c
+++ b/src/strife/s_sound.c
@@ -137,6 +137,7 @@ void S_Init(int sfxVolume, int musicVolume, int voiceVolume)
{
int i;
+ I_SetOPLDriverVer(opl_v_new);
I_PrecacheSounds(S_sfx, NUMSFX);
S_SetSfxVolume(sfxVolume);