Merge pull request #510 from zsilencer/master

use mixer for title music, crowd noise, rain/thunder, and sound effects
This commit is contained in:
Ted John 2014-10-08 07:23:26 +01:00
commit b20a7a6250
8 changed files with 160 additions and 25 deletions

View File

@ -27,12 +27,14 @@
#include "../world/map.h"
#include "../world/sprite.h"
#include "audio.h"
#include "mixer.h"
int gAudioDeviceCount;
audio_device *gAudioDevices = NULL;
rct_vehicle_sound gVehicleSoundList[AUDIO_MAX_VEHICLE_SOUNDS];
rct_vehicle_sound_params gVehicleSoundParamsList[AUDIO_MAX_VEHICLE_SOUNDS];
rct_vehicle_sound_params *gVehicleSoundParamsListEnd;
void* gMusicChannels[4];
void audio_init(int i)
{
@ -166,7 +168,7 @@ void audio_close()
{
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) != -1) {
stop_other_sounds();
stop_peep_sounds();
stop_crowd_sound();
stop_title_music();
if (RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0)) {
stop_ride_music();
@ -1279,13 +1281,16 @@ int sound_play_panned(int sound_id, int ebx, sint16 x, sint16 y, sint16 z)
if (!RCT2_GLOBAL(0x009AAC6D, uint8)) {
pan = 0;
}
#ifdef USE_MIXER
Mixer_Play_Effect(sound_id, MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), 1, 1);
#else
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_prepare(sound_id, &other_sound->sound, 1, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint32));
RCT2_GLOBAL(0x014241BC, uint32) = 0;
RCT2_GLOBAL(0x014241BC, uint32) = 1;
result = sound_play(&other_sound->sound, 0, volume, pan, 0);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
#endif
}
return result;
}
@ -1330,6 +1335,9 @@ void start_title_music()
{
if ((RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0)) && RCT2_GLOBAL(0x009AF59D, uint8) & 1 && RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1) {
if (!RCT2_GLOBAL(0x009AF600, uint8)) {
#ifdef USE_MIXER
gMusicChannels[3] = Mixer_Play_Music(gMusicChannels[3], PATH_ID_CSS17);
#else
RCT2_GLOBAL(0x014241BC, uint32) = 1;
int result = sound_channel_load_file2(3, (char*)get_file_path(PATH_ID_CSS17), 0);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
@ -1338,6 +1346,7 @@ void start_title_music()
sound_channel_play(3, 1, 0, 0, 0);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
}
#endif
RCT2_GLOBAL(0x009AF600, uint8) = 1;
}
} else {
@ -1605,7 +1614,7 @@ void pause_sounds()
stop_other_sounds();
stop_vehicle_sounds();
stop_ride_music();
stop_peep_sounds();
stop_crowd_sound();
}
g_sounds_disabled = 1;
}
@ -1695,13 +1704,20 @@ void stop_ride_music()
*
* rct2: 0x006BD07F
*/
void stop_peep_sounds()
void stop_crowd_sound()
{
if ((RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0))) {
if (RCT2_GLOBAL(0x009AF5FC, uint32) != 1) {
#ifdef USE_MIXER
if (gMusicChannels[2]) {
Mixer_Stop_Channel(gMusicChannels[2]);
gMusicChannels[2] = 0;
}
#else
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_channel_stop(2);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
#endif
RCT2_GLOBAL(0x009AF5FC, uint32) = 1;
}
}
@ -1715,9 +1731,16 @@ void stop_title_music()
{
if (RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0)) {
if (RCT2_GLOBAL(0x009AF600, uint8) != 0) {
#ifdef USE_MIXER
if (gMusicChannels[3]) {
Mixer_Stop_Channel(gMusicChannels[3]);
gMusicChannels[3] = 0;
}
#else
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_channel_stop(3);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
#endif
}
}
RCT2_GLOBAL(0x009AF600, uint8) = 0;
@ -1794,7 +1817,7 @@ void sub_6BC348()
*/
void sub_6BC6D8()
{
int edi;
rct_music_info* edi;
int ebx;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)) {
if ((RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0))) {
@ -1810,7 +1833,7 @@ void sub_6BC6D8()
v8++;
if (v9 >= music_info->volume) {
v9 = music_info->volume;
edi = (int)music_info;
edi = music_info;
}
}
}
@ -1819,7 +1842,7 @@ void sub_6BC6D8()
if (v8 <= 1) {
break;
}
edi = -1;
edi->id = -1;
}
while (1) {
@ -1831,7 +1854,7 @@ void sub_6BC6D8()
v8++;
if (v9 >= music_info->volume) {
v9 = music_info->volume;
edi = (int)music_info;
edi = music_info;
}
}
music_info++;
@ -1839,9 +1862,8 @@ void sub_6BC6D8()
if (v8 <= 2) {
break;
}
edi = -1;
edi->id = -1;
}
rct_music_info2* music_info2 = &RCT2_GLOBAL(0x009AF46C, rct_music_info2);
int channel = 0;
do {
@ -1922,9 +1944,7 @@ void sub_6BC6D8()
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) = 0;
}
}
return;
}
}
@ -1949,7 +1969,6 @@ void sub_6BC6D8()
}
}
}
}
}

View File

@ -149,6 +149,7 @@ typedef struct {
extern rct_vehicle_sound gVehicleSoundList[AUDIO_MAX_VEHICLE_SOUNDS];
extern rct_vehicle_sound_params gVehicleSoundParamsList[AUDIO_MAX_VEHICLE_SOUNDS];
extern rct_vehicle_sound_params *gVehicleSoundParamsListEnd;
extern void* gMusicChannels[4];
int get_dsound_devices();
int dsound_create_primary_buffer(int a, int device, int channels, int samples, int bits);
@ -193,7 +194,7 @@ void stop_completed_sounds();
void stop_other_sounds();
void stop_vehicle_sounds();
void stop_ride_music();
void stop_peep_sounds();
void stop_crowd_sound();
void stop_title_music();
void start_title_music();
void unpause_sounds();

View File

@ -109,6 +109,11 @@ void Sample::Unload()
length = 0;
}
bool Sample::Loaded()
{
return data != 0;
}
bool Sample::Convert(AudioFormat format)
{
if(Sample::format.format != format.format || Sample::format.channels != format.channels || Sample::format.freq != format.freq){
@ -193,9 +198,11 @@ const AudioFormat* Stream::Format()
Channel::Channel()
{
rate = 1;
resampler = 0;
SetRate(1);
SetVolume(SDL_MIX_MAXVOLUME);
SetPan(0.5f);
done = true;
}
Channel::~Channel()
@ -211,6 +218,7 @@ void Channel::Play(Stream& stream, int loop = MIXER_LOOP_NONE)
Channel::stream = &stream;
Channel::loop = loop;
offset = 0;
done = false;
}
void Channel::SetRate(double rate)
@ -245,6 +253,11 @@ void Channel::SetPan(float pan)
volume_r = (float)sin(Channel::pan * M_PI / 2.0);
}
bool Channel::IsPlaying()
{
return !done;
}
void Mixer::Init(const char* device)
{
Close();
@ -291,12 +304,13 @@ void Mixer::Unlock()
SDL_UnlockAudioDevice(deviceid);
}
Channel* Mixer::Play(Stream& stream, int loop)
Channel* Mixer::Play(Stream& stream, int loop, bool deleteondone)
{
Lock();
Channel* newchannel = new (std::nothrow) Channel();
if (newchannel) {
newchannel->Play(stream, loop);
newchannel->deleteondone = deleteondone;
channels.push_back(newchannel);
}
Unlock();
@ -311,18 +325,39 @@ void Mixer::Stop(Channel& channel)
Unlock();
}
bool Mixer::LoadMusic(int pathid)
{
if (pathid >= PATH_ID_END) {
return false;
}
if (!musicsamples[pathid].Loaded()) {
const char* filename = get_file_path(pathid);
musicstreams[pathid].SetSource_Sample(musicsamples[pathid]);
return musicsamples[pathid].Load(filename);
} else {
return true;
}
}
void SDLCALL Mixer::Callback(void* arg, uint8* stream, int length)
{
Mixer* mixer = (Mixer*)arg;
memset(stream, 0, length);
for (std::list<Channel*>::iterator i = mixer->channels.begin(); i != mixer->channels.end(); i++){
std::list<Channel*>::iterator i = mixer->channels.begin();
while (i != mixer->channels.end()) {
mixer->MixChannel(*(*i), stream, length);
if ((*i)->done && (*i)->deleteondone) {
delete (*i);
i = mixer->channels.erase(i);
} else {
i++;
}
}
}
void Mixer::MixChannel(Channel& channel, uint8* data, int length)
{
if (channel.stream) {
if (channel.stream && !channel.done) {
if (!channel.resampler) {
channel.resampler = speex_resampler_init(format.channels, format.freq, format.freq, 0, 0);
}
@ -422,6 +457,9 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length)
channel.offset = 0;
}
} while(loaded < length && channel.loop != 0);
if (channel.loop == 0 && channel.offset >= channel.stream->Length()) {
channel.done = true;
}
}
}
@ -478,13 +516,13 @@ void Mixer_Init(const char* device)
gMixer.Init(device);
}
void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate)
void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate, int deleteondone)
{
if (id >= SOUND_MAXID) {
return 0;
}
gMixer.Lock();
Channel* channel = gMixer.Play(gMixer.css1streams[id], loop);
Channel* channel = gMixer.Play(gMixer.css1streams[id], loop, deleteondone != 0);
if (channel) {
channel->SetVolume(volume);
channel->SetPan(pan);
@ -518,4 +556,17 @@ void Mixer_Channel_Rate(void* channel, double rate)
gMixer.Lock();
((Channel*)channel)->SetRate(rate);
gMixer.Unlock();
}
int Mixer_Channel_IsPlaying(void* channel)
{
return ((Channel*)channel)->IsPlaying();
}
void* Mixer_Play_Music(void* channel, int pathid)
{
if (!(Channel*)channel && gMixer.LoadMusic(pathid)) {
return gMixer.Play(gMixer.musicstreams[pathid], MIXER_LOOP_INFINITE, false);
}
return channel;
}

View File

@ -51,6 +51,7 @@ public:
bool Load(const char* filename);
bool LoadCSS1(const char* filename, unsigned int offset);
void Unload();
bool Loaded();
bool Convert(AudioFormat format);
const uint8* Data();
unsigned long Length();
@ -92,6 +93,7 @@ public:
void SetRate(double rate);
void SetVolume(int volume);
void SetPan(float pan);
bool IsPlaying();
friend class Mixer;
@ -102,6 +104,8 @@ private:
int volume;
float volume_l, volume_r;
float pan;
bool done;
bool deleteondone;
SpeexResamplerState* resampler;
Stream* stream;
};
@ -113,10 +117,12 @@ public:
void Close();
void Lock();
void Unlock();
Channel* Play(Stream& stream, int loop);
Channel* Play(Stream& stream, int loop, bool deleteondone);
void Stop(Channel& channel);
bool LoadMusic(int pathid);
Stream css1streams[SOUND_MAXID];
Stream musicstreams[PATH_ID_END];
private:
static void SDLCALL Callback(void* arg, uint8* data, int length);
@ -129,6 +135,7 @@ private:
AudioFormat format;
uint8* effectbuffer;
Sample css1samples[SOUND_MAXID];
Sample musicsamples[PATH_ID_END];
std::list<Channel*> channels;
};
@ -137,13 +144,15 @@ extern "C"
#endif
void Mixer_Init(const char* device);
void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate);
void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate, int deleteondone);
void Mixer_Stop_Channel(void* channel);
void Mixer_Channel_Volume(void* channel, int volume);
void Mixer_Channel_Pan(void* channel, float pan);
void Mixer_Channel_Rate(void* channel, double rate);
int Mixer_Channel_IsPlaying(void* channel);
void* Mixer_Play_Music(void* channel, int pathid);
static int DStoMixerVolume(int volume) { return (int)(SDL_MIX_MAXVOLUME * (pow(10, (float)volume / 2000))); };
static int DStoMixerVolume(int volume) { return (int)(SDL_MIX_MAXVOLUME * (SDL_pow(10, (float)volume / 2000))); };
static float DStoMixerPan(int pan) { return (((float)pan + -DSBPAN_LEFT) / DSBPAN_RIGHT) / 2; };
static double DStoMixerRate(int frequency) { return (double)frequency / 22050; };

View File

@ -21,6 +21,7 @@
#include <windows.h>
#include "../addresses.h"
#include "../audio/audio.h"
#include "../audio/mixer.h"
#include "../interface/window.h"
#include "../localisation/localisation.h"
#include "../management/news_item.h"
@ -376,14 +377,26 @@ void peep_update_crowd_noise()
// Check if crowd noise is already playing
if (RCT2_GLOBAL(0x009AF5FC, uint32) == 1) {
// Load and play crowd noise
#ifdef USE_MIXER
gMusicChannels[2] = Mixer_Play_Music(gMusicChannels[2], PATH_ID_CSS2);
if (gMusicChannels[2]) {
Mixer_Channel_Volume(gMusicChannels[2], DStoMixerVolume(volume));
RCT2_GLOBAL(0x009AF5FC, uint32) = volume;
}
#else
if (sound_channel_load_file2(2, (char*)get_file_path(PATH_ID_CSS2), 0)) {
sound_channel_play(2, 1, volume, 0, 0);
RCT2_GLOBAL(0x009AF5FC, uint32) = volume;
}
#endif
} else {
// Alter crowd noise volume
if (RCT2_GLOBAL(0x009AF5FC, uint32) != volume) {
#ifdef USE_MIXER
Mixer_Channel_Volume(gMusicChannels[2], DStoMixerVolume(volume));
#else
sound_channel_set_volume(2, volume);//RCT2_CALLPROC_2(0x00401AD3, int, int, 2, volume);
#endif
RCT2_GLOBAL(0x009AF5FC, uint32) = volume;
}
}

View File

@ -380,7 +380,7 @@ void vehicle_sounds_update()
pan = 0;
}
#ifdef USE_MIXER
vehicle_sound->sound1_channel = Mixer_Play_Effect(sprite->vehicle.sound1_id, looping ? MIXER_LOOP_INFINITE : MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), DStoMixerRate(frequency));
vehicle_sound->sound1_channel = Mixer_Play_Effect(sprite->vehicle.sound1_id, looping ? MIXER_LOOP_INFINITE : MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), DStoMixerRate(frequency), 0);
#else
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_play(&vehicle_sound->sound1, looping, volume, pan, frequency);
@ -481,7 +481,7 @@ void vehicle_sounds_update()
pan = 0;
}
#ifdef USE_MIXER
vehicle_sound->sound2_channel = Mixer_Play_Effect(sprite->vehicle.sound2_id, looping ? MIXER_LOOP_INFINITE : MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), DStoMixerRate(frequency));
vehicle_sound->sound2_channel = Mixer_Play_Effect(sprite->vehicle.sound2_id, looping ? MIXER_LOOP_INFINITE : MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), DStoMixerRate(frequency), 0);
#else
RCT2_GLOBAL(0x014241BC, uint32) = 1;
sound_play(&vehicle_sound->sound2, looping, volume, pan, frequency);

View File

@ -504,11 +504,13 @@ static void window_options_dropdown()
case WIDX_SOUND_DROPDOWN:
audio_init2(dropdownIndex);
if (dropdownIndex < gAudioDeviceCount) {
#ifdef USE_MIXER
int devicenum = dropdownIndex;
if (devicenum == 0) {
devicenum = 1;
}
Mixer_Init(gAudioDevices[devicenum].name);
#endif
}
/*#ifdef _MSC_VER
__asm movzx ax, dropdownIndex

View File

@ -20,6 +20,7 @@
#include "../addresses.h"
#include "../audio/audio.h"
#include "../audio/mixer.h"
#include "../drawing/drawing.h"
#include "../localisation/date.h"
#include "../scenario.h"
@ -52,8 +53,10 @@ static const rct_weather_transition* climate_transitions[4];
// Sound data
static int _rainVolume = 1;
static rct_sound _rainSoundInstance;
static void* _rainSoundChannel;
static unsigned int _lightningTimer, _thunderTimer;
static rct_sound _thunderSoundInstance[MAX_THUNDER_INSTANCES];
static void* _thunderSoundChannels[MAX_THUNDER_INSTANCES];
static int _thunderStatus[MAX_THUNDER_INSTANCES] = { THUNDER_STATUS_NULL, THUNDER_STATUS_NULL };
static unsigned int _thunderSoundId;
static int _thunderVolume;
@ -203,21 +206,43 @@ static void climate_update_rain_sound()
if (_climateCurrentWeatherEffect == 1 || _climateCurrentWeatherEffect == 2) {
if (_rainVolume == 1) {
// Start playing the rain sound
#ifdef USE_MIXER
_rainSoundChannel = Mixer_Play_Effect(SOUND_RAIN_1, MIXER_LOOP_INFINITE, DStoMixerVolume(-4000), 0.5f, 1, 0);
#else
if (sound_prepare(SOUND_RAIN_1, &_rainSoundInstance, 1, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint32)))
sound_play(&_rainSoundInstance, 1, -4000, 0, 0);
#endif
_rainVolume = -4000;
} else {
// Increase rain sound
_rainVolume = min(-1400, _rainVolume + 80);
#ifdef USE_MIXER
if (_rainSoundChannel) {
Mixer_Channel_Volume(_rainSoundChannel, DStoMixerVolume(_rainVolume));
}
#else
sound_set_volume(&_rainSoundInstance, _rainVolume);
#endif
}
} else if (_rainVolume != 1) {
// Decrease rain sound
_rainVolume -= 80;
if (_rainVolume > -4000) {
#ifdef USE_MIXER
if (_rainSoundChannel) {
Mixer_Channel_Volume(_rainSoundChannel, DStoMixerVolume(_rainVolume));
}
#else
sound_set_volume(&_rainSoundInstance, _rainVolume);
#endif
} else {
#ifdef USE_MIXER
if (_rainSoundChannel) {
Mixer_Stop_Channel(_rainSoundChannel);
}
#else
sound_stop(&_rainSoundInstance);
#endif
_rainVolume = 1;
}
}
@ -247,10 +272,17 @@ static void climate_update_thunder_sound()
if (_thunderStatus[i] == THUNDER_STATUS_NULL)
continue;
#ifdef USE_MIXER
if (!Mixer_Channel_IsPlaying(_thunderSoundChannels[i])) {
Mixer_Stop_Channel(_thunderSoundChannels[i]);
_thunderStatus[i] = THUNDER_STATUS_NULL;
}
#else
if (!sound_is_playing(&_thunderSoundInstance[i])) {
sound_stop(&_thunderSoundInstance[i]);
_thunderStatus[i] = THUNDER_STATUS_NULL;
}
#endif
}
}
@ -293,12 +325,20 @@ static void climate_update_thunder()
static int climate_play_thunder(int instanceIndex, int soundId, int volume, int pan)
{
#ifdef USE_MIXER
_thunderSoundChannels[instanceIndex] = Mixer_Play_Effect(soundId, MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), 1, 0);
if (_thunderSoundChannels[instanceIndex]) {
_thunderStatus[instanceIndex] = THUNDER_STATUS_PLAYING;
return 1;
}
#else
if (sound_prepare(soundId, &_thunderSoundInstance[instanceIndex], 1, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint32))) {
sound_play(&_thunderSoundInstance[instanceIndex], 0, volume, pan, 0);
_thunderStatus[instanceIndex] = THUNDER_STATUS_PLAYING;
return 1;
}
#endif
return 0;
}