From ed4029d07a75a36c2aa3f50770bb749753bcd8ec Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Mon, 28 Dec 2009 10:15:35 +0000 Subject: Sound: * Fixed minor errors in AUD_BufferReader.cpp and AUD_LoopFactory.h * Added a first version of a bandpass filter using fftw3 --- intern/audaspace/CMakeLists.txt | 13 +-- intern/audaspace/FX/AUD_LoopFactory.h | 2 +- intern/audaspace/SConscript | 5 + intern/audaspace/fftw/AUD_BandPassFactory.cpp | 79 ++++++++++++++++ intern/audaspace/fftw/AUD_BandPassFactory.h | 88 ++++++++++++++++++ intern/audaspace/fftw/AUD_BandPassReader.cpp | 126 ++++++++++++++++++++++++++ intern/audaspace/fftw/AUD_BandPassReader.h | 99 ++++++++++++++++++++ intern/audaspace/intern/AUD_BufferReader.cpp | 2 +- 8 files changed, 406 insertions(+), 8 deletions(-) create mode 100644 intern/audaspace/fftw/AUD_BandPassFactory.cpp create mode 100644 intern/audaspace/fftw/AUD_BandPassFactory.h create mode 100644 intern/audaspace/fftw/AUD_BandPassReader.cpp create mode 100644 intern/audaspace/fftw/AUD_BandPassReader.h (limited to 'intern') diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt index 587ef30979b..0965a467201 100644 --- a/intern/audaspace/CMakeLists.txt +++ b/intern/audaspace/CMakeLists.txt @@ -40,11 +40,6 @@ IF(WITH_OPENAL) SET(INC ${INC} OpenAL ${OPENAL_INCLUDE_DIR}) FILE(GLOB OPENALSRC OpenAL/*.cpp) ADD_DEFINITIONS(-DWITH_OPENAL) - - STRING(REGEX MATCH ".*ramework.*" FRAMEWORK ${OPENAL_INCLUDE_DIR}) - IF(FRAMEWORK) - ADD_DEFINITIONS(-DAPPLE_FRAMEWORK_FIX) - ENDIF(FRAMEWORK) ENDIF(WITH_OPENAL) IF(WITH_JACK) @@ -59,6 +54,12 @@ IF(WITH_SNDFILE) ADD_DEFINITIONS(-DWITH_SNDFILE) ENDIF(WITH_SNDFILE) -SET(SRC ${SRC} ${FFMPEGSRC} ${SNDFILESRC} ${SDLSRC} ${OPENALSRC} ${JACKSRC}) +IF(WITH_FFTW3) + SET(INC ${INC} fftw ${FFTW3_INC}) + FILE(GLOB FFTW3SRC fftw/*.cpp) + ADD_DEFINITIONS(-DWITH_FFTW3) +ENDIF(WITH_FFTW3) + +SET(SRC ${SRC} ${FFMPEGSRC} ${SNDFILESRC} ${FFTW3SRC} ${SDLSRC} ${OPENALSRC} ${JACKSRC}) BLENDERLIB(bf_audaspace "${SRC}" "${INC}") diff --git a/intern/audaspace/FX/AUD_LoopFactory.h b/intern/audaspace/FX/AUD_LoopFactory.h index 461d8c9ab69..c81d906b82e 100644 --- a/intern/audaspace/FX/AUD_LoopFactory.h +++ b/intern/audaspace/FX/AUD_LoopFactory.h @@ -38,7 +38,7 @@ private: /** * The loop count. */ - float m_loop; + int m_loop; public: /** diff --git a/intern/audaspace/SConscript b/intern/audaspace/SConscript index 025fa5a2379..ac3f8ca71a0 100644 --- a/intern/audaspace/SConscript +++ b/intern/audaspace/SConscript @@ -31,4 +31,9 @@ if env['WITH_BF_SNDFILE']: incs += ' sndfile ' + env['BF_SNDFILE_INC'] defs.append('WITH_SNDFILE') +if env['WITH_BF_FFTW3']: + sources += env.Glob('fftw/*.cpp') + incs += ' fftw ' + env['BF_FFTW3_INC'] + defs.append('WITH_FFTW3') + env.BlenderLib ('bf_audaspace', sources, Split(incs), defs, libtype=['intern','player'], priority = [25,215] ) diff --git a/intern/audaspace/fftw/AUD_BandPassFactory.cpp b/intern/audaspace/fftw/AUD_BandPassFactory.cpp new file mode 100644 index 00000000000..5a957081208 --- /dev/null +++ b/intern/audaspace/fftw/AUD_BandPassFactory.cpp @@ -0,0 +1,79 @@ +/* + * $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_BandPassFactory.h" +#include "AUD_BandPassReader.h" + +AUD_BandPassFactory::AUD_BandPassFactory(AUD_IFactory* factory, float low, + float high) : + AUD_EffectFactory(factory), + m_low(low), + m_high(high) {} + +AUD_BandPassFactory::AUD_BandPassFactory(float low, float high) : + AUD_EffectFactory(0), + m_low(low), + m_high(high) {} + +float AUD_BandPassFactory::getLow() +{ + return m_low; +} + +float AUD_BandPassFactory::getHigh() +{ + return m_high; +} + +void AUD_BandPassFactory::setLow(float low) +{ + m_low = low; +} + +void AUD_BandPassFactory::setHigh(float high) +{ + m_high = high; +} + +AUD_IReader* AUD_BandPassFactory::createReader() +{ + AUD_IReader* reader = getReader(); + + 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; + } + } + + return reader; +} diff --git a/intern/audaspace/fftw/AUD_BandPassFactory.h b/intern/audaspace/fftw/AUD_BandPassFactory.h new file mode 100644 index 00000000000..6e1e686bc3c --- /dev/null +++ b/intern/audaspace/fftw/AUD_BandPassFactory.h @@ -0,0 +1,88 @@ +/* + * $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_BANDPASSFACTORY +#define AUD_BANDPASSFACTORY + +#include "AUD_EffectFactory.h" + +/** + * This factory creates a band pass filter for a sound wave. + */ +class AUD_BandPassFactory : public AUD_EffectFactory +{ +private: + /** + * The lowest frequency to be passed. + */ + float m_low; + + /** + * The highest frequency to be passed. + */ + float m_high; + +public: + /** + * Creates a new band pass factory. + * \param factory The input factory. + * \param low The lowest passed frequency. + * \param high The highest passed frequency. + */ + AUD_BandPassFactory(AUD_IFactory* factory, float low, float high); + + /** + * Creates a new band pass factory. + * \param low The lowest passed frequency. + * \param high The highest passed frequency. + */ + AUD_BandPassFactory(float low, float high); + + /** + * Returns the lowest passed frequency. + */ + float getLow(); + + /** + * Returns the highest passed frequency. + */ + float getHigh(); + + /** + * Sets the lowest passed frequency. + * \param low The lowest passed frequency. + */ + void setLow(float low); + + /** + * Sets the highest passed frequency. + * \param high The highest passed frequency. + */ + void setHigh(float hight); + + virtual AUD_IReader* createReader(); +}; + +#endif //AUD_BANDPASSFACTORY diff --git a/intern/audaspace/fftw/AUD_BandPassReader.cpp b/intern/audaspace/fftw/AUD_BandPassReader.cpp new file mode 100644 index 00000000000..34d7193866f --- /dev/null +++ b/intern/audaspace/fftw/AUD_BandPassReader.cpp @@ -0,0 +1,126 @@ +/* + * $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_BandPassReader.h" +#include "AUD_Buffer.h" + +#include +#include + +AUD_BandPassReader::AUD_BandPassReader(AUD_IReader* reader, float low, + float high) : + AUD_EffectReader(reader), m_low(low), m_high(high) +{ + m_buffer = new AUD_Buffer(); AUD_NEW("buffer") + m_in = new AUD_Buffer(); AUD_NEW("buffer") + m_out = new AUD_Buffer(); AUD_NEW("buffer") + m_length = 0; +} + +AUD_BandPassReader::~AUD_BandPassReader() +{ + if(m_length != 0) + { + fftw_destroy_plan(m_forward); + fftw_destroy_plan(m_backward); + } + + delete m_buffer; AUD_DELETE("buffer") + delete m_in; AUD_DELETE("buffer") + delete m_out; AUD_DELETE("buffer") +} + +AUD_ReaderType AUD_BandPassReader::getType() +{ + return m_reader->getType(); +} + +void AUD_BandPassReader::read(int & length, sample_t* & buffer) +{ + AUD_Specs specs = m_reader->getSpecs(); + + m_reader->read(length, buffer); + + if(length > 0) + { + if(length * AUD_SAMPLE_SIZE(specs) > m_buffer->getSize()) + m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); + + if(length != m_length) + { + if(m_length != 0) + { + fftw_destroy_plan(m_forward); + fftw_destroy_plan(m_backward); + } + + m_length = length; + printf("WINDOW: %d\n", m_length); + + if(m_length * sizeof(double) > m_in->getSize()) + { + m_in->resize(m_length * sizeof(double)); + m_out->resize((m_length / 2 + 1) * sizeof(fftw_complex)); + } + + m_forward = fftw_plan_dft_r2c_1d(m_length, + (double*)m_in->getBuffer(), + (fftw_complex*)m_out->getBuffer(), + FFTW_ESTIMATE); + m_backward = fftw_plan_dft_c2r_1d(m_length, + (fftw_complex*)m_out->getBuffer(), + (double*)m_in->getBuffer(), + FFTW_ESTIMATE); + } + + float* source = (float*) buffer; + double* target = (double*) m_in->getBuffer(); + float* target2 = (float*) 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]; + + fftw_execute(m_forward); + + for(int i = 0; i < m_length / 2 + 1; i++) + { + frequency = i * specs.rate / (m_length / 2.0 + 1.0); + if((frequency < m_low) || (frequency > m_high)) + complex[i][0] = complex[i][1] = 0.0; + } + + fftw_execute(m_backward); + + for(int i = 0; i < m_length; i++) + target2[i * specs.channels + channel] = target[i] / m_length; + } + } + + buffer = m_buffer->getBuffer(); +} diff --git a/intern/audaspace/fftw/AUD_BandPassReader.h b/intern/audaspace/fftw/AUD_BandPassReader.h new file mode 100644 index 00000000000..7a8fd3b94d5 --- /dev/null +++ b/intern/audaspace/fftw/AUD_BandPassReader.h @@ -0,0 +1,99 @@ +/* + * $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_BANDPASSREADER +#define AUD_BANDPASSREADER + +#include + +#include "AUD_EffectReader.h" +class AUD_Buffer; + +/** + * This class only passes a specific frequency band of another reader. + */ +class AUD_BandPassReader : public AUD_EffectReader +{ +private: + /** + * The playback buffer. + */ + AUD_Buffer *m_buffer; + + /** + * The input buffer for fourier transformations. + */ + AUD_Buffer *m_in; + + /** + * The output buffer for fourier transformations. + */ + AUD_Buffer *m_out; + + /** + * The lowest passed frequency. + */ + float m_low; + + /** + * The highest passed frequency. + */ + float m_high; + + /** + * The fftw plan for forward transformation. + */ + fftw_plan m_forward; + + /** + * The fftw plan for backward transformation. + */ + fftw_plan m_backward; + + /** + * The length of the plans. + */ + int m_length; + +public: + /** + * Creates a new band pass reader. + * \param reader The reader to read from. + * \param low The lowest passed frequency. + * \param high The highest passed frequency. + * \exception AUD_Exception Thrown if the reader specified is NULL. + */ + AUD_BandPassReader(AUD_IReader* reader, float low, float high); + + /** + * Destroys the reader. + */ + virtual ~AUD_BandPassReader(); + + virtual AUD_ReaderType getType(); + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_BANDPASSREADER diff --git a/intern/audaspace/intern/AUD_BufferReader.cpp b/intern/audaspace/intern/AUD_BufferReader.cpp index 47bf5d3d171..6cea849bdfc 100644 --- a/intern/audaspace/intern/AUD_BufferReader.cpp +++ b/intern/audaspace/intern/AUD_BufferReader.cpp @@ -81,7 +81,7 @@ void AUD_BufferReader::read(int & length, sample_t* & buffer) buffer = m_buffer.get()->getBuffer()+m_position*sample_size; - // in case the end of the buffer is reach + // 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; -- cgit v1.2.3