mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-15 19:13:07 +01:00
Merge pull request #25520 from Gymnasiast/small-audio-cleanup
Small audio cleanup
This commit is contained in:
@@ -254,7 +254,7 @@ namespace OpenRCT2::Audio
|
||||
size_t readLen = _source->Read(dst, _offset, bytesToRead);
|
||||
if (readLen > 0)
|
||||
{
|
||||
dst = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dst) + readLen);
|
||||
dst = static_cast<void*>(static_cast<uint8_t*>(dst) + readLen);
|
||||
bytesToRead -= readLen;
|
||||
bytesRead += readLen;
|
||||
_offset += readLen;
|
||||
|
||||
@@ -40,9 +40,9 @@ void AudioMixer::Init(const char* device)
|
||||
|
||||
SDL_AudioSpec have;
|
||||
_deviceId = SDL_OpenAudioDevice(device, 0, &want, &have, 0);
|
||||
_format.format = have.format;
|
||||
_format.channels = have.channels;
|
||||
_format.freq = have.freq;
|
||||
_outputFormat.format = have.format;
|
||||
_outputFormat.channels = have.channels;
|
||||
_outputFormat.freq = have.freq;
|
||||
|
||||
SDL_PauseAudioDevice(_deviceId, 0);
|
||||
}
|
||||
@@ -121,7 +121,7 @@ void AudioMixer::RemoveReleasedSources()
|
||||
|
||||
const AudioFormat& AudioMixer::GetFormat() const
|
||||
{
|
||||
return _format;
|
||||
return _outputFormat;
|
||||
}
|
||||
|
||||
void AudioMixer::GetNextAudioChunk(uint8_t* dst, size_t length)
|
||||
@@ -173,10 +173,10 @@ void AudioMixer::UpdateAdjustedSound()
|
||||
|
||||
void AudioMixer::MixChannel(ISDLAudioChannel* channel, uint8_t* data, size_t length)
|
||||
{
|
||||
int32_t byteRate = _format.GetByteRate();
|
||||
auto numSamples = static_cast<int32_t>(length / byteRate);
|
||||
int32_t outputByteRate = _outputFormat.GetByteRate();
|
||||
auto numSamples = static_cast<int32_t>(length / outputByteRate);
|
||||
double rate = 1;
|
||||
if (_format.format == AUDIO_S16SYS)
|
||||
if (_outputFormat.format == AUDIO_S16SYS)
|
||||
{
|
||||
rate = channel->GetRate();
|
||||
}
|
||||
@@ -185,11 +185,11 @@ void AudioMixer::MixChannel(ISDLAudioChannel* channel, uint8_t* data, size_t len
|
||||
SDL_AudioCVT cvt;
|
||||
cvt.len_ratio = 1;
|
||||
AudioFormat streamformat = channel->GetFormat();
|
||||
if (streamformat != _format)
|
||||
if (streamformat != _outputFormat)
|
||||
{
|
||||
if (SDL_BuildAudioCVT(
|
||||
&cvt, streamformat.format, streamformat.channels, streamformat.freq, _format.format, _format.channels,
|
||||
_format.freq)
|
||||
&cvt, streamformat.format, streamformat.channels, streamformat.freq, _outputFormat.format,
|
||||
_outputFormat.channels, _outputFormat.freq)
|
||||
== -1)
|
||||
{
|
||||
// Unable to convert channel data
|
||||
@@ -200,7 +200,7 @@ void AudioMixer::MixChannel(ISDLAudioChannel* channel, uint8_t* data, size_t len
|
||||
|
||||
// Read raw PCM from channel
|
||||
int32_t readSamples = numSamples * rate;
|
||||
auto readLength = static_cast<size_t>(readSamples / cvt.len_ratio) * byteRate;
|
||||
auto readLength = static_cast<size_t>(readSamples / cvt.len_ratio) * outputByteRate;
|
||||
_channelBuffer.resize(readLength);
|
||||
size_t bytesRead = channel->Read(_channelBuffer.data(), readLength);
|
||||
|
||||
@@ -228,43 +228,45 @@ void AudioMixer::MixChannel(ISDLAudioChannel* channel, uint8_t* data, size_t len
|
||||
// Apply effects
|
||||
if (rate != 1)
|
||||
{
|
||||
auto inRate = static_cast<int32_t>(bufferLen / byteRate);
|
||||
auto inRate = static_cast<int32_t>(bufferLen / outputByteRate);
|
||||
int32_t outRate = numSamples;
|
||||
if (bytesRead != readLength)
|
||||
{
|
||||
inRate = _format.freq;
|
||||
outRate = _format.freq * (1 / rate);
|
||||
inRate = _outputFormat.freq;
|
||||
outRate = _outputFormat.freq * (1 / rate);
|
||||
}
|
||||
_effectBuffer.resize(length);
|
||||
bufferLen = ApplyResample(channel, buffer, static_cast<int32_t>(bufferLen / byteRate), numSamples, inRate, outRate);
|
||||
bufferLen = ApplyResample(
|
||||
channel, buffer, static_cast<int32_t>(bufferLen / outputByteRate), numSamples, inRate, outRate);
|
||||
buffer = _effectBuffer.data();
|
||||
}
|
||||
|
||||
// Apply panning and volume
|
||||
ApplyPan(channel, buffer, bufferLen, byteRate);
|
||||
ApplyPan(channel, buffer, bufferLen, outputByteRate);
|
||||
int32_t mixVolume = ApplyVolume(channel, buffer, bufferLen);
|
||||
|
||||
// Finally mix on to destination buffer
|
||||
size_t dstLength = std::min(length, bufferLen);
|
||||
SDL_MixAudioFormat(data, static_cast<const uint8_t*>(buffer), _format.format, static_cast<uint32_t>(dstLength), mixVolume);
|
||||
SDL_MixAudioFormat(
|
||||
data, static_cast<const uint8_t*>(buffer), _outputFormat.format, static_cast<uint32_t>(dstLength), mixVolume);
|
||||
|
||||
channel->UpdateOldVolume();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resample the given buffer into _effectBuffer.
|
||||
* Assumes that srcBuffer is the same format as _format.
|
||||
* Assumes that srcBuffer is the same format as _outputFormat.
|
||||
*/
|
||||
size_t AudioMixer::ApplyResample(
|
||||
ISDLAudioChannel* channel, const void* srcBuffer, int32_t srcSamples, int32_t dstSamples, int32_t inRate, int32_t outRate)
|
||||
{
|
||||
int32_t byteRate = _format.GetByteRate();
|
||||
int32_t outputByteRate = _outputFormat.GetByteRate();
|
||||
|
||||
// Create resampler
|
||||
SpeexResamplerState* resampler = channel->GetResampler();
|
||||
if (resampler == nullptr)
|
||||
{
|
||||
resampler = speex_resampler_init(_format.channels, _format.freq, _format.freq, 0, nullptr);
|
||||
resampler = speex_resampler_init(_outputFormat.channels, _outputFormat.freq, _outputFormat.freq, 0, nullptr);
|
||||
channel->SetResampler(resampler);
|
||||
}
|
||||
speex_resampler_set_rate(resampler, inRate, outRate);
|
||||
@@ -275,14 +277,14 @@ size_t AudioMixer::ApplyResample(
|
||||
resampler, static_cast<const spx_int16_t*>(srcBuffer), &inLen, reinterpret_cast<spx_int16_t*>(_effectBuffer.data()),
|
||||
&outLen);
|
||||
|
||||
return outLen * byteRate;
|
||||
return outLen * outputByteRate;
|
||||
}
|
||||
|
||||
void AudioMixer::ApplyPan(const IAudioChannel* channel, void* buffer, size_t len, size_t sampleSize)
|
||||
{
|
||||
if (channel->GetPan() != 0.5f && _format.channels == 2)
|
||||
if (channel->GetPan() != 0.5f && _outputFormat.channels == 2)
|
||||
{
|
||||
switch (_format.format)
|
||||
switch (_outputFormat.format)
|
||||
{
|
||||
case AUDIO_S16SYS:
|
||||
EffectPanS16(channel, static_cast<int16_t*>(buffer), static_cast<int32_t>(len / sampleSize));
|
||||
@@ -331,8 +333,8 @@ int32_t AudioMixer::ApplyVolume(const IAudioChannel* channel, void* buffer, size
|
||||
mixVolume = kMixerVolumeMax;
|
||||
|
||||
// Fade between volume levels to smooth out sound and minimize clicks from sudden volume changes
|
||||
int32_t fadeLength = static_cast<int32_t>(len) / _format.BytesPerSample();
|
||||
switch (_format.format)
|
||||
int32_t fadeLength = static_cast<int32_t>(len) / _outputFormat.BytesPerSample();
|
||||
switch (_outputFormat.format)
|
||||
{
|
||||
case AUDIO_S16SYS:
|
||||
EffectFadeS16(static_cast<int16_t*>(buffer), fadeLength, startVolume, endVolume);
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace OpenRCT2::Audio
|
||||
std::vector<std::unique_ptr<SDLAudioSource>> _sources;
|
||||
|
||||
SDL_AudioDeviceID _deviceId = 0;
|
||||
AudioFormat _format = {};
|
||||
AudioFormat _outputFormat = {};
|
||||
std::list<std::shared_ptr<ISDLAudioChannel>> _channels;
|
||||
float _volume = 1.0f;
|
||||
float _adjustSoundVolume = 0.0f;
|
||||
@@ -67,7 +67,7 @@ namespace OpenRCT2::Audio
|
||||
|
||||
/**
|
||||
* Resample the given buffer into _effectBuffer.
|
||||
* Assumes that srcBuffer is the same format as _format.
|
||||
* Assumes that srcBuffer is the same format as _outputFormat.
|
||||
*/
|
||||
size_t ApplyResample(
|
||||
ISDLAudioChannel* channel, const void* srcBuffer, int32_t srcSamples, int32_t dstSamples, int32_t inRate,
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace OpenRCT2::Audio
|
||||
_currentOffset = offset;
|
||||
}
|
||||
|
||||
auto dst8 = reinterpret_cast<uint8_t*>(dst);
|
||||
auto dst8 = static_cast<uint8_t*>(dst);
|
||||
auto bytesRead = ReadFromDecodeBuffer(dst8, len);
|
||||
dst8 += bytesRead;
|
||||
if (bytesRead < len)
|
||||
@@ -171,7 +171,7 @@ namespace OpenRCT2::Audio
|
||||
static FLAC__StreamDecoderReadStatus FlacCallbackRead(
|
||||
const FLAC__StreamDecoder* decoder, FLAC__byte buffer[], size_t* bytes, void* clientData)
|
||||
{
|
||||
auto* self = reinterpret_cast<FlacAudioSource*>(clientData);
|
||||
auto* self = static_cast<FlacAudioSource*>(clientData);
|
||||
if (*bytes > 0)
|
||||
{
|
||||
*bytes = SDL_RWread(self->_rw, buffer, sizeof(FLAC__byte), *bytes);
|
||||
@@ -193,7 +193,7 @@ namespace OpenRCT2::Audio
|
||||
static FLAC__StreamDecoderSeekStatus FlacCallbackSeek(
|
||||
const FLAC__StreamDecoder* decoder, FLAC__uint64 absoluteByteOffset, void* clientData)
|
||||
{
|
||||
auto* self = reinterpret_cast<FlacAudioSource*>(clientData);
|
||||
auto* self = static_cast<FlacAudioSource*>(clientData);
|
||||
if (SDL_RWseek(self->_rw, absoluteByteOffset, RW_SEEK_SET) < 0)
|
||||
{
|
||||
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
|
||||
@@ -207,7 +207,7 @@ namespace OpenRCT2::Audio
|
||||
static FLAC__StreamDecoderTellStatus FlacCallbackTell(
|
||||
const FLAC__StreamDecoder* decoder, FLAC__uint64* absoluteByteOffset, void* clientData)
|
||||
{
|
||||
auto* self = reinterpret_cast<FlacAudioSource*>(clientData);
|
||||
auto* self = static_cast<FlacAudioSource*>(clientData);
|
||||
auto pos = SDL_RWtell(self->_rw);
|
||||
if (pos < 0)
|
||||
{
|
||||
@@ -223,7 +223,7 @@ namespace OpenRCT2::Audio
|
||||
static FLAC__StreamDecoderLengthStatus FlacCallbackLength(
|
||||
const FLAC__StreamDecoder* decoder, FLAC__uint64* streamLength, void* clientData)
|
||||
{
|
||||
auto* self = reinterpret_cast<FlacAudioSource*>(clientData);
|
||||
auto* self = static_cast<FlacAudioSource*>(clientData);
|
||||
auto pos = SDL_RWtell(self->_rw);
|
||||
auto length = SDL_RWseek(self->_rw, 0, RW_SEEK_END);
|
||||
if (SDL_RWseek(self->_rw, pos, RW_SEEK_SET) != pos || length < 0)
|
||||
@@ -239,7 +239,7 @@ namespace OpenRCT2::Audio
|
||||
|
||||
static FLAC__bool FlacCallbackEof(const FLAC__StreamDecoder* decoder, void* clientData)
|
||||
{
|
||||
auto* self = reinterpret_cast<FlacAudioSource*>(clientData);
|
||||
auto* self = static_cast<FlacAudioSource*>(clientData);
|
||||
auto pos = SDL_RWtell(self->_rw);
|
||||
auto end = SDL_RWseek(self->_rw, 0, RW_SEEK_END);
|
||||
if (pos == end)
|
||||
@@ -256,7 +256,7 @@ namespace OpenRCT2::Audio
|
||||
static FLAC__StreamDecoderWriteStatus FlacCallbackWrite(
|
||||
const FLAC__StreamDecoder* decoder, const FLAC__Frame* frame, const FLAC__int32* const buffer[], void* clientData)
|
||||
{
|
||||
auto* self = reinterpret_cast<FlacAudioSource*>(clientData);
|
||||
auto* self = static_cast<FlacAudioSource*>(clientData);
|
||||
|
||||
// Determine sizes
|
||||
auto channels = self->_format.channels;
|
||||
@@ -301,7 +301,7 @@ namespace OpenRCT2::Audio
|
||||
static void FlacCallbackMetadata(
|
||||
const FLAC__StreamDecoder* decoder, const FLAC__StreamMetadata* metadata, void* clientData)
|
||||
{
|
||||
auto* self = reinterpret_cast<FlacAudioSource*>(clientData);
|
||||
auto* self = static_cast<FlacAudioSource*>(clientData);
|
||||
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
|
||||
{
|
||||
self->_bitsPerSample = metadata->data.stream_info.bits_per_sample;
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace OpenRCT2::Audio
|
||||
auto src = _data.data();
|
||||
if (src != nullptr)
|
||||
{
|
||||
std::copy_n(src + offset, bytesToRead, reinterpret_cast<uint8_t*>(dst));
|
||||
std::copy_n(src + offset, bytesToRead, static_cast<uint8_t*>(dst));
|
||||
}
|
||||
}
|
||||
return bytesToRead;
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace OpenRCT2::Audio
|
||||
}
|
||||
|
||||
auto readLen = static_cast<int64_t>(len);
|
||||
auto dst8 = reinterpret_cast<char*>(dst);
|
||||
auto dst8 = static_cast<char*>(dst);
|
||||
int64_t totalBytesRead{};
|
||||
int64_t bytesRead;
|
||||
do
|
||||
@@ -139,17 +139,17 @@ namespace OpenRCT2::Audio
|
||||
private:
|
||||
static size_t VorbisCallbackRead(void* ptr, size_t size, size_t nmemb, void* datasource)
|
||||
{
|
||||
return SDL_RWread(reinterpret_cast<SDL_RWops*>(datasource), ptr, size, nmemb);
|
||||
return SDL_RWread(static_cast<SDL_RWops*>(datasource), ptr, size, nmemb);
|
||||
}
|
||||
|
||||
static int VorbisCallbackSeek(void* datasource, ogg_int64_t offset, int whence)
|
||||
{
|
||||
return (SDL_RWseek(reinterpret_cast<SDL_RWops*>(datasource), offset, whence) < 0) ? -1 : 0;
|
||||
return (SDL_RWseek(static_cast<SDL_RWops*>(datasource), offset, whence) < 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
static long VorbisCallbackTell(void* datasource)
|
||||
{
|
||||
return static_cast<long>(SDL_RWtell(reinterpret_cast<SDL_RWops*>(datasource)));
|
||||
return static_cast<long>(SDL_RWtell(static_cast<SDL_RWops*>(datasource)));
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user