mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-27 16:54:52 +01:00
use mixer for title music, crowd noise, rain/thunder, and sound effects
This commit is contained in:
@@ -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()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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; };
|
||||
|
||||
|
||||
Reference in New Issue
Block a user