diff options
Diffstat (limited to 'intern/audaspace/SRC')
-rw-r--r-- | intern/audaspace/SRC/AUD_SRCResampleFactory.cpp | 53 | ||||
-rw-r--r-- | intern/audaspace/SRC/AUD_SRCResampleFactory.h | 46 | ||||
-rw-r--r-- | intern/audaspace/SRC/AUD_SRCResampleReader.cpp | 119 | ||||
-rw-r--r-- | intern/audaspace/SRC/AUD_SRCResampleReader.h | 102 |
4 files changed, 320 insertions, 0 deletions
diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp new file mode 100644 index 00000000000..bcace340b24 --- /dev/null +++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp @@ -0,0 +1,53 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * AudaSpace 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 3 of the License, or + * (at your option) any later version. + * + * AudaSpace 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 AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_SRCResampleFactory.h" +#include "AUD_SRCResampleReader.h" + +AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IReader* reader, + AUD_Specs specs) : + AUD_ResampleFactory(reader, specs) {} + +AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IFactory* factory, + AUD_Specs specs) : + AUD_ResampleFactory(factory, specs) {} + +AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_Specs specs) : + AUD_ResampleFactory(specs) {} + +AUD_IReader* AUD_SRCResampleFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + if(reader != 0) + { + if(reader->getSpecs().rate != m_specs.rate) + { + reader = new AUD_SRCResampleReader(reader, m_specs); + AUD_NEW("reader") + } + } + return reader; +} diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.h b/intern/audaspace/SRC/AUD_SRCResampleFactory.h new file mode 100644 index 00000000000..c23c1d2c82e --- /dev/null +++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.h @@ -0,0 +1,46 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * AudaSpace 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 3 of the License, or + * (at your option) any later version. + * + * AudaSpace 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 AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_SRCRESAMPLEFACTORY +#define AUD_SRCRESAMPLEFACTORY + +#include "AUD_ResampleFactory.h" + +/** + * This factory creates a resampling reader that uses libsamplerate for + * resampling. + * \note The format of the input must be float. + */ +class AUD_SRCResampleFactory : public AUD_ResampleFactory +{ +public: + AUD_SRCResampleFactory(AUD_IReader* reader, AUD_Specs specs); + AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_Specs specs); + AUD_SRCResampleFactory(AUD_Specs specs); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_SRCRESAMPLEFACTORY diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp new file mode 100644 index 00000000000..f7564d3c010 --- /dev/null +++ b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp @@ -0,0 +1,119 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * AudaSpace 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 3 of the License, or + * (at your option) any later version. + * + * AudaSpace 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 AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_SRCResampleReader.h" +#include "AUD_Buffer.h" + +#include <math.h> +#include <cstring> +#include <stdio.h> + +static long src_callback(void *cb_data, float **data) +{ + return ((AUD_SRCResampleReader*)cb_data)->doCallback(data); +} + +AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader, + AUD_Specs specs) : + AUD_EffectReader(reader) +{ + m_sspecs = reader->getSpecs(); + + if(m_sspecs.format != AUD_FORMAT_FLOAT32) + { + delete m_reader; AUD_DELETE("reader") + AUD_THROW(AUD_ERROR_READER); + } + + m_tspecs = specs; + m_tspecs.channels = m_sspecs.channels; + m_tspecs.format = m_sspecs.format; + m_factor = (double)m_tspecs.rate / (double)m_sspecs.rate; + + int error; + m_src = src_callback_new(src_callback, + SRC_SINC_MEDIUM_QUALITY, + m_sspecs.channels, + &error, + this); + + if(!m_src) + { + // XXX printf("%s\n", src_strerror(error)); + delete m_reader; AUD_DELETE("reader") + AUD_THROW(AUD_ERROR_READER); + } + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") +} + +AUD_SRCResampleReader::~AUD_SRCResampleReader() +{ + delete m_buffer; AUD_DELETE("buffer") + + src_delete(m_src); +} + +long AUD_SRCResampleReader::doCallback(float** data) +{ + int length = m_buffer->getSize() / 4 / m_tspecs.channels; + sample_t* buffer; + + m_reader->read(length, buffer); + + *data = (float*)buffer; + return length; +} + +void AUD_SRCResampleReader::seek(int position) +{ + m_reader->seek(position / m_factor); + src_reset(m_src); +} + +int AUD_SRCResampleReader::getLength() +{ + return m_reader->getLength() * m_factor; +} + +int AUD_SRCResampleReader::getPosition() +{ + return m_reader->getPosition() * m_factor; +} + +AUD_Specs AUD_SRCResampleReader::getSpecs() +{ + return m_tspecs; +} + +void AUD_SRCResampleReader::read(int & length, sample_t* & buffer) +{ + if(m_buffer->getSize() < length * m_tspecs.channels * 4) + m_buffer->resize(length * m_tspecs.channels * 4); + + buffer = m_buffer->getBuffer(); + + length = src_callback_read(m_src, m_factor, length, (float*)buffer); +} diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.h b/intern/audaspace/SRC/AUD_SRCResampleReader.h new file mode 100644 index 00000000000..1bacdb3965c --- /dev/null +++ b/intern/audaspace/SRC/AUD_SRCResampleReader.h @@ -0,0 +1,102 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 Jörg Hermann Müller + * + * This file is part of AudaSpace. + * + * AudaSpace 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 3 of the License, or + * (at your option) any later version. + * + * AudaSpace 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 AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_SRCRESAMPLEREADER +#define AUD_SRCRESAMPLEREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +#include <samplerate.h> + +/** + * This class mixes a sound source with help of the SDL library. + * Unfortunately SDL is only capable of 8 and 16 bit audio, mono and stereo, as + * well as resampling only 2^n sample rate relationships where n is a natural + * number. + * \warning Although SDL can only resample 2^n sample rate relationships, this + * class doesn't check for compliance, so in case of other factors, + * the behaviour is undefined. + */ +class AUD_SRCResampleReader : public AUD_EffectReader +{ +private: + /** + * The resampling factor. + */ + double m_factor; + + /** + * The sound output buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The target specification. + */ + AUD_Specs m_tspecs; + + /** + * The sample specification of the source. + */ + AUD_Specs m_sspecs; + + /** + * The src state structure. + */ + SRC_STATE* m_src; + +public: + /** + * Creates a resampling reader. + * \param reader The reader to mix. + * \param specs The target specification. + * \exception AUD_Exception Thrown if the source specification cannot be + * mixed to the target specification or if the reader is + * NULL. + */ + AUD_SRCResampleReader(AUD_IReader* reader, AUD_Specs specs); + + /** + * Destroys the reader. + */ + ~AUD_SRCResampleReader(); + + /** + * The callback function for SRC. + * \warning Do not call! + * \param data The pointer to the float data. + * \return The count of samples in the float data. + */ + long doCallback(float** data); + + virtual void seek(int position); + virtual int getLength(); + virtual int getPosition(); + virtual AUD_Specs getSpecs(); + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_SRCRESAMPLEREADER |