OpenRCT2/src/audio/mixer.cpp

621 lines
15 KiB
C++
Raw Normal View History

/*****************************************************************************
* Copyright (c) 2014 Ted John
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* This file is part of OpenRCT2.
*
* OpenRCT2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include <math.h>
#include <SDL.h>
extern "C" {
#include "../config.h"
#include "../platform/platform.h"
#include "audio.h"
}
#include "mixer.h"
Mixer gMixer;
Sample::Sample()
{
data = 0;
length = 0;
issdlwav = false;
}
Sample::~Sample()
{
Unload();
}
bool Sample::Load(const char* filename)
{
Unload();
SDL_RWops* rw = SDL_RWFromFile(filename, "rb");
if (!rw) {
SDL_RWclose(rw);
return false;
}
SDL_AudioSpec audiospec;
memset(&audiospec, 0, sizeof(audiospec));
SDL_AudioSpec* spec = SDL_LoadWAV_RW(rw, false, &audiospec, &data, (Uint32*)&length);
if (spec != NULL) {
format.freq = spec->freq;
format.format = spec->format;
format.channels = spec->channels;
issdlwav = true;
} else {
return false;
}
return true;
}
bool Sample::LoadCSS1(const char* filename, unsigned int offset)
{
Unload();
SDL_RWops* rw = SDL_RWFromFile(filename, "rb");
if (!rw) {
return false;
}
Uint32 numsounds;
SDL_RWread(rw, &numsounds, sizeof(numsounds), 1);
if (offset > numsounds) {
SDL_RWclose(rw);
return false;
}
SDL_RWseek(rw, offset * 4, RW_SEEK_CUR);
Uint32 soundoffset;
SDL_RWread(rw, &soundoffset, sizeof(soundoffset), 1);
SDL_RWseek(rw, soundoffset, RW_SEEK_SET);
Uint32 soundsize;
SDL_RWread(rw, &soundsize, sizeof(soundsize), 1);
length = soundsize;
WAVEFORMATEX waveformat;
SDL_RWread(rw, &waveformat, sizeof(waveformat), 1);
format.freq = waveformat.nSamplesPerSec;
format.format = AUDIO_S16LSB;
format.channels = waveformat.nChannels;
data = new uint8[length];
SDL_RWread(rw, data, length, 1);
SDL_RWclose(rw);
return true;
}
void Sample::Unload()
{
if (data) {
if (issdlwav) {
SDL_FreeWAV(data);
} else {
delete[] data;
}
data = 0;
}
issdlwav = false;
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){
SDL_AudioCVT cvt;
if (SDL_BuildAudioCVT(&cvt, Sample::format.format, Sample::format.channels, Sample::format.freq, format.format, format.channels, format.freq) < 0) {
return false;
}
cvt.len = length;
cvt.buf = (Uint8*)new uint8[cvt.len * cvt.len_mult];
memcpy(cvt.buf, data, length);
if (SDL_ConvertAudio(&cvt) < 0) {
delete[] cvt.buf;
return false;
}
Unload();
data = cvt.buf;
length = cvt.len_cvt;
Sample::format = format;
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
return true;
}
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
return false;
}
const uint8* Sample::Data()
{
return data;
}
unsigned long Sample::Length()
{
return length;
}
Stream::Stream()
{
sourcetype = SOURCE_NONE;
}
unsigned long Stream::GetSome(unsigned long offset, const uint8** data, unsigned long length)
{
unsigned long size = length;
switch(sourcetype) {
case SOURCE_SAMPLE:
if (offset >= sample->Length()) {
return 0;
}
if (offset + length > sample->Length()) {
size = sample->Length() - offset;
}
*data = &sample->Data()[offset];
return size;
break;
}
return 0;
}
unsigned long Stream::Length()
{
switch(sourcetype) {
case SOURCE_SAMPLE:
return sample->Length();
break;
}
return 0;
}
void Stream::SetSource_Sample(Sample& sample)
{
sourcetype = SOURCE_SAMPLE;
Stream::sample = &sample;
}
const AudioFormat* Stream::Format()
{
switch(sourcetype) {
case SOURCE_SAMPLE:
return &sample->format;
break;
}
return 0;
}
Channel::Channel()
{
resampler = 0;
SetRate(1);
SetVolume(SDL_MIX_MAXVOLUME);
oldvolume = 0;
SetPan(0.5f);
done = true;
stopping = false;
}
Channel::~Channel()
{
if (resampler) {
speex_resampler_destroy(resampler);
resampler = 0;
}
}
2014-09-19 04:48:04 +02:00
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)
{
Channel::rate = rate;
if (Channel::rate < 0.001) {
Channel::rate = 0.001;
}
}
void Channel::SetVolume(int volume)
{
Channel::volume = volume;
if (volume > SDL_MIX_MAXVOLUME) {
Channel::volume = SDL_MIX_MAXVOLUME;
}
if (volume < 0) {
Channel::volume = 0;
}
}
void Channel::SetPan(float pan)
{
Channel::pan = pan;
if (pan > 1) {
Channel::pan = 1;
}
if (pan < 0) {
Channel::pan = 0;
}
volume_l = (float)sin((1.0 - Channel::pan) * M_PI / 2.0);
volume_r = (float)sin(Channel::pan * M_PI / 2.0);
}
bool Channel::IsPlaying()
{
return !done;
}
void Mixer::Init(const char* device)
{
Close();
SDL_AudioSpec want, have;
SDL_zero(want);
want.freq = 44100;
want.format = AUDIO_S16SYS;
want.channels = 2;
want.samples = 1024;
want.callback = Callback;
want.userdata = this;
deviceid = SDL_OpenAudioDevice(device, 0, &want, &have, 0);
format.format = have.format;
format.channels = have.channels;
format.freq = have.freq;
const char* filename = get_file_path(PATH_ID_CSS1);
for (int i = 0; i < SOUND_MAXID; i++) {
css1samples[i].LoadCSS1(filename, i);
css1samples[i].Convert(format); // convert to audio output format, saves some cpu usage but requires a bit more memory, optional
css1streams[i].SetSource_Sample(css1samples[i]);
}
effectbuffer = new uint8[(have.samples * format.BytesPerSample() * format.channels) + 200];
SDL_PauseAudioDevice(deviceid, 0);
}
void Mixer::Close()
{
2014-10-07 20:16:17 +02:00
Lock();
while (channels.begin() != channels.end()) {
delete *(channels.begin());
channels.erase(channels.begin());
2014-10-07 20:16:17 +02:00
}
Unlock();
SDL_CloseAudioDevice(deviceid);
delete[] effectbuffer;
}
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
void Mixer::Lock()
{
SDL_LockAudioDevice(deviceid);
}
void Mixer::Unlock()
{
SDL_UnlockAudioDevice(deviceid);
}
Channel* Mixer::Play(Stream& stream, int loop, bool deleteondone)
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
{
Lock();
Channel* newchannel = new (std::nothrow) Channel();
if (newchannel) {
newchannel->Play(stream, loop);
newchannel->deleteondone = deleteondone;
newchannel->stopping = false;
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
channels.push_back(newchannel);
}
Unlock();
return newchannel;
}
void Mixer::Stop(Channel& channel)
{
Lock();
channel.stopping = true;
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
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);
std::list<Channel*>::iterator i = mixer->channels.begin();
while (i != mixer->channels.end()) {
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
mixer->MixChannel(*(*i), stream, length);
if (((*i)->done && (*i)->deleteondone) || (*i)->stopping) {
delete (*i);
i = mixer->channels.erase(i);
} else {
i++;
}
}
}
void Mixer::MixChannel(Channel& channel, uint8* data, int length)
{
if (channel.stream && !channel.done) {
AudioFormat channelformat = *channel.stream->Format();
int loaded = 0;
SDL_AudioCVT cvt;
cvt.len_ratio = 1;
do {
int samplesize = format.channels * format.BytesPerSample();
int samples = length / samplesize;
int samplesloaded = loaded / samplesize;
2014-10-07 20:16:17 +02:00
double rate = 1;
if (format.format == AUDIO_S16SYS) {
rate = channel.rate;
}
int samplestoread = (int)ceil((samples - samplesloaded) * rate);
int lengthloaded = 0;
if (channel.offset < channel.stream->Length()) {
bool mustconvert = false;
if (MustConvert(*channel.stream)) {
if (SDL_BuildAudioCVT(&cvt, channelformat.format, channelformat.channels, channelformat.freq, Mixer::format.format, Mixer::format.channels, Mixer::format.freq) == -1) {
break;
}
mustconvert = true;
}
const uint8* datastream = 0;
int readfromstream = (channel.stream->GetSome(channel.offset, &datastream, (int)(((samplestoread) * samplesize) / cvt.len_ratio)) / channelformat.BytesPerSample()) * channelformat.BytesPerSample();
if (readfromstream == 0) {
break;
}
int volume = channel.volume;
uint8* dataconverted = 0;
const uint8* tomix = 0;
if (mustconvert) {
if (Convert(cvt, datastream, readfromstream, &dataconverted)) {
tomix = dataconverted;
lengthloaded = (cvt.len_cvt / samplesize) * samplesize;
} else {
break;
}
} else {
tomix = datastream;
lengthloaded = readfromstream;
}
bool effectbufferloaded = false;
2014-10-07 20:16:17 +02:00
if (rate != 1 && format.format == AUDIO_S16SYS) {
int in_len = (int)(ceil((double)lengthloaded / samplesize));
int out_len = samples + 20; // needs some extra, otherwise resampler sometimes doesn't process all the input samples
if (!channel.resampler) {
channel.resampler = speex_resampler_init(format.channels, format.freq, format.freq, 0, 0);
}
2014-10-07 20:16:17 +02:00
speex_resampler_set_rate(channel.resampler, format.freq, (int)(format.freq * (1 / rate)));
speex_resampler_process_interleaved_int(channel.resampler, (const spx_int16_t*)tomix, (spx_uint32_t*)&in_len, (spx_int16_t*)effectbuffer, (spx_uint32_t*)&out_len);
effectbufferloaded = true;
tomix = effectbuffer;
lengthloaded = (out_len * samplesize);
}
if (channel.pan != 0.5f && format.channels == 2) {
if (!effectbufferloaded) {
memcpy(effectbuffer, tomix, lengthloaded);
effectbufferloaded = true;
tomix = effectbuffer;
}
switch (format.format) {
case AUDIO_S16SYS:
EffectPanS16(channel, (sint16*)effectbuffer, lengthloaded / samplesize);
break;
case AUDIO_U8:
EffectPanU8(channel, (uint8*)effectbuffer, lengthloaded / samplesize);
2014-10-07 20:16:17 +02:00
break;
}
}
int mixlength = lengthloaded;
if (loaded + mixlength > length) {
mixlength = length - loaded;
}
int startvolume = channel.oldvolume;
int endvolume = channel.volume;
if (channel.stopping) {
endvolume = 0;
}
2014-10-16 04:02:56 +02:00
int mixvolume = volume;
if (startvolume != endvolume) {
// fade between volume levels to smooth out sound and minimize clicks from sudden volume changes
if (!effectbufferloaded) {
memcpy(effectbuffer, tomix, lengthloaded);
effectbufferloaded = true;
tomix = effectbuffer;
}
2014-10-16 04:02:56 +02:00
mixvolume = SDL_MIX_MAXVOLUME; // set to max since we are adjusting the volume ourselves
int fadelength = mixlength / format.BytesPerSample();
switch (format.format) {
case AUDIO_S16SYS:
EffectFadeS16((sint16*)effectbuffer, fadelength, startvolume, endvolume);
break;
case AUDIO_U8:
EffectFadeU8((uint8*)effectbuffer, fadelength, startvolume, endvolume);
break;
}
}
2014-10-16 04:02:56 +02:00
SDL_MixAudioFormat(&data[loaded], tomix, format.format, mixlength, mixvolume);
if (dataconverted) {
delete[] dataconverted;
}
channel.offset += readfromstream;
}
loaded += lengthloaded;
if (channel.loop != 0 && channel.offset >= channel.stream->Length()) {
if (channel.loop != -1) {
channel.loop--;
}
channel.offset = 0;
}
} while(loaded < length && channel.loop != 0 && !channel.stopping);
channel.oldvolume = channel.volume;
if (channel.loop == 0 && channel.offset >= channel.stream->Length()) {
channel.done = true;
}
}
}
void Mixer::EffectPanS16(Channel& channel, sint16* data, int length)
{
float left = channel.volume_l;
float right = channel.volume_r;
for (int i = 0; i < length * 2; i += 2) {
data[i] = (sint16)(data[i] * left);
data[i + 1] = (sint16)(data[i + 1] * right);
}
}
void Mixer::EffectPanU8(Channel& channel, uint8* data, int length)
{
float left = channel.volume_l;
float right = channel.volume_r;
for (int i = 0; i < length * 2; i += 2) {
data[i] = (uint8)(data[i] * left);
data[i + 1] = (uint8)(data[i + 1] * right);
}
}
void Mixer::EffectFadeS16(sint16* data, int length, int startvolume, int endvolume)
{
float startvolume_f = (float)startvolume / SDL_MIX_MAXVOLUME;
float endvolume_f = (float)endvolume / SDL_MIX_MAXVOLUME;
for (int i = 0; i < length; i++) {
float t = (float)i / length;
data[i] = (sint16)(data[i] * ((1 - t) * startvolume_f + t * endvolume_f));
}
}
void Mixer::EffectFadeU8(uint8* data, int length, int startvolume, int endvolume)
{
float startvolume_f = (float)startvolume / SDL_MIX_MAXVOLUME;
float endvolume_f = (float)endvolume / SDL_MIX_MAXVOLUME;
for (int i = 0; i < length; i++) {
float t = (float)i / length;
data[i] = (uint8)(data[i] * ((1 - t) * startvolume_f + t * endvolume_f));
}
}
bool Mixer::MustConvert(Stream& stream)
{
const AudioFormat* streamformat = stream.Format();
if (!streamformat) {
return false;
}
if (streamformat->format != format.format || streamformat->channels != format.channels || streamformat->freq != format.freq) {
return true;
}
return false;
}
bool Mixer::Convert(SDL_AudioCVT& cvt, const uint8* data, unsigned long length, uint8** dataout)
{
if (length == 0 || cvt.len_mult == 0) {
return false;
}
cvt.len = length;
cvt.buf = (Uint8*)new uint8[cvt.len * cvt.len_mult];
memcpy(cvt.buf, data, length);
if (SDL_ConvertAudio(&cvt) < 0) {
delete[] cvt.buf;
return false;
}
*dataout = cvt.buf;
return true;
}
void Mixer_Init(const char* device)
{
gMixer.Init(device);
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
}
void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate, int deleteondone)
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
{
if (id >= SOUND_MAXID) {
return 0;
}
gMixer.Lock();
Channel* channel = gMixer.Play(gMixer.css1streams[id], loop, deleteondone != 0);
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
if (channel) {
channel->SetVolume(volume);
channel->SetPan(pan);
channel->SetRate(rate);
}
gMixer.Unlock();
return channel;
}
void Mixer_Stop_Channel(void* channel)
{
gMixer.Stop(*(Channel*)channel);
}
void Mixer_Channel_Volume(void* channel, int volume)
{
2014-10-07 20:16:17 +02:00
gMixer.Lock();
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
((Channel*)channel)->SetVolume(volume);
2014-10-07 20:16:17 +02:00
gMixer.Unlock();
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
}
void Mixer_Channel_Pan(void* channel, float pan)
{
2014-10-07 20:16:17 +02:00
gMixer.Lock();
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
((Channel*)channel)->SetPan(pan);
2014-10-07 20:16:17 +02:00
gMixer.Unlock();
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
}
void Mixer_Channel_Rate(void* channel, double rate)
{
2014-10-07 20:16:17 +02:00
gMixer.Lock();
vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2 vehicle sounds now using Mixer Fixed bug that caused widgets to miss draw. Fix #335 Merge pull request #505 from duncanspumpkin/gfx_rect Fixed bug that caused widgets to miss draw. fix #506 Paths can no longer be placed Merge branch 'master' of https://github.com/IntelOrca/OpenRCT2 Merge branch 'master' of https://github.com/zsilencer/OpenRCT2
2014-10-07 04:21:55 +02:00
((Channel*)channel)->SetRate(rate);
2014-10-07 20:16:17 +02:00
gMixer.Unlock();
}
int Mixer_Channel_IsPlaying(void* channel)
{
return ((Channel*)channel)->IsPlaying();
}
2014-10-08 20:15:16 +02:00
void* Mixer_Play_Music(int pathid)
{
2014-10-08 20:15:16 +02:00
if (gMixer.LoadMusic(pathid)) {
return gMixer.Play(gMixer.musicstreams[pathid], MIXER_LOOP_INFINITE, false);
}
2014-10-08 20:15:16 +02:00
return 0;
}