diff options
Diffstat (limited to 'audio/softsynth/mt32/SampleRateConverter.cpp')
-rw-r--r-- | audio/softsynth/mt32/SampleRateConverter.cpp | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/audio/softsynth/mt32/SampleRateConverter.cpp b/audio/softsynth/mt32/SampleRateConverter.cpp new file mode 100644 index 0000000000..70f860f395 --- /dev/null +++ b/audio/softsynth/mt32/SampleRateConverter.cpp @@ -0,0 +1,97 @@ +/* Copyright (C) 2015-2017 Sergey V. Mikayev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "SampleRateConverter.h" + +#if MT32EMU_WITH_LIBSOXR_RESAMPLER +#include "srchelper/SoxrAdapter.h" +#elif MT32EMU_WITH_LIBSAMPLERATE_RESAMPLER +#include "srchelper/SamplerateAdapter.h" +#else +#include "srchelper/InternalResampler.h" +#endif + +#include "Synth.h" + +using namespace MT32Emu; + +static inline void *createDelegate(Synth &synth, double targetSampleRate, SampleRateConverter::Quality quality) { +#if MT32EMU_WITH_LIBSOXR_RESAMPLER + return new SoxrAdapter(synth, targetSampleRate, quality); +#elif MT32EMU_WITH_LIBSAMPLERATE_RESAMPLER + return new SamplerateAdapter(synth, targetSampleRate, quality); +#else + return new InternalResampler(synth, targetSampleRate, quality); +#endif +} + +AnalogOutputMode SampleRateConverter::getBestAnalogOutputMode(double targetSampleRate) { + if (Synth::getStereoOutputSampleRate(AnalogOutputMode_ACCURATE) < targetSampleRate) { + return AnalogOutputMode_OVERSAMPLED; + } else if (Synth::getStereoOutputSampleRate(AnalogOutputMode_COARSE) < targetSampleRate) { + return AnalogOutputMode_ACCURATE; + } + return AnalogOutputMode_COARSE; +} + +SampleRateConverter::SampleRateConverter(Synth &useSynth, double targetSampleRate, Quality useQuality) : + synthInternalToTargetSampleRateRatio(SAMPLE_RATE / targetSampleRate), + srcDelegate(createDelegate(useSynth, targetSampleRate, useQuality)) +{} + +SampleRateConverter::~SampleRateConverter() { +#if MT32EMU_WITH_LIBSOXR_RESAMPLER + delete static_cast<SoxrAdapter *>(srcDelegate); +#elif MT32EMU_WITH_LIBSAMPLERATE_RESAMPLER + delete static_cast<SamplerateAdapter *>(srcDelegate); +#else + delete static_cast<InternalResampler *>(srcDelegate); +#endif +} + +void SampleRateConverter::getOutputSamples(float *buffer, unsigned int length) { +#if MT32EMU_WITH_LIBSOXR_RESAMPLER + static_cast<SoxrAdapter *>(srcDelegate)->getOutputSamples(buffer, length); +#elif MT32EMU_WITH_LIBSAMPLERATE_RESAMPLER + static_cast<SamplerateAdapter *>(srcDelegate)->getOutputSamples(buffer, length); +#else + static_cast<InternalResampler *>(srcDelegate)->getOutputSamples(buffer, length); +#endif +} + +void SampleRateConverter::getOutputSamples(Bit16s *outBuffer, unsigned int length) { + static const unsigned int CHANNEL_COUNT = 2; + + float floatBuffer[CHANNEL_COUNT * MAX_SAMPLES_PER_RUN]; + while (length > 0) { + const unsigned int size = MAX_SAMPLES_PER_RUN < length ? MAX_SAMPLES_PER_RUN : length; + getOutputSamples(floatBuffer, size); + float *outs = floatBuffer; + float *ends = floatBuffer + CHANNEL_COUNT * size; + while (outs < ends) { + *(outBuffer++) = Synth::convertSample(*(outs++)); + } + length -= size; + } +} + +double SampleRateConverter::convertOutputToSynthTimestamp(double outputTimestamp) const { + return outputTimestamp * synthInternalToTargetSampleRateRatio; +} + +double SampleRateConverter::convertSynthToOutputTimestamp(double synthTimestamp) const { + return synthTimestamp / synthInternalToTargetSampleRateRatio; +} |