diff options
-rw-r--r-- | src/doom/s_sound.c | 1 | ||||
-rw-r--r-- | src/heretic/s_sound.c | 1 | ||||
-rw-r--r-- | src/hexen/s_sound.c | 1 | ||||
-rw-r--r-- | src/i_oplmusic.c | 158 | ||||
-rw-r--r-- | src/i_sound.c | 6 | ||||
-rw-r--r-- | src/i_sound.h | 7 | ||||
-rw-r--r-- | src/strife/s_sound.c | 1 |
7 files changed, 157 insertions, 18 deletions
diff --git a/src/doom/s_sound.c b/src/doom/s_sound.c index f6d8be13..5a97a2f6 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 c02f1941..c3e4df27 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 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: @@ -390,6 +395,8 @@ static opl_voice_t *GetFreeVoice(void) *rover = result; result->next = NULL; + voice_alloced_num++; + return result; } @@ -409,6 +416,7 @@ static void RemoveVoiceFromAllocedList(opl_voice_t *voice) { *rover = voice->next; voice->next = NULL; + voice_alloced_num--; break; } @@ -418,13 +426,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); @@ -440,6 +455,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 @@ -510,6 +531,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) @@ -634,8 +660,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", @@ -650,15 +677,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; } } } @@ -696,6 +739,39 @@ static void ReplaceExistingVoice() 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) { @@ -849,6 +925,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", @@ -891,20 +968,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); + } } } @@ -943,14 +1045,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..eac21307 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 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 ver) +{ + opl_drv_ver = ver; +} + diff --git a/src/i_sound.h b/src/i_sound.h index e429e960..0808ac87 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; + +void I_SetOPLDriverVer(opl_driver_ver 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); |