noise.cpp

Go to the documentation of this file.
00001 #include <algorithm>
00002 #include <stdlib.h>
00003 #include "basic_source.h"
00004 #include "internal.h"
00005 #include "types.h"
00006 
00007 namespace audiere {
00008 
00009   class WhiteNoise : public BasicSource {
00010   public:
00011     void ADR_CALL getFormat(
00012       int& channel_count,
00013       int& sample_rate,
00014       SampleFormat& sample_format)
00015     {
00016       channel_count = 1;
00017       sample_rate   = 44100;
00018       sample_format = SF_S16;
00019     }
00020 
00021     int doRead(int frame_count, void* buffer) {
00022       s16* out = (s16*)buffer;
00023       for (int i = 0; i < frame_count; ++i) {
00024         *out++ = (rand() % 65536 - 32768);
00025       }
00026       return frame_count;
00027     }
00028 
00029     void ADR_CALL reset() {
00030     }
00031   };
00032 
00033   ADR_EXPORT(SampleSource*) AdrCreateWhiteNoise() {
00034     return new WhiteNoise();
00035   }
00036 
00037 
00038   // pink noise generation thanks to PortAudio (http://portaudio.com)
00039   static const int MAX_RANDOM_ROWS = 30;
00040   static const int RANDOM_BITS = 24;
00041   static const int RANDOM_SHIFT = sizeof(long) * 8 - RANDOM_BITS;
00042 
00043 
00044   class PinkNoise : public BasicSource {
00045   public:
00046     PinkNoise() {
00047       doReset();
00048     }
00049 
00050     void ADR_CALL getFormat(
00051       int& channel_count,
00052       int& sample_rate,
00053       SampleFormat& sample_format)
00054     {
00055       channel_count = 1;
00056       sample_rate   = 44100;
00057       sample_format = SF_S16;
00058     }
00059 
00060     int doRead(int frame_count, void* buffer) {
00061       s16* out = (s16*)buffer;
00062       for (int i = 0; i < frame_count; ++i) {
00063         *out++ = s16(generate() * 32767 - 16384);
00064       }
00065       return frame_count;
00066     }
00067 
00068     void ADR_CALL reset() {
00069       doReset();
00070     }
00071 
00072   private:
00073     void doReset() {
00074       static const int numRows = 12;
00075 
00076       m_seed = 22222;
00077 
00078       m_index = 0;
00079       m_index_mask = (1 << numRows) - 1;
00080 
00081       // Calculate maximum possible signed random value.
00082       // Extra 1 for white noise always added.
00083       long pmax = (numRows + 1) * (1 << (RANDOM_BITS - 1));
00084       m_scalar = 1.0f / pmax;
00085       
00086       std::fill(m_rows, m_rows + numRows, 0);
00087       m_running_sum = 0;
00088     }
00089 
00090     float generate() {
00091       // Increment and mask index.
00092       m_index = (m_index + 1) & m_index_mask;
00093 
00094       // If index is zero, don't update any random values.
00095       if (m_index) {
00096         // Determine how many trailing zeros in PinkIndex.
00097         // This algorithm will hang if n==0 so test first.
00098         int numZeros = 0;
00099         int n = m_index;
00100         while ((n & 1) == 0) {
00101           n = n >> 1;
00102           numZeros++;
00103         }
00104         // Replace the indexed ROWS random value.
00105         // Subtract and add back to RunningSum instead of adding all the random
00106         // values together. Only one changes each time.
00107         m_running_sum -= m_rows[numZeros];
00108         long newRandom = generateRandom() >> RANDOM_SHIFT;
00109         m_running_sum += newRandom;
00110         m_rows[numZeros] = newRandom;
00111       }
00112 
00113       // Add extra white noise value.
00114       long newRandom = generateRandom() >> RANDOM_SHIFT;
00115       long sum = m_running_sum + newRandom;
00116       // Scale to range of -1.0 to 0.9999.
00117       return m_scalar * sum;
00118     }
00119 
00120     long generateRandom() {
00121       m_seed = (m_seed * 196314165) + 907633515;
00122       return m_seed;
00123     }
00124 
00125     long  m_rows[MAX_RANDOM_ROWS];
00126     long  m_running_sum;
00127     int   m_index;
00128     int   m_index_mask;
00129     float m_scalar;
00130 
00131     long m_seed;
00132   };
00133 
00134   ADR_EXPORT(SampleSource*) AdrCreatePinkNoise() {
00135     return new PinkNoise();
00136   }
00137 
00138 }

Generated on Mon Feb 13 23:07:47 2006 for audiere by  doxygen 1.4.6