Sound:
authorJoerg Mueller <nexyon@gmail.com>
Mon, 28 Dec 2009 10:15:35 +0000 (10:15 +0000)
committerJoerg Mueller <nexyon@gmail.com>
Mon, 28 Dec 2009 10:15:35 +0000 (10:15 +0000)
* 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
intern/audaspace/FX/AUD_LoopFactory.h
intern/audaspace/SConscript
intern/audaspace/fftw/AUD_BandPassFactory.cpp [new file with mode: 0644]
intern/audaspace/fftw/AUD_BandPassFactory.h [new file with mode: 0644]
intern/audaspace/fftw/AUD_BandPassReader.cpp [new file with mode: 0644]
intern/audaspace/fftw/AUD_BandPassReader.h [new file with mode: 0644]
intern/audaspace/intern/AUD_BufferReader.cpp

index 587ef30..0965a46 100644 (file)
@@ -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}")
index 461d8c9..c81d906 100644 (file)
@@ -38,7 +38,7 @@ private:
        /**
         * The loop count.
         */
-       float m_loop;
+       int m_loop;
 
 public:
        /**
index 025fa5a..ac3f8ca 100644 (file)
@@ -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 (file)
index 0000000..5a95708
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ *
+ * ***** 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 (file)
index 0000000..6e1e686
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ *
+ * ***** 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 (file)
index 0000000..34d7193
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_BandPassReader.h"
+#include "AUD_Buffer.h"
+
+#include <cstring>
+#include <stdio.h>
+
+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 (file)
index 0000000..7a8fd3b
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_BANDPASSREADER
+#define AUD_BANDPASSREADER
+
+#include <fftw3.h>
+
+#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
index 47bf5d3..6cea849 100644 (file)
@@ -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;