From 174eccf07851c4e7f669b194cd8951ca98bc5c81 Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Fri, 1 Jan 2010 05:09:30 +0000 Subject: Huge new year audio commit! * Refactored the whole audaspace library to use float as sample format over all readers. * Added new Readers like the linear resampler, envelope, lowpass, highpass and butterworth. * Note: The butterworth filter isn't working correctly, some bug in there... Maybe also true for the envelope. * Added a sound to f-curve operator that behaves mostly like the soundtracker script of technoestupido. --- intern/audaspace/FX/AUD_ButterworthFactory.cpp | 49 +++++ intern/audaspace/FX/AUD_ButterworthFactory.h | 59 ++++++ intern/audaspace/FX/AUD_ButterworthReader.cpp | 120 ++++++++++++ intern/audaspace/FX/AUD_ButterworthReader.h | 83 ++++++++ intern/audaspace/FX/AUD_DelayReader.cpp | 21 +- intern/audaspace/FX/AUD_DoubleReader.cpp | 9 +- intern/audaspace/FX/AUD_EnvelopeFactory.cpp | 58 ++++++ intern/audaspace/FX/AUD_EnvelopeFactory.h | 82 ++++++++ intern/audaspace/FX/AUD_EnvelopeReader.cpp | 86 ++++++++ intern/audaspace/FX/AUD_EnvelopeReader.h | 84 ++++++++ intern/audaspace/FX/AUD_FaderReader.cpp | 59 ++---- intern/audaspace/FX/AUD_FaderReader.h | 6 - intern/audaspace/FX/AUD_HighpassFactory.cpp | 51 +++++ intern/audaspace/FX/AUD_HighpassFactory.h | 66 +++++++ intern/audaspace/FX/AUD_HighpassReader.cpp | 112 +++++++++++ intern/audaspace/FX/AUD_HighpassReader.h | 83 ++++++++ intern/audaspace/FX/AUD_LoopReader.cpp | 12 +- intern/audaspace/FX/AUD_LowpassFactory.cpp | 51 +++++ intern/audaspace/FX/AUD_LowpassFactory.h | 66 +++++++ intern/audaspace/FX/AUD_LowpassReader.cpp | 111 +++++++++++ intern/audaspace/FX/AUD_LowpassReader.h | 83 ++++++++ intern/audaspace/FX/AUD_RectifyReader.cpp | 37 +--- intern/audaspace/FX/AUD_RectifyReader.h | 6 - intern/audaspace/FX/AUD_ReverseReader.cpp | 18 +- intern/audaspace/FX/AUD_VolumeReader.cpp | 32 +-- intern/audaspace/FX/AUD_VolumeReader.h | 6 - intern/audaspace/OpenAL/AUD_OpenALDevice.cpp | 106 +++------- intern/audaspace/OpenAL/AUD_OpenALDevice.h | 13 +- intern/audaspace/SDL/AUD_SDLDevice.cpp | 8 +- intern/audaspace/SDL/AUD_SDLDevice.h | 3 +- intern/audaspace/SDL/AUD_SDLMixer.cpp | 83 -------- intern/audaspace/SDL/AUD_SDLMixer.h | 76 -------- intern/audaspace/SDL/AUD_SDLMixerFactory.cpp | 65 ------- intern/audaspace/SDL/AUD_SDLMixerFactory.h | 45 ----- intern/audaspace/SDL/AUD_SDLMixerReader.cpp | 216 --------------------- intern/audaspace/SDL/AUD_SDLMixerReader.h | 128 ------------ intern/audaspace/SRC/AUD_SRCResampleFactory.cpp | 8 +- intern/audaspace/SRC/AUD_SRCResampleFactory.h | 7 +- intern/audaspace/SRC/AUD_SRCResampleReader.cpp | 25 +-- intern/audaspace/SRC/AUD_SRCResampleReader.h | 8 +- intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp | 195 ++++++++----------- intern/audaspace/ffmpeg/AUD_FFMPEGReader.h | 13 +- intern/audaspace/fftw/AUD_BandPassFactory.cpp | 12 +- intern/audaspace/fftw/AUD_BandPassReader.cpp | 6 +- intern/audaspace/intern/AUD_Buffer.cpp | 8 +- intern/audaspace/intern/AUD_Buffer.h | 2 +- intern/audaspace/intern/AUD_BufferReader.cpp | 6 +- intern/audaspace/intern/AUD_C-API.cpp | 67 +++++-- intern/audaspace/intern/AUD_C-API.h | 14 +- .../audaspace/intern/AUD_ChannelMapperFactory.cpp | 6 +- intern/audaspace/intern/AUD_ChannelMapperFactory.h | 6 +- .../audaspace/intern/AUD_ChannelMapperReader.cpp | 12 +- intern/audaspace/intern/AUD_ConverterFactory.cpp | 8 +- intern/audaspace/intern/AUD_ConverterFactory.h | 6 +- intern/audaspace/intern/AUD_ConverterFunctions.cpp | 164 ++++------------ intern/audaspace/intern/AUD_ConverterFunctions.h | 125 ++++-------- intern/audaspace/intern/AUD_ConverterReader.cpp | 195 ++----------------- intern/audaspace/intern/AUD_ConverterReader.h | 4 +- intern/audaspace/intern/AUD_FloatMixer.cpp | 172 ---------------- intern/audaspace/intern/AUD_FloatMixer.h | 100 ---------- intern/audaspace/intern/AUD_IDevice.h | 2 +- intern/audaspace/intern/AUD_IMixer.h | 77 -------- .../audaspace/intern/AUD_LinearResampleFactory.cpp | 53 +++++ .../audaspace/intern/AUD_LinearResampleFactory.h | 44 +++++ .../audaspace/intern/AUD_LinearResampleReader.cpp | 138 +++++++++++++ intern/audaspace/intern/AUD_LinearResampleReader.h | 94 +++++++++ intern/audaspace/intern/AUD_Mixer.cpp | 156 +++++++++++++++ intern/audaspace/intern/AUD_Mixer.h | 125 ++++++++++++ intern/audaspace/intern/AUD_MixerFactory.cpp | 10 +- intern/audaspace/intern/AUD_MixerFactory.h | 12 +- intern/audaspace/intern/AUD_NULLDevice.cpp | 2 +- intern/audaspace/intern/AUD_NULLDevice.h | 4 +- intern/audaspace/intern/AUD_ReadDevice.cpp | 12 +- intern/audaspace/intern/AUD_ReadDevice.h | 4 +- intern/audaspace/intern/AUD_SinusReader.cpp | 19 +- intern/audaspace/intern/AUD_SoftwareDevice.cpp | 19 +- intern/audaspace/intern/AUD_SoftwareDevice.h | 18 +- intern/audaspace/intern/AUD_Space.h | 36 +++- .../audaspace/intern/AUD_StreamBufferFactory.cpp | 4 +- intern/audaspace/jack/AUD_JackDevice.cpp | 9 +- intern/audaspace/jack/AUD_JackDevice.h | 2 +- intern/audaspace/sndfile/AUD_SndFileReader.cpp | 61 +----- intern/audaspace/sndfile/AUD_SndFileReader.h | 5 - source/blender/blenkernel/BKE_sound.h | 2 +- source/blender/blenkernel/intern/sequencer.c | 2 +- source/blender/blenkernel/intern/sound.c | 4 +- source/blender/blenkernel/intern/writeffmpeg.c | 2 +- source/blender/editors/sound/sound_ops.c | 2 +- source/blender/editors/space_graph/graph_edit.c | 135 +++++++++++++ source/blender/editors/space_graph/graph_intern.h | 1 + source/blender/editors/space_graph/graph_ops.c | 1 + 91 files changed, 2483 insertions(+), 1934 deletions(-) create mode 100644 intern/audaspace/FX/AUD_ButterworthFactory.cpp create mode 100644 intern/audaspace/FX/AUD_ButterworthFactory.h create mode 100644 intern/audaspace/FX/AUD_ButterworthReader.cpp create mode 100644 intern/audaspace/FX/AUD_ButterworthReader.h create mode 100644 intern/audaspace/FX/AUD_EnvelopeFactory.cpp create mode 100644 intern/audaspace/FX/AUD_EnvelopeFactory.h create mode 100644 intern/audaspace/FX/AUD_EnvelopeReader.cpp create mode 100644 intern/audaspace/FX/AUD_EnvelopeReader.h create mode 100644 intern/audaspace/FX/AUD_HighpassFactory.cpp create mode 100644 intern/audaspace/FX/AUD_HighpassFactory.h create mode 100644 intern/audaspace/FX/AUD_HighpassReader.cpp create mode 100644 intern/audaspace/FX/AUD_HighpassReader.h create mode 100644 intern/audaspace/FX/AUD_LowpassFactory.cpp create mode 100644 intern/audaspace/FX/AUD_LowpassFactory.h create mode 100644 intern/audaspace/FX/AUD_LowpassReader.cpp create mode 100644 intern/audaspace/FX/AUD_LowpassReader.h delete mode 100644 intern/audaspace/SDL/AUD_SDLMixer.cpp delete mode 100644 intern/audaspace/SDL/AUD_SDLMixer.h delete mode 100644 intern/audaspace/SDL/AUD_SDLMixerFactory.cpp delete mode 100644 intern/audaspace/SDL/AUD_SDLMixerFactory.h delete mode 100644 intern/audaspace/SDL/AUD_SDLMixerReader.cpp delete mode 100644 intern/audaspace/SDL/AUD_SDLMixerReader.h delete mode 100644 intern/audaspace/intern/AUD_FloatMixer.cpp delete mode 100644 intern/audaspace/intern/AUD_FloatMixer.h delete mode 100644 intern/audaspace/intern/AUD_IMixer.h create mode 100644 intern/audaspace/intern/AUD_LinearResampleFactory.cpp create mode 100644 intern/audaspace/intern/AUD_LinearResampleFactory.h create mode 100644 intern/audaspace/intern/AUD_LinearResampleReader.cpp create mode 100644 intern/audaspace/intern/AUD_LinearResampleReader.h create mode 100644 intern/audaspace/intern/AUD_Mixer.cpp create mode 100644 intern/audaspace/intern/AUD_Mixer.h diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.cpp b/intern/audaspace/FX/AUD_ButterworthFactory.cpp new file mode 100644 index 00000000000..fd0a53def7c --- /dev/null +++ b/intern/audaspace/FX/AUD_ButterworthFactory.cpp @@ -0,0 +1,49 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_ButterworthFactory.h" +#include "AUD_ButterworthReader.h" + +AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_IFactory* factory, + float frequency) : + AUD_EffectFactory(factory), + m_frequency(frequency) {} + +AUD_ButterworthFactory::AUD_ButterworthFactory(float frequency) : + AUD_EffectFactory(0), + m_frequency(frequency) {} + +AUD_IReader* AUD_ButterworthFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + if(reader != 0) + { + reader = new AUD_ButterworthReader(reader, m_frequency); + AUD_NEW("reader") + } + + return reader; +} diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.h b/intern/audaspace/FX/AUD_ButterworthFactory.h new file mode 100644 index 00000000000..69169531d70 --- /dev/null +++ b/intern/audaspace/FX/AUD_ButterworthFactory.h @@ -0,0 +1,59 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_BUTTERWORTHFACTORY +#define AUD_BUTTERWORTHFACTORY + +#include "AUD_EffectFactory.h" + +/** + * This factory creates a butterworth filter reader. + */ +class AUD_ButterworthFactory : public AUD_EffectFactory +{ +private: + /** + * The attack value in seconds. + */ + float m_frequency; + +public: + /** + * Creates a new butterworth factory. + * \param factory The input factory. + * \param frequency The cutoff frequency. + */ + AUD_ButterworthFactory(AUD_IFactory* factory, float frequency); + + /** + * Creates a new butterworth factory. + * \param frequency The cutoff frequency. + */ + AUD_ButterworthFactory(float frequency); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_BUTTERWORTHFACTORY diff --git a/intern/audaspace/FX/AUD_ButterworthReader.cpp b/intern/audaspace/FX/AUD_ButterworthReader.cpp new file mode 100644 index 00000000000..adcae87ce9f --- /dev/null +++ b/intern/audaspace/FX/AUD_ButterworthReader.cpp @@ -0,0 +1,120 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_ButterworthReader.h" +#include "AUD_Buffer.h" + +#include +#include + +#define BWPB41 0.76536686473 +#define BWPB42 1.84775906502 +#define CC channels + channel + +AUD_ButterworthReader::AUD_ButterworthReader(AUD_IReader* reader, + float frequency) : + AUD_EffectReader(reader) +{ + AUD_Specs specs = reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + + m_outvalues = new AUD_Buffer(samplesize * 5); AUD_NEW("buffer") + memset(m_outvalues->getBuffer(), 0, samplesize * 5); + + m_invalues = new AUD_Buffer(samplesize * 5); AUD_NEW("buffer") + memset(m_invalues->getBuffer(), 0, samplesize * 5); + + m_position = 0; + + // calculate coefficients + float omega = 2 * tan(frequency * M_PI / specs.rate); + float o2 = omega * omega; + float o4 = o2 * o2; + float x1 = o2 + 2 * BWPB41 * omega + 4; + float x2 = o2 + 2 * BWPB42 * omega + 4; + float y1 = o2 - 2 * BWPB41 * omega + 4; + float y2 = o2 - 2 * BWPB42 * omega + 4; + float o228 = 2 * o2 - 8; + float norm = x1 * x2; + m_coeff[0][0] = 0; + m_coeff[0][1] = (x1 + x2) * o228 / norm; + m_coeff[0][2] = (x1 * y2 + x2 * y1 + o228 * o228) / norm; + m_coeff[0][3] = (y1 + y2) * o228 / norm; + m_coeff[0][4] = y1 * y2 / norm; + m_coeff[1][4] = m_coeff[1][0] = o4 / norm; + m_coeff[1][3] = m_coeff[1][1] = 4 * o4 / norm; + m_coeff[1][2] = 6 * o4 / norm; +} + +AUD_ButterworthReader::~AUD_ButterworthReader() +{ + delete m_buffer; AUD_DELETE("buffer") + + delete m_outvalues; AUD_DELETE("buffer") + delete m_invalues; AUD_DELETE("buffer"); +} + +void AUD_ButterworthReader::read(int & length, sample_t* & buffer) +{ + sample_t* buf; + sample_t* outvalues; + sample_t* invalues; + + outvalues = m_outvalues->getBuffer(); + invalues = m_invalues->getBuffer(); + + AUD_Specs specs = m_reader->getSpecs(); + + m_reader->read(length, buf); + + if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs)) + m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); + + buffer = m_buffer->getBuffer(); + int channels = specs.channels; + + for(int channel = 0; channel < channels; channel++) + { + for(int i = 0; i < length; i++) + { + invalues[m_position * CC] = buf[i * CC]; + outvalues[m_position * CC] = 0; + + for(int j = 0; j < 4; j++) + { + outvalues[m_position * CC] += m_coeff[1][j] * + invalues[((m_position + j) % 5) * CC] - + m_coeff[0][j] * + outvalues[((m_position + j) % 5) * CC]; + } + + buffer[i * CC] = outvalues[m_position * CC]; + + m_position = (m_position + 4) % 5; + } + } +} diff --git a/intern/audaspace/FX/AUD_ButterworthReader.h b/intern/audaspace/FX/AUD_ButterworthReader.h new file mode 100644 index 00000000000..b1cbd4e3820 --- /dev/null +++ b/intern/audaspace/FX/AUD_ButterworthReader.h @@ -0,0 +1,83 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_BUTTERWORTHREADER +#define AUD_BUTTERWORTHREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +/** + * This class represents a butterworth filter. + */ +class AUD_ButterworthReader : public AUD_EffectReader +{ +private: + /** + * The playback buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The last out values buffer. + */ + AUD_Buffer *m_outvalues; + + /** + * The last in values buffer. + */ + AUD_Buffer *m_invalues; + + /** + * The position for buffer cycling. + */ + int m_position; + + /** + * Filter coefficients. + */ + float m_coeff[2][5]; + +public: + /** + * Creates a new butterworth reader. + * \param reader The reader to read from. + * \param attack The attack value in seconds. + * \param release The release value in seconds. + * \param threshold The threshold value. + * \param arthreshold The attack/release threshold value. + * \exception AUD_Exception Thrown if the reader specified is NULL. + */ + AUD_ButterworthReader(AUD_IReader* reader, float frequency); + + /** + * Destroys the reader. + */ + virtual ~AUD_ButterworthReader(); + + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_BUTTERWORTHREADER diff --git a/intern/audaspace/FX/AUD_DelayReader.cpp b/intern/audaspace/FX/AUD_DelayReader.cpp index 38d3b893b5c..f2521f645aa 100644 --- a/intern/audaspace/FX/AUD_DelayReader.cpp +++ b/intern/audaspace/FX/AUD_DelayReader.cpp @@ -77,31 +77,26 @@ void AUD_DelayReader::read(int & length, sample_t* & buffer) { if(m_remdelay > 0) { - int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs()); + AUD_Specs specs = m_reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); - if(m_buffer->getSize() < length*samplesize) - m_buffer->resize(length*samplesize); + if(m_buffer->getSize() < length * samplesize) + m_buffer->resize(length * samplesize); if(length > m_remdelay) { - if(getSpecs().format == AUD_FORMAT_U8) - memset(m_buffer->getBuffer(), 0x80, m_remdelay*samplesize); - else - memset(m_buffer->getBuffer(), 0, m_remdelay*samplesize); + memset(m_buffer->getBuffer(), 0, m_remdelay * samplesize); int len = length - m_remdelay; m_reader->read(len, buffer); - memcpy(m_buffer->getBuffer()+m_remdelay*samplesize, - buffer, len*samplesize); + memcpy(m_buffer->getBuffer() + m_remdelay * specs.channels, + buffer, len * samplesize); if(len < length-m_remdelay) length = m_remdelay + len; m_remdelay = 0; } else { - if(getSpecs().format == AUD_FORMAT_U8) - memset(m_buffer->getBuffer(), 0x80, length*samplesize); - else - memset(m_buffer->getBuffer(), 0, length*samplesize); + memset(m_buffer->getBuffer(), 0, length * samplesize); m_remdelay -= length; } buffer = m_buffer->getBuffer(); diff --git a/intern/audaspace/FX/AUD_DoubleReader.cpp b/intern/audaspace/FX/AUD_DoubleReader.cpp index 8d3afbf2f1d..1e51a094427 100644 --- a/intern/audaspace/FX/AUD_DoubleReader.cpp +++ b/intern/audaspace/FX/AUD_DoubleReader.cpp @@ -137,15 +137,16 @@ void AUD_DoubleReader::read(int & length, sample_t* & buffer) m_reader1->read(len, buffer); if(len < length) { - int samplesize = AUD_SAMPLE_SIZE(m_reader1->getSpecs()); + AUD_Specs specs = m_reader1->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); if(m_buffer->getSize() < length * samplesize) m_buffer->resize(length * samplesize); - memcpy(m_buffer->getBuffer(), buffer, len*samplesize); + memcpy(m_buffer->getBuffer(), buffer, len * samplesize); len = length - len; length -= len; m_reader2->read(len, buffer); - memcpy(m_buffer->getBuffer() + length*samplesize, - buffer, len*samplesize); + memcpy(m_buffer->getBuffer() + length * specs.channels, buffer, + len * samplesize); length += len; buffer = m_buffer->getBuffer(); m_finished1 = true; diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.cpp b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp new file mode 100644 index 00000000000..c3b2c3f24fe --- /dev/null +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp @@ -0,0 +1,58 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_EnvelopeFactory.h" +#include "AUD_EnvelopeReader.h" + +AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, + float release, float threshold, + float arthreshold) : + AUD_EffectFactory(factory), + m_attack(attack), + m_release(release), + m_threshold(threshold), + m_arthreshold(arthreshold) {} + +AUD_EnvelopeFactory::AUD_EnvelopeFactory(float attack, float release, + float threshold, float arthreshold) : + AUD_EffectFactory(0), + m_attack(attack), + m_release(release), + m_threshold(threshold), + m_arthreshold(arthreshold) {} + +AUD_IReader* AUD_EnvelopeFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + if(reader != 0) + { + reader = new AUD_EnvelopeReader(reader, m_attack, m_release, + m_threshold, m_arthreshold); + AUD_NEW("reader") + } + + return reader; +} diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.h b/intern/audaspace/FX/AUD_EnvelopeFactory.h new file mode 100644 index 00000000000..c79e5472e30 --- /dev/null +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.h @@ -0,0 +1,82 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_ENVELOPEFACTORY +#define AUD_ENVELOPEFACTORY + +#include "AUD_EffectFactory.h" + +/** + * This factory creates an envelope follower reader. + */ +class AUD_EnvelopeFactory : public AUD_EffectFactory +{ +private: + /** + * The attack value in seconds. + */ + float m_attack; + + /** + * The release value in seconds. + */ + float m_release; + + /** + * The threshold value. + */ + float m_threshold; + + /** + * The attack/release threshold value. + */ + float m_arthreshold; + +public: + /** + * Creates a new envelope factory. + * \param factory The input factory. + * \param attack The attack value in seconds. + * \param release The release value in seconds. + * \param threshold The threshold value. + * \param arthreshold The attack/release threshold value. + */ + AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, float release, + float threshold, float arthreshold); + + /** + * Creates a new envelope factory. + * \param attack The attack value in seconds. + * \param release The release value in seconds. + * \param threshold The threshold value. + * \param arthreshold The attack/release threshold value. + */ + AUD_EnvelopeFactory(float attack, float release, float threshold, + float arthreshold); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_ENVELOPEFACTORY diff --git a/intern/audaspace/FX/AUD_EnvelopeReader.cpp b/intern/audaspace/FX/AUD_EnvelopeReader.cpp new file mode 100644 index 00000000000..f41aee1d4bc --- /dev/null +++ b/intern/audaspace/FX/AUD_EnvelopeReader.cpp @@ -0,0 +1,86 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_EnvelopeReader.h" +#include "AUD_Buffer.h" + +#include +#include + +AUD_EnvelopeReader::AUD_EnvelopeReader(AUD_IReader* reader, float attack, + float release, float threshold, + float arthreshold) : + AUD_EffectReader(reader), + m_threshold(threshold) +{ + AUD_Specs specs = reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + + m_envelopes = new AUD_Buffer(samplesize); + AUD_NEW("buffer") + memset(m_envelopes->getBuffer(), 0, samplesize); + + m_bAttack = pow(arthreshold, 1.0/(specs.rate * attack)); + m_bRelease = pow(arthreshold, 1.0/(specs.rate * release)); +} + +AUD_EnvelopeReader::~AUD_EnvelopeReader() +{ + delete m_buffer; AUD_DELETE("buffer") + delete m_envelopes; AUD_DELETE("buffer") +} + +void AUD_EnvelopeReader::read(int & length, sample_t* & buffer) +{ + sample_t* buf; + sample_t* envelopes; + envelopes = m_envelopes->getBuffer(); + + AUD_Specs specs = m_reader->getSpecs(); + + m_reader->read(length, buf); + if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs)) + m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); + + buffer = m_buffer->getBuffer(); + + sample_t value; + + for(int channel = 0; channel < specs.channels; channel++) + { + for(int i = 0; i < length; i++) + { + value = fabs(buf[i * specs.channels + channel]); + if(value < m_threshold) + value = 0.0f; + + buffer[i * specs.channels + channel] = envelopes[channel] = + ((value > envelopes[channel]) ? m_bAttack : m_bRelease) * + (envelopes[channel] - value) + value; + } + } +} diff --git a/intern/audaspace/FX/AUD_EnvelopeReader.h b/intern/audaspace/FX/AUD_EnvelopeReader.h new file mode 100644 index 00000000000..ff9dd23d34c --- /dev/null +++ b/intern/audaspace/FX/AUD_EnvelopeReader.h @@ -0,0 +1,84 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_ENVELOPEREADER +#define AUD_ENVELOPEREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +/** + * This class represents an envelope follower. + */ +class AUD_EnvelopeReader : public AUD_EffectReader +{ +private: + /** + * The playback buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The last envelopes buffer. + */ + AUD_Buffer *m_envelopes; + + /** + * Attack b value. + */ + float m_bAttack; + + /** + * Release b value. + */ + float m_bRelease; + + /** + * Threshold value. + */ + float m_threshold; + +public: + /** + * Creates a new envelope reader. + * \param reader The reader to read from. + * \param attack The attack value in seconds. + * \param release The release value in seconds. + * \param threshold The threshold value. + * \param arthreshold The attack/release threshold value. + * \exception AUD_Exception Thrown if the reader specified is NULL. + */ + AUD_EnvelopeReader(AUD_IReader* reader, float attack, float release, + float threshold, float arthreshold); + + /** + * Destroys the reader. + */ + virtual ~AUD_EnvelopeReader(); + + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_ENVELOPEREADER diff --git a/intern/audaspace/FX/AUD_FaderReader.cpp b/intern/audaspace/FX/AUD_FaderReader.cpp index d5096e7fae1..6c7ea6e0a01 100644 --- a/intern/audaspace/FX/AUD_FaderReader.cpp +++ b/intern/audaspace/FX/AUD_FaderReader.cpp @@ -35,35 +35,6 @@ AUD_FaderReader::AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type, m_start(start), m_length(length) { - int bigendian = 1; - bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian - - switch(m_reader->getSpecs().format) - { - case AUD_FORMAT_S16: - m_adjust = AUD_volume_adjust; - break; - case AUD_FORMAT_S32: - m_adjust = AUD_volume_adjust; - break; - case AUD_FORMAT_FLOAT32: - m_adjust = AUD_volume_adjust; - break; - case AUD_FORMAT_FLOAT64: - m_adjust = AUD_volume_adjust; - break; - case AUD_FORMAT_U8: - m_adjust = AUD_volume_adjust_u8; - break; - case AUD_FORMAT_S24: - m_adjust = bigendian ? AUD_volume_adjust_s24_be : - AUD_volume_adjust_s24_le; - break; - default: - delete m_reader; - AUD_THROW(AUD_ERROR_READER); - } - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } @@ -93,9 +64,7 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer) if(m_type != AUD_FADE_OUT) { buffer = m_buffer->getBuffer(); - memset(buffer, - specs.format == AUD_FORMAT_U8 ? 0x80 : 0, - length * samplesize); + memset(buffer, 0, length * samplesize); } } else if(position / (float)specs.rate >= m_start+m_length) @@ -103,9 +72,7 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer) if(m_type == AUD_FADE_OUT) { buffer = m_buffer->getBuffer(); - memset(buffer, - specs.format == AUD_FORMAT_U8 ? 0x80 : 0, - length * samplesize); + memset(buffer, 0, length * samplesize); } } else @@ -113,19 +80,21 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer) sample_t* buf = m_buffer->getBuffer(); float volume; - for(int i = 0; i < length; i++) + for(int i = 0; i < length * specs.channels; i++) { - volume = (((position+i)/(float)specs.rate)-m_start) / m_length; - if(volume > 1.0f) - volume = 1.0f; - else if(volume < 0.0f) - volume = 0.0f; + if(i % specs.channels == 0) + { + volume = (((position+i)/(float)specs.rate)-m_start) / m_length; + if(volume > 1.0f) + volume = 1.0f; + else if(volume < 0.0f) + volume = 0.0f; - if(m_type == AUD_FADE_OUT) - volume = 1.0f - volume; + if(m_type == AUD_FADE_OUT) + volume = 1.0f - volume; + } - m_adjust(buf + i * samplesize, buffer + i * samplesize, - specs.channels, volume); + buf[i] = buffer[i] * volume; } buffer = buf; diff --git a/intern/audaspace/FX/AUD_FaderReader.h b/intern/audaspace/FX/AUD_FaderReader.h index 773643b2f5d..a75ac6e7a47 100644 --- a/intern/audaspace/FX/AUD_FaderReader.h +++ b/intern/audaspace/FX/AUD_FaderReader.h @@ -27,7 +27,6 @@ #define AUD_FADERREADER #include "AUD_EffectReader.h" -#include "AUD_ConverterFunctions.h" class AUD_Buffer; /** @@ -58,11 +57,6 @@ private: */ float m_length; - /** - * Volume adjustment function. - */ - AUD_volume_adjust_f m_adjust; - public: /** * Creates a new fader reader. diff --git a/intern/audaspace/FX/AUD_HighpassFactory.cpp b/intern/audaspace/FX/AUD_HighpassFactory.cpp new file mode 100644 index 00000000000..384d36beab7 --- /dev/null +++ b/intern/audaspace/FX/AUD_HighpassFactory.cpp @@ -0,0 +1,51 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_HighpassFactory.h" +#include "AUD_HighpassReader.h" + +AUD_HighpassFactory::AUD_HighpassFactory(AUD_IFactory* factory, float frequency, + float Q) : + AUD_EffectFactory(factory), + m_frequency(frequency), + m_Q(Q) {} + +AUD_HighpassFactory::AUD_HighpassFactory(float frequency, float Q) : + AUD_EffectFactory(0), + m_frequency(frequency), + m_Q(Q) {} + +AUD_IReader* AUD_HighpassFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + if(reader != 0) + { + reader = new AUD_HighpassReader(reader, m_frequency, m_Q); + AUD_NEW("reader") + } + + return reader; +} diff --git a/intern/audaspace/FX/AUD_HighpassFactory.h b/intern/audaspace/FX/AUD_HighpassFactory.h new file mode 100644 index 00000000000..cce21eed27d --- /dev/null +++ b/intern/audaspace/FX/AUD_HighpassFactory.h @@ -0,0 +1,66 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_HIGHPASSFACTORY +#define AUD_HIGHPASSFACTORY + +#include "AUD_EffectFactory.h" + +/** + * This factory creates a highpass filter reader. + */ +class AUD_HighpassFactory : public AUD_EffectFactory +{ +private: + /** + * The attack value in seconds. + */ + float m_frequency; + + /** + * The Q factor. + */ + float m_Q; + +public: + /** + * Creates a new highpass factory. + * \param factory The input factory. + * \param frequency The cutoff frequency. + * \param Q The Q factor. + */ + AUD_HighpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0); + + /** + * Creates a new highpass factory. + * \param frequency The cutoff frequency. + * \param Q The Q factor. + */ + AUD_HighpassFactory(float frequency, float Q = 1.0); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_HIGHPASSFACTORY diff --git a/intern/audaspace/FX/AUD_HighpassReader.cpp b/intern/audaspace/FX/AUD_HighpassReader.cpp new file mode 100644 index 00000000000..8240854fc06 --- /dev/null +++ b/intern/audaspace/FX/AUD_HighpassReader.cpp @@ -0,0 +1,112 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_HighpassReader.h" +#include "AUD_Buffer.h" + +#include +#include + +#define CC channels + channel + +AUD_HighpassReader::AUD_HighpassReader(AUD_IReader* reader, float frequency, + float Q) : + AUD_EffectReader(reader) +{ + AUD_Specs specs = reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + + m_outvalues = new AUD_Buffer(samplesize * AUD_HIGHPASS_ORDER); + AUD_NEW("buffer") + memset(m_outvalues->getBuffer(), 0, samplesize * AUD_HIGHPASS_ORDER); + + m_invalues = new AUD_Buffer(samplesize * AUD_HIGHPASS_ORDER); + AUD_NEW("buffer") + memset(m_invalues->getBuffer(), 0, samplesize * AUD_HIGHPASS_ORDER); + + m_position = 0; + + // calculate coefficients + float w0 = 2.0 * M_PI * frequency / specs.rate; + float alpha = sin(w0) / (2 * Q); + float norm = 1 + alpha; + m_coeff[0][0] = 0; + m_coeff[0][1] = -2 * cos(w0) / norm; + m_coeff[0][2] = (1 - alpha) / norm; + m_coeff[1][2] = m_coeff[1][0] = (1 + cos(w0)) / (2 * norm); + m_coeff[1][1] = (-1 - cos(w0)) / norm; +} + +AUD_HighpassReader::~AUD_HighpassReader() +{ + delete m_buffer; AUD_DELETE("buffer") + + delete m_outvalues; AUD_DELETE("buffer") + delete m_invalues; AUD_DELETE("buffer"); +} + +void AUD_HighpassReader::read(int & length, sample_t* & buffer) +{ + sample_t* buf; + sample_t* outvalues; + sample_t* invalues; + + outvalues = m_outvalues->getBuffer(); + invalues = m_invalues->getBuffer(); + + AUD_Specs specs = m_reader->getSpecs(); + + m_reader->read(length, buf); + + if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs)) + m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); + + buffer = m_buffer->getBuffer(); + int channels = specs.channels; + + for(int channel = 0; channel < channels; channel++) + { + for(int i = 0; i < length; i++) + { + invalues[m_position * CC] = buf[i * CC]; + outvalues[m_position * CC] = 0; + + for(int j = 0; j < AUD_HIGHPASS_ORDER; j++) + { + outvalues[m_position * CC] += m_coeff[1][j] * + invalues[((m_position + j) % AUD_HIGHPASS_ORDER) * CC] - + m_coeff[0][j] * + outvalues[((m_position + j) % AUD_HIGHPASS_ORDER) * CC]; + } + + buffer[i * CC] = outvalues[m_position * CC]; + + m_position = (m_position + AUD_HIGHPASS_ORDER-1) % + AUD_HIGHPASS_ORDER; + } + } +} diff --git a/intern/audaspace/FX/AUD_HighpassReader.h b/intern/audaspace/FX/AUD_HighpassReader.h new file mode 100644 index 00000000000..dc28a62e45b --- /dev/null +++ b/intern/audaspace/FX/AUD_HighpassReader.h @@ -0,0 +1,83 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_HIGHPASSREADER +#define AUD_HIGHPASSREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +#define AUD_HIGHPASS_ORDER 3 + +/** + * This class represents a highpass filter. + */ +class AUD_HighpassReader : public AUD_EffectReader +{ +private: + /** + * The playback buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The last out values buffer. + */ + AUD_Buffer *m_outvalues; + + /** + * The last in values buffer. + */ + AUD_Buffer *m_invalues; + + /** + * The position for buffer cycling. + */ + int m_position; + + /** + * Filter coefficients. + */ + float m_coeff[2][AUD_HIGHPASS_ORDER]; + +public: + /** + * Creates a new highpass reader. + * \param reader The reader to read from. + * \param frequency The cutoff frequency. + * \param Q The Q factor. + * \exception AUD_Exception Thrown if the reader specified is NULL. + */ + AUD_HighpassReader(AUD_IReader* reader, float frequency, float Q); + + /** + * Destroys the reader. + */ + virtual ~AUD_HighpassReader(); + + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_HIGHPASSREADER diff --git a/intern/audaspace/FX/AUD_LoopReader.cpp b/intern/audaspace/FX/AUD_LoopReader.cpp index 9e270321013..7d70fc20221 100644 --- a/intern/audaspace/FX/AUD_LoopReader.cpp +++ b/intern/audaspace/FX/AUD_LoopReader.cpp @@ -27,7 +27,6 @@ #include "AUD_Buffer.h" #include -#include AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) : AUD_EffectReader(reader), m_loop(loop) @@ -62,7 +61,8 @@ bool AUD_LoopReader::notify(AUD_Message &message) void AUD_LoopReader::read(int & length, sample_t* & buffer) { - int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs()); + AUD_Specs specs = m_reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); int len = length; @@ -72,10 +72,10 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer) { int pos = 0; - if(m_buffer->getSize() < length*samplesize) - m_buffer->resize(length*samplesize); + if(m_buffer->getSize() < length * samplesize) + m_buffer->resize(length * samplesize); - memcpy(m_buffer->getBuffer() + pos * samplesize, + memcpy(m_buffer->getBuffer() + pos * specs.channels, buffer, len * samplesize); pos += len; @@ -93,7 +93,7 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer) if(!len) break; - memcpy(m_buffer->getBuffer() + pos * samplesize, + memcpy(m_buffer->getBuffer() + pos * specs.channels, buffer, len * samplesize); pos += len; diff --git a/intern/audaspace/FX/AUD_LowpassFactory.cpp b/intern/audaspace/FX/AUD_LowpassFactory.cpp new file mode 100644 index 00000000000..05dc5ff3994 --- /dev/null +++ b/intern/audaspace/FX/AUD_LowpassFactory.cpp @@ -0,0 +1,51 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_LowpassFactory.h" +#include "AUD_LowpassReader.h" + +AUD_LowpassFactory::AUD_LowpassFactory(AUD_IFactory* factory, float frequency, + float Q) : + AUD_EffectFactory(factory), + m_frequency(frequency), + m_Q(Q) {} + +AUD_LowpassFactory::AUD_LowpassFactory(float frequency, float Q) : + AUD_EffectFactory(0), + m_frequency(frequency), + m_Q(Q) {} + +AUD_IReader* AUD_LowpassFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + if(reader != 0) + { + reader = new AUD_LowpassReader(reader, m_frequency, m_Q); + AUD_NEW("reader") + } + + return reader; +} diff --git a/intern/audaspace/FX/AUD_LowpassFactory.h b/intern/audaspace/FX/AUD_LowpassFactory.h new file mode 100644 index 00000000000..0455e2491e6 --- /dev/null +++ b/intern/audaspace/FX/AUD_LowpassFactory.h @@ -0,0 +1,66 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_LOWPASSFACTORY +#define AUD_LOWPASSFACTORY + +#include "AUD_EffectFactory.h" + +/** + * This factory creates a lowpass filter reader. + */ +class AUD_LowpassFactory : public AUD_EffectFactory +{ +private: + /** + * The attack value in seconds. + */ + float m_frequency; + + /** + * The Q factor. + */ + float m_Q; + +public: + /** + * Creates a new lowpass factory. + * \param factory The input factory. + * \param frequency The cutoff frequency. + * \param Q The Q factor. + */ + AUD_LowpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0); + + /** + * Creates a new lowpass factory. + * \param frequency The cutoff frequency. + * \param Q The Q factor. + */ + AUD_LowpassFactory(float frequency, float Q = 1.0); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_LOWPASSFACTORY diff --git a/intern/audaspace/FX/AUD_LowpassReader.cpp b/intern/audaspace/FX/AUD_LowpassReader.cpp new file mode 100644 index 00000000000..373d0218360 --- /dev/null +++ b/intern/audaspace/FX/AUD_LowpassReader.cpp @@ -0,0 +1,111 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_LowpassReader.h" +#include "AUD_Buffer.h" + +#include +#include + +#define CC channels + channel + +AUD_LowpassReader::AUD_LowpassReader(AUD_IReader* reader, float frequency, + float Q) : + AUD_EffectReader(reader) +{ + AUD_Specs specs = reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + + m_outvalues = new AUD_Buffer(samplesize * AUD_LOWPASS_ORDER); + AUD_NEW("buffer") + memset(m_outvalues->getBuffer(), 0, samplesize * AUD_LOWPASS_ORDER); + + m_invalues = new AUD_Buffer(samplesize * AUD_LOWPASS_ORDER); + AUD_NEW("buffer") + memset(m_invalues->getBuffer(), 0, samplesize * AUD_LOWPASS_ORDER); + + m_position = 0; + + // calculate coefficients + float w0 = 2.0 * M_PI * frequency / specs.rate; + float alpha = sin(w0) / (2 * Q); + float norm = 1 + alpha; + m_coeff[0][0] = 0; + m_coeff[0][1] = -2 * cos(w0) / norm; + m_coeff[0][2] = (1 - alpha) / norm; + m_coeff[1][2] = m_coeff[1][0] = (1 - cos(w0)) / (2 * norm); + m_coeff[1][1] = (1 - cos(w0)) / norm; +} + +AUD_LowpassReader::~AUD_LowpassReader() +{ + delete m_buffer; AUD_DELETE("buffer") + + delete m_outvalues; AUD_DELETE("buffer") + delete m_invalues; AUD_DELETE("buffer"); +} + +void AUD_LowpassReader::read(int & length, sample_t* & buffer) +{ + sample_t* buf; + sample_t* outvalues; + sample_t* invalues; + + outvalues = m_outvalues->getBuffer(); + invalues = m_invalues->getBuffer(); + + AUD_Specs specs = m_reader->getSpecs(); + + m_reader->read(length, buf); + + if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs)) + m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); + + buffer = m_buffer->getBuffer(); + int channels = specs.channels; + + for(int channel = 0; channel < channels; channel++) + { + for(int i = 0; i < length; i++) + { + invalues[m_position * CC] = buf[i * CC]; + outvalues[m_position * CC] = 0; + + for(int j = 0; j < AUD_LOWPASS_ORDER; j++) + { + outvalues[m_position * CC] += m_coeff[1][j] * + invalues[((m_position + j) % AUD_LOWPASS_ORDER) * CC] - + m_coeff[0][j] * + outvalues[((m_position + j) % AUD_LOWPASS_ORDER) * CC]; + } + + buffer[i * CC] = outvalues[m_position * CC]; + + m_position = (m_position + AUD_LOWPASS_ORDER-1) % AUD_LOWPASS_ORDER; + } + } +} diff --git a/intern/audaspace/FX/AUD_LowpassReader.h b/intern/audaspace/FX/AUD_LowpassReader.h new file mode 100644 index 00000000000..a490ba52c1c --- /dev/null +++ b/intern/audaspace/FX/AUD_LowpassReader.h @@ -0,0 +1,83 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_LOWPASSREADER +#define AUD_LOWPASSREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +#define AUD_LOWPASS_ORDER 3 + +/** + * This class represents a lowpass filter. + */ +class AUD_LowpassReader : public AUD_EffectReader +{ +private: + /** + * The playback buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The last out values buffer. + */ + AUD_Buffer *m_outvalues; + + /** + * The last in values buffer. + */ + AUD_Buffer *m_invalues; + + /** + * The position for buffer cycling. + */ + int m_position; + + /** + * Filter coefficients. + */ + float m_coeff[2][AUD_LOWPASS_ORDER]; + +public: + /** + * Creates a new lowpass reader. + * \param reader The reader to read from. + * \param frequency The cutoff frequency. + * \param Q The Q factor. + * \exception AUD_Exception Thrown if the reader specified is NULL. + */ + AUD_LowpassReader(AUD_IReader* reader, float frequency, float Q); + + /** + * Destroys the reader. + */ + virtual ~AUD_LowpassReader(); + + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_LOWPASSREADER diff --git a/intern/audaspace/FX/AUD_RectifyReader.cpp b/intern/audaspace/FX/AUD_RectifyReader.cpp index 9839aefa838..5d3ce80e811 100644 --- a/intern/audaspace/FX/AUD_RectifyReader.cpp +++ b/intern/audaspace/FX/AUD_RectifyReader.cpp @@ -26,39 +26,11 @@ #include "AUD_RectifyReader.h" #include "AUD_Buffer.h" -#include +#include AUD_RectifyReader::AUD_RectifyReader(AUD_IReader* reader) : AUD_EffectReader(reader) { - int bigendian = 1; - bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian - - switch(m_reader->getSpecs().format) - { - case AUD_FORMAT_S16: - m_rectify = AUD_rectify; - break; - case AUD_FORMAT_S32: - m_rectify = AUD_rectify; - break; - case AUD_FORMAT_FLOAT32: - m_rectify = AUD_rectify; - break; - case AUD_FORMAT_FLOAT64: - m_rectify = AUD_rectify; - break; - case AUD_FORMAT_U8: - m_rectify = AUD_rectify_u8; - break; - case AUD_FORMAT_S24: - m_rectify = bigendian ? AUD_rectify_s24_be : AUD_rectify_s24_le; - break; - default: - delete m_reader; - AUD_THROW(AUD_ERROR_READER); - } - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } @@ -73,10 +45,11 @@ void AUD_RectifyReader::read(int & length, sample_t* & buffer) AUD_Specs specs = m_reader->getSpecs(); m_reader->read(length, buf); - if(m_buffer->getSize() < length*AUD_SAMPLE_SIZE(specs)) - m_buffer->resize(length*AUD_SAMPLE_SIZE(specs)); + if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs)) + m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); buffer = m_buffer->getBuffer(); - m_rectify(buffer, buf, length * specs.channels); + for(int i = 0; i < length * specs.channels; i++) + buffer[i] = fabs(buf[i]); } diff --git a/intern/audaspace/FX/AUD_RectifyReader.h b/intern/audaspace/FX/AUD_RectifyReader.h index 17423811cdc..afbe2e59cab 100644 --- a/intern/audaspace/FX/AUD_RectifyReader.h +++ b/intern/audaspace/FX/AUD_RectifyReader.h @@ -27,7 +27,6 @@ #define AUD_RECTIFYREADER #include "AUD_EffectReader.h" -#include "AUD_ConverterFunctions.h" class AUD_Buffer; /** @@ -41,11 +40,6 @@ private: */ AUD_Buffer *m_buffer; - /** - * Rectifying function. - */ - AUD_rectify_f m_rectify; - public: /** * Creates a new rectify reader. diff --git a/intern/audaspace/FX/AUD_ReverseReader.cpp b/intern/audaspace/FX/AUD_ReverseReader.cpp index 043480b91b9..82d6c70ce53 100644 --- a/intern/audaspace/FX/AUD_ReverseReader.cpp +++ b/intern/audaspace/FX/AUD_ReverseReader.cpp @@ -65,7 +65,7 @@ int AUD_ReverseReader::getPosition() void AUD_ReverseReader::read(int & length, sample_t* & buffer) { // first correct the length - if(m_position+length > m_length) + if(m_position + length > m_length) length = m_length-m_position; if(length <= 0) @@ -74,7 +74,8 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer) return; } - int samplesize = AUD_SAMPLE_SIZE(getSpecs()); + AUD_Specs specs = getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); // resize buffer if needed if(m_buffer->getSize() < length * samplesize) @@ -86,23 +87,20 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer) int len = length; // read from reader - m_reader->seek(m_length-m_position-len); + m_reader->seek(m_length - m_position - len); m_reader->read(len, buf); // set null if reader didn't give enough data if(len < length) { - if(getSpecs().format == AUD_FORMAT_U8) - memset(buffer, 0x80, (length-len)*samplesize); - else - memset(buffer, 0, (length-len)*samplesize); - buffer += length-len; + memset(buffer, 0, (length - len) * samplesize); + buffer += (length - len) * specs.channels; } // copy the samples reverted for(int i = 0; i < len; i++) - memcpy(buffer + i * samplesize, - buf + (len - 1 - i) * samplesize, + memcpy(buffer + i * specs.channels, + buf + (len - 1 - i) * specs.channels, samplesize); m_position += length; diff --git a/intern/audaspace/FX/AUD_VolumeReader.cpp b/intern/audaspace/FX/AUD_VolumeReader.cpp index fc3f20152a6..f094c1e4ea3 100644 --- a/intern/audaspace/FX/AUD_VolumeReader.cpp +++ b/intern/audaspace/FX/AUD_VolumeReader.cpp @@ -32,35 +32,6 @@ AUD_VolumeReader::AUD_VolumeReader(AUD_IReader* reader, float volume) : AUD_EffectReader(reader), m_volume(volume) { - int bigendian = 1; - bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian - - switch(m_reader->getSpecs().format) - { - case AUD_FORMAT_S16: - m_adjust = AUD_volume_adjust; - break; - case AUD_FORMAT_S32: - m_adjust = AUD_volume_adjust; - break; - case AUD_FORMAT_FLOAT32: - m_adjust = AUD_volume_adjust; - break; - case AUD_FORMAT_FLOAT64: - m_adjust = AUD_volume_adjust; - break; - case AUD_FORMAT_U8: - m_adjust = AUD_volume_adjust_u8; - break; - case AUD_FORMAT_S24: - m_adjust = bigendian ? AUD_volume_adjust_s24_be : - AUD_volume_adjust_s24_le; - break; - default: - delete m_reader; - AUD_THROW(AUD_ERROR_READER); - } - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } @@ -93,5 +64,6 @@ void AUD_VolumeReader::read(int & length, sample_t* & buffer) buffer = m_buffer->getBuffer(); - m_adjust(buffer, buf, length * specs.channels, m_volume); + for(int i = 0; i < length * specs.channels; i++) + buffer[i] = buf[i] * m_volume; } diff --git a/intern/audaspace/FX/AUD_VolumeReader.h b/intern/audaspace/FX/AUD_VolumeReader.h index f38ae4d265c..489f85b10f2 100644 --- a/intern/audaspace/FX/AUD_VolumeReader.h +++ b/intern/audaspace/FX/AUD_VolumeReader.h @@ -27,7 +27,6 @@ #define AUD_VOLUMEREADER #include "AUD_EffectReader.h" -#include "AUD_ConverterFunctions.h" class AUD_Buffer; /** @@ -46,11 +45,6 @@ private: */ float m_volume; - /** - * Volume adjustment function. - */ - AUD_volume_adjust_f m_adjust; - public: /** * Creates a new volume reader. diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp index aa9f425d6fb..dfd5d29e4aa 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp @@ -25,7 +25,6 @@ #include "AUD_OpenALDevice.h" #include "AUD_IReader.h" -#include "AUD_IMixer.h" #include "AUD_ConverterFactory.h" #include "AUD_SourceCaps.h" @@ -119,7 +118,7 @@ void AUD_OpenALDevice::updateStreams() sample_t* buffer; ALint info; - AUD_Specs specs; + AUD_DeviceSpecs specs = m_specs; while(1) { @@ -145,7 +144,7 @@ void AUD_OpenALDevice::updateStreams() if(info) { - specs = sound->reader->getSpecs(); + specs.specs = sound->reader->getSpecs(); // for all empty buffers while(info--) @@ -177,8 +176,8 @@ void AUD_OpenALDevice::updateStreams() // fill with new data alBufferData(sound->buffers[sound->current], sound->format, - buffer, - length * AUD_SAMPLE_SIZE(specs), + buffer, length * + AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); if(alGetError() != AL_NO_ERROR) @@ -264,7 +263,7 @@ bool AUD_OpenALDevice::isValid(AUD_Handle* handle) return false; } -AUD_OpenALDevice::AUD_OpenALDevice(AUD_Specs specs, int buffersize) +AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) { // cannot determine how many channels or which format OpenAL uses, but // it at least is able to play 16 bit stereo audio @@ -289,14 +288,17 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_Specs specs, int buffersize) // check for specific formats and channel counts to be played back if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE) + { specs.format = AUD_FORMAT_FLOAT32; + m_converter = NULL; + } + else + m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory") m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE; alGetError(); - m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory") - m_specs = specs; m_buffersize = buffersize; m_playing = false; @@ -378,12 +380,13 @@ AUD_OpenALDevice::~AUD_OpenALDevice() alcDestroyContext(m_context); alcCloseDevice(m_device); - delete m_converter; AUD_DELETE("factory") + if(m_converter) + delete m_converter; AUD_DELETE("factory") pthread_mutex_destroy(&m_mutex); } -AUD_Specs AUD_OpenALDevice::getSpecs() +AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() { return m_specs; } @@ -393,45 +396,8 @@ bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs) bool valid = true; format = 0; - switch(specs.format) + switch(m_specs.format) { - case AUD_FORMAT_U8: - switch(specs.channels) - { - case AUD_CHANNELS_MONO: - format = AL_FORMAT_MONO8; - break; - case AUD_CHANNELS_STEREO: - format = AL_FORMAT_STEREO8; - break; - case AUD_CHANNELS_SURROUND4: - if(m_useMC) - { - format = alGetEnumValue("AL_FORMAT_QUAD8"); - break; - } - case AUD_CHANNELS_SURROUND51: - if(m_useMC) - { - format = alGetEnumValue("AL_FORMAT_51CHN8"); - break; - } - case AUD_CHANNELS_SURROUND61: - if(m_useMC) - { - format = alGetEnumValue("AL_FORMAT_61CHN8"); - break; - } - case AUD_CHANNELS_SURROUND71: - if(m_useMC) - { - format = alGetEnumValue("AL_FORMAT_71CHN8"); - break; - } - default: - valid = false; - } - break; case AUD_FORMAT_S16: switch(specs.channels) { @@ -591,23 +557,16 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) if(reader == NULL) AUD_THROW(AUD_ERROR_READER); - AUD_Specs specs; - - specs = reader->getSpecs(); + AUD_DeviceSpecs specs = m_specs; + specs.specs = reader->getSpecs(); // check format - bool valid = true; + bool valid = specs.channels != AUD_CHANNELS_INVALID; - if(specs.format == AUD_FORMAT_INVALID) - valid = false; - else if(specs.format == AUD_FORMAT_S24 || - specs.format == AUD_FORMAT_S32 || - specs.format == AUD_FORMAT_FLOAT32 || - specs.format == AUD_FORMAT_FLOAT64) + if(m_converter) { m_converter->setReader(reader); reader = m_converter->createReader(); - specs = reader->getSpecs(); } // create the handle @@ -618,7 +577,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) sound->isBuffered = false; sound->data_end = false; - valid &= getFormat(sound->format, specs); + valid &= getFormat(sound->format, specs.specs); if(!valid) { @@ -647,7 +606,8 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) length = m_buffersize; reader->read(length, buf); alBufferData(sound->buffers[i], sound->format, buf, - length * AUD_SAMPLE_SIZE(specs), specs.rate); + length * AUD_DEVICE_SAMPLE_SIZE(specs), + specs.rate); if(alGetError() != AL_NO_ERROR) AUD_THROW(AUD_ERROR_OPENAL); } @@ -875,14 +835,16 @@ bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position) { sample_t* buf; int length; - AUD_Specs specs = alhandle->reader->getSpecs(); + AUD_DeviceSpecs specs = m_specs; + specs.specs = alhandle->reader->getSpecs(); for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++) { length = m_buffersize; alhandle->reader->read(length, buf); alBufferData(alhandle->buffers[i], alhandle->format, - buf, length * AUD_SAMPLE_SIZE(specs), + buf, + length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); if(alGetError() != AL_NO_ERROR) @@ -1021,6 +983,7 @@ bool AUD_OpenALDevice::setCapability(int capability, void *value) // load the factory into an OpenAL buffer if(factory) { + // check if the factory is already buffered lock(); for(AUD_BFIterator i = m_bufferedFactories->begin(); i != m_bufferedFactories->end(); i++) @@ -1040,32 +1003,25 @@ bool AUD_OpenALDevice::setCapability(int capability, void *value) if(reader == NULL) return false; - AUD_Specs specs; - - specs = reader->getSpecs(); + AUD_DeviceSpecs specs = m_specs; + specs.specs = reader->getSpecs(); // determine format bool valid = reader->getType() == AUD_TYPE_BUFFER; if(valid) { - if(specs.format == AUD_FORMAT_INVALID) - valid = false; - else if(specs.format == AUD_FORMAT_S24 || - specs.format == AUD_FORMAT_S32 || - specs.format == AUD_FORMAT_FLOAT32 || - specs.format == AUD_FORMAT_FLOAT64) + if(m_converter) { m_converter->setReader(reader); reader = m_converter->createReader(); - specs = reader->getSpecs(); } } ALenum format; if(valid) - valid = getFormat(format, specs); + valid = getFormat(format, specs.specs); if(!valid) { @@ -1094,7 +1050,7 @@ bool AUD_OpenALDevice::setCapability(int capability, void *value) reader->read(length, buf); alBufferData(bf->buffer, format, buf, - length * AUD_SAMPLE_SIZE(specs), + length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); if(alGetError() != AL_NO_ERROR) AUD_THROW(AUD_ERROR_OPENAL); diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.h b/intern/audaspace/OpenAL/AUD_OpenALDevice.h index 074cd3d1924..cb8c83ab810 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.h +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.h @@ -56,7 +56,7 @@ private: /** * The specification of the device. */ - AUD_Specs m_specs; + AUD_DeviceSpecs m_specs; /** * Whether the device has the AL_EXT_MCFORMATS extension. @@ -64,8 +64,8 @@ private: bool m_useMC; /** - * The converter factory for readers with wrong input format. - */ + * The converter factory for readers with wrong input format. + */ AUD_ConverterFactory* m_converter; /** @@ -118,7 +118,7 @@ private: /** * Gets the format according to the specs. * \param format The variable to put the format into. - * \param specs The specs to read the format from. + * \param specs The specs to read the channel count from. * \return Whether the format is valid or not. */ bool getFormat(ALenum &format, AUD_Specs specs); @@ -132,7 +132,8 @@ public: * \note The buffersize will be multiplicated by three for this device. * \exception AUD_Exception Thrown if the audio device cannot be opened. */ - AUD_OpenALDevice(AUD_Specs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE); + AUD_OpenALDevice(AUD_DeviceSpecs specs, + int buffersize = AUD_DEFAULT_BUFFER_SIZE); /** * Streaming thread main function. @@ -141,7 +142,7 @@ public: virtual ~AUD_OpenALDevice(); - virtual AUD_Specs getSpecs(); + virtual AUD_DeviceSpecs getSpecs(); virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false); virtual bool pause(AUD_Handle* handle); virtual bool resume(AUD_Handle* handle); diff --git a/intern/audaspace/SDL/AUD_SDLDevice.cpp b/intern/audaspace/SDL/AUD_SDLDevice.cpp index dd443e7f5c7..1a385af8a0c 100644 --- a/intern/audaspace/SDL/AUD_SDLDevice.cpp +++ b/intern/audaspace/SDL/AUD_SDLDevice.cpp @@ -23,7 +23,6 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#include "AUD_SDLMixer.h" #include "AUD_SDLDevice.h" #include "AUD_IReader.h" @@ -31,10 +30,10 @@ void AUD_SDLDevice::SDL_mix(void *data, Uint8* buffer, int length) { AUD_SDLDevice* device = (AUD_SDLDevice*)data; - device->mix((sample_t*)buffer, length/AUD_SAMPLE_SIZE(device->m_specs)); + device->mix((data_t*)buffer,length/AUD_DEVICE_SAMPLE_SIZE(device->m_specs)); } -AUD_SDLDevice::AUD_SDLDevice(AUD_Specs specs, int buffersize) +AUD_SDLDevice::AUD_SDLDevice(AUD_DeviceSpecs specs, int buffersize) { if(specs.channels == AUD_CHANNELS_INVALID) specs.channels = AUD_CHANNELS_STEREO; @@ -69,9 +68,6 @@ AUD_SDLDevice::AUD_SDLDevice(AUD_Specs specs, int buffersize) else AUD_THROW(AUD_ERROR_SDL); - m_mixer = new AUD_SDLMixer(); AUD_NEW("mixer") - m_mixer->setSpecs(m_specs); - create(); } diff --git a/intern/audaspace/SDL/AUD_SDLDevice.h b/intern/audaspace/SDL/AUD_SDLDevice.h index e2c6f7631b7..4b7de1996e8 100644 --- a/intern/audaspace/SDL/AUD_SDLDevice.h +++ b/intern/audaspace/SDL/AUD_SDLDevice.h @@ -55,7 +55,8 @@ public: * \note The specification really used for opening the device may differ. * \exception AUD_Exception Thrown if the audio device cannot be opened. */ - AUD_SDLDevice(AUD_Specs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE); + AUD_SDLDevice(AUD_DeviceSpecs specs, + int buffersize = AUD_DEFAULT_BUFFER_SIZE); /** * Closes the SDL audio device. diff --git a/intern/audaspace/SDL/AUD_SDLMixer.cpp b/intern/audaspace/SDL/AUD_SDLMixer.cpp deleted file mode 100644 index cacc0c7063c..00000000000 --- a/intern/audaspace/SDL/AUD_SDLMixer.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * $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 . - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#include "AUD_SDLMixer.h" -#include "AUD_SDLMixerFactory.h" - -#include - -AUD_SDLMixer::AUD_SDLMixer() -{ - m_factory = NULL; -} - -AUD_SDLMixer::~AUD_SDLMixer() -{ - if(m_factory) - { - delete m_factory; AUD_DELETE("factory") - } -} - -AUD_IReader* AUD_SDLMixer::prepare(AUD_IReader* reader) -{ - m_factory->setReader(reader); - return m_factory->createReader(); -} - -void AUD_SDLMixer::setSpecs(AUD_Specs specs) -{ - m_samplesize = AUD_SAMPLE_SIZE(specs); - if(m_factory) - { - delete m_factory; AUD_DELETE("factory") - } - m_factory = new AUD_SDLMixerFactory(specs); AUD_NEW("factory") -} - -void AUD_SDLMixer::add(sample_t* buffer, AUD_Specs specs, int length, - float volume) -{ - AUD_SDLMixerBuffer buf; - buf.buffer = buffer; - buf.length = length; - buf.volume = volume; - m_buffers.push_back(buf); -} - -void AUD_SDLMixer::superpose(sample_t* buffer, int length, float volume) -{ - AUD_SDLMixerBuffer buf; - - while(!m_buffers.empty()) - { - buf = m_buffers.front(); - m_buffers.pop_front(); - SDL_MixAudio((Uint8*)buffer, - (Uint8*)buf.buffer, - buf.length * m_samplesize, - (int)(SDL_MIX_MAXVOLUME * volume * buf.volume)); - } -} diff --git a/intern/audaspace/SDL/AUD_SDLMixer.h b/intern/audaspace/SDL/AUD_SDLMixer.h deleted file mode 100644 index 2cc4e51f66d..00000000000 --- a/intern/audaspace/SDL/AUD_SDLMixer.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * $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 . - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#ifndef AUD_SDLMIXER -#define AUD_SDLMIXER - -#include "AUD_IMixer.h" -class AUD_SDLMixerFactory; -#include - -struct AUD_SDLMixerBuffer -{ - sample_t* buffer; - int length; - float volume; -}; - -/** - * This class is able to mix audiosignals with the help of SDL. - */ -class AUD_SDLMixer : public AUD_IMixer -{ -private: - /** - * The mixer factory that prepares all readers for superposition. - */ - AUD_SDLMixerFactory* m_factory; - - /** - * The list of buffers to superpose. - */ - std::list m_buffers; - - /** - * The size of an output sample. - */ - int m_samplesize; - -public: - /** - * Creates the mixer. - */ - AUD_SDLMixer(); - - virtual ~AUD_SDLMixer(); - - virtual AUD_IReader* prepare(AUD_IReader* reader); - virtual void setSpecs(AUD_Specs specs); - virtual void add(sample_t* buffer, AUD_Specs specs, int length, - float volume); - virtual void superpose(sample_t* buffer, int length, float volume); -}; - -#endif //AUD_SDLMIXER diff --git a/intern/audaspace/SDL/AUD_SDLMixerFactory.cpp b/intern/audaspace/SDL/AUD_SDLMixerFactory.cpp deleted file mode 100644 index e0b0c7d3603..00000000000 --- a/intern/audaspace/SDL/AUD_SDLMixerFactory.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * $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 . - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#include "AUD_SDLMixerFactory.h" -#include "AUD_SDLMixerReader.h" - -#include - -AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_IReader* reader, AUD_Specs specs) : - AUD_MixerFactory(reader, specs) {} - -AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_IFactory* factory, AUD_Specs specs) : - AUD_MixerFactory(factory, specs) {} - -AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_Specs specs) : - AUD_MixerFactory(specs) {} - -AUD_IReader* AUD_SDLMixerFactory::createReader() -{ - AUD_IReader* reader = getReader(); - - if(reader != 0) - { - AUD_Specs specs = reader->getSpecs(); - if(memcmp(&m_specs, &specs, sizeof(AUD_Specs)) != 0) - { - try - { - reader = new AUD_SDLMixerReader(reader, m_specs); - AUD_NEW("reader") - } - catch(AUD_Exception e) - { - // return 0 in case SDL cannot mix the source - if(e.error != AUD_ERROR_SDL) - throw; - else - reader = NULL; - } - } - } - return reader; -} diff --git a/intern/audaspace/SDL/AUD_SDLMixerFactory.h b/intern/audaspace/SDL/AUD_SDLMixerFactory.h deleted file mode 100644 index 44b36d06859..00000000000 --- a/intern/audaspace/SDL/AUD_SDLMixerFactory.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * $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 . - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#ifndef AUD_SDLMIXERFACTORY -#define AUD_SDLMIXERFACTORY - -#include "AUD_MixerFactory.h" - -/** - * This factory creates a resampling reader that uses SDL's resampling - * functionality which unfortunately is very very very limited. - */ -class AUD_SDLMixerFactory : public AUD_MixerFactory -{ -public: - AUD_SDLMixerFactory(AUD_IReader* reader, AUD_Specs specs); - AUD_SDLMixerFactory(AUD_IFactory* factory, AUD_Specs specs); - AUD_SDLMixerFactory(AUD_Specs specs); - - virtual AUD_IReader* createReader(); -}; - -#endif //AUD_SDLMIXERFACTORY diff --git a/intern/audaspace/SDL/AUD_SDLMixerReader.cpp b/intern/audaspace/SDL/AUD_SDLMixerReader.cpp deleted file mode 100644 index 0a47e36533a..00000000000 --- a/intern/audaspace/SDL/AUD_SDLMixerReader.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * $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 . - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#include "AUD_SDLMixerReader.h" -#include "AUD_Buffer.h" - -#include - -inline Uint16 AUD_TO_SDL(AUD_SampleFormat format) -{ - // SDL only supports 8 and 16 bit audio - switch(format) - { - case AUD_FORMAT_U8: - return AUDIO_U8; - case AUD_FORMAT_S16: - return AUDIO_S16SYS; - default: - AUD_THROW(AUD_ERROR_SDL); - } -} - -// greatest common divisor -inline int gcd(int a, int b) -{ - int c; - - // make sure a is the bigger - if(b > a) - { - c = b; - b = a; - a = c; - } - - // greetings from Euclides - while(b != 0) - { - c = a % b; - a = b; - b = c; - } - return a; -} - -AUD_SDLMixerReader::AUD_SDLMixerReader(AUD_IReader* reader, - AUD_Specs specs) -{ - if(reader == NULL) - AUD_THROW(AUD_ERROR_READER); - - m_reader = reader; - m_tspecs = specs; - m_sspecs = reader->getSpecs(); - - try - { - // SDL only supports 8 and 16 bit sample formats - if(SDL_BuildAudioCVT(&m_cvt, - AUD_TO_SDL(m_sspecs.format), - m_sspecs.channels, - m_sspecs.rate, - AUD_TO_SDL(specs.format), - specs.channels, - specs.rate) == -1) - AUD_THROW(AUD_ERROR_SDL); - } - catch(AUD_Exception) - { - delete m_reader; AUD_DELETE("reader") - throw; - } - - m_eor = false; - m_rsposition = 0; - m_rssize = 0; - m_ssize = m_sspecs.rate / gcd(specs.rate, m_sspecs.rate); - m_tsize = m_tspecs.rate * m_ssize / m_sspecs.rate; - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - m_rsbuffer = new AUD_Buffer(); AUD_NEW("buffer") -} - -AUD_SDLMixerReader::~AUD_SDLMixerReader() -{ - delete m_reader; AUD_DELETE("reader") - delete m_buffer; AUD_DELETE("buffer") - delete m_rsbuffer; AUD_DELETE("buffer") -} - -bool AUD_SDLMixerReader::isSeekable() -{ - return m_reader->isSeekable(); -} - -void AUD_SDLMixerReader::seek(int position) -{ - m_reader->seek(position * m_ssize / m_tsize); - m_eor = false; -} - -int AUD_SDLMixerReader::getLength() -{ - return m_reader->getLength() * m_tsize / m_ssize; -} - -int AUD_SDLMixerReader::getPosition() -{ - return m_reader->getPosition() * m_tsize / m_ssize; -} - -AUD_Specs AUD_SDLMixerReader::getSpecs() -{ - return m_tspecs; -} - -AUD_ReaderType AUD_SDLMixerReader::getType() -{ - return m_reader->getType(); -} - -bool AUD_SDLMixerReader::notify(AUD_Message &message) -{ - return m_reader->notify(message); -} - -void AUD_SDLMixerReader::read(int & length, sample_t* & buffer) -{ - // sample count for the target buffer without getting a shift - int tns = length + m_tsize - length % m_tsize; - // sample count for the source buffer without getting a shift - int sns = tns * m_ssize / m_tsize; - // target sample size - int tss = AUD_SAMPLE_SIZE(m_tspecs); - // source sample size - int sss = AUD_SAMPLE_SIZE(m_sspecs); - - // input is output buffer - int buf_size = AUD_MAX(tns*tss, sns*sss); - - // resize if necessary - if(m_rsbuffer->getSize() < buf_size) - m_rsbuffer->resize(buf_size, true); - - if(m_buffer->getSize() < length*tss) - m_buffer->resize(length*tss); - - buffer = m_buffer->getBuffer(); - int size; - int index = 0; - sample_t* buf; - - while(index < length) - { - if(m_rsposition == m_rssize) - { - // no more data - if(m_eor) - length = index; - // mix - else - { - // read from source - size = sns; - m_reader->read(size, buf); - - // prepare - m_cvt.buf = m_rsbuffer->getBuffer(); - m_cvt.len = size*sss; - memcpy(m_cvt.buf, buf, size*sss); - - // convert - SDL_ConvertAudio(&m_cvt); - - // end of reader - if(size < sns) - m_eor = true; - - m_rsposition = 0; - m_rssize = size * m_tsize / m_ssize; - } - } - - // size to copy - size = AUD_MIN(m_rssize-m_rsposition, length-index); - - // copy - memcpy(m_buffer->getBuffer() + index * tss, - m_rsbuffer->getBuffer() + m_rsposition * tss, - size*tss); - m_rsposition += size; - index += size; - } -} diff --git a/intern/audaspace/SDL/AUD_SDLMixerReader.h b/intern/audaspace/SDL/AUD_SDLMixerReader.h deleted file mode 100644 index 56668d02171..00000000000 --- a/intern/audaspace/SDL/AUD_SDLMixerReader.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * $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 . - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#ifndef AUD_SDLMIXERREADER -#define AUD_SDLMIXERREADER - -#include "AUD_IReader.h" -class AUD_Buffer; - -#include - -/** - * 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_SDLMixerReader : public AUD_IReader -{ -private: - /** - * The reader that is being mixed. - */ - AUD_IReader* m_reader; - - /** - * The current reading position in the resampling buffer. - */ - int m_rsposition; - - /** - * The count of mixed samples in the resampling buffer. - */ - int m_rssize; - - /** - * The smallest count of source samples to get a fractionless resampling - * factor. - */ - int m_ssize; - - /** - * The smallest count of target samples to get a fractionless resampling - * factor. - */ - int m_tsize; - - /** - * The sound output buffer. - */ - AUD_Buffer *m_buffer; - - /** - * The resampling buffer. - */ - AUD_Buffer *m_rsbuffer; - - /** - * The target specification. - */ - AUD_Specs m_tspecs; - - /** - * The sample specification of the source. - */ - AUD_Specs m_sspecs; - - /** - * Saves whether the end of the source has been reached. - */ - bool m_eor; - - /** - * The SDL_AudioCVT structure used for resampling. - */ - SDL_AudioCVT m_cvt; - -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_SDLMixerReader(AUD_IReader* reader, AUD_Specs specs); - /** - * Destroys the reader. - */ - ~AUD_SDLMixerReader(); - - virtual bool isSeekable(); - virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); - virtual AUD_Specs getSpecs(); - virtual AUD_ReaderType getType(); - virtual bool notify(AUD_Message &message); - virtual void read(int & length, sample_t* & buffer); -}; - -#endif //AUD_SDLMIXERREADER diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp index bcace340b24..caafbd14327 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp +++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp @@ -27,14 +27,14 @@ #include "AUD_SRCResampleReader.h" AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IReader* reader, - AUD_Specs specs) : + AUD_DeviceSpecs specs) : AUD_ResampleFactory(reader, specs) {} AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IFactory* factory, - AUD_Specs specs) : + AUD_DeviceSpecs specs) : AUD_ResampleFactory(factory, specs) {} -AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_Specs specs) : +AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_DeviceSpecs specs) : AUD_ResampleFactory(specs) {} AUD_IReader* AUD_SRCResampleFactory::createReader() @@ -45,7 +45,7 @@ AUD_IReader* AUD_SRCResampleFactory::createReader() { if(reader->getSpecs().rate != m_specs.rate) { - reader = new AUD_SRCResampleReader(reader, m_specs); + reader = new AUD_SRCResampleReader(reader, m_specs.specs); AUD_NEW("reader") } } diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.h b/intern/audaspace/SRC/AUD_SRCResampleFactory.h index c23c1d2c82e..4b16c70169c 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleFactory.h +++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.h @@ -31,14 +31,13 @@ /** * 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); + AUD_SRCResampleFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); + AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_SRCResampleFactory(AUD_DeviceSpecs specs); virtual AUD_IReader* createReader(); }; diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp index f7564d3c010..940f4245316 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp +++ b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp @@ -26,9 +26,9 @@ #include "AUD_SRCResampleReader.h" #include "AUD_Buffer.h" -#include +#include #include -#include +#include static long src_callback(void *cb_data, float **data) { @@ -41,15 +41,8 @@ AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* 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; @@ -71,9 +64,9 @@ AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader, AUD_SRCResampleReader::~AUD_SRCResampleReader() { - delete m_buffer; AUD_DELETE("buffer") - src_delete(m_src); + + delete m_buffer; AUD_DELETE("buffer") } long AUD_SRCResampleReader::doCallback(float** data) @@ -83,7 +76,7 @@ long AUD_SRCResampleReader::doCallback(float** data) m_reader->read(length, buffer); - *data = (float*)buffer; + *data = buffer; return length; } @@ -110,10 +103,12 @@ AUD_Specs AUD_SRCResampleReader::getSpecs() 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); + int size = length * AUD_SAMPLE_SIZE(m_tspecs); + + if(m_buffer->getSize() < size) + m_buffer->resize(size); buffer = m_buffer->getBuffer(); - length = src_callback_read(m_src, m_factor, length, (float*)buffer); + length = src_callback_read(m_src, m_factor, length, buffer); } diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.h b/intern/audaspace/SRC/AUD_SRCResampleReader.h index 1bacdb3965c..4fe30b48c6e 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleReader.h +++ b/intern/audaspace/SRC/AUD_SRCResampleReader.h @@ -32,13 +32,7 @@ class AUD_Buffer; #include /** - * 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. + * This resampling reader uses libsamplerate for resampling. */ class AUD_SRCResampleReader : public AUD_EffectReader { diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp index 0384ba5e0e6..027ac015eb5 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp @@ -34,26 +34,6 @@ extern "C" { #include } -// This function transforms a FFMPEG SampleFormat to our own sample format -static inline AUD_SampleFormat FFMPEG_TO_AUD(SampleFormat fmt) -{ - switch(fmt) - { - case SAMPLE_FMT_U8: - return AUD_FORMAT_U8; - case SAMPLE_FMT_S16: - return AUD_FORMAT_S16; - case SAMPLE_FMT_S32: - return AUD_FORMAT_S32; - case SAMPLE_FMT_FLT: - return AUD_FORMAT_FLOAT32; - case SAMPLE_FMT_DBL: - return AUD_FORMAT_FLOAT64; - default: - return AUD_FORMAT_INVALID; - } -} - int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer) { // save packet parameters @@ -78,11 +58,11 @@ int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer) // read samples from the packet data_size = buf_size - buf_pos; /*read_length = avcodec_decode_audio3(m_codecCtx, - (int16_t*)(buffer->getBuffer()+buf_pos), + (int16_t*)(((data_t*)buffer->getBuffer())+buf_pos), &data_size, packet);*/ read_length = avcodec_decode_audio2(m_codecCtx, - (int16_t*)(buffer->getBuffer()+buf_pos), + (int16_t*)(((data_t*)buffer->getBuffer())+buf_pos), &data_size, audio_pkg_data, audio_pkg_size); @@ -101,78 +81,108 @@ int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer) return buf_pos; } -AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename) +void AUD_FFMPEGReader::init() { m_position = 0; m_pkgbuf_left = 0; - m_byteiocontext = NULL; - // open file - if(av_open_input_file(&m_formatCtx, filename, NULL, 0, NULL)!=0) - AUD_THROW(AUD_ERROR_FILE); + if(av_find_stream_info(m_formatCtx)<0) + AUD_THROW(AUD_ERROR_FFMPEG); - try - { - if(av_find_stream_info(m_formatCtx)<0) - AUD_THROW(AUD_ERROR_FFMPEG); + // find audio stream and codec + m_stream = -1; - // find audio stream and codec - m_stream = -1; + for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++) + if((m_formatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) + && (m_stream < 0)) + { + m_stream=i; + break; + } + if(m_stream == -1) + AUD_THROW(AUD_ERROR_FFMPEG); - for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++) - if((m_formatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) - && (m_stream < 0)) - { - m_stream=i; - break; - } - if(m_stream == -1) - AUD_THROW(AUD_ERROR_FFMPEG); + m_codecCtx = m_formatCtx->streams[m_stream]->codec; - m_codecCtx = m_formatCtx->streams[m_stream]->codec; + // get a decoder and open it + AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id); + if(!aCodec) + AUD_THROW(AUD_ERROR_FFMPEG); - // get a decoder and open it - AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id); - if(!aCodec) - AUD_THROW(AUD_ERROR_FFMPEG); + if(avcodec_open(m_codecCtx, aCodec)<0) + AUD_THROW(AUD_ERROR_FFMPEG); - if(avcodec_open(m_codecCtx, aCodec)<0) - AUD_THROW(AUD_ERROR_FFMPEG); + // XXX this prints file information to stdout: + //dump_format(m_formatCtx, 0, NULL, 0); - // XXX this prints file information to stdout: - //dump_format(m_formatCtx, 0, filename, 0); + m_specs.channels = (AUD_Channels) m_codecCtx->channels; - m_specs.channels = (AUD_Channels) m_codecCtx->channels; - m_specs.format = FFMPEG_TO_AUD(m_codecCtx->sample_fmt); - m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate; - } - catch(AUD_Exception) + switch(m_codecCtx->sample_fmt) { - av_close_input_file(m_formatCtx); - throw; + case SAMPLE_FMT_U8: + m_convert = AUD_convert_u8_float; + m_specs.format = AUD_FORMAT_U8; + break; + case SAMPLE_FMT_S16: + m_convert = AUD_convert_s16_float; + m_specs.format = AUD_FORMAT_S16; + break; + case SAMPLE_FMT_S32: + m_convert = AUD_convert_s32_float; + m_specs.format = AUD_FORMAT_S32; + break; + case SAMPLE_FMT_FLT: + m_convert = AUD_convert_copy; + m_specs.format = AUD_FORMAT_FLOAT32; + break; + case SAMPLE_FMT_DBL: + m_convert = AUD_convert_double_float; + m_specs.format = AUD_FORMAT_FLOAT64; + break; + default: + AUD_THROW(AUD_ERROR_FILE); } + m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate; + // last but not least if there hasn't been any error, create the buffers m_buffer = new AUD_Buffer(); AUD_NEW("buffer") m_pkgbuf = new AUD_Buffer(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1); AUD_NEW("buffer") } +AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename) +{ + m_byteiocontext = NULL; + + // open file + if(av_open_input_file(&m_formatCtx, filename, NULL, 0, NULL)!=0) + AUD_THROW(AUD_ERROR_FILE); + + try + { + init(); + } + catch(AUD_Exception) + { + av_close_input_file(m_formatCtx); + throw; + } +} + AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference buffer) { - m_position = 0; - m_pkgbuf_left = 0; m_byteiocontext = (ByteIOContext*)av_mallocz(sizeof(ByteIOContext)); AUD_NEW("byteiocontext") m_membuffer = buffer; - if(init_put_byte(m_byteiocontext, buffer.get()->getBuffer(), buffer.get()->getSize(), 0, - NULL, NULL, NULL, NULL) != 0) + if(init_put_byte(m_byteiocontext, (data_t*)buffer.get()->getBuffer(), + buffer.get()->getSize(), 0, NULL, NULL, NULL, NULL) != 0) AUD_THROW(AUD_ERROR_FILE); AVProbeData probe_data; probe_data.filename = ""; - probe_data.buf = buffer.get()->getBuffer(); + probe_data.buf = (data_t*)buffer.get()->getBuffer(); probe_data.buf_size = buffer.get()->getSize(); AVInputFormat* fmt = av_probe_input_format(&probe_data, 1); @@ -182,38 +192,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference buffer) try { - if(av_find_stream_info(m_formatCtx)<0) - AUD_THROW(AUD_ERROR_FFMPEG); - - // find audio stream and codec - m_stream = -1; - - for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++) - if((m_formatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) - && (m_stream < 0)) - { - m_stream=i; - break; - } - if(m_stream == -1) - AUD_THROW(AUD_ERROR_FFMPEG); - - m_codecCtx = m_formatCtx->streams[m_stream]->codec; - - // get a decoder and open it - AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id); - if(!aCodec) - AUD_THROW(AUD_ERROR_FFMPEG); - - if(avcodec_open(m_codecCtx, aCodec)<0) - AUD_THROW(AUD_ERROR_FFMPEG); - - // XXX this prints stream information to stdout: - //dump_format(m_formatCtx, 0, NULL, 0); - - m_specs.channels = (AUD_Channels) m_codecCtx->channels; - m_specs.format = FFMPEG_TO_AUD(m_codecCtx->sample_fmt); - m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate; + init(); } catch(AUD_Exception) { @@ -221,11 +200,6 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference buffer) av_free(m_byteiocontext); AUD_DELETE("byteiocontext") throw; } - - // last but not least if there hasn't been any error, create the buffers - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - m_pkgbuf = new AUD_Buffer(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1); - AUD_NEW("buffer") } AUD_FFMPEGReader::~AUD_FFMPEGReader() @@ -316,7 +290,7 @@ int AUD_FFMPEGReader::getPosition() AUD_Specs AUD_FFMPEGReader::getSpecs() { - return m_specs; + return m_specs.specs; } AUD_ReaderType AUD_FFMPEGReader::getType() @@ -336,11 +310,11 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) int data_size = 0; int pkgbuf_pos; int left = length; - int sample_size = AUD_SAMPLE_SIZE(m_specs); + int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs); // resize output buffer if necessary - if(m_buffer->getSize() < length*sample_size) - m_buffer->resize(length*sample_size); + if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(m_specs)) + m_buffer->resize(length * AUD_SAMPLE_SIZE(m_specs)); buffer = m_buffer->getBuffer(); pkgbuf_pos = m_pkgbuf_left; @@ -350,8 +324,9 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) if(pkgbuf_pos > 0) { data_size = AUD_MIN(pkgbuf_pos, left * sample_size); - memcpy(buffer, m_pkgbuf->getBuffer(), data_size); - buffer += data_size; + m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(), + data_size / AUD_FORMAT_SIZE(m_specs.format)); + buffer += data_size / AUD_FORMAT_SIZE(m_specs.format); left -= data_size/sample_size; } @@ -366,8 +341,9 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) // copy to output buffer data_size = AUD_MIN(pkgbuf_pos, left * sample_size); - memcpy(buffer, m_pkgbuf->getBuffer(), data_size); - buffer += data_size; + m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(), + data_size / AUD_FORMAT_SIZE(m_specs.format)); + buffer += data_size / AUD_FORMAT_SIZE(m_specs.format); left -= data_size/sample_size; } av_free_packet(&packet); @@ -376,7 +352,8 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) if(pkgbuf_pos > data_size) { m_pkgbuf_left = pkgbuf_pos-data_size; - memmove(m_pkgbuf->getBuffer(), m_pkgbuf->getBuffer()+data_size, + memmove(m_pkgbuf->getBuffer(), + ((data_t*)m_pkgbuf->getBuffer())+data_size, pkgbuf_pos-data_size); } diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h index 6e303934f36..f992fdf7a34 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h @@ -26,6 +26,7 @@ #ifndef AUD_FFMPEGREADER #define AUD_FFMPEGREADER +#include "AUD_ConverterFunctions.h" #include "AUD_IReader.h" #include "AUD_Reference.h" class AUD_Buffer; @@ -59,7 +60,7 @@ private: /** * The specification of the audio data. */ - AUD_Specs m_specs; + AUD_DeviceSpecs m_specs; /** * The buffer for package reading. @@ -91,6 +92,11 @@ private: */ int m_stream; + /** + * Converter function. + */ + AUD_convert_f m_convert; + /** * The memory file to read from, only saved to keep the buffer alive. */ @@ -104,6 +110,11 @@ private: */ int decode(AVPacket* packet, AUD_Buffer* buffer); + /** + * Initializes the object. + */ + void init(); + public: /** * Creates a new reader. diff --git a/intern/audaspace/fftw/AUD_BandPassFactory.cpp b/intern/audaspace/fftw/AUD_BandPassFactory.cpp index 5a957081208..2950cdf8bad 100644 --- a/intern/audaspace/fftw/AUD_BandPassFactory.cpp +++ b/intern/audaspace/fftw/AUD_BandPassFactory.cpp @@ -63,16 +63,8 @@ AUD_IReader* AUD_BandPassFactory::createReader() if(reader != 0) { - if(reader->getSpecs().format == AUD_FORMAT_FLOAT32) - { - reader = new AUD_BandPassReader(reader, m_low, m_high); - AUD_NEW("reader") - } - else - { - delete reader; AUD_DELETE("reader") - return 0; - } + reader = new AUD_BandPassReader(reader, m_low, m_high); + AUD_NEW("reader") } return reader; diff --git a/intern/audaspace/fftw/AUD_BandPassReader.cpp b/intern/audaspace/fftw/AUD_BandPassReader.cpp index 34d7193866f..e77b69863f1 100644 --- a/intern/audaspace/fftw/AUD_BandPassReader.cpp +++ b/intern/audaspace/fftw/AUD_BandPassReader.cpp @@ -77,7 +77,6 @@ void AUD_BandPassReader::read(int & length, sample_t* & buffer) } m_length = length; - printf("WINDOW: %d\n", m_length); if(m_length * sizeof(double) > m_in->getSize()) { @@ -95,16 +94,15 @@ void AUD_BandPassReader::read(int & length, sample_t* & buffer) FFTW_ESTIMATE); } - float* source = (float*) buffer; double* target = (double*) m_in->getBuffer(); - float* target2 = (float*) m_buffer->getBuffer(); + sample_t* target2 = m_buffer->getBuffer(); fftw_complex* complex = (fftw_complex*) m_out->getBuffer(); float frequency; for(int channel = 0; channel < specs.channels; channel++) { for(int i = 0; i < m_length; i++) - target[i] = source[i * specs.channels + channel]; + target[i] = buffer[i * specs.channels + channel]; fftw_execute(m_forward); diff --git a/intern/audaspace/intern/AUD_Buffer.cpp b/intern/audaspace/intern/AUD_Buffer.cpp index 71deae0e87e..a8e74a023bf 100644 --- a/intern/audaspace/intern/AUD_Buffer.cpp +++ b/intern/audaspace/intern/AUD_Buffer.cpp @@ -27,14 +27,14 @@ #include "AUD_Space.h" #include -#include +#include #define AUD_ALIGN(a) (a + 16 - ((long)a & 15)) AUD_Buffer::AUD_Buffer(int size) { m_size = size; - m_buffer = (sample_t*) malloc(size+16); AUD_NEW("buffer") + m_buffer = (data_t*) malloc(size+16); AUD_NEW("buffer") } AUD_Buffer::~AUD_Buffer() @@ -44,7 +44,7 @@ AUD_Buffer::~AUD_Buffer() sample_t* AUD_Buffer::getBuffer() { - return AUD_ALIGN(m_buffer); + return (sample_t*) AUD_ALIGN(m_buffer); } int AUD_Buffer::getSize() @@ -54,7 +54,7 @@ int AUD_Buffer::getSize() void AUD_Buffer::resize(int size, bool keep) { - sample_t* buffer = (sample_t*) malloc(size+16); AUD_NEW("buffer") + data_t* buffer = (data_t*) malloc(size+16); AUD_NEW("buffer") // copy old data over if wanted if(keep) diff --git a/intern/audaspace/intern/AUD_Buffer.h b/intern/audaspace/intern/AUD_Buffer.h index 64959b03799..f745ee6154b 100644 --- a/intern/audaspace/intern/AUD_Buffer.h +++ b/intern/audaspace/intern/AUD_Buffer.h @@ -39,7 +39,7 @@ private: int m_size; /// The pointer to the buffer memory. - sample_t* m_buffer; + data_t* m_buffer; public: /** diff --git a/intern/audaspace/intern/AUD_BufferReader.cpp b/intern/audaspace/intern/AUD_BufferReader.cpp index 6cea849bdfc..0101de338bd 100644 --- a/intern/audaspace/intern/AUD_BufferReader.cpp +++ b/intern/audaspace/intern/AUD_BufferReader.cpp @@ -79,11 +79,11 @@ void AUD_BufferReader::read(int & length, sample_t* & buffer) { int sample_size = AUD_SAMPLE_SIZE(m_specs); - buffer = m_buffer.get()->getBuffer()+m_position*sample_size; + buffer = m_buffer.get()->getBuffer() + m_position * m_specs.channels; // in case the end of the buffer is reached - if(m_buffer.get()->getSize() < (m_position+length)*sample_size) - length = m_buffer.get()->getSize()/sample_size-m_position; + if(m_buffer.get()->getSize() < (m_position + length) * sample_size) + length = m_buffer.get()->getSize() / sample_size - m_position; if(length < 0) length = 0; diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp index cd6b95b1d9e..964ac2e650c 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -23,6 +23,9 @@ * ***** END LGPL LICENSE BLOCK ***** */ +#include +#include + #include "AUD_NULLDevice.h" #include "AUD_I3DDevice.h" #include "AUD_FileFactory.h" @@ -32,13 +35,18 @@ #include "AUD_PingPongFactory.h" #include "AUD_LoopFactory.h" #include "AUD_RectifyFactory.h" +#include "AUD_EnvelopeFactory.h" +#include "AUD_LinearResampleFactory.h" +#include "AUD_LowpassFactory.h" +#include "AUD_HighpassFactory.h" +#include "AUD_ChannelMapperFactory.h" +#include "AUD_Buffer.h" #include "AUD_ReadDevice.h" #include "AUD_SourceCaps.h" #include "AUD_IReader.h" #ifdef WITH_SDL #include "AUD_SDLDevice.h" -#include "AUD_FloatMixer.h" #endif #ifdef WITH_OPENAL @@ -55,7 +63,7 @@ extern "C" { } #endif -#include +#include typedef AUD_IFactory AUD_Sound; typedef AUD_ReadDevice AUD_Device; @@ -71,7 +79,7 @@ static AUD_IDevice* AUD_device = NULL; static int AUD_available_devices[4]; static AUD_I3DDevice* AUD_3ddevice = NULL; -int AUD_init(AUD_DeviceType device, AUD_Specs specs, int buffersize) +int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) { #ifdef WITH_FFMPEG av_register_all(); @@ -90,12 +98,8 @@ int AUD_init(AUD_DeviceType device, AUD_Specs specs, int buffersize) break; #ifdef WITH_SDL case AUD_SDL_DEVICE: - { - dev = new AUD_SDLDevice(specs, buffersize); - AUD_FloatMixer* mixer = new AUD_FloatMixer(); - ((AUD_SDLDevice*)dev)->setMixer(mixer); - break; - } + dev = new AUD_SDLDevice(specs, buffersize); + break; #endif #ifdef WITH_OPENAL case AUD_OPENAL_DEVICE: @@ -177,7 +181,6 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound* sound) else { info.specs.channels = AUD_CHANNELS_INVALID; - info.specs.format = AUD_FORMAT_INVALID; info.specs.rate = AUD_RATE_INVALID; info.length = 0.0; } @@ -519,7 +522,7 @@ int AUD_setSoundPitch(AUD_Handle* handle, float pitch) return false; } -AUD_Device* AUD_openReadDevice(AUD_Specs specs) +AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs) { try { @@ -578,7 +581,7 @@ int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Handle* handle, return false; } -int AUD_readDevice(AUD_Device* device, sample_t* buffer, int length) +int AUD_readDevice(AUD_Device* device, data_t* buffer, int length) { assert(device); assert(buffer); @@ -605,3 +608,43 @@ void AUD_closeReadDevice(AUD_Device* device) { } } + +float* AUD_readSoundBuffer(const char* filename, float low, float high, + float attack, float release, float threshold, + int samplerate, int* length) +{ + AUD_Buffer buffer; + AUD_DeviceSpecs specs; + specs.channels = AUD_CHANNELS_MONO; + specs.rate = (AUD_SampleRate)samplerate; + + AUD_FileFactory file(filename); + AUD_ChannelMapperFactory mapper(&file, specs); + AUD_LowpassFactory lowpass(&mapper, high); + AUD_HighpassFactory highpass(&lowpass, low); + AUD_EnvelopeFactory envelope(&highpass, attack, release, threshold, 0.1f); + AUD_LinearResampleFactory resampler(&envelope, specs); + + AUD_IReader* reader = resampler.createReader(); + + if(reader == NULL) + return NULL; + + int len; + int position = 0; + sample_t* readbuffer; + do + { + len = samplerate; + buffer.resize((position + len) * sizeof(float), true); + reader->read(len, readbuffer); + memcpy(buffer.getBuffer() + position, readbuffer, len * sizeof(float)); + position += len; + } while(len != 0); + delete reader; + + float* result = (float*)malloc(position * sizeof(float)); + memcpy(result, buffer.getBuffer(), position * sizeof(float)); + *length = position; + return result; +} diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h index 866f0248cb2..9223c870ccf 100644 --- a/intern/audaspace/intern/AUD_C-API.h +++ b/intern/audaspace/intern/AUD_C-API.h @@ -59,7 +59,7 @@ typedef struct * \param buffersize The buffersize for the device. * \return Whether the device has been initialized. */ -extern int AUD_init(AUD_DeviceType device, AUD_Specs specs, int buffersize); +extern int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize); /** * Returns a integer list with available sound devices. The last one is always @@ -304,7 +304,7 @@ extern int AUD_setSoundPitch(AUD_Handle* handle, float pitch); * \param specs The specification of the audio data. * \return A device handle. */ -extern AUD_Device* AUD_openReadDevice(AUD_Specs specs); +extern AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs); /** * Sets the main volume of a device. @@ -342,7 +342,7 @@ extern int AUD_setDeviceSoundVolume(AUD_Device* device, * played back currently, in that case the buffer is filled with * silence. */ -extern int AUD_readDevice(AUD_Device* device, sample_t* buffer, int length); +extern int AUD_readDevice(AUD_Device* device, data_t* buffer, int length); /** * Closes a read device. @@ -350,6 +350,14 @@ extern int AUD_readDevice(AUD_Device* device, sample_t* buffer, int length); */ extern void AUD_closeReadDevice(AUD_Device* device); +/** + * Reads a sound file into a newly created float buffer. + * The sound is therefore bandpassed, rectified and resampled. + */ +extern float* AUD_readSoundBuffer(const char* filename, float low, float high, + float attack, float release, float threshold, + int samplerate, int* length); + #ifdef __cplusplus } #endif diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp index 66205a58015..3420ed16649 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp @@ -29,20 +29,20 @@ #include AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IReader* reader, - AUD_Specs specs) : + AUD_DeviceSpecs specs) : AUD_MixerFactory(reader, specs) { memset(m_mapping, 0, sizeof(m_mapping)); } AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IFactory* factory, - AUD_Specs specs) : + AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) { memset(m_mapping, 0, sizeof(m_mapping)); } -AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_Specs specs) : +AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_DeviceSpecs specs) : AUD_MixerFactory(specs) { memset(m_mapping, 0, sizeof(m_mapping)); diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.h b/intern/audaspace/intern/AUD_ChannelMapperFactory.h index c2c39f4bdf6..a67bfa12123 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.h +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.h @@ -41,9 +41,9 @@ private: float **m_mapping[9]; public: - AUD_ChannelMapperFactory(AUD_IReader* reader, AUD_Specs specs); - AUD_ChannelMapperFactory(AUD_IFactory* factory, AUD_Specs specs); - AUD_ChannelMapperFactory(AUD_Specs specs); + AUD_ChannelMapperFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); + AUD_ChannelMapperFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_ChannelMapperFactory(AUD_DeviceSpecs specs); virtual ~AUD_ChannelMapperFactory(); diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp index 61f97c08a8e..4de5875a33f 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp @@ -32,12 +32,6 @@ AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader, { m_specs = reader->getSpecs(); - if(m_specs.format != AUD_FORMAT_FLOAT32) - { - delete m_reader; AUD_DELETE("reader") - AUD_THROW(AUD_ERROR_READER); - } - int channels = -1; m_rch = m_specs.channels; while(mapping[++channels] != 0); @@ -89,9 +83,9 @@ void AUD_ChannelMapperReader::read(int & length, sample_t* & buffer) if(m_buffer->getSize() < length * 4 * channels) m_buffer->resize(length * 4 * channels); - float* in = (float*)buffer; - float* out = (float*)m_buffer->getBuffer(); - float sum; + sample_t* in = buffer; + sample_t* out = m_buffer->getBuffer(); + sample_t sum; for(int i = 0; i < length; i++) { diff --git a/intern/audaspace/intern/AUD_ConverterFactory.cpp b/intern/audaspace/intern/AUD_ConverterFactory.cpp index a1a86662072..1c6d5468251 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.cpp +++ b/intern/audaspace/intern/AUD_ConverterFactory.cpp @@ -27,14 +27,14 @@ #include "AUD_ConverterReader.h" AUD_ConverterFactory::AUD_ConverterFactory(AUD_IReader* reader, - AUD_Specs specs) : + AUD_DeviceSpecs specs) : AUD_MixerFactory(reader, specs) {} AUD_ConverterFactory::AUD_ConverterFactory(AUD_IFactory* factory, - AUD_Specs specs) : + AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) {} -AUD_ConverterFactory::AUD_ConverterFactory(AUD_Specs specs) : +AUD_ConverterFactory::AUD_ConverterFactory(AUD_DeviceSpecs specs) : AUD_MixerFactory(specs) {} AUD_IReader* AUD_ConverterFactory::createReader() @@ -43,7 +43,7 @@ AUD_IReader* AUD_ConverterFactory::createReader() if(reader != 0) { - if(reader->getSpecs().format != m_specs.format) + if(m_specs.format != AUD_FORMAT_FLOAT32) { reader = new AUD_ConverterReader(reader, m_specs); AUD_NEW("reader") diff --git a/intern/audaspace/intern/AUD_ConverterFactory.h b/intern/audaspace/intern/AUD_ConverterFactory.h index 3778e8d8f03..11ca6c9f0a8 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.h +++ b/intern/audaspace/intern/AUD_ConverterFactory.h @@ -35,9 +35,9 @@ class AUD_ConverterFactory : public AUD_MixerFactory { public: - AUD_ConverterFactory(AUD_IReader* reader, AUD_Specs specs); - AUD_ConverterFactory(AUD_IFactory* factory, AUD_Specs specs); - AUD_ConverterFactory(AUD_Specs specs); + AUD_ConverterFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); + AUD_ConverterFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_ConverterFactory(AUD_DeviceSpecs specs); virtual AUD_IReader* createReader(); }; diff --git a/intern/audaspace/intern/AUD_ConverterFunctions.cpp b/intern/audaspace/intern/AUD_ConverterFunctions.cpp index 1b5d07bcc61..70018917d43 100644 --- a/intern/audaspace/intern/AUD_ConverterFunctions.cpp +++ b/intern/audaspace/intern/AUD_ConverterFunctions.cpp @@ -36,14 +36,14 @@ #define AUD_FLT_MAX 1.0 #define AUD_FLT_MIN -1.0 -void AUD_convert_u8_s16(sample_t* target, sample_t* source, int length) +void AUD_convert_u8_s16(data_t* target, data_t* source, int length) { int16_t* t = (int16_t*) target; for(int i = 0; i < length; i++) t[i] = (((int16_t)source[i]) - AUD_U8_0) << 8; } -void AUD_convert_u8_s24_be(sample_t* target, sample_t* source, int length) +void AUD_convert_u8_s24_be(data_t* target, data_t* source, int length) { for(int i = 0; i < length; i++) { @@ -53,7 +53,7 @@ void AUD_convert_u8_s24_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_u8_s24_le(sample_t* target, sample_t* source, int length) +void AUD_convert_u8_s24_le(data_t* target, data_t* source, int length) { for(int i = 0; i < length; i++) { @@ -63,35 +63,35 @@ void AUD_convert_u8_s24_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_u8_s32(sample_t* target, sample_t* source, int length) +void AUD_convert_u8_s32(data_t* target, data_t* source, int length) { int32_t* t = (int32_t*) target; for(int i = 0; i < length; i++) t[i] = (((int32_t)source[i]) - AUD_U8_0) << 24; } -void AUD_convert_u8_float(sample_t* target, sample_t* source, int length) +void AUD_convert_u8_float(data_t* target, data_t* source, int length) { float* t = (float*) target; for(int i = 0; i < length; i++) t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((float)AUD_U8_0); } -void AUD_convert_u8_double(sample_t* target, sample_t* source, int length) +void AUD_convert_u8_double(data_t* target, data_t* source, int length) { double* t = (double*) target; for(int i = 0; i < length; i++) t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((double)AUD_U8_0); } -void AUD_convert_s16_u8(sample_t* target, sample_t* source, int length) +void AUD_convert_s16_u8(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; for(int i = 0; i < length; i++) target[i] = (unsigned char)((s[i] >> 8) + AUD_U8_0); } -void AUD_convert_s16_s24_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s16_s24_be(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; for(int i = 0; i < length; i++) @@ -102,7 +102,7 @@ void AUD_convert_s16_s24_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s16_s24_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s16_s24_le(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; for(int i = 0; i < length; i++) @@ -113,7 +113,7 @@ void AUD_convert_s16_s24_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s16_s32(sample_t* target, sample_t* source, int length) +void AUD_convert_s16_s32(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; int32_t* t = (int32_t*) target; @@ -121,7 +121,7 @@ void AUD_convert_s16_s32(sample_t* target, sample_t* source, int length) t[i] = ((int32_t)s[i]) << 16; } -void AUD_convert_s16_float(sample_t* target, sample_t* source, int length) +void AUD_convert_s16_float(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; float* t = (float*) target; @@ -129,7 +129,7 @@ void AUD_convert_s16_float(sample_t* target, sample_t* source, int length) t[i] = s[i] / AUD_S16_FLT; } -void AUD_convert_s16_double(sample_t* target, sample_t* source, int length) +void AUD_convert_s16_double(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; double* t = (double*) target; @@ -137,52 +137,52 @@ void AUD_convert_s16_double(sample_t* target, sample_t* source, int length) t[i] = s[i] / AUD_S16_FLT; } -void AUD_convert_s24_u8_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_u8_be(data_t* target, data_t* source, int length) { for(int i = 0; i < length; i++) target[i] = source[i*3] ^ AUD_U8_0; } -void AUD_convert_s24_u8_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_u8_le(data_t* target, data_t* source, int length) { for(int i = 0; i < length; i++) target[i] = source[i*3+2] ^ AUD_U8_0; } -void AUD_convert_s24_s16_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_s16_be(data_t* target, data_t* source, int length) { int16_t* t = (int16_t*) target; for(int i = 0; i < length; i++) t[i] = source[i*3] << 8 | source[i*3+1]; } -void AUD_convert_s24_s16_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_s16_le(data_t* target, data_t* source, int length) { int16_t* t = (int16_t*) target; for(int i = 0; i < length; i++) t[i] = source[i*3+2] << 8 | source[i*3+1]; } -void AUD_convert_s24_s24(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_s24(data_t* target, data_t* source, int length) { memcpy(target, source, length * 3); } -void AUD_convert_s24_s32_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_s32_be(data_t* target, data_t* source, int length) { int32_t* t = (int32_t*) target; for(int i = 0; i < length; i++) t[i] = source[i*3] << 24 | source[i*3+1] << 16 | source[i*3+2] << 8; } -void AUD_convert_s24_s32_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_s32_le(data_t* target, data_t* source, int length) { int32_t* t = (int32_t*) target; for(int i = 0; i < length; i++) t[i] = source[i*3+2] << 24 | source[i*3+1] << 16 | source[i*3] << 8; } -void AUD_convert_s24_float_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_float_be(data_t* target, data_t* source, int length) { float* t = (float*) target; int32_t s; @@ -193,7 +193,7 @@ void AUD_convert_s24_float_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s24_float_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_float_le(data_t* target, data_t* source, int length) { float* t = (float*) target; int32_t s; @@ -204,7 +204,7 @@ void AUD_convert_s24_float_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s24_double_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_double_be(data_t* target, data_t* source, int length) { double* t = (double*) target; int32_t s; @@ -215,7 +215,7 @@ void AUD_convert_s24_double_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s24_double_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s24_double_le(data_t* target, data_t* source, int length) { double* t = (double*) target; int32_t s; @@ -226,14 +226,14 @@ void AUD_convert_s24_double_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s32_u8(sample_t* target, sample_t* source, int length) +void AUD_convert_s32_u8(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; for(int i = 0; i < length; i++) target[i] = (unsigned char)((s[i] >> 24) + AUD_U8_0); } -void AUD_convert_s32_s16(sample_t* target, sample_t* source, int length) +void AUD_convert_s32_s16(data_t* target, data_t* source, int length) { int16_t* t = (int16_t*) target; int32_t* s = (int32_t*) source; @@ -241,7 +241,7 @@ void AUD_convert_s32_s16(sample_t* target, sample_t* source, int length) t[i] = s[i] >> 16; } -void AUD_convert_s32_s24_be(sample_t* target, sample_t* source, int length) +void AUD_convert_s32_s24_be(data_t* target, data_t* source, int length) { int32_t* s = (int32_t*) source; for(int i = 0; i < length; i++) @@ -252,7 +252,7 @@ void AUD_convert_s32_s24_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s32_s24_le(sample_t* target, sample_t* source, int length) +void AUD_convert_s32_s24_le(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; for(int i = 0; i < length; i++) @@ -263,7 +263,7 @@ void AUD_convert_s32_s24_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_s32_float(sample_t* target, sample_t* source, int length) +void AUD_convert_s32_float(data_t* target, data_t* source, int length) { int32_t* s = (int32_t*) source; float* t = (float*) target; @@ -271,7 +271,7 @@ void AUD_convert_s32_float(sample_t* target, sample_t* source, int length) t[i] = s[i] / AUD_S32_FLT; } -void AUD_convert_s32_double(sample_t* target, sample_t* source, int length) +void AUD_convert_s32_double(data_t* target, data_t* source, int length) { int32_t* s = (int32_t*) source; double* t = (double*) target; @@ -279,7 +279,7 @@ void AUD_convert_s32_double(sample_t* target, sample_t* source, int length) t[i] = s[i] / AUD_S32_FLT; } -void AUD_convert_float_u8(sample_t* target, sample_t* source, int length) +void AUD_convert_float_u8(data_t* target, data_t* source, int length) { float* s = (float*) source; float t; @@ -295,7 +295,7 @@ void AUD_convert_float_u8(sample_t* target, sample_t* source, int length) } } -void AUD_convert_float_s16(sample_t* target, sample_t* source, int length) +void AUD_convert_float_s16(data_t* target, data_t* source, int length) { int16_t* t = (int16_t*) target; float* s = (float*) source; @@ -310,7 +310,7 @@ void AUD_convert_float_s16(sample_t* target, sample_t* source, int length) } } -void AUD_convert_float_s24_be(sample_t* target, sample_t* source, int length) +void AUD_convert_float_s24_be(data_t* target, data_t* source, int length) { int32_t t; float* s = (float*) source; @@ -328,7 +328,7 @@ void AUD_convert_float_s24_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_float_s24_le(sample_t* target, sample_t* source, int length) +void AUD_convert_float_s24_le(data_t* target, data_t* source, int length) { int32_t t; float* s = (float*) source; @@ -346,7 +346,7 @@ void AUD_convert_float_s24_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_float_s32(sample_t* target, sample_t* source, int length) +void AUD_convert_float_s32(data_t* target, data_t* source, int length) { int32_t* t = (int32_t*) target; float* s = (float*) source; @@ -361,7 +361,7 @@ void AUD_convert_float_s32(sample_t* target, sample_t* source, int length) } } -void AUD_convert_float_double(sample_t* target, sample_t* source, int length) +void AUD_convert_float_double(data_t* target, data_t* source, int length) { float* s = (float*) source; double* t = (double*) target; @@ -369,7 +369,7 @@ void AUD_convert_float_double(sample_t* target, sample_t* source, int length) t[i] = s[i]; } -void AUD_convert_double_u8(sample_t* target, sample_t* source, int length) +void AUD_convert_double_u8(data_t* target, data_t* source, int length) { double* s = (double*) source; double t; @@ -385,7 +385,7 @@ void AUD_convert_double_u8(sample_t* target, sample_t* source, int length) } } -void AUD_convert_double_s16(sample_t* target, sample_t* source, int length) +void AUD_convert_double_s16(data_t* target, data_t* source, int length) { int16_t* t = (int16_t*) target; double* s = (double*) source; @@ -400,7 +400,7 @@ void AUD_convert_double_s16(sample_t* target, sample_t* source, int length) } } -void AUD_convert_double_s24_be(sample_t* target, sample_t* source, int length) +void AUD_convert_double_s24_be(data_t* target, data_t* source, int length) { int32_t t; double* s = (double*) source; @@ -418,7 +418,7 @@ void AUD_convert_double_s24_be(sample_t* target, sample_t* source, int length) } } -void AUD_convert_double_s24_le(sample_t* target, sample_t* source, int length) +void AUD_convert_double_s24_le(data_t* target, data_t* source, int length) { int32_t t; double* s = (double*) source; @@ -436,7 +436,7 @@ void AUD_convert_double_s24_le(sample_t* target, sample_t* source, int length) } } -void AUD_convert_double_s32(sample_t* target, sample_t* source, int length) +void AUD_convert_double_s32(data_t* target, data_t* source, int length) { int32_t* t = (int32_t*) target; double* s = (double*) source; @@ -451,92 +451,10 @@ void AUD_convert_double_s32(sample_t* target, sample_t* source, int length) } } -void AUD_convert_double_float(sample_t* target, sample_t* source, int length) +void AUD_convert_double_float(data_t* target, data_t* source, int length) { double* s = (double*) source; float* t = (float*) target; for(int i = 0; i < length; i++) t[i] = s[i]; } - -void AUD_volume_adjust_u8(sample_t* target, sample_t* source, - int count, float volume) -{ - for(int i=0; i> 23) * 255) << 24; - value *= volume; - target[i+2] = value >> 16; - target[i+1] = value >> 8; - target[i] = value; - } -} - -void AUD_volume_adjust_s24_be(sample_t* target, sample_t* source, - int count, float volume) -{ - count *= 3; - int value; - - for(int i=0; i < count; i+=3) - { - value = source[i] << 16 | source[i+1] << 8 | source[i+2]; - value |= (((value & 0x800000) >> 23) * 255) << 24; - value *= volume; - target[i] = value >> 16; - target[i+1] = value >> 8; - target[i+2] = value; - } -} - -void AUD_rectify_u8(sample_t* target, sample_t* source, int count) -{ - for(int i=0; i> 23) * 255) << 24; - if(value < 0) - value = -value; - target[i+2] = value >> 16; - target[i+1] = value >> 8; - target[i] = value; - } -} - -void AUD_rectify_s24_be(sample_t* target, sample_t* source, int count) -{ - count *= 3; - int value; - - for(int i=0; i < count; i+=3) - { - value = source[i] << 16 | source[i+1] << 8 | source[i+2]; - value |= (((value & 0x800000) >> 23) * 255) << 24; - if(value < 0) - value = -value; - target[i] = value >> 16; - target[i+1] = value >> 8; - target[i+2] = value; - } -} - diff --git a/intern/audaspace/intern/AUD_ConverterFunctions.h b/intern/audaspace/intern/AUD_ConverterFunctions.h index 686e58704b7..a925f138aa2 100644 --- a/intern/audaspace/intern/AUD_ConverterFunctions.h +++ b/intern/audaspace/intern/AUD_ConverterFunctions.h @@ -41,133 +41,94 @@ #include #endif -typedef void (*AUD_convert_f)(sample_t* target, sample_t* source, int length); - -typedef void (*AUD_volume_adjust_f)(sample_t* target, sample_t* source, - int count, float volume); - -typedef void (*AUD_rectify_f)(sample_t* target, sample_t* source, int count); +typedef void (*AUD_convert_f)(data_t* target, data_t* source, int length); template -void AUD_convert_copy(sample_t* target, sample_t* source, int length) +void AUD_convert_copy(data_t* target, data_t* source, int length) { memcpy(target, source, length*sizeof(T)); } -void AUD_convert_u8_s16(sample_t* target, sample_t* source, int length); - -void AUD_convert_u8_s24_be(sample_t* target, sample_t* source, int length); - -void AUD_convert_u8_s24_le(sample_t* target, sample_t* source, int length); - -void AUD_convert_u8_s32(sample_t* target, sample_t* source, int length); - -void AUD_convert_u8_float(sample_t* target, sample_t* source, int length); - -void AUD_convert_u8_double(sample_t* target, sample_t* source, int length); - -void AUD_convert_s16_u8(sample_t* target, sample_t* source, int length); +void AUD_convert_u8_s16(data_t* target, data_t* source, int length); -void AUD_convert_s16_s24_be(sample_t* target, sample_t* source, int length); +void AUD_convert_u8_s24_be(data_t* target, data_t* source, int length); -void AUD_convert_s16_s24_le(sample_t* target, sample_t* source, int length); +void AUD_convert_u8_s24_le(data_t* target, data_t* source, int length); -void AUD_convert_s16_s32(sample_t* target, sample_t* source, int length); +void AUD_convert_u8_s32(data_t* target, data_t* source, int length); -void AUD_convert_s16_float(sample_t* target, sample_t* source, int length); +void AUD_convert_u8_float(data_t* target, data_t* source, int length); -void AUD_convert_s16_double(sample_t* target, sample_t* source, int length); +void AUD_convert_u8_double(data_t* target, data_t* source, int length); -void AUD_convert_s24_u8_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s16_u8(data_t* target, data_t* source, int length); -void AUD_convert_s24_u8_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s16_s24_be(data_t* target, data_t* source, int length); -void AUD_convert_s24_s16_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s16_s24_le(data_t* target, data_t* source, int length); -void AUD_convert_s24_s16_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s16_s32(data_t* target, data_t* source, int length); -void AUD_convert_s24_s24(sample_t* target, sample_t* source, int length); +void AUD_convert_s16_float(data_t* target, data_t* source, int length); -void AUD_convert_s24_s32_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s16_double(data_t* target, data_t* source, int length); -void AUD_convert_s24_s32_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_u8_be(data_t* target, data_t* source, int length); -void AUD_convert_s24_float_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_u8_le(data_t* target, data_t* source, int length); -void AUD_convert_s24_float_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_s16_be(data_t* target, data_t* source, int length); -void AUD_convert_s24_double_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_s16_le(data_t* target, data_t* source, int length); -void AUD_convert_s24_double_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_s24(data_t* target, data_t* source, int length); -void AUD_convert_s32_u8(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_s32_be(data_t* target, data_t* source, int length); -void AUD_convert_s32_s16(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_s32_le(data_t* target, data_t* source, int length); -void AUD_convert_s32_s24_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_float_be(data_t* target, data_t* source, int length); -void AUD_convert_s32_s24_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_float_le(data_t* target, data_t* source, int length); -void AUD_convert_s32_float(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_double_be(data_t* target, data_t* source, int length); -void AUD_convert_s32_double(sample_t* target, sample_t* source, int length); +void AUD_convert_s24_double_le(data_t* target, data_t* source, int length); -void AUD_convert_float_u8(sample_t* target, sample_t* source, int length); +void AUD_convert_s32_u8(data_t* target, data_t* source, int length); -void AUD_convert_float_s16(sample_t* target, sample_t* source, int length); +void AUD_convert_s32_s16(data_t* target, data_t* source, int length); -void AUD_convert_float_s24_be(sample_t* target, sample_t* source, int length); +void AUD_convert_s32_s24_be(data_t* target, data_t* source, int length); -void AUD_convert_float_s24_le(sample_t* target, sample_t* source, int length); +void AUD_convert_s32_s24_le(data_t* target, data_t* source, int length); -void AUD_convert_float_s32(sample_t* target, sample_t* source, int length); +void AUD_convert_s32_float(data_t* target, data_t* source, int length); -void AUD_convert_float_double(sample_t* target, sample_t* source, int length); +void AUD_convert_s32_double(data_t* target, data_t* source, int length); -void AUD_convert_double_u8(sample_t* target, sample_t* source, int length); +void AUD_convert_float_u8(data_t* target, data_t* source, int length); -void AUD_convert_double_s16(sample_t* target, sample_t* source, int length); +void AUD_convert_float_s16(data_t* target, data_t* source, int length); -void AUD_convert_double_s24_be(sample_t* target, sample_t* source, int length); +void AUD_convert_float_s24_be(data_t* target, data_t* source, int length); -void AUD_convert_double_s24_le(sample_t* target, sample_t* source, int length); +void AUD_convert_float_s24_le(data_t* target, data_t* source, int length); -void AUD_convert_double_s32(sample_t* target, sample_t* source, int length); +void AUD_convert_float_s32(data_t* target, data_t* source, int length); -void AUD_convert_double_float(sample_t* target, sample_t* source, int length); +void AUD_convert_float_double(data_t* target, data_t* source, int length); -template -void AUD_volume_adjust(sample_t* target, sample_t* source, - int count, float volume) -{ - T* t = (T*)target; - T* s = (T*)source; - for(int i=0; i < count; i++) - t[i] = (T)(s[i] * volume); -} - -void AUD_volume_adjust_u8(sample_t* target, sample_t* source, - int count, float volume); +void AUD_convert_double_u8(data_t* target, data_t* source, int length); -void AUD_volume_adjust_s24_le(sample_t* target, sample_t* source, - int count, float volume); +void AUD_convert_double_s16(data_t* target, data_t* source, int length); -void AUD_volume_adjust_s24_be(sample_t* target, sample_t* source, - int count, float volume); - -template -void AUD_rectify(sample_t* target, sample_t* source, int count) -{ - T* t = (T*)target; - T* s = (T*)source; - for(int i=0; i < count; i++) - t[i] = s[i] < 0 ? -s[i] : s[i]; -} +void AUD_convert_double_s24_be(data_t* target, data_t* source, int length); -void AUD_rectify_u8(sample_t* target, sample_t* source, int count); +void AUD_convert_double_s24_le(data_t* target, data_t* source, int length); -void AUD_rectify_s24_le(sample_t* target, sample_t* source, int count); +void AUD_convert_double_s32(data_t* target, data_t* source, int length); -void AUD_rectify_s24_be(sample_t* target, sample_t* source, int count); +void AUD_convert_double_float(data_t* target, data_t* source, int length); #endif //AUD_CONVERTERFUNCTIONS diff --git a/intern/audaspace/intern/AUD_ConverterReader.cpp b/intern/audaspace/intern/AUD_ConverterReader.cpp index da25a2b7460..808144085bb 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.cpp +++ b/intern/audaspace/intern/AUD_ConverterReader.cpp @@ -26,205 +26,37 @@ #include "AUD_ConverterReader.h" #include "AUD_Buffer.h" -AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader, AUD_Specs specs) : +AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader, + AUD_DeviceSpecs specs) : AUD_EffectReader(reader) { - m_specs = reader->getSpecs(); + m_specs.specs = reader->getSpecs(); int bigendian = 1; bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian - switch(m_specs.format) + switch(specs.format) { case AUD_FORMAT_U8: - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_copy; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_u8_s16; - break; - case AUD_FORMAT_S24: - if(bigendian) - m_convert = AUD_convert_u8_s24_be; - else - m_convert = AUD_convert_u8_s24_le; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_u8_s32; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_u8_float; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_u8_double; - break; - default: - break; - } + m_convert = AUD_convert_float_u8; break; case AUD_FORMAT_S16: - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_s16_u8; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_copy; - break; - case AUD_FORMAT_S24: - if(bigendian) - m_convert = AUD_convert_s16_s24_be; - else - m_convert = AUD_convert_s16_s24_le; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_s16_s32; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_s16_float; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_s16_double; - break; - default: - break; - } + m_convert = AUD_convert_float_s16; break; case AUD_FORMAT_S24: if(bigendian) - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_u8_s24_be; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_s16_s24_be; - break; - case AUD_FORMAT_S24: - m_convert = AUD_convert_s24_s24; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_s32_s24_be; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_float_s24_be; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_double_s24_be; - break; - default: - break; - } + m_convert = AUD_convert_float_s24_be; else - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_u8_s24_le; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_s16_s24_le; - break; - case AUD_FORMAT_S24: - m_convert = AUD_convert_s24_s24; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_s32_s24_le; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_float_s24_le; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_double_s24_le; - break; - default: - break; - } + m_convert = AUD_convert_float_s24_le; break; case AUD_FORMAT_S32: - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_s32_u8; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_s32_s16; - break; - case AUD_FORMAT_S24: - if(bigendian) - m_convert = AUD_convert_s32_s24_be; - else - m_convert = AUD_convert_s32_s24_le; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_copy; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_s32_float; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_s32_double; - break; - default: - break; - } + m_convert = AUD_convert_float_s32; break; case AUD_FORMAT_FLOAT32: - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_float_u8; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_float_s16; - break; - case AUD_FORMAT_S24: - if(bigendian) - m_convert = AUD_convert_float_s24_be; - else - m_convert = AUD_convert_float_s24_le; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_float_s32; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_copy; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_float_double; - break; - default: - break; - } + m_convert = AUD_convert_copy; break; case AUD_FORMAT_FLOAT64: - switch(specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_double_u8; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_double_s16; - break; - case AUD_FORMAT_S24: - if(bigendian) - m_convert = AUD_convert_double_s24_be; - else - m_convert = AUD_convert_double_s24_le; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_double_s32; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_double_float; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_copy; - break; - default: - break; - } + m_convert = AUD_convert_float_double; break; default: break; @@ -242,7 +74,7 @@ AUD_ConverterReader::~AUD_ConverterReader() AUD_Specs AUD_ConverterReader::getSpecs() { - return m_specs; + return m_specs.specs; } void AUD_ConverterReader::read(int & length, sample_t* & buffer) @@ -254,7 +86,8 @@ void AUD_ConverterReader::read(int & length, sample_t* & buffer) if(m_buffer->getSize() < length*samplesize) m_buffer->resize(length*samplesize); - m_convert(m_buffer->getBuffer(), buffer, length*m_specs.channels); + m_convert((data_t*)m_buffer->getBuffer(), (data_t*)buffer, + length * m_specs.channels); buffer = m_buffer->getBuffer(); } diff --git a/intern/audaspace/intern/AUD_ConverterReader.h b/intern/audaspace/intern/AUD_ConverterReader.h index f855372b636..ba49bbfd9ba 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.h +++ b/intern/audaspace/intern/AUD_ConverterReader.h @@ -44,7 +44,7 @@ private: /** * The target specification. */ - AUD_Specs m_specs; + AUD_DeviceSpecs m_specs; /** * Converter function. @@ -58,7 +58,7 @@ public: * \param specs The target specification. * \exception AUD_Exception Thrown if the reader is NULL. */ - AUD_ConverterReader(AUD_IReader* reader, AUD_Specs specs); + AUD_ConverterReader(AUD_IReader* reader, AUD_DeviceSpecs specs); /** * Destroys the reader. */ diff --git a/intern/audaspace/intern/AUD_FloatMixer.cpp b/intern/audaspace/intern/AUD_FloatMixer.cpp deleted file mode 100644 index f7133b9c30e..00000000000 --- a/intern/audaspace/intern/AUD_FloatMixer.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* - * $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 . - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#include "AUD_FloatMixer.h" -#include "AUD_ConverterFactory.h" -#include "AUD_SRCResampleFactory.h" -#include "AUD_ChannelMapperFactory.h" -#include "AUD_IReader.h" -#include "AUD_Buffer.h" - -#include - -AUD_FloatMixer::AUD_FloatMixer() -{ - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - - m_converter = NULL; - m_resampler = NULL; - m_mapper = NULL; -} - -AUD_FloatMixer::~AUD_FloatMixer() -{ - delete m_buffer; AUD_DELETE("buffer") - - if(m_converter) - { - delete m_converter; AUD_DELETE("factory") - } - if(m_resampler) - { - delete m_resampler; AUD_DELETE("factory") - } - if(m_mapper) - { - delete m_mapper; AUD_DELETE("factory") - } -} - -AUD_IReader* AUD_FloatMixer::prepare(AUD_IReader* reader) -{ - m_converter->setReader(reader); - reader = m_converter->createReader(); - - m_resampler->setReader(reader); - reader = m_resampler->createReader(); - - if(reader->getSpecs().channels != m_specs.channels) - { - m_mapper->setReader(reader); - reader = m_mapper->createReader(); - } - - return reader; -} - -void AUD_FloatMixer::setSpecs(AUD_Specs specs) -{ - m_specs = specs; - - if(m_converter) - { - delete m_converter; AUD_DELETE("factory") - } - if(m_resampler) - { - delete m_resampler; AUD_DELETE("factory") - } - if(m_mapper) - { - delete m_mapper; AUD_DELETE("factory") - } - - specs.format = AUD_FORMAT_FLOAT32; - - m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory") - m_resampler = new AUD_SRCResampleFactory(specs); AUD_NEW("factory") - m_mapper = new AUD_ChannelMapperFactory(specs); AUD_NEW("factory") - - int bigendian = 1; - bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian - - switch(m_specs.format) - { - case AUD_FORMAT_U8: - m_convert = AUD_convert_float_u8; - break; - case AUD_FORMAT_S16: - m_convert = AUD_convert_float_s16; - break; - case AUD_FORMAT_S24: - if(bigendian) - m_convert = AUD_convert_float_s24_be; - else - m_convert = AUD_convert_float_s24_le; - break; - case AUD_FORMAT_S32: - m_convert = AUD_convert_float_s32; - break; - case AUD_FORMAT_FLOAT32: - m_convert = AUD_convert_copy; - break; - case AUD_FORMAT_FLOAT64: - m_convert = AUD_convert_float_double; - break; - default: - break; - } -} - -void AUD_FloatMixer::add(sample_t* buffer, AUD_Specs specs, int length, - float volume) -{ - AUD_FloatMixerBuffer buf; - buf.buffer = buffer; - buf.length = length; - buf.volume = volume; - m_buffers.push_back(buf); -} - -void AUD_FloatMixer::superpose(sample_t* buffer, int length, float volume) -{ - AUD_FloatMixerBuffer buf; - - int channels = m_specs.channels; - - if(m_buffer->getSize() < length * channels * 4) - m_buffer->resize(length * channels * 4); - - float* out = (float*)m_buffer->getBuffer(); - float* in; - - memset(out, 0, length * channels * 4); - - int end; - - while(!m_buffers.empty()) - { - buf = m_buffers.front(); - m_buffers.pop_front(); - - end = buf.length*channels; - in = (float*) buf.buffer; - - for(int i = 0; i < end; i++) - out[i] += in[i]*buf.volume * volume; - } - - m_convert(buffer, (sample_t*) out, length * channels); -} diff --git a/intern/audaspace/intern/AUD_FloatMixer.h b/intern/audaspace/intern/AUD_FloatMixer.h deleted file mode 100644 index 728a0faf3cb..00000000000 --- a/intern/audaspace/intern/AUD_FloatMixer.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * $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 . - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#ifndef AUD_FLOATMIXER -#define AUD_FLOATMIXER - -#include "AUD_IMixer.h" -#include "AUD_ConverterFunctions.h" -class AUD_ConverterFactory; -class AUD_SRCResampleFactory; -class AUD_ChannelMapperFactory; -class AUD_Buffer; -#include - -struct AUD_FloatMixerBuffer -{ - sample_t* buffer; - int length; - float volume; -}; - -/** - * This class is able to mix two audiosignals with floats. - */ -class AUD_FloatMixer : public AUD_IMixer -{ -private: - /** - * The converter factory that converts all readers for superposition. - */ - AUD_ConverterFactory* m_converter; - - /** - * The resampling factory that resamples all readers for superposition. - */ - AUD_SRCResampleFactory* m_resampler; - - /** - * The channel mapper factory that maps all readers for superposition. - */ - AUD_ChannelMapperFactory* m_mapper; - - /** - * The list of buffers to superpose. - */ - std::list m_buffers; - - /** - * The output specification. - */ - AUD_Specs m_specs; - - /** - * The temporary mixing buffer. - */ - AUD_Buffer* m_buffer; - - /** - * Converter function. - */ - AUD_convert_f m_convert; - -public: - /** - * Creates the mixer. - */ - AUD_FloatMixer(); - - virtual ~AUD_FloatMixer(); - - virtual AUD_IReader* prepare(AUD_IReader* reader); - virtual void setSpecs(AUD_Specs specs); - virtual void add(sample_t* buffer, AUD_Specs specs, int length, - float volume); - virtual void superpose(sample_t* buffer, int length, float volume); -}; - -#endif //AUD_FLOATMIXER diff --git a/intern/audaspace/intern/AUD_IDevice.h b/intern/audaspace/intern/AUD_IDevice.h index af2cae206f3..e924f57cefc 100644 --- a/intern/audaspace/intern/AUD_IDevice.h +++ b/intern/audaspace/intern/AUD_IDevice.h @@ -53,7 +53,7 @@ public: /** * Returns the specification of the device. */ - virtual AUD_Specs getSpecs()=0; + virtual AUD_DeviceSpecs getSpecs()=0; /** * Plays a sound source. diff --git a/intern/audaspace/intern/AUD_IMixer.h b/intern/audaspace/intern/AUD_IMixer.h deleted file mode 100644 index c65e4c69cf7..00000000000 --- a/intern/audaspace/intern/AUD_IMixer.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * $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 . - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#ifndef AUD_IMIXER -#define AUD_IMIXER - -#include "AUD_Space.h" -class AUD_IReader; - -/** - * This class is able to mix audiosignals of different format and channel count. - * \note This class doesn't do resampling! - */ -class AUD_IMixer -{ -public: - /** - * Destroys the mixer. - */ - virtual ~AUD_IMixer(){} - - /** - * This funuction prepares a reader for playback. - * \param reader The reader to prepare. - * \return The reader that should be used for playback. - */ - virtual AUD_IReader* prepare(AUD_IReader* reader)=0; - - /** - * Sets the target specification for superposing. - * \param specs The target specification. - */ - virtual void setSpecs(AUD_Specs specs)=0; - - /** - * Adds a buffer for superposition. - * \param buffer The buffer to superpose. - * \param specs The specification of the buffer. - * \param start The start sample of the buffer. - * \param length The length of the buffer in samples. - * \param volume The mixing volume. Must be a value between 0.0 and 1.0. - */ - virtual void add(sample_t* buffer, AUD_Specs specs, int length, - float volume)=0; - - /** - * Superposes all added buffers into an output buffer. - * \param buffer The target buffer for superposing. - * \param length The length of the buffer in samples. - * \param volume The mixing volume. Must be a value between 0.0 and 1.0. - */ - virtual void superpose(sample_t* buffer, int length, float volume)=0; -}; - -#endif //AUD_IMIXER diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.cpp b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp new file mode 100644 index 00000000000..e738fc17693 --- /dev/null +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_LinearResampleFactory.h" +#include "AUD_LinearResampleReader.h" + +AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_IReader* reader, + AUD_DeviceSpecs specs) : + AUD_ResampleFactory(reader, specs) {} + +AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_IFactory* factory, + AUD_DeviceSpecs specs) : + AUD_ResampleFactory(factory, specs) {} + +AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_DeviceSpecs specs) : + AUD_ResampleFactory(specs) {} + +AUD_IReader* AUD_LinearResampleFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + if(reader != 0) + { + if(reader->getSpecs().rate != m_specs.rate) + { + reader = new AUD_LinearResampleReader(reader, m_specs.specs); + AUD_NEW("reader") + } + } + return reader; +} diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.h b/intern/audaspace/intern/AUD_LinearResampleFactory.h new file mode 100644 index 00000000000..81a9d623815 --- /dev/null +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.h @@ -0,0 +1,44 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_LINEARRESAMPLEFACTORY +#define AUD_LINEARRESAMPLEFACTORY + +#include "AUD_ResampleFactory.h" + +/** + * This factory creates a resampling reader that does simple linear resampling. + */ +class AUD_LinearResampleFactory : public AUD_ResampleFactory +{ +public: + AUD_LinearResampleFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); + AUD_LinearResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_LinearResampleFactory(AUD_DeviceSpecs specs); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_LINEARRESAMPLEFACTORY diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.cpp b/intern/audaspace/intern/AUD_LinearResampleReader.cpp new file mode 100644 index 00000000000..70e29b9570d --- /dev/null +++ b/intern/audaspace/intern/AUD_LinearResampleReader.cpp @@ -0,0 +1,138 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_LinearResampleReader.h" +#include "AUD_Buffer.h" + +#include +#include +#include + +AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_IReader* reader, + AUD_Specs specs) : + AUD_EffectReader(reader) +{ + m_sspecs = reader->getSpecs(); + + m_tspecs = specs; + m_tspecs.channels = m_sspecs.channels; + m_factor = (float)m_tspecs.rate / (float)m_sspecs.rate; + + m_position = 0; + m_sposition = 0; + + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + m_cache = new AUD_Buffer(2 * AUD_SAMPLE_SIZE(specs)); AUD_NEW("buffer") +} + +AUD_LinearResampleReader::~AUD_LinearResampleReader() +{ + delete m_buffer; AUD_DELETE("buffer") + delete m_cache; AUD_DELETE("buffer") +} + +void AUD_LinearResampleReader::seek(int position) +{ + m_position = position; + m_sposition = floor(position / m_factor); + m_reader->seek(m_sposition); +} + +int AUD_LinearResampleReader::getLength() +{ + return m_reader->getLength() * m_factor; +} + +int AUD_LinearResampleReader::getPosition() +{ + return m_position; +} + +AUD_Specs AUD_LinearResampleReader::getSpecs() +{ + return m_tspecs; +} + +void AUD_LinearResampleReader::read(int & length, sample_t* & buffer) +{ + int size = length * AUD_SAMPLE_SIZE(m_tspecs); + + if(m_buffer->getSize() < size) + m_buffer->resize(size); + + int need = ceil((m_position + length) / m_factor) + 1 - m_sposition; + int len = need; + sample_t* buf; + buffer = m_buffer->getBuffer(); + + m_reader->read(len, buf); + + if(len < need) + length = floor((m_sposition + len - 1) * m_factor) - m_position; + + float spos; + sample_t low, high; + int channels = m_sspecs.channels; + + for(int channel = 0; channel < channels; channel++) + { + for(int i = 0; i < length; i++) + { + spos = (m_position + i) / m_factor - m_sposition; + + if((floor(spos) < -2) || (ceil(spos) >= len)) + { + fprintf(stderr, "FATAL ERROR: REPORT THIS TO neXyon!\n"); +// exit(1); + } + + if(floor(spos) < 0) + { + low = m_cache->getBuffer()[(int)(floor(spos) + 2) * channels + + channel]; + if(ceil(spos) < 0) + high = m_cache->getBuffer()[(int)(ceil(spos) + 2) + * channels + channel]; + else + high = buf[(int)ceil(spos) * channels + channel]; + } + else + { + low = buf[(int)floor(spos) * channels + channel]; + high = buf[(int)ceil(spos) * channels + channel]; + } + buffer[i * channels + channel] = low + (spos - floor(spos)) * + (high - low); + } + } + + if(len > 1) + memcpy(m_cache->getBuffer(), buf + (len - 2) * channels, 2 * channels); + else if(len == 1) + memcpy(m_cache->getBuffer() + 1 * channels, buf, channels); + + m_sposition += len; + m_position += length; +} diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.h b/intern/audaspace/intern/AUD_LinearResampleReader.h new file mode 100644 index 00000000000..c86b8b76c59 --- /dev/null +++ b/intern/audaspace/intern/AUD_LinearResampleReader.h @@ -0,0 +1,94 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_LINEARRESAMPLEREADER +#define AUD_LINEARRESAMPLEREADER + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +/** + * This resampling reader uses libsamplerate for resampling. + */ +class AUD_LinearResampleReader : public AUD_EffectReader +{ +private: + /** + * The resampling factor. + */ + float m_factor; + + /** + * The current position. + */ + int m_position; + + /** + * The current reading source position. + */ + int m_sposition; + + /** + * The sound output buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The input caching buffer. + */ + AUD_Buffer *m_cache; + + /** + * The target specification. + */ + AUD_Specs m_tspecs; + + /** + * The sample specification of the source. + */ + AUD_Specs m_sspecs; + +public: + /** + * Creates a resampling reader. + * \param reader The reader to mix. + * \param specs The target specification. + * \exception AUD_Exception Thrown if the reader is NULL. + */ + AUD_LinearResampleReader(AUD_IReader* reader, AUD_Specs specs); + + /** + * Destroys the reader. + */ + ~AUD_LinearResampleReader(); + + 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_LINEARRESAMPLEREADER diff --git a/intern/audaspace/intern/AUD_Mixer.cpp b/intern/audaspace/intern/AUD_Mixer.cpp new file mode 100644 index 00000000000..bddc719b179 --- /dev/null +++ b/intern/audaspace/intern/AUD_Mixer.cpp @@ -0,0 +1,156 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_Mixer.h" +#include "AUD_SRCResampleFactory.h" +#include "AUD_ChannelMapperFactory.h" +#include "AUD_IReader.h" +#include "AUD_Buffer.h" + +#include + +AUD_Mixer::AUD_Mixer() +{ + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + + m_resampler = NULL; + m_mapper = NULL; +} + +AUD_Mixer::~AUD_Mixer() +{ + delete m_buffer; AUD_DELETE("buffer") + + + if(m_resampler) + { + delete m_resampler; AUD_DELETE("factory") + } + if(m_mapper) + { + delete m_mapper; AUD_DELETE("factory") + } +} + +AUD_IReader* AUD_Mixer::prepare(AUD_IReader* reader) +{ + m_resampler->setReader(reader); + reader = m_resampler->createReader(); + + if(reader->getSpecs().channels != m_specs.channels) + { + m_mapper->setReader(reader); + reader = m_mapper->createReader(); + } + + return reader; +} + +void AUD_Mixer::setSpecs(AUD_DeviceSpecs specs) +{ + m_specs = specs; + + if(m_resampler) + { + delete m_resampler; AUD_DELETE("factory") + } + if(m_mapper) + { + delete m_mapper; AUD_DELETE("factory") + } + + m_resampler = new AUD_SRCResampleFactory(specs); AUD_NEW("factory") + m_mapper = new AUD_ChannelMapperFactory(specs); AUD_NEW("factory") + + int bigendian = 1; + bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian + + switch(m_specs.format) + { + case AUD_FORMAT_U8: + m_convert = AUD_convert_float_u8; + break; + case AUD_FORMAT_S16: + m_convert = AUD_convert_float_s16; + break; + case AUD_FORMAT_S24: + if(bigendian) + m_convert = AUD_convert_float_s24_be; + else + m_convert = AUD_convert_float_s24_le; + break; + case AUD_FORMAT_S32: + m_convert = AUD_convert_float_s32; + break; + case AUD_FORMAT_FLOAT32: + m_convert = AUD_convert_copy; + break; + case AUD_FORMAT_FLOAT64: + m_convert = AUD_convert_float_double; + break; + default: + break; + } +} + +void AUD_Mixer::add(sample_t* buffer, int length, float volume) +{ + AUD_MixerBuffer buf; + buf.buffer = buffer; + buf.length = length; + buf.volume = volume; + m_buffers.push_back(buf); +} + +void AUD_Mixer::superpose(data_t* buffer, int length, float volume) +{ + AUD_MixerBuffer buf; + + int channels = m_specs.channels; + + if(m_buffer->getSize() < length * channels * 4) + m_buffer->resize(length * channels * 4); + + sample_t* out = m_buffer->getBuffer(); + sample_t* in; + + memset(out, 0, length * channels * 4); + + int end; + + while(!m_buffers.empty()) + { + buf = m_buffers.front(); + m_buffers.pop_front(); + + end = buf.length*channels; + in = buf.buffer; + + for(int i = 0; i < end; i++) + out[i] += in[i]*buf.volume * volume; + } + + m_convert(buffer, (data_t*) out, length * channels); +} diff --git a/intern/audaspace/intern/AUD_Mixer.h b/intern/audaspace/intern/AUD_Mixer.h new file mode 100644 index 00000000000..5097b9ec2a6 --- /dev/null +++ b/intern/audaspace/intern/AUD_Mixer.h @@ -0,0 +1,125 @@ +/* + * $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 . + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_MIXER +#define AUD_MIXER + +#include "AUD_ConverterFunctions.h" +class AUD_ConverterFactory; +class AUD_SRCResampleFactory; +class AUD_ChannelMapperFactory; +class AUD_Buffer; +class AUD_IReader; +#include + +struct AUD_MixerBuffer +{ + sample_t* buffer; + int length; + float volume; +}; + +/** + * This class is able to mix audiosignals of different channel count and sample + * rate and convert it to a specific output format. + * It uses a default ChannelMapperFactory and a SRCResampleFactory for + * the perparation. + */ +class AUD_Mixer +{ +private: + /** + * The resampling factory that resamples all readers for superposition. + */ + AUD_SRCResampleFactory* m_resampler; + + /** + * The channel mapper factory that maps all readers for superposition. + */ + AUD_ChannelMapperFactory* m_mapper; + + /** + * The list of buffers to superpose. + */ + std::list m_buffers; + + /** + * The output specification. + */ + AUD_DeviceSpecs m_specs; + + /** + * The temporary mixing buffer. + */ + AUD_Buffer* m_buffer; + + /** + * Converter function. + */ + AUD_convert_f m_convert; + +public: + /** + * Creates the mixer. + */ + AUD_Mixer(); + + /** + * Destroys the mixer. + */ + ~AUD_Mixer(); + + /** + * This funuction prepares a reader for playback. + * \param reader The reader to prepare. + * \return The reader that should be used for playback. + */ + AUD_IReader* prepare(AUD_IReader* reader); + + /** + * Sets the target specification for superposing. + * \param specs The target specification. + */ + void setSpecs(AUD_DeviceSpecs specs); + + /** + * Adds a buffer for superposition. + * \param buffer The buffer to superpose. + * \param start The start sample of the buffer. + * \param length The length of the buffer in samples. + * \param volume The mixing volume. Must be a value between 0.0 and 1.0. + */ + void add(sample_t* buffer, int length, float volume); + + /** + * Superposes all added buffers into an output buffer. + * \param buffer The target buffer for superposing. + * \param length The length of the buffer in samples. + * \param volume The mixing volume. Must be a value between 0.0 and 1.0. + */ + void superpose(data_t* buffer, int length, float volume); +}; + +#endif //AUD_MIXER diff --git a/intern/audaspace/intern/AUD_MixerFactory.cpp b/intern/audaspace/intern/AUD_MixerFactory.cpp index db38d1004db..e78818301fa 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.cpp +++ b/intern/audaspace/intern/AUD_MixerFactory.cpp @@ -49,7 +49,7 @@ AUD_IReader* AUD_MixerFactory::getReader() } AUD_MixerFactory::AUD_MixerFactory(AUD_IReader* reader, - AUD_Specs specs) + AUD_DeviceSpecs specs) { m_specs = specs; m_reader = reader; @@ -57,14 +57,14 @@ AUD_MixerFactory::AUD_MixerFactory(AUD_IReader* reader, } AUD_MixerFactory::AUD_MixerFactory(AUD_IFactory* factory, - AUD_Specs specs) + AUD_DeviceSpecs specs) { m_specs = specs; m_reader = 0; m_factory = factory; } -AUD_MixerFactory::AUD_MixerFactory(AUD_Specs specs) +AUD_MixerFactory::AUD_MixerFactory(AUD_DeviceSpecs specs) { m_specs = specs; m_reader = 0; @@ -79,12 +79,12 @@ AUD_MixerFactory::~AUD_MixerFactory() } } -AUD_Specs AUD_MixerFactory::getSpecs() +AUD_DeviceSpecs AUD_MixerFactory::getSpecs() { return m_specs; } -void AUD_MixerFactory::setSpecs(AUD_Specs specs) +void AUD_MixerFactory::setSpecs(AUD_DeviceSpecs specs) { m_specs = specs; } diff --git a/intern/audaspace/intern/AUD_MixerFactory.h b/intern/audaspace/intern/AUD_MixerFactory.h index c61dd283c67..a2f4aa78d76 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.h +++ b/intern/audaspace/intern/AUD_MixerFactory.h @@ -47,7 +47,7 @@ protected: /** * The target specification for resampling. */ - AUD_Specs m_specs; + AUD_DeviceSpecs m_specs; /** * Returns the reader created out of the factory or taken from m_reader. @@ -63,20 +63,20 @@ public: * \param reader The reader to mix. * \param specs The target specification. */ - AUD_MixerFactory(AUD_IReader* reader, AUD_Specs specs); + AUD_MixerFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); /** * Creates a new factory. * \param factory The factory to create the readers to mix out of. * \param specs The target specification. */ - AUD_MixerFactory(AUD_IFactory* factory, AUD_Specs specs); + AUD_MixerFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); /** * Creates a new factory. * \param specs The target specification. */ - AUD_MixerFactory(AUD_Specs specs); + AUD_MixerFactory(AUD_DeviceSpecs specs); /** * Destroys the resampling factory. @@ -86,13 +86,13 @@ public: /** * Returns the target specification for resampling. */ - AUD_Specs getSpecs(); + AUD_DeviceSpecs getSpecs(); /** * Sets the target specification for resampling. * \param specs The specification. */ - void setSpecs(AUD_Specs specs); + void setSpecs(AUD_DeviceSpecs specs); /** * Sets the reader for resampling. diff --git a/intern/audaspace/intern/AUD_NULLDevice.cpp b/intern/audaspace/intern/AUD_NULLDevice.cpp index d237b71b67e..3936695c28f 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.cpp +++ b/intern/audaspace/intern/AUD_NULLDevice.cpp @@ -34,7 +34,7 @@ AUD_NULLDevice::AUD_NULLDevice() m_specs.rate = AUD_RATE_INVALID; } -AUD_Specs AUD_NULLDevice::getSpecs() +AUD_DeviceSpecs AUD_NULLDevice::getSpecs() { return m_specs; } diff --git a/intern/audaspace/intern/AUD_NULLDevice.h b/intern/audaspace/intern/AUD_NULLDevice.h index 155f24f8837..91ddd23cf71 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.h +++ b/intern/audaspace/intern/AUD_NULLDevice.h @@ -37,7 +37,7 @@ private: /** * The specs of the device. */ - AUD_Specs m_specs; + AUD_DeviceSpecs m_specs; public: /** @@ -45,7 +45,7 @@ public: */ AUD_NULLDevice(); - virtual AUD_Specs getSpecs(); + virtual AUD_DeviceSpecs getSpecs(); virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false); virtual bool pause(AUD_Handle* handle); virtual bool resume(AUD_Handle* handle); diff --git a/intern/audaspace/intern/AUD_ReadDevice.cpp b/intern/audaspace/intern/AUD_ReadDevice.cpp index e2c1d2fac81..37a7d1ae295 100644 --- a/intern/audaspace/intern/AUD_ReadDevice.cpp +++ b/intern/audaspace/intern/AUD_ReadDevice.cpp @@ -23,17 +23,17 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#include "AUD_FloatMixer.h" +#include "AUD_Mixer.h" #include "AUD_ReadDevice.h" #include "AUD_IReader.h" #include -AUD_ReadDevice::AUD_ReadDevice(AUD_Specs specs) +AUD_ReadDevice::AUD_ReadDevice(AUD_DeviceSpecs specs) { m_specs = specs; - m_mixer = new AUD_FloatMixer(); AUD_NEW("mixer") + m_mixer = new AUD_Mixer(); AUD_NEW("mixer") m_mixer->setSpecs(m_specs); m_playing = false; @@ -46,15 +46,15 @@ AUD_ReadDevice::~AUD_ReadDevice() destroy(); } -bool AUD_ReadDevice::read(sample_t* buffer, int length) +bool AUD_ReadDevice::read(data_t* buffer, int length) { if(m_playing) mix(buffer, length); else if(m_specs.format == AUD_FORMAT_U8) - memset(buffer, 0x80, length * AUD_SAMPLE_SIZE(m_specs)); + memset(buffer, 0x80, length * AUD_DEVICE_SAMPLE_SIZE(m_specs)); else - memset(buffer, 0, length * AUD_SAMPLE_SIZE(m_specs)); + memset(buffer, 0, length * AUD_DEVICE_SAMPLE_SIZE(m_specs)); return m_playing; } diff --git a/intern/audaspace/intern/AUD_ReadDevice.h b/intern/audaspace/intern/AUD_ReadDevice.h index d69b0c31ea5..3fd90df7755 100644 --- a/intern/audaspace/intern/AUD_ReadDevice.h +++ b/intern/audaspace/intern/AUD_ReadDevice.h @@ -47,7 +47,7 @@ public: * Creates a new read device. * \param specs The wanted audio specification. */ - AUD_ReadDevice(AUD_Specs specs); + AUD_ReadDevice(AUD_DeviceSpecs specs); /** * Closes the device. @@ -62,7 +62,7 @@ public: * played back currently, in that case the buffer is filled with * silence. */ - bool read(sample_t* buffer, int length); + bool read(data_t* buffer, int length); }; #endif //AUD_READDEVICE diff --git a/intern/audaspace/intern/AUD_SinusReader.cpp b/intern/audaspace/intern/AUD_SinusReader.cpp index 87e2f789d66..83a1a3ed3c3 100644 --- a/intern/audaspace/intern/AUD_SinusReader.cpp +++ b/intern/audaspace/intern/AUD_SinusReader.cpp @@ -26,7 +26,7 @@ #include "AUD_SinusReader.h" #include "AUD_Buffer.h" -#include +#include #ifndef M_PI #define M_PI 3.14159265358979323846 @@ -69,8 +69,7 @@ AUD_Specs AUD_SinusReader::getSpecs() { AUD_Specs specs; specs.rate = m_sampleRate; - specs.format = AUD_FORMAT_S16; - specs.channels = AUD_CHANNELS_STEREO; + specs.channels = AUD_CHANNELS_MONO; return specs; } @@ -87,18 +86,16 @@ bool AUD_SinusReader::notify(AUD_Message &message) void AUD_SinusReader::read(int & length, sample_t* & buffer) { // resize if necessary - if(m_buffer->getSize() < length*4) - m_buffer->resize(length*4); + if(m_buffer->getSize() < length * sizeof(sample_t)) + m_buffer->resize(length * sizeof(sample_t)); // fill with sine data - short* buf = (short*) m_buffer->getBuffer(); - for(int i=0; i < length; i++) + buffer = m_buffer->getBuffer(); + for(int i = 0; i < length; i++) { - buf[i*2] = sin((m_position + i) * 2.0 * M_PI * m_frequency / - (float)m_sampleRate) * 32700; - buf[i*2+1] = buf[i*2]; + buffer[i] = sin((m_position + i) * 2.0 * M_PI * m_frequency / + (float)m_sampleRate); } - buffer = (sample_t*)buf; m_position += length; } diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp index 42a90a6f15e..142251c7e2d 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp +++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp @@ -25,7 +25,7 @@ #include "AUD_SoftwareDevice.h" #include "AUD_IReader.h" -#include "AUD_IMixer.h" +#include "AUD_Mixer.h" #include "AUD_IFactory.h" #include "AUD_SourceCaps.h" @@ -52,6 +52,8 @@ void AUD_SoftwareDevice::create() m_pausedSounds = new std::list(); AUD_NEW("list") m_playback = false; m_volume = 1.0; + m_mixer = new AUD_Mixer(); AUD_NEW("mixer") + m_mixer->setSpecs(m_specs); pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); @@ -90,7 +92,7 @@ void AUD_SoftwareDevice::destroy() pthread_mutex_destroy(&m_mutex); } -void AUD_SoftwareDevice::mix(sample_t* buffer, int length) +void AUD_SoftwareDevice::mix(data_t* buffer, int length) { lock(); @@ -98,7 +100,7 @@ void AUD_SoftwareDevice::mix(sample_t* buffer, int length) AUD_SoftwareHandle* sound; int len; sample_t* buf; - int sample_size = AUD_SAMPLE_SIZE(m_specs); + int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs); std::list stopSounds; // for all sounds @@ -114,7 +116,7 @@ void AUD_SoftwareDevice::mix(sample_t* buffer, int length) len = length; sound->reader->read(len, buf); - m_mixer->add(buf, sound->reader->getSpecs(), len, sound->volume); + m_mixer->add(buf, len, sound->volume); // in case the end of the sound is reached if(len < length) @@ -159,14 +161,7 @@ bool AUD_SoftwareDevice::isValid(AUD_Handle* handle) return false; } -void AUD_SoftwareDevice::setMixer(AUD_IMixer* mixer) -{ - delete m_mixer; AUD_DELETE("mixer") - m_mixer = mixer; - mixer->setSpecs(m_specs); -} - -AUD_Specs AUD_SoftwareDevice::getSpecs() +AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() { return m_specs; } diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h index 3768786fa9c..a12fddb1e00 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.h +++ b/intern/audaspace/intern/AUD_SoftwareDevice.h @@ -28,7 +28,7 @@ #include "AUD_IDevice.h" struct AUD_SoftwareHandle; -class AUD_IMixer; +class AUD_Mixer; #include #include @@ -47,12 +47,12 @@ protected: /** * The specification of the device. */ - AUD_Specs m_specs; + AUD_DeviceSpecs m_specs; /** - * The mixer. Will be deleted by the destroy function. + * The mixer. */ - AUD_IMixer* m_mixer; + AUD_Mixer* m_mixer; /** * Initializes member variables. @@ -69,7 +69,7 @@ protected: * \param buffer The target buffer. * \param length The length in samples to be filled. */ - void mix(sample_t* buffer, int length); + void mix(data_t* buffer, int length); /** * This function tells the device, to start or pause playback. @@ -111,13 +111,7 @@ private: bool isValid(AUD_Handle* handle); public: - /** - * Sets a new mixer. - * \param mixer The new mixer. - */ - void setMixer(AUD_IMixer* mixer); - - virtual AUD_Specs getSpecs(); + virtual AUD_DeviceSpecs getSpecs(); virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false); virtual bool pause(AUD_Handle* handle); virtual bool resume(AUD_Handle* handle); diff --git a/intern/audaspace/intern/AUD_Space.h b/intern/audaspace/intern/AUD_Space.h index 123d9c272a0..1d60be3979b 100644 --- a/intern/audaspace/intern/AUD_Space.h +++ b/intern/audaspace/intern/AUD_Space.h @@ -28,8 +28,10 @@ /// The size of a format in bytes. #define AUD_FORMAT_SIZE(format) (format & 0x0F) +/// The size of a sample in the specified device format in bytes. +#define AUD_DEVICE_SAMPLE_SIZE(specs) (specs.channels * (specs.format & 0x0F)) /// The size of a sample in the specified format in bytes. -#define AUD_SAMPLE_SIZE(specs) (specs.channels * (specs.format & 0x0F)) +#define AUD_SAMPLE_SIZE(specs) (specs.channels * sizeof(sample_t)) /// Throws a AUD_Exception with the provided error code. #define AUD_THROW(exception) { AUD_Exception e; e.error = exception; throw e; } @@ -233,22 +235,42 @@ typedef enum AUD_3DSS_CONE_OUTER_GAIN /// Cone outer gain. } AUD_3DSourceSetting; -/// Sample pointer type. -typedef unsigned char sample_t; +/// Sample type.(float samples) +typedef float sample_t; -/// Specification of a sound source or device. +/// Sample data type (format samples) +typedef unsigned char data_t; + +/// Specification of a sound source. typedef struct { /// Sample rate in Hz. AUD_SampleRate rate; - /// Sample format. - AUD_SampleFormat format; - /// Channel count. AUD_Channels channels; } AUD_Specs; +/// Specification of a sound device. +typedef struct +{ + /// Sample format. + AUD_SampleFormat format; + + union + { + struct + { + /// Sample rate in Hz. + AUD_SampleRate rate; + + /// Channel count. + AUD_Channels channels; + }; + AUD_Specs specs; + }; +} AUD_DeviceSpecs; + /// Exception structure. typedef struct { diff --git a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp index 11391fa4a08..4d2cd9e2505 100644 --- a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp +++ b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp @@ -61,9 +61,9 @@ AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory) // read more length = size-index; reader->read(length, buffer); - memcpy(m_buffer.get()->getBuffer()+index*sample_size, + memcpy(m_buffer.get()->getBuffer() + index * m_specs.channels, buffer, - length*sample_size); + length * sample_size); size += AUD_BUFFER_RESIZE_BYTES / sample_size; index += length; } diff --git a/intern/audaspace/jack/AUD_JackDevice.cpp b/intern/audaspace/jack/AUD_JackDevice.cpp index 4d8ab93d672..acd37de870c 100644 --- a/intern/audaspace/jack/AUD_JackDevice.cpp +++ b/intern/audaspace/jack/AUD_JackDevice.cpp @@ -23,7 +23,7 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#include "AUD_FloatMixer.h" +#include "AUD_Mixer.h" #include "AUD_JackDevice.h" #include "AUD_IReader.h" #include "AUD_Buffer.h" @@ -38,7 +38,7 @@ int AUD_JackDevice::jack_mix(jack_nframes_t length, void *data) unsigned int samplesize = AUD_SAMPLE_SIZE(device->m_specs); if(device->m_buffer->getSize() < samplesize * length) device->m_buffer->resize(samplesize * length); - device->mix(device->m_buffer->getBuffer(), length); + device->mix((data_t*)device->m_buffer->getBuffer(), length); float* in = (float*) device->m_buffer->getBuffer(); float* out; @@ -60,7 +60,7 @@ void AUD_JackDevice::jack_shutdown(void *data) device->m_valid = false; } -AUD_JackDevice::AUD_JackDevice(AUD_Specs specs) +AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs) { if(specs.channels == AUD_CHANNELS_INVALID) specs.channels = AUD_CHANNELS_STEREO; @@ -123,9 +123,6 @@ AUD_JackDevice::AUD_JackDevice(AUD_Specs specs) free(ports); } - m_mixer = new AUD_FloatMixer(); AUD_NEW("mixer") - m_mixer->setSpecs(m_specs); - m_valid = true; create(); diff --git a/intern/audaspace/jack/AUD_JackDevice.h b/intern/audaspace/jack/AUD_JackDevice.h index f0c887a2f43..5a073a69432 100644 --- a/intern/audaspace/jack/AUD_JackDevice.h +++ b/intern/audaspace/jack/AUD_JackDevice.h @@ -81,7 +81,7 @@ public: * \param specs The wanted audio specification, where only the channel count is important. * \exception AUD_Exception Thrown if the audio device cannot be opened. */ - AUD_JackDevice(AUD_Specs specs); + AUD_JackDevice(AUD_DeviceSpecs specs); /** * Closes the Jack client. diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.cpp b/intern/audaspace/sndfile/AUD_SndFileReader.cpp index 485818552bb..f9ed8d6388e 100644 --- a/intern/audaspace/sndfile/AUD_SndFileReader.cpp +++ b/intern/audaspace/sndfile/AUD_SndFileReader.cpp @@ -28,31 +28,14 @@ #include -// This function transforms a SampleFormat to our own sample format -static inline AUD_SampleFormat SNDFILE_TO_AUD(int fmt) -{ - switch(fmt & SF_FORMAT_SUBMASK) - { - // only read s16, s32 and double as they are - case SF_FORMAT_PCM_16: - return AUD_FORMAT_S16; - case SF_FORMAT_PCM_32: - return AUD_FORMAT_S32; - case SF_FORMAT_DOUBLE: - return AUD_FORMAT_FLOAT64; - // read all other formats as floats - default: - return AUD_FORMAT_FLOAT32; - } -} - sf_count_t AUD_SndFileReader::vio_get_filelen(void *user_data) { AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; return reader->m_membuffer.get()->getSize(); } -sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence, void *user_data) +sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence, + void *user_data) { AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; @@ -72,14 +55,16 @@ sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence, void *user return reader->m_memoffset; } -sf_count_t AUD_SndFileReader::vio_read(void *ptr, sf_count_t count, void *user_data) +sf_count_t AUD_SndFileReader::vio_read(void *ptr, sf_count_t count, + void *user_data) { AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; if(reader->m_memoffset + count > reader->m_membuffer.get()->getSize()) count = reader->m_membuffer.get()->getSize() - reader->m_memoffset; - memcpy(ptr, reader->m_membuffer.get()->getBuffer() + reader->m_memoffset, count); + memcpy(ptr, ((data_t*)reader->m_membuffer.get()->getBuffer()) + + reader->m_memoffset, count); reader->m_memoffset += count; return count; @@ -103,27 +88,11 @@ AUD_SndFileReader::AUD_SndFileReader(const char* filename) AUD_THROW(AUD_ERROR_FILE); m_specs.channels = (AUD_Channels) sfinfo.channels; - m_specs.format = SNDFILE_TO_AUD(sfinfo.format); m_specs.rate = (AUD_SampleRate) sfinfo.samplerate; m_length = sfinfo.frames; m_seekable = sfinfo.seekable; m_position = 0; - switch(m_specs.format) - { - case AUD_FORMAT_S16: - m_read = (sf_read_f) sf_readf_short; - break; - case AUD_FORMAT_S32: - m_read = (sf_read_f) sf_readf_int; - break; - case AUD_FORMAT_FLOAT64: - m_read = (sf_read_f) sf_readf_double; - break; - default: - m_read = (sf_read_f) sf_readf_float; - } - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } @@ -147,27 +116,11 @@ AUD_SndFileReader::AUD_SndFileReader(AUD_Reference buffer) AUD_THROW(AUD_ERROR_FILE); m_specs.channels = (AUD_Channels) sfinfo.channels; - m_specs.format = SNDFILE_TO_AUD(sfinfo.format); m_specs.rate = (AUD_SampleRate) sfinfo.samplerate; m_length = sfinfo.frames; m_seekable = sfinfo.seekable; m_position = 0; - switch(m_specs.format) - { - case AUD_FORMAT_S16: - m_read = (sf_read_f) sf_readf_short; - break; - case AUD_FORMAT_S32: - m_read = (sf_read_f) sf_readf_int; - break; - case AUD_FORMAT_FLOAT64: - m_read = (sf_read_f) sf_readf_double; - break; - default: - m_read = (sf_read_f) sf_readf_float; - } - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } @@ -227,7 +180,7 @@ void AUD_SndFileReader::read(int & length, sample_t* & buffer) buffer = m_buffer->getBuffer(); - length = m_read(m_sndfile, buffer, length); + length = sf_readf_float(m_sndfile, buffer, length); m_position += length; } diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.h b/intern/audaspace/sndfile/AUD_SndFileReader.h index da890ef53ca..8886b6e9efc 100644 --- a/intern/audaspace/sndfile/AUD_SndFileReader.h +++ b/intern/audaspace/sndfile/AUD_SndFileReader.h @@ -70,11 +70,6 @@ private: */ SNDFILE* m_sndfile; - /** - * The reading function. - */ - sf_read_f m_read; - /** * The virtual IO structure for memory file reading. */ diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 64ce1983e7d..8722485b97d 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -73,7 +73,7 @@ void sound_update_playing(struct bContext *C); void sound_scrub(struct bContext *C); #ifdef AUD_CAPI -AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end, float volume); +AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, int end, float volume); #endif void sound_stop_all(struct bContext *C); diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index aa81cea79f5..767834159b2 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -3792,7 +3792,7 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo info = AUD_getInfo(sound->handle); - if (info.specs.format == AUD_FORMAT_INVALID) { + if (info.specs.channels == AUD_CHANNELS_INVALID) { sound_delete(C, sound); //if(op) // BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 74c6afdc018..3232e2677b5 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -40,7 +40,7 @@ void sound_disable() void sound_init() { - AUD_Specs specs; + AUD_DeviceSpecs specs; int device, buffersize; device = U.audiodevice; @@ -455,7 +455,7 @@ void sound_scrub(struct bContext *C) } } -AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end, float volume) +AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, int end, float volume) { AUD_Device* mixdown = AUD_openReadDevice(specs); SoundHandle *handle; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 417679417e4..5b58f0bfedc 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -832,7 +832,7 @@ int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, Repo if(ffmpeg_multiplex_audio && audio_stream) { AVCodecContext* c = get_codec_from_stream(audio_stream); - AUD_Specs specs; + AUD_DeviceSpecs specs; specs.channels = c->channels; specs.format = AUD_FORMAT_S16; specs.rate = rd->ffcodecdata.audio_mixrate; diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 3b42fc7b382..d48a322f562 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -81,7 +81,7 @@ static int open_exec(bContext *C, wmOperator *op) info = AUD_getInfo(sound->handle); - if (info.specs.format == AUD_FORMAT_INVALID) { + if (info.specs.channels == AUD_CHANNELS_INVALID) { sound_delete(C, sound); BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); return OPERATOR_CANCELLED; diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 8ac3f2efefb..607425665af 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -36,6 +36,8 @@ #include #endif +#include "AUD_C-API.h" + #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" @@ -990,6 +992,139 @@ void GRAPH_OT_bake (wmOperatorType *ot) // todo: add props for start/end frames } +/* ******************** Sound Bake F-Curve Operator *********************** */ +/* This operator bakes the given sound to the selected F-Curves */ + +/* ------------------- */ + +/* Custom data storage passed to the F-Sample-ing function, + * which provides the necessary info for baking the sound + */ +typedef struct tSoundBakeInfo { + float* samples; + int length; + int cfra; +} tSoundBakeInfo; + +/* ------------------- */ + +/* Sampling callback used to determine the value from the sound to + * save in the F-Curve at the specified frame + */ +static float fcurve_samplingcb_sound (FCurve *fcu, void *data, float evaltime) +{ + tSoundBakeInfo *sbi= (tSoundBakeInfo *)data; + + int position = evaltime - sbi->cfra; + if((position < 0) || (position >= sbi->length)) + return 0.0f; + + return sbi->samples[position]; +} + +/* ------------------- */ + +static int graphkeys_sound_bake_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + tSoundBakeInfo sbi; + Scene *scene= NULL; + int start, end; + + char path[FILE_MAX]; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + RNA_string_get(op->ptr, "path", path); + + scene= ac.scene; /* current scene */ + + /* store necessary data for the baking steps */ + sbi.samples = AUD_readSoundBuffer(path, + RNA_float_get(op->ptr, "low"), + RNA_float_get(op->ptr, "high"), + RNA_float_get(op->ptr, "attack"), + RNA_float_get(op->ptr, "release"), + RNA_float_get(op->ptr, "threshold"), + FPS, &sbi.length); + + if (sbi.samples == NULL) { + BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); + return OPERATOR_CANCELLED; + } + + /* determine extents of the baking */ + sbi.cfra = start = CFRA; + end = CFRA + sbi.length - 1; + + /* filter anim channels */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* loop through all selected F-Curves, replacing its data with the sound samples */ + for (ale= anim_data.first; ale; ale= ale->next) { + FCurve *fcu= (FCurve *)ale->key_data; + + /* sample the sound */ + fcurve_store_samples(fcu, &sbi, start, end, fcurve_samplingcb_sound); + } + + /* free sample data */ + free(sbi.samples); + + /* admin and redraws */ + BLI_freelistN(&anim_data); + + /* validate keyframes after editing */ + ANIM_editkeyframes_refresh(&ac); + + /* set notifier that 'keyframes' have changed */ + WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); + + return OPERATOR_FINISHED; +} + +static int graphkeys_sound_bake_invoke (bContext *C, wmOperator *op, wmEvent *event) +{ + bAnimContext ac; + + /* verify editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + return WM_operator_filesel(C, op, event); +} + +void GRAPH_OT_sound_bake (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Bake Sound to F-Curves"; + ot->idname= "GRAPH_OT_sound_bake"; + ot->description= "Bakes a sound wave to selected F-Curves."; + + /* api callbacks */ + ot->invoke= graphkeys_sound_bake_invoke; + ot->exec= graphkeys_sound_bake_exec; + ot->poll= graphop_selected_fcurve_poll; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_filesel(ot, FOLDERFILE|SOUNDFILE|MOVIEFILE, FILE_SPECIAL); + RNA_def_float(ot->srna, "low", 0.0f, 0.0, 100000.0, "Lowest frequency", "", 0.1, 1000.00); + RNA_def_float(ot->srna, "high", 100000.0, 0.0, 100000.0, "Highest frequency", "", 0.1, 1000.00); + RNA_def_float(ot->srna, "attack", 0.005, 0.0, 2.0, "Attack time", "", 0.01, 0.1); + RNA_def_float(ot->srna, "release", 0.2, 0.0, 5.0, "Release time", "", 0.01, 0.2); + RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold", "", 0.01, 0.1); +} + /* ******************** Sample Keyframes Operator *********************** */ /* This operator 'bakes' the values of the curve into new keyframes between pairs * of selected keyframes. It is useful for creating keyframes for tweaking overlap. diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index 87e03247353..ec6f38c93b7 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -100,6 +100,7 @@ void GRAPH_OT_delete(struct wmOperatorType *ot); void GRAPH_OT_clean(struct wmOperatorType *ot); void GRAPH_OT_sample(struct wmOperatorType *ot); void GRAPH_OT_bake(struct wmOperatorType *ot); +void GRAPH_OT_sound_bake(struct wmOperatorType *ot); void GRAPH_OT_smooth(struct wmOperatorType *ot); void GRAPH_OT_handle_type(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 295ee869979..7be2d7b3e4b 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -247,6 +247,7 @@ void graphedit_operatortypes(void) WM_operatortype_append(GRAPH_OT_extrapolation_type); WM_operatortype_append(GRAPH_OT_sample); WM_operatortype_append(GRAPH_OT_bake); + WM_operatortype_append(GRAPH_OT_sound_bake); WM_operatortype_append(GRAPH_OT_smooth); WM_operatortype_append(GRAPH_OT_clean); WM_operatortype_append(GRAPH_OT_delete); -- cgit v1.2.3