From 6bec0322e4bd5ed4f2c5e1839e6bcea4b01eccde Mon Sep 17 00:00:00 2001 From: Karl Blomster Date: Tue, 15 Jul 2008 21:31:09 +0000 Subject: [PATCH] split out the downmixing audio provider into its own .h/.cpp, in preparation for using it in the ffmpeg audio provider. Originally committed to SVN as r2257. --- aegisub/audio_provider_downmix.cpp | 118 +++++++++++++++++++++++++++++ aegisub/audio_provider_downmix.h | 49 ++++++++++++ aegisub/audio_provider_pcm.cpp | 86 +-------------------- 3 files changed, 168 insertions(+), 85 deletions(-) create mode 100644 aegisub/audio_provider_downmix.cpp create mode 100644 aegisub/audio_provider_downmix.h diff --git a/aegisub/audio_provider_downmix.cpp b/aegisub/audio_provider_downmix.cpp new file mode 100644 index 000000000..02570fa33 --- /dev/null +++ b/aegisub/audio_provider_downmix.cpp @@ -0,0 +1,118 @@ +// Copyright (c) 2007-2008, Niels Martin Hansen +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:jiifurusu@gmail.com + + +////////////////// +// Headers +#include "audio_provider_downmix.h" + + +////////////////// +// Constructor +DownmixingAudioProvider::DownmixingAudioProvider(AudioProvider *source) { + filename = source->GetFilename(); + channels = 1; // target + src_channels = source->GetChannels(); + num_samples = source->GetNumSamples(); + bytes_per_sample = source->GetBytesPerSample(); + sample_rate = source->GetSampleRate(); + + // We now own this + provider = source; + + if (!(bytes_per_sample == 1 || bytes_per_sample == 2)) + throw _T("Downmixing Audio Provider: Can only downmix 8 and 16 bit audio"); +} + +///////////////// +// Destructor +DownmixingAudioProvider::~DownmixingAudioProvider() { + delete provider; +} + +//////////////// +// Actual work happens here +void DownmixingAudioProvider::GetAudio(void *buf, int64_t start, int64_t count) { + if (count == 0) return; + + // We can do this ourselves + if (start >= num_samples) { + if (bytes_per_sample == 1) + // 8 bit formats are usually unsigned with bias 127 + memset(buf, 127, count); + else + // While everything else is signed + memset(buf, 0, count*bytes_per_sample); + + return; + } + + // So alloc some temporary memory for this + // Depending on use, this might be made faster by using + // a pre-allocced block of memory...? + char *tmp = new char[count*bytes_per_sample*src_channels]; + + provider->GetAudio(tmp, start, count); + + // Now downmix + // Just average the samples over the channels (really bad if they're out of phase!) + // XXX: Assuming here that sample data are in machine endian, an upstream provider should ensure that + if (bytes_per_sample == 1) { + uint8_t *src = (uint8_t *)tmp; + uint8_t *dst = (uint8_t *)buf; + + while (count > 0) { + int sum = 0; + for (int c = 0; c < src_channels; c++) + sum += *(src++); + *(dst++) = (uint8_t)(sum / src_channels); + count--; + } + } + else if (bytes_per_sample == 2) { + int16_t *src = (int16_t *)tmp; + int16_t *dst = (int16_t *)buf; + + while (count > 0) { + int sum = 0; + for (int c = 0; c < src_channels; c++) + sum += *(src++); + *(dst++) = (int16_t)(sum / src_channels); + count--; + } + } + + // Done downmixing, free the work buffer + delete[] tmp; +} diff --git a/aegisub/audio_provider_downmix.h b/aegisub/audio_provider_downmix.h new file mode 100644 index 000000000..792818a62 --- /dev/null +++ b/aegisub/audio_provider_downmix.h @@ -0,0 +1,49 @@ +// Copyright (c) 2007-2008, Niels Martin Hansen +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of the Aegisub Group nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// ----------------------------------------------------------------------------- +// +// AEGISUB +// +// Website: http://aegisub.cellosoft.com +// Contact: mailto:jiifurusu@gmail.com +// + +#include "include/aegisub/audio_provider.h" + +class DownmixingAudioProvider : public AudioProvider { +private: + AudioProvider *provider; + int src_channels; + +public: + DownmixingAudioProvider(AudioProvider *source); + ~DownmixingAudioProvider(); + + void GetAudio(void *buf, int64_t start, int64_t count); + +}; \ No newline at end of file diff --git a/aegisub/audio_provider_pcm.cpp b/aegisub/audio_provider_pcm.cpp index 39fcdc368..27fdc184a 100644 --- a/aegisub/audio_provider_pcm.cpp +++ b/aegisub/audio_provider_pcm.cpp @@ -37,6 +37,7 @@ #include #include #include "audio_provider_pcm.h" +#include "audio_provider_downmix.h" #include "utils.h" #include "aegisub_endian.h" #include @@ -370,91 +371,6 @@ public: }; -// Mix down any number of channels to mono - -class DownmixingAudioProvider : public AudioProvider { -private: - AudioProvider *provider; - int src_channels; - -public: - DownmixingAudioProvider(AudioProvider *source) - { - filename = source->GetFilename(); - channels = 1; // target - src_channels = source->GetChannels(); - num_samples = source->GetNumSamples(); - bytes_per_sample = source->GetBytesPerSample(); - sample_rate = source->GetSampleRate(); - - // We now own this - provider = source; - - if (!(bytes_per_sample == 1 || bytes_per_sample == 2)) throw _T("Downmixing Audio Provider: Can only downmix 8 and 16 bit audio"); - } - - ~DownmixingAudioProvider() - { - delete provider; - } - - void GetAudio(void *buf, int64_t start, int64_t count) - { - if (count == 0) return; - - // We can do this ourselves - if (start >= num_samples) { - if (bytes_per_sample == 1) - // 8 bit formats are usually unsigned with bias 127 - memset(buf, 127, count); - else - // While everything else is signed - memset(buf, 0, count*bytes_per_sample); - - return; - } - - // So alloc some temporary memory for this - // Depending on use, this might be made faster by using - // a pre-allocced block of memory...? - char *tmp = new char[count*bytes_per_sample*src_channels]; - - provider->GetAudio(tmp, start, count); - - // Now downmix - // Just average the samples over the channels (really bad if they're out of phase!) - // XXX: Assuming here that sample data are in machine endian, an upstream provider should ensure that - if (bytes_per_sample == 1) { - uint8_t *src = (uint8_t *)tmp; - uint8_t *dst = (uint8_t *)buf; - - while (count > 0) { - int sum = 0; - for (int c = 0; c < src_channels; c++) - sum += *(src++); - *(dst++) = (uint8_t)(sum / src_channels); - count--; - } - } - else if (bytes_per_sample == 2) { - int16_t *src = (int16_t *)tmp; - int16_t *dst = (int16_t *)buf; - - while (count > 0) { - int sum = 0; - for (int c = 0; c < src_channels; c++) - sum += *(src++); - *(dst++) = (int16_t)(sum / src_channels); - count--; - } - } - - // Done downmixing, free the work buffer - delete[] tmp; - } -}; - - AudioProvider *CreatePCMAudioProvider(const wxString &filename) { AudioProvider *provider = 0;