From 994e50048a21755d84ef46a25c8b5f7919881cab Mon Sep 17 00:00:00 2001 From: Ristellise Date: Wed, 10 Aug 2022 21:23:56 +0800 Subject: [PATCH] Finish up XAudio with a round of bugfixes --- libaegisub/audio/provider.cpp | 5 ++--- libaegisub/audio/provider_lock.cpp | 5 +++++ libaegisub/audio/provider_ram.cpp | 6 +++--- src/audio_provider_ffmpegsource.cpp | 13 ++++++++----- src/audio_renderer_spectrum.cpp | 4 ++-- src/audio_renderer_waveform.cpp | 2 +- 6 files changed, 21 insertions(+), 14 deletions(-) diff --git a/libaegisub/audio/provider.cpp b/libaegisub/audio/provider.cpp index b7ad7847c..0abb67eeb 100644 --- a/libaegisub/audio/provider.cpp +++ b/libaegisub/audio/provider.cpp @@ -73,7 +73,6 @@ public: } namespace agi { - void AudioProvider::FillBufferInt16Mono(int16_t* buf, int64_t start, int64_t count) const { if (!float_samples && bytes_per_sample == 2 && channels == 1) { FillBuffer(buf, start, count); @@ -242,7 +241,7 @@ void SaveAudioClip(AudioProvider const& provider, fs::path const& path, int star out.write("WAVEfmt "); out.write(16); // Size of chunk - out.write(1); // compression format (PCM) + out.write(provider.AreSamplesFloat() ? 3 : 1); // compression format (1: WAVE_FORMAT_PCM, 3: WAVE_FORMAT_IEEE_FLOAT) out.write(provider.GetChannels()); out.write(provider.GetSampleRate()); out.write(provider.GetSampleRate() * provider.GetChannels() * provider.GetBytesPerSample()); @@ -262,4 +261,4 @@ void SaveAudioClip(AudioProvider const& provider, fs::path const& path, int star out.write(buf); } } -} +} \ No newline at end of file diff --git a/libaegisub/audio/provider_lock.cpp b/libaegisub/audio/provider_lock.cpp index eb397e410..e405487a1 100644 --- a/libaegisub/audio/provider_lock.cpp +++ b/libaegisub/audio/provider_lock.cpp @@ -29,6 +29,11 @@ class LockAudioProvider final : public agi::AudioProviderWrapper { source->GetAudio(buf, start, count); } + void FillBufferInt16Mono(int16_t *buf, int64_t start, int64_t count) const override { + std::unique_lock lock(mutex); + source->GetInt16MonoAudio(buf, start, count); + } + public: LockAudioProvider(std::unique_ptr src) : AudioProviderWrapper(std::move(src)) diff --git a/libaegisub/audio/provider_ram.cpp b/libaegisub/audio/provider_ram.cpp index 3f070c87e..e708b0112 100644 --- a/libaegisub/audio/provider_ram.cpp +++ b/libaegisub/audio/provider_ram.cpp @@ -46,14 +46,14 @@ public: decoded_samples = 0; try { - blockcache.resize((source->GetNumSamples() * source->GetBytesPerSample() + CacheBlockSize - 1) >> CacheBits); + blockcache.resize((num_samples * bytes_per_sample * channels + CacheBlockSize - 1) >> CacheBits); } catch (std::bad_alloc const&) { throw AudioProviderError("Not enough memory available to cache in RAM"); } decoder = std::thread([&] { - int64_t readsize = CacheBlockSize / source->GetBytesPerSample(); + int64_t readsize = CacheBlockSize / bytes_per_sample / channels; for (size_t i = 0; i < blockcache.size(); i++) { if (cancelled) break; auto actual_read = std::min(readsize, num_samples - i * readsize); @@ -95,4 +95,4 @@ namespace agi { std::unique_ptr CreateRAMAudioProvider(std::unique_ptr src) { return agi::make_unique(std::move(src)); } -} +} \ No newline at end of file diff --git a/src/audio_provider_ffmpegsource.cpp b/src/audio_provider_ffmpegsource.cpp index 46e1412f5..1c109220f 100644 --- a/src/audio_provider_ffmpegsource.cpp +++ b/src/audio_provider_ffmpegsource.cpp @@ -126,8 +126,10 @@ void FFmpegSourceAudioProvider::LoadAudio(agi::fs::path const& filename) { // reindex if the error handling mode has changed FFMS_IndexErrorHandling ErrorHandling = GetErrorHandlingMode(); +#if FFMS_VERSION >= ((2 << 24) | (17 << 16) | (2 << 8) | 0) if (Index && FFMS_GetErrorHandling(Index) != ErrorHandling) Index = nullptr; +#endif // moment of truth if (!Index) { @@ -165,22 +167,23 @@ void FFmpegSourceAudioProvider::LoadAudio(agi::fs::path const& filename) { throw agi::AudioProviderError("unknown or unsupported sample format"); } +#if FFMS_VERSION >= ((2 << 24) | (17 << 16) | (4 << 8) | 0) if (OPT_GET("Provider/Audio/FFmpegSource/Downmix")->GetBool()) { - if (channels > 2 || bytes_per_sample != 2 || float_samples) { + if (channels > 1 || bytes_per_sample != 2 || float_samples) { std::unique_ptr opt(FFMS_CreateResampleOptions(AudioSource), FFMS_DestroyResampleOptions); - if (channels > 2) - opt->ChannelLayout = FFMS_CH_FRONT_LEFT | FFMS_CH_FRONT_RIGHT; + opt->ChannelLayout = FFMS_CH_FRONT_CENTER; opt->SampleFormat = FFMS_FMT_S16; // Might fail if FFMS2 wasn't built with libavresample if (!FFMS_SetOutputFormatA(AudioSource, opt.get(), nullptr)) { - channels = channels > 2 ? 2 : channels; + channels = 1; bytes_per_sample = 2; float_samples = false; } } } +#endif } } @@ -189,4 +192,4 @@ std::unique_ptr CreateFFmpegSourceAudioProvider(agi::fs::pat return agi::make_unique(file, br); } -#endif /* WITH_FFMS2 */ +#endif /* WITH_FFMS2 */ \ No newline at end of file diff --git a/src/audio_renderer_spectrum.cpp b/src/audio_renderer_spectrum.cpp index 217090a6f..7190c448a 100644 --- a/src/audio_renderer_spectrum.cpp +++ b/src/audio_renderer_spectrum.cpp @@ -208,8 +208,8 @@ void AudioSpectrumRenderer::FillBlock(size_t block_index, float *block) assert(block); int64_t first_sample = (((int64_t)block_index) << derivation_dist) - ((int64_t)1 << derivation_size); - provider->GetAudio(&audio_scratch[0], first_sample, 2 << derivation_size); - + provider->GetInt16MonoAudio(audio_scratch.data(), first_sample, 2 << derivation_size); + // Because the FFTs used here are unnormalized DFTs, we have to compensate // the possible length difference between derivation_size used in the // calculations and its user-provided counterpart. Thus, the display is diff --git a/src/audio_renderer_waveform.cpp b/src/audio_renderer_waveform.cpp index d5bb802fb..789dca024 100644 --- a/src/audio_renderer_waveform.cpp +++ b/src/audio_renderer_waveform.cpp @@ -88,7 +88,7 @@ void AudioWaveformRenderer::Render(wxBitmap &bmp, int start, AudioRenderingStyle for (int x = 0; x < rect.width; ++x) { - provider->GetAudio(audio_buffer.get(), (int64_t)cur_sample, (int64_t)pixel_samples); + provider->GetInt16MonoAudio(reinterpret_cast(audio_buffer.get()), (int64_t)cur_sample, (int64_t)pixel_samples); cur_sample += pixel_samples; int peak_min = 0, peak_max = 0;