aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/soundlib/AudioReadTarget.h
diff options
context:
space:
mode:
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/soundlib/AudioReadTarget.h')
-rw-r--r--Src/external_dependencies/openmpt-trunk/soundlib/AudioReadTarget.h142
1 files changed, 142 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/soundlib/AudioReadTarget.h b/Src/external_dependencies/openmpt-trunk/soundlib/AudioReadTarget.h
new file mode 100644
index 00000000..76799d91
--- /dev/null
+++ b/Src/external_dependencies/openmpt-trunk/soundlib/AudioReadTarget.h
@@ -0,0 +1,142 @@
+/*
+ * AudioReadTarget.h
+ * -----------------
+ * Purpose: Callback class implementations for audio data read via CSoundFile::Read.
+ * Notes : (currently none)
+ * Authors: OpenMPT Devs
+ * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
+ */
+
+#pragma once
+
+#include "openmpt/all/BuildSettings.hpp"
+
+#include "Sndfile.h"
+#include "mpt/audio/span.hpp"
+#include "openmpt/soundbase/SampleFormat.hpp"
+#include "openmpt/soundbase/CopyMix.hpp"
+#include "openmpt/soundbase/Dither.hpp"
+#include "MixerLoops.h"
+#include "Mixer.h"
+#include "../common/Dither.h"
+
+#include <type_traits>
+
+
+OPENMPT_NAMESPACE_BEGIN
+
+
+template <typename Taudio_span, typename TDithers = DithersOpenMPT>
+class AudioTargetBuffer
+ : public IAudioTarget
+{
+private:
+ std::size_t countRendered;
+ TDithers &dithers;
+protected:
+ Taudio_span outputBuffer;
+public:
+ AudioTargetBuffer(Taudio_span buf, TDithers &dithers_)
+ : countRendered(0)
+ , dithers(dithers_)
+ , outputBuffer(buf)
+ {
+ return;
+ }
+ std::size_t GetRenderedCount() const { return countRendered; }
+public:
+ void Process(mpt::audio_span_interleaved<MixSampleInt> buffer) override
+ {
+ std::visit(
+ [&](auto &ditherInstance)
+ {
+ ConvertBufferMixInternalFixedToBuffer<MixSampleIntTraits::mix_fractional_bits, false>(mpt::make_audio_span_with_offset(outputBuffer, countRendered), buffer, ditherInstance, buffer.size_channels(), buffer.size_frames());
+ },
+ dithers.Variant()
+ );
+ countRendered += buffer.size_frames();
+ }
+ void Process(mpt::audio_span_interleaved<MixSampleFloat> buffer) override
+ {
+ std::visit(
+ [&](auto &ditherInstance)
+ {
+ ConvertBufferMixInternalToBuffer<false>(mpt::make_audio_span_with_offset(outputBuffer, countRendered), buffer, ditherInstance, buffer.size_channels(), buffer.size_frames());
+ },
+ dithers.Variant()
+ );
+ countRendered += buffer.size_frames();
+ }
+};
+
+
+template <typename Taudio_span, typename TDithers = DithersOpenMPT>
+class AudioTargetBufferWithGain
+ : public AudioTargetBuffer<Taudio_span>
+{
+private:
+ using Tbase = AudioTargetBuffer<Taudio_span>;
+private:
+ const float gainFactor;
+public:
+ AudioTargetBufferWithGain(Taudio_span buf, TDithers &dithers, float gainFactor_)
+ : Tbase(buf, dithers)
+ , gainFactor(gainFactor_)
+ {
+ return;
+ }
+public:
+ void Process(mpt::audio_span_interleaved<MixSampleInt> buffer) override
+ {
+ const std::size_t countRendered_ = Tbase::GetRenderedCount();
+ if constexpr(!std::is_floating_point<typename Taudio_span::sample_type>::value)
+ {
+ int32 gainFactor16_16 = mpt::saturate_round<int32>(gainFactor * (1 << 16));
+ if(gainFactor16_16 != (1<<16))
+ {
+ // only apply gain when != +/- 0dB
+ // no clipping prevention is done here
+ for(std::size_t frame = 0; frame < buffer.size_frames(); ++frame)
+ {
+ for(std::size_t channel = 0; channel < buffer.size_channels(); ++channel)
+ {
+ buffer(channel, frame) = Util::muldiv(buffer(channel, frame), gainFactor16_16, 1 << 16);
+ }
+ }
+ }
+ }
+ Tbase::Process(buffer);
+ if constexpr(std::is_floating_point<typename Taudio_span::sample_type>::value)
+ {
+ if(gainFactor != 1.0f)
+ {
+ // only apply gain when != +/- 0dB
+ for(std::size_t frame = 0; frame < buffer.size_frames(); ++frame)
+ {
+ for(std::size_t channel = 0; channel < buffer.size_channels(); ++channel)
+ {
+ Tbase::outputBuffer(channel, countRendered_ + frame) *= gainFactor;
+ }
+ }
+ }
+ }
+ }
+ void Process(mpt::audio_span_interleaved<MixSampleFloat> buffer) override
+ {
+ if(gainFactor != 1.0f)
+ {
+ // only apply gain when != +/- 0dB
+ for(std::size_t frame = 0; frame < buffer.size_frames(); ++frame)
+ {
+ for(std::size_t channel = 0; channel < buffer.size_channels(); ++channel)
+ {
+ buffer(channel, frame) *= gainFactor;
+ }
+ }
+ }
+ Tbase::Process(buffer);
+ }
+};
+
+
+OPENMPT_NAMESPACE_END