From 71894fd76965199d8196492b47c0c060a1c9e891 Mon Sep 17 00:00:00 2001 From: wangqr Date: Sat, 2 Nov 2019 02:26:36 -0400 Subject: [PATCH] Fix bugs in ram audio provider There was some magic bit operations to calculate the cache block offsets. This only works when both bytes_per_sample and channels are power of 2. Originally the format is assumed to be int16 mono, which satisfies this requirement. However in case we use original audio data, the channels can be something not a power of 2 (e.g. for 5.1 channel audio the number of channels is 6). This will break the calculation. We rewrite the calculation, without using those bit operations. --- libaegisub/audio/provider_ram.cpp | 8 +++++--- src/audio_player_xaudio2.cpp | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libaegisub/audio/provider_ram.cpp b/libaegisub/audio/provider_ram.cpp index 6502f2508..29ae004b6 100644 --- a/libaegisub/audio/provider_ram.cpp +++ b/libaegisub/audio/provider_ram.cpp @@ -77,9 +77,11 @@ void RAMAudioProvider::FillBuffer(void *buf, int64_t start, int64_t count) const break; } - const size_t i = (start * bytes_per_sample * channels) >> CacheBits; - const int start_offset = (start * bytes_per_sample * channels) & (CacheBlockSize-1); - const int read_size = std::min(bytes_remaining, CacheBlockSize - start_offset); + const int64_t samples_per_block = CacheBlockSize / bytes_per_sample / channels; + + const size_t i = start / samples_per_block; + const int start_offset = (start % samples_per_block) * bytes_per_sample * channels; + const int read_size = std::min(bytes_remaining, samples_per_block * bytes_per_sample * channels - start_offset); memcpy(charbuf, &blockcache[i][start_offset], read_size); charbuf += read_size; diff --git a/src/audio_player_xaudio2.cpp b/src/audio_player_xaudio2.cpp index 3692ba679..9503b5704 100644 --- a/src/audio_player_xaudio2.cpp +++ b/src/audio_player_xaudio2.cpp @@ -472,7 +472,7 @@ XAudio2Thread::XAudio2Thread(agi::AudioProvider* provider, int WantedLatency, in , is_playing(CreateEvent(0, TRUE, FALSE, 0)) , error_happened(CreateEvent(0, FALSE, FALSE, 0)) , wanted_latency(WantedLatency) - , buffer_length(BufferLength) + , buffer_length(BufferLength < XAUDIO2_MAX_QUEUED_BUFFERS ? BufferLength : XAUDIO2_MAX_QUEUED_BUFFERS) , provider(provider) , buffer_occupied(BufferLength) {