Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 7 of 7

Thread: Teensy 3.2 Sound Level Meter (sound measurement device)

  1. #1
    Junior Member
    Join Date
    Feb 2016
    Posts
    5

    Teensy 3.2 Sound Level Meter (sound measurement device)

    Hi, I have been working for some time now on creating a sound level meter using the Teensy 3.2 (since it is perfect for this application). A SLM can be used for measuring sound pressure levels and reporting them an an A-weighted dB(sound pressure level), which is the NIOSH standard for measuring sound. At the moment it seems to be accurate to around 1-3 dB, but I am sure it can be improved (hoping for a little help from all you experts out there). I am hoping that this code will be good enough for people to be able to use for sound measurement with audio equipment, or for safety monitoring. I have built off the FFT library and used a lot of help from an open MIT course (http://alumni.media.mit.edu/~dlanman...ibel_meter.pdf). I have a few questions (and I am sure I have made some mistakes) about my code.
    First: Here is my code

    Code:
    /* This program first computes a 1024 point FFT using the Audio Library provided by Pual Stoffregen. It then applies an a-weighting to the samples, sums them, 
     *  then converts to dB SPL. Here, I have used the ADC for the microphone input instead of the audio shield. The Audio design tool provided by PJRC can be used to set up the 
     *  audio connection. The microphone ciruit I used can be found at http://electronics.stackexchange.com/questions/16595/how-to-make-a-clean-amplified-microphone-analog-to-digital-conversion 
     *  and is designed by Olin Lathrop I replaced R7 and R8 with 47K resistors. I also used the circuit diagram in the Audio design tool on PJRC (under the ADC tab there is a sample circuit). To provide a DC offset of .6V. 
     */
     
    #include <Audio.h>
    #include <Wire.h> 
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    #define GREEN 10
    float n;
    int i;
    float v[512] = {0};
    float magnitude = 0;
    float dB_holder;
    int db_int;
    float a_weight[512] = {0.000491601, 0.007439144, 0.026456683, 0.057237193, 0.097648235, 0.145530499, 0.19895028, 0.256192702, 0.315753433, 0.376341431, 0.436880336, 0.496502258, 0.554533348, 0.610473237, 0.663971116, 0.714800959, 0.762837753, 0.808035908, 0.85041046, 0.890021233, 0.926959868, 0.961339445, 0.993286373, 1.022934171, 1.050418819, 1.075875354, 1.099435459, 1.12122582, 1.141367062, 1.159973138, 1.177151032, 1.193000704, 1.207615207, 1.221080906, 1.233477786, 1.244879798, 1.255355228, 1.264967081, 1.273773452, 1.281827897, 1.289179783, 1.29587462, 1.301954369, 1.307457742, 1.312420463, 1.316875521, 1.320853401, 1.324382291, 1.327488281, 1.330195534, 1.332526449, 1.334501812, 1.336140927, 1.337461742, 1.338480956, 1.339214128, 1.339675764, 1.339879407, 1.33983771, 1.33956251, 1.339064892, 1.338355246, 1.337443324, 1.336338287, 1.33504875, 1.333582824, 1.331948154, 1.330151954, 1.328201037, 1.326101843, 1.323860472, 1.3214827, 1.318974007, 1.316339599, 1.313584419, 1.310713175, 1.307730349, 1.304640214, 1.301446848, 1.298154147, 1.294765835, 1.291285478, 1.28771649, 1.284062146, 1.280325589, 1.276509835, 1.272617788, 1.268652238, 1.264615874, 1.260511287, 1.256340974, 1.252107348, 1.247812737, 1.243459393, 1.239049492, 1.234585143, 1.230068386, 1.2255012, 1.220885501, 1.216223152, 1.211515958, 1.206765674, 1.201974005, 1.19714261, 1.1922731, 1.187367045, 1.182425973, 1.177451372, 1.172444693, 1.167407348, 1.162340715, 1.157246139, 1.152124932, 1.146978373, 1.141807712, 1.136614169, 1.131398936, 1.126163178, 1.120908033, 1.115634612, 1.110344003, 1.105037268, 1.099715447, 1.094379556, 1.08903059, 1.083669521, 1.078297301, 1.072914859, 1.067523108, 1.062122937, 1.05671522, 1.05130081, 1.045880542, 1.040455233, 1.035025683, 1.029592675, 1.024156975, 1.018719333, 1.013280482, 1.00784114, 1.00240201, 0.996963778, 0.991527118, 0.986092686, 0.980661126, 0.975233068, 0.969809127, 0.964389904, 0.958975988, 0.953567954, 0.948166364, 0.942771769, 0.937384705, 0.932005696, 0.926635255, 0.921273883, 0.915922069, 0.91058029, 0.905249011, 0.899928687, 0.894619763, 0.88932267, 0.88403783, 0.878765656, 0.873506548, 0.868260896, 0.863029082, 0.857811477, 0.852608441, 0.847420326, 0.842247473, 0.837090216, 0.831948877, 0.826823771, 0.821715204, 0.816623471, 0.811548862, 0.806491654, 0.80145212, 0.796430522, 0.791427115, 0.786442146, 0.781475853, 0.776528467, 0.771600212, 0.766691304, 0.761801951, 0.756932355, 0.752082709, 0.747253202, 0.742444013, 0.737655316, 0.732887277, 0.728140056, 0.723413808, 0.71870868, 0.714024813, 0.709362343, 0.704721397, 0.700102099, 0.695504567, 0.690928912, 0.686375241, 0.681843653, 0.677334244, 0.672847104, 0.668382317, 0.663939963, 0.659520116, 0.655122846, 0.650748219, 0.646396293, 0.642067124, 0.637760764, 0.633477258, 0.629216649, 0.624978975, 0.620764269, 0.616572561, 0.612403877, 0.608258238, 0.604135661, 0.600036161, 0.595959749, 0.59190643, 0.587876209, 0.583869084, 0.579885053, 0.575924108, 0.571986239, 0.568071433, 0.564179674, 0.560310942, 0.556465216, 0.552642469, 0.548842674, 0.5450658, 0.541311815, 0.537580682, 0.533872363, 0.530186816, 0.526524, 0.522883867, 0.519266371, 0.51567146, 0.512099084, 0.508549187, 0.505021714, 0.501516605, 0.498033801, 0.49457324, 0.491134857, 0.487718587, 0.484324362, 0.480952113, 0.47760177, 0.47427326, 0.47096651, 0.467681443, 0.464417985, 0.461176056, 0.457955577, 0.454756467, 0.451578645, 0.448422028, 0.445286531, 0.442172069, 0.439078556, 0.436005904, 0.432954025, 0.429922829, 0.426912226, 0.423922125, 0.420952434, 0.41800306, 0.41507391, 0.412164889, 0.409275902, 0.406406853, 0.403557647, 0.400728185, 0.397918372, 0.395128108, 0.392357295, 0.389605834, 0.386873625, 0.384160569, 0.381466565, 0.378791512, 0.37613531, 0.373497856, 0.37087905, 0.368278789, 0.36569697, 0.363133492, 0.360588252, 0.358061147, 0.355552074, 0.353060929, 0.35058761, 0.348132012, 0.345694033, 0.343273569, 0.340870517, 0.338484772, 0.336116231, 0.333764791, 0.331430348, 0.329112798, 0.326812038, 0.324527964, 0.322260474, 0.320009464, 0.31777483, 0.315556471, 0.313354282, 0.311168162, 0.308998008, 0.306843717, 0.304705188, 0.302582319, 0.300475007, 0.298383152, 0.296306653, 0.294245408, 0.292199316, 0.290168278, 0.288152193, 0.286150961, 0.284164484, 0.28219266, 0.280235393, 0.278292582, 0.276364131, 0.27444994, 0.272549913, 0.270663953, 0.268791961, 0.266933843, 0.265089501, 0.263258841, 0.261441767, 0.259638183, 0.257847996, 0.256071111, 0.254307435, 0.252556875, 0.250819337, 0.249094729, 0.247382959, 0.245683935, 0.243997567, 0.242323763, 0.240662434, 0.239013489, 0.23737684, 0.235752397, 0.234140071, 0.232539776, 0.230951422, 0.229374924, 0.227810195, 0.226257148, 0.224715697, 0.223185759, 0.221667247, 0.220160077, 0.218664167, 0.217179432, 0.215705789, 0.214243158, 0.212791454, 0.211350598, 0.209920507, 0.208501103, 0.207092304, 0.205694032, 0.204306207, 0.202928752, 0.201561587, 0.200204635, 0.19885782, 0.197521065, 0.196194293, 0.19487743, 0.193570399, 0.192273127, 0.19098554, 0.189707563, 0.188439124, 0.187180149, 0.185930567, 0.184690306, 0.183459294, 0.182237461, 0.181024737, 0.179821051, 0.178626335, 0.177440519, 0.176263535, 0.175095315, 0.173935792, 0.172784898, 0.171642567, 0.170508733, 0.16938333, 0.168266293, 0.167157558, 0.166057059, 0.164964734, 0.163880519, 0.162804351, 0.161736168, 0.160675908, 0.159623508, 0.158578909, 0.157542048, 0.156512867, 0.155491306, 0.154477304, 0.153470803, 0.152471745, 0.151480071, 0.150495724, 0.149518647, 0.148548783, 0.147586076, 0.146630469, 0.145681907, 0.144740336, 0.143805699, 0.142877944, 0.141957016, 0.141042862, 0.140135428, 0.139234663, 0.138340513, 0.137452928, 0.136571854, 0.135697243, 0.134829041, 0.133967201, 0.133111671, 0.132262402, 0.131419345, 0.130582451, 0.129751671, 0.128926959, 0.128108265, 0.127295544, 0.126488747, 0.125687829, 0.124892743, 0.124103444, 0.123319885, 0.122542022, 0.121769811, 0.121003206, 0.120242164, 0.119486641, 0.118736594, 0.117991979, 0.117252754, 0.116518877, 0.115790306, 0.115066999, 0.114348914, 0.113636011, 0.112928249, 0.112225587, 0.111527986, 0.110835406, 0.110147807, 0.109465151, 0.108787398, 0.108114511, 0.10744645, 0.106783179, 0.106124659, 0.105470853, 0.104821725, 0.104177238, 0.103537355, 0.10290204, 0.102271258, 0.101644973, 0.10102315, 0.100405754, 0.09979275, 0.099184104, 0.098579782, 0.09797975, 0.097383975, 0.096792423, 0.096205061, 0.095621857, 0.095042778, 0.094467792, 0.093896867, 0.093329972, 0.092767075, 0.092208144, 0.091653149, 0.09110206, 0.090554845, 0.090011475, 0.08947192, 0.088936151, 0.088404136, 0.087875849, 0.087351259, 0.086830338};
    
    // Sample time in milliseconds
    unsigned long Sampletime_ms = 1000;
    unsigned long Starttime;
    int l = 0;
    
    
    AudioInputAnalog         adc1;           //xy=155,82
    AudioAnalyzeFFT1024      fft1024_1;      //xy=348,95
    AudioConnection          patchCord1(adc1, fft1024_1); //created using the Teensy Audio design GUI
    //AudioSynthWaveformSine sinewave;// Generate sine wave to analyze, un-comment sinewave.frequency and sinewave.amplitude in setup
    //AudioConnection patchCord1(sinewave, 0, fft1024_1, 0); //Generate input signal for test, do not change these #s
    
    
    void setup() {
      AudioMemory(12);
      Serial.begin(9600);
      Wire.begin(8); //I2c communication w/ Arduino
      Wire.onRequest(requestEvent); //I2C communication with Arduino
      fft1024_1.windowFunction(AudioWindowHanning1024);
      pinMode( GREEN, OUTPUT); //toggle led after each send to arduino
      //sinewave.amplitude(0.4); // From 0 at min to 1 at max
      //sinewave.frequency(1000.0); //Anywhere from 0 to 20kHz
    }
    
    void loop() 
    { 
      magnitude = 0;
      dB_holder = 0;
      
      //get the current time;
      Starttime = millis();
      
      while((millis() - Starttime) < Sampletime_ms){
        if (fft1024_1.available()) {
          for (i=0; i<511; i++) {
            n = fft1024_1.read(i);
            n = n * a_weight[i];
            v[i] = n;
            v[i] = 0.001953125 * pow(v[i],2); // 1/512 samples = .0019....
            magnitude = v[i] + magnitude;
          }
          magnitude = db(magnitude);
          dB_holder = dB_holder + magnitude;
          magnitude = 0;
          ++l; 
        }
      }
      dB_holder=dB_holder/l;
      db_int = (int) dB_holder;
      Serial.println(db_int);
      l = 0;
    }
    
    float db(float n) {
       return log10f(n) * 10.0f + 125; 
       }
                       
    void requestEvent() { //I2C communiation with Arduino. I am using the Arduino as a central hub for attaching many other types of sensors, including this one.
      byte myArray[1]; 
      myArray[0] = db_int;
      Wire.write(myArray, 1);
      digitalWrite(GREEN, HIGH);
      delay(100);
      digitalWrite(GREEN, LOW);
    }
    As you can see I have made a lookup table for the A-weighting and it is rather long. In the future I will make it a separate header file, but at the moment this works.
    My First question I have is what the sample length of the FFT function is. I have assumed that it is 512, because in the Hanning window Paul normalizes with this number (1/512). Is this correct? If this is true would the sample time period be then 512/44.1k = .0116s? I use this number when I am summing the individual magnitudes. The only reason I ask is because I would like to make a "slow" response time of 1s, so instead of changing the FFT sample number, I just run the regular loop over 1 second and average the dB levels over that period. I do not think this is the best way to do the sampling. My second question is whether I am correctly applying the weighting filter. Using the generated sine wave, it seems to respond correctly when changing the frequency while keeping the intensity at the same level. It also seems to respond well with the microphone and a produced noise, until I get into higher frequencies and I begin to see attenuation of the signal, which might very well just be the microphone and amplifying circuit (in which case I will change the A-weighting table to include a linearizing correction factor for the microphone input.) I also decided to sum all the real valued input signals (1/N(magnitude)^2) instead of 1/2 of them because I felt wierd excluding half of the sample data. Any help would be very much appreciated, and if there is something I can do to help make this code more usable for someone else, please let me know.

  2. #2
    Junior Member
    Join Date
    Feb 2016
    Posts
    5
    I realize that it may be hard to calibrate to dBspl if you do not use the same microphone I use. I am wondering how accurate it would be to calibrate based off of the microphones given sensitivity in the data sheets. If someone reading this would like to use the same microphone I am using, it is the electret taken off of the Adafruit max4466 breakout board. I decided to use my own amplifying circuit because the Adafruit circuit seems to have a large drop off in gain at any frequency above 8kHz. The microphone itself fairly linear, so I used it.

  3. #3
    Junior Member
    Join Date
    May 2019
    Posts
    7
    Taken this code and simplified it, made some changes as the SPL calculation was off.. noise floor is a bit higher than I would expect from 13 bit, but otherwise it works great. Trying to make this into a 8x octave band SPL meter, with 1000ms or 125ms averaging options. Comments and tips are highly appreciated:


    Code:
    /* Uses ADC1 as analog audio input, computes a 1024 point single sided spectrum using FFT1024 in the Audio Library provided by Pual Stoffregen. 
     *  It then applies an a-weighting to the 512 single sided spectum bins, 
     *  It sums the squareroot of the frequency bins, and squares it again after the suming of all freqeuncy bins is complete. 
     *  It then takes the 20 * Log10 to obtaine  dBA SPL figure
     *  For testing I used a Panasonic wm-34a electret, fed from the 3.3V, through a 4k7 resistor. Signal output was taken from the 4k7 resitor via a 1uF
     *  capacitor to pin 16 (a.k.a A2). It callibrated to 94.04dB and 113.97dB with a B&K type 4231 callibrator, settles to 69.2dB without sound (noise floor)
     *  Thijs SchramaŽ04-05-2019
     */
     
    #include <Audio.h>
    #include <Wire.h> 
    #include <SD.h> 
    
    int i;
    float v[512] = {0};
    float magnitude = 0;
    float dB_holder;
    float a_weight[512] = {0.000491601, 0.007439144, 0.026456683, 0.057237193, 0.097648235, 0.145530499, 0.19895028, 0.256192702, 0.315753433, 0.376341431, 0.436880336, 0.496502258, 0.554533348, 0.610473237, 0.663971116, 0.714800959, 0.762837753, 0.808035908, 0.85041046, 0.890021233, 0.926959868, 0.961339445, 0.993286373, 1.022934171, 1.050418819, 1.075875354, 1.099435459, 1.12122582, 1.141367062, 1.159973138, 1.177151032, 1.193000704, 1.207615207, 1.221080906, 1.233477786, 1.244879798, 1.255355228, 1.264967081, 1.273773452, 1.281827897, 1.289179783, 1.29587462, 1.301954369, 1.307457742, 1.312420463, 1.316875521, 1.320853401, 1.324382291, 1.327488281, 1.330195534, 1.332526449, 1.334501812, 1.336140927, 1.337461742, 1.338480956, 1.339214128, 1.339675764, 1.339879407, 1.33983771, 1.33956251, 1.339064892, 1.338355246, 1.337443324, 1.336338287, 1.33504875, 1.333582824, 1.331948154, 1.330151954, 1.328201037, 1.326101843, 1.323860472, 1.3214827, 1.318974007, 1.316339599, 1.313584419, 1.310713175, 1.307730349, 1.304640214, 1.301446848, 1.298154147, 1.294765835, 1.291285478, 1.28771649, 1.284062146, 1.280325589, 1.276509835, 1.272617788, 1.268652238, 1.264615874, 1.260511287, 1.256340974, 1.252107348, 1.247812737, 1.243459393, 1.239049492, 1.234585143, 1.230068386, 1.2255012, 1.220885501, 1.216223152, 1.211515958, 1.206765674, 1.201974005, 1.19714261, 1.1922731, 1.187367045, 1.182425973, 1.177451372, 1.172444693, 1.167407348, 1.162340715, 1.157246139, 1.152124932, 1.146978373, 1.141807712, 1.136614169, 1.131398936, 1.126163178, 1.120908033, 1.115634612, 1.110344003, 1.105037268, 1.099715447, 1.094379556, 1.08903059, 1.083669521, 1.078297301, 1.072914859, 1.067523108, 1.062122937, 1.05671522, 1.05130081, 1.045880542, 1.040455233, 1.035025683, 1.029592675, 1.024156975, 1.018719333, 1.013280482, 1.00784114, 1.00240201, 0.996963778, 0.991527118, 0.986092686, 0.980661126, 0.975233068, 0.969809127, 0.964389904, 0.958975988, 0.953567954, 0.948166364, 0.942771769, 0.937384705, 0.932005696, 0.926635255, 0.921273883, 0.915922069, 0.91058029, 0.905249011, 0.899928687, 0.894619763, 0.88932267, 0.88403783, 0.878765656, 0.873506548, 0.868260896, 0.863029082, 0.857811477, 0.852608441, 0.847420326, 0.842247473, 0.837090216, 0.831948877, 0.826823771, 0.821715204, 0.816623471, 0.811548862, 0.806491654, 0.80145212, 0.796430522, 0.791427115, 0.786442146, 0.781475853, 0.776528467, 0.771600212, 0.766691304, 0.761801951, 0.756932355, 0.752082709, 0.747253202, 0.742444013, 0.737655316, 0.732887277, 0.728140056, 0.723413808, 0.71870868, 0.714024813, 0.709362343, 0.704721397, 0.700102099, 0.695504567, 0.690928912, 0.686375241, 0.681843653, 0.677334244, 0.672847104, 0.668382317, 0.663939963, 0.659520116, 0.655122846, 0.650748219, 0.646396293, 0.642067124, 0.637760764, 0.633477258, 0.629216649, 0.624978975, 0.620764269, 0.616572561, 0.612403877, 0.608258238, 0.604135661, 0.600036161, 0.595959749, 0.59190643, 0.587876209, 0.583869084, 0.579885053, 0.575924108, 0.571986239, 0.568071433, 0.564179674, 0.560310942, 0.556465216, 0.552642469, 0.548842674, 0.5450658, 0.541311815, 0.537580682, 0.533872363, 0.530186816, 0.526524, 0.522883867, 0.519266371, 0.51567146, 0.512099084, 0.508549187, 0.505021714, 0.501516605, 0.498033801, 0.49457324, 0.491134857, 0.487718587, 0.484324362, 0.480952113, 0.47760177, 0.47427326, 0.47096651, 0.467681443, 0.464417985, 0.461176056, 0.457955577, 0.454756467, 0.451578645, 0.448422028, 0.445286531, 0.442172069, 0.439078556, 0.436005904, 0.432954025, 0.429922829, 0.426912226, 0.423922125, 0.420952434, 0.41800306, 0.41507391, 0.412164889, 0.409275902, 0.406406853, 0.403557647, 0.400728185, 0.397918372, 0.395128108, 0.392357295, 0.389605834, 0.386873625, 0.384160569, 0.381466565, 0.378791512, 0.37613531, 0.373497856, 0.37087905, 0.368278789, 0.36569697, 0.363133492, 0.360588252, 0.358061147, 0.355552074, 0.353060929, 0.35058761, 0.348132012, 0.345694033, 0.343273569, 0.340870517, 0.338484772, 0.336116231, 0.333764791, 0.331430348, 0.329112798, 0.326812038, 0.324527964, 0.322260474, 0.320009464, 0.31777483, 0.315556471, 0.313354282, 0.311168162, 0.308998008, 0.306843717, 0.304705188, 0.302582319, 0.300475007, 0.298383152, 0.296306653, 0.294245408, 0.292199316, 0.290168278, 0.288152193, 0.286150961, 0.284164484, 0.28219266, 0.280235393, 0.278292582, 0.276364131, 0.27444994, 0.272549913, 0.270663953, 0.268791961, 0.266933843, 0.265089501, 0.263258841, 0.261441767, 0.259638183, 0.257847996, 0.256071111, 0.254307435, 0.252556875, 0.250819337, 0.249094729, 0.247382959, 0.245683935, 0.243997567, 0.242323763, 0.240662434, 0.239013489, 0.23737684, 0.235752397, 0.234140071, 0.232539776, 0.230951422, 0.229374924, 0.227810195, 0.226257148, 0.224715697, 0.223185759, 0.221667247, 0.220160077, 0.218664167, 0.217179432, 0.215705789, 0.214243158, 0.212791454, 0.211350598, 0.209920507, 0.208501103, 0.207092304, 0.205694032, 0.204306207, 0.202928752, 0.201561587, 0.200204635, 0.19885782, 0.197521065, 0.196194293, 0.19487743, 0.193570399, 0.192273127, 0.19098554, 0.189707563, 0.188439124, 0.187180149, 0.185930567, 0.184690306, 0.183459294, 0.182237461, 0.181024737, 0.179821051, 0.178626335, 0.177440519, 0.176263535, 0.175095315, 0.173935792, 0.172784898, 0.171642567, 0.170508733, 0.16938333, 0.168266293, 0.167157558, 0.166057059, 0.164964734, 0.163880519, 0.162804351, 0.161736168, 0.160675908, 0.159623508, 0.158578909, 0.157542048, 0.156512867, 0.155491306, 0.154477304, 0.153470803, 0.152471745, 0.151480071, 0.150495724, 0.149518647, 0.148548783, 0.147586076, 0.146630469, 0.145681907, 0.144740336, 0.143805699, 0.142877944, 0.141957016, 0.141042862, 0.140135428, 0.139234663, 0.138340513, 0.137452928, 0.136571854, 0.135697243, 0.134829041, 0.133967201, 0.133111671, 0.132262402, 0.131419345, 0.130582451, 0.129751671, 0.128926959, 0.128108265, 0.127295544, 0.126488747, 0.125687829, 0.124892743, 0.124103444, 0.123319885, 0.122542022, 0.121769811, 0.121003206, 0.120242164, 0.119486641, 0.118736594, 0.117991979, 0.117252754, 0.116518877, 0.115790306, 0.115066999, 0.114348914, 0.113636011, 0.112928249, 0.112225587, 0.111527986, 0.110835406, 0.110147807, 0.109465151, 0.108787398, 0.108114511, 0.10744645, 0.106783179, 0.106124659, 0.105470853, 0.104821725, 0.104177238, 0.103537355, 0.10290204, 0.102271258, 0.101644973, 0.10102315, 0.100405754, 0.09979275, 0.099184104, 0.098579782, 0.09797975, 0.097383975, 0.096792423, 0.096205061, 0.095621857, 0.095042778, 0.094467792, 0.093896867, 0.093329972, 0.092767075, 0.092208144, 0.091653149, 0.09110206, 0.090554845, 0.090011475, 0.08947192, 0.088936151, 0.088404136, 0.087875849, 0.087351259, 0.086830338};
    
    AudioInputAnalog         adc1;
    AudioAnalyzeFFT1024      fft1024_1;
    AudioConnection          patchCord1(adc1, fft1024_1); //created using the Teensy Audio design GUI, comment out for testing a simulated signal
    
    //prepare simulated signal, uncomment for testing a simulated signal
    //AudioSynthWaveformSine sinewave;
    //AudioConnection patchCord1(sinewave, 0, fft1024_1, 0); 
    
    void setup() {
      analogReadResolution(16);
      AudioMemory(12);
      Serial.begin(115200);
      fft1024_1.windowFunction(AudioWindowHanning1024);
    
      //generate simulated signal, uncomment for testing a simulated signal
      //sinewave.amplitude(0.05);        //  0 min to 1  max
      //sinewave.frequency(1000.0);     //  Anywhere from 0 to 20000
    }
    
    void loop() 
    { 
      if (fft1024_1.available()) {
          magnitude = 0;
          dB_holder = 0;
          float v[512] = {0};
          
          for (i=0; i<512; i++) {
            v[i] = fft1024_1.read(i) * a_weight[i];
            magnitude = magnitude + sq(v[i]);
          }
          magnitude = sqrt(magnitude);
          
          
          dB_holder = log10f(magnitude) * 20  + 125.05;
          Serial.println(dB_holder,2); // f[23] = 1kHz, f[82] = 3.5kHz, f[252] = 12kHz
      }
    }

  4. #4
    Junior Member
    Join Date
    May 2019
    Posts
    7
    Got the octaveband SPL meter working usethe spectrum BIN weigthing factors for each octave band. These BIN weigthing factor BTW, were squared by the OP; they were way off! So I had the sqrt them again, or type in 512 individual numbers

    Especially in the higher bands, there is an elevated noise floor. This seems to be gereated by the FFT routine, as the floor floor is also present when I use a AudioSynthWaveformSineHires. Too bad I cann't make a 1/3rd octave SPL meter; that would require a longer FFT length.

    I hope some people will try out this code and give me some feedback. these are my first step in TeensyLand


    Code:
    /* Uses ADC1 as analog audio input, computes a 1024 point single sided spectrum using FFT1024 in the Audio Library provided by Pual Stoffregen. 
     *  It then applies an a-weighting to the 512 single sided spectum bins, 
     *  It sums the squareroot of the frequency bins, and squares it again after the suming of all freqeuncy bins is complete. 
     *  It then takes the 20 * Log10 to obtain  the dBA SPL figure
     *  For testing I used a Panasonic wm-34a electret, fed from the 3.3V, through a 4k7 resistor. Signal output was taken from the 4k7 resitor via a 1uF
     *  capacitor to pin 16 (a.k.a A2). It callibrated to 94.04dB and 113.97dB with a B&K type 4231 callibrator, settles to 69.2dB without sound (noise floor)
     *    
     *  octaveband BIN numbers (@ fft1024, fs=44.1kHz) could be improve by fractional BIN weigthing:  
     *  2, 3/4, 5/8, 9/16, 17/32, 33/65 , 66/131, 132/262
     *   
     *  Thijs SchramaŽ04-05-2019
     */
     
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioSynthWaveformSineHires sine_hires1;    //xy=167,294
    AudioInputAnalog         adc1;           //xy=191,184
    AudioMixer4              mixer1;         //xy=373,182
    AudioAnalyzeFFT1024      fft1024_1;      //xy=421,292
    AudioConnection          patchCord1(sine_hires1, 0, mixer1, 1);
    AudioConnection          patchCord2(adc1, 0, mixer1, 0);
    AudioConnection          patchCord3(mixer1, fft1024_1);
    // GUItool: end automatically generated code
    
    float a_weight[] = {0.000491601, 0.007439144, 0.026456683, 0.057237193, 0.097648235, 0.145530499, 0.19895028, 0.256192702, 0.315753433, 0.376341431, 0.436880336, 0.496502258, 0.554533348, 0.610473237, 0.663971116, 0.714800959, 0.762837753, 0.808035908, 0.85041046, 0.890021233, 0.926959868, 0.961339445, 0.993286373, 1.022934171, 1.050418819, 1.075875354, 1.099435459, 1.12122582, 1.141367062, 1.159973138, 1.177151032, 1.193000704, 1.207615207, 1.221080906, 1.233477786, 1.244879798, 1.255355228, 1.264967081, 1.273773452, 1.281827897, 1.289179783, 1.29587462, 1.301954369, 1.307457742, 1.312420463, 1.316875521, 1.320853401, 1.324382291, 1.327488281, 1.330195534, 1.332526449, 1.334501812, 1.336140927, 1.337461742, 1.338480956, 1.339214128, 1.339675764, 1.339879407, 1.33983771, 1.33956251, 1.339064892, 1.338355246, 1.337443324, 1.336338287, 1.33504875, 1.333582824, 1.331948154, 1.330151954, 1.328201037, 1.326101843, 1.323860472, 1.3214827, 1.318974007, 1.316339599, 1.313584419, 1.310713175, 1.307730349, 1.304640214, 1.301446848, 1.298154147, 1.294765835, 1.291285478, 1.28771649, 1.284062146, 1.280325589, 1.276509835, 1.272617788, 1.268652238, 1.264615874, 1.260511287, 1.256340974, 1.252107348, 1.247812737, 1.243459393, 1.239049492, 1.234585143, 1.230068386, 1.2255012, 1.220885501, 1.216223152, 1.211515958, 1.206765674, 1.201974005, 1.19714261, 1.1922731, 1.187367045, 1.182425973, 1.177451372, 1.172444693, 1.167407348, 1.162340715, 1.157246139, 1.152124932, 1.146978373, 1.141807712, 1.136614169, 1.131398936, 1.126163178, 1.120908033, 1.115634612, 1.110344003, 1.105037268, 1.099715447, 1.094379556, 1.08903059, 1.083669521, 1.078297301, 1.072914859, 1.067523108, 1.062122937, 1.05671522, 1.05130081, 1.045880542, 1.040455233, 1.035025683, 1.029592675, 1.024156975, 1.018719333, 1.013280482, 1.00784114, 1.00240201, 0.996963778, 0.991527118, 0.986092686, 0.980661126, 0.975233068, 0.969809127, 0.964389904, 0.958975988, 0.953567954, 0.948166364, 0.942771769, 0.937384705, 0.932005696, 0.926635255, 0.921273883, 0.915922069, 0.91058029, 0.905249011, 0.899928687, 0.894619763, 0.88932267, 0.88403783, 0.878765656, 0.873506548, 0.868260896, 0.863029082, 0.857811477, 0.852608441, 0.847420326, 0.842247473, 0.837090216, 0.831948877, 0.826823771, 0.821715204, 0.816623471, 0.811548862, 0.806491654, 0.80145212, 0.796430522, 0.791427115, 0.786442146, 0.781475853, 0.776528467, 0.771600212, 0.766691304, 0.761801951, 0.756932355, 0.752082709, 0.747253202, 0.742444013, 0.737655316, 0.732887277, 0.728140056, 0.723413808, 0.71870868, 0.714024813, 0.709362343, 0.704721397, 0.700102099, 0.695504567, 0.690928912, 0.686375241, 0.681843653, 0.677334244, 0.672847104, 0.668382317, 0.663939963, 0.659520116, 0.655122846, 0.650748219, 0.646396293, 0.642067124, 0.637760764, 0.633477258, 0.629216649, 0.624978975, 0.620764269, 0.616572561, 0.612403877, 0.608258238, 0.604135661, 0.600036161, 0.595959749, 0.59190643, 0.587876209, 0.583869084, 0.579885053, 0.575924108, 0.571986239, 0.568071433, 0.564179674, 0.560310942, 0.556465216, 0.552642469, 0.548842674, 0.5450658, 0.541311815, 0.537580682, 0.533872363, 0.530186816, 0.526524, 0.522883867, 0.519266371, 0.51567146, 0.512099084, 0.508549187, 0.505021714, 0.501516605, 0.498033801, 0.49457324, 0.491134857, 0.487718587, 0.484324362, 0.480952113, 0.47760177, 0.47427326, 0.47096651, 0.467681443, 0.464417985, 0.461176056, 0.457955577, 0.454756467, 0.451578645, 0.448422028, 0.445286531, 0.442172069, 0.439078556, 0.436005904, 0.432954025, 0.429922829, 0.426912226, 0.423922125, 0.420952434, 0.41800306, 0.41507391, 0.412164889, 0.409275902, 0.406406853, 0.403557647, 0.400728185, 0.397918372, 0.395128108, 0.392357295, 0.389605834, 0.386873625, 0.384160569, 0.381466565, 0.378791512, 0.37613531, 0.373497856, 0.37087905, 0.368278789, 0.36569697, 0.363133492, 0.360588252, 0.358061147, 0.355552074, 0.353060929, 0.35058761, 0.348132012, 0.345694033, 0.343273569, 0.340870517, 0.338484772, 0.336116231, 0.333764791, 0.331430348, 0.329112798, 0.326812038, 0.324527964, 0.322260474, 0.320009464, 0.31777483, 0.315556471, 0.313354282, 0.311168162, 0.308998008, 0.306843717, 0.304705188, 0.302582319, 0.300475007, 0.298383152, 0.296306653, 0.294245408, 0.292199316, 0.290168278, 0.288152193, 0.286150961, 0.284164484, 0.28219266, 0.280235393, 0.278292582, 0.276364131, 0.27444994, 0.272549913, 0.270663953, 0.268791961, 0.266933843, 0.265089501, 0.263258841, 0.261441767, 0.259638183, 0.257847996, 0.256071111, 0.254307435, 0.252556875, 0.250819337, 0.249094729, 0.247382959, 0.245683935, 0.243997567, 0.242323763, 0.240662434, 0.239013489, 0.23737684, 0.235752397, 0.234140071, 0.232539776, 0.230951422, 0.229374924, 0.227810195, 0.226257148, 0.224715697, 0.223185759, 0.221667247, 0.220160077, 0.218664167, 0.217179432, 0.215705789, 0.214243158, 0.212791454, 0.211350598, 0.209920507, 0.208501103, 0.207092304, 0.205694032, 0.204306207, 0.202928752, 0.201561587, 0.200204635, 0.19885782, 0.197521065, 0.196194293, 0.19487743, 0.193570399, 0.192273127, 0.19098554, 0.189707563, 0.188439124, 0.187180149, 0.185930567, 0.184690306, 0.183459294, 0.182237461, 0.181024737, 0.179821051, 0.178626335, 0.177440519, 0.176263535, 0.175095315, 0.173935792, 0.172784898, 0.171642567, 0.170508733, 0.16938333, 0.168266293, 0.167157558, 0.166057059, 0.164964734, 0.163880519, 0.162804351, 0.161736168, 0.160675908, 0.159623508, 0.158578909, 0.157542048, 0.156512867, 0.155491306, 0.154477304, 0.153470803, 0.152471745, 0.151480071, 0.150495724, 0.149518647, 0.148548783, 0.147586076, 0.146630469, 0.145681907, 0.144740336, 0.143805699, 0.142877944, 0.141957016, 0.141042862, 0.140135428, 0.139234663, 0.138340513, 0.137452928, 0.136571854, 0.135697243, 0.134829041, 0.133967201, 0.133111671, 0.132262402, 0.131419345, 0.130582451, 0.129751671, 0.128926959, 0.128108265, 0.127295544, 0.126488747, 0.125687829, 0.124892743, 0.124103444, 0.123319885, 0.122542022, 0.121769811, 0.121003206, 0.120242164, 0.119486641, 0.118736594, 0.117991979, 0.117252754, 0.116518877, 0.115790306, 0.115066999, 0.114348914, 0.113636011, 0.112928249, 0.112225587, 0.111527986, 0.110835406, 0.110147807, 0.109465151, 0.108787398, 0.108114511, 0.10744645, 0.106783179, 0.106124659, 0.105470853, 0.104821725, 0.104177238, 0.103537355, 0.10290204, 0.102271258, 0.101644973, 0.10102315, 0.100405754, 0.09979275, 0.099184104, 0.098579782, 0.09797975, 0.097383975, 0.096792423, 0.096205061, 0.095621857, 0.095042778, 0.094467792, 0.093896867, 0.093329972, 0.092767075, 0.092208144, 0.091653149, 0.09110206, 0.090554845, 0.090011475, 0.08947192, 0.088936151, 0.088404136, 0.087875849, 0.087351259, 0.086830338};
    int oct             = 0;                                   // octaveband counter
    int i               = 0;                                   // freq bin counter
    int n               = 0;                                   // averaging counter
    int ave             = 11;                                  // nr of averages
    float v[511]        = {0};                                 // bin magnitude values
    float magn[]        = {0,0,0,0,0,0,0,0};                   // temporaly magnitude of 8 bands 
    float magn_f[]      = {0,0,0,0,0,0,0,0};                   // final magnitude of 8 bands after averaging 
    float dB_oct[]      = {0,0,0,0,0,0,0,0};                   // dB converted value of 8 bands after averaging 
    int bin_low[]       = {0, 2, 5, 10, 22, 41,  83, 166 };    // lowest  BIN number to include for 8 octavebands
    int bin_high[]      = {1, 3, 6, 12, 25, 50, 102, 204 };    // highest BIN number to include for 8 octavebands
    float mes = 0.00;
    
    void setup() { 
      sine_hires1.amplitude(1);     // generate a high resolution sine for testing
      sine_hires1.frequency(1000);   // set the frequency
      mixer1.gain(0, 1);            // mix in the the ADC Microphone
      mixer1.gain(1, 0);            // or mix the generated sine for testing
      fft1024_1.windowFunction(AudioWindowHanning1024); // Hanning for best, broadband, out of band, attenuation
      AudioMemory(12);
      Serial.begin(115200);
    }
    
    void loop() { 
      if (fft1024_1.available()) {
        magn[0]  = 0;                                          //reset the temporaly octavebands magnitue values to zero
        magn[1]  = 0; 
        magn[2]  = 0; 
        magn[3]  = 0; 
        magn[4]  = 0; 
        magn[5]  = 0; 
        magn[6]  = 0;
        magn[7]  = 0;
        for (oct=0; oct<8; oct++) {                               // repeat 8 times for 8 octave bands          
          for (i=bin_low[oct]; i<bin_high[oct]; i++) {            // retreive this octave BIN values and multiply each with their a_weigthing factor 
            v[i] = fft1024_1.read(i) * sqrt(a_weight[i]);
            magn[oct] = magn[oct] + sq(v[i]);                     // sum their squared value, since they are uncorrelated signals
          }
          magn[oct]   = sqrt(magn[oct]);                          // squareroot the SUM value, since they are uncorrelated signals
          magn_f[oct] = magn_f[oct] + magn[oct];                  // add value to average holder
        }    
        n      = n+1;                                             // keep track of number of averages = n
        if (n == ave) {                                           // once number of averages is reached
          Serial.println(999.99,2); // debug thingie
          for (oct=0; oct<8; oct++) {                             // repeat 8 times for 8 octave bands
            magn_f[oct]  = magn_f[oct]/ave;                       // divide by number of averages      
            dB_oct[oct]  = log10f(magn_f[oct]) * 20  + 120.20;    // convert to dB
            Serial.println(dB_oct[oct],2);
            magn_f[oct] = 0;
            dB_oct[oct] = 0;
          }
          n         = 0;                                          // reset averaging counter
        }
      }
    }
    and a Matlab visualistion routine :

    Code:
    % MATLAB code for octaveband SPL meter, works with teensy 3.6 via serial com port connection, adjust COM port for your system
    
    clearvars
    close all
    
    dBoct = 60*ones(1,8);
    
    figure(1)
    clf
    set(gcf,'Position',[317         349        1418         650])
    bh1 = bar(dBoct);
    grid on; grid minor;
    ylim([10 121])
    xlim([0.5 8.5])
    ylabel 'dB]'
    xlabel 'octaveband'
    title 'Octaveband meter met Teensy 3.6'
    set(gca,'FontSize',24)
    hold on
    plot([0 9],[94 94])
    for n=1:8
        th(n)=text(n,100,num2str(dBoct(n)),'FontSize',20)
    end
    drawnow
    
    %seriallist
    s = serial('COM6', 'BaudRate', 115200);
    fopen(s);
    formatSpec = '%f';
    disp('serial port connected')
    
    global KEY_IS_PRESSED
    KEY_IS_PRESSED = 0;
    gcf
    set(gcf, 'KeyPressFcn', @myKeyPressFcn)
    
    while ~KEY_IS_PRESSED
        mes = fscanf(s,formatSpec);
        if mes == 999.99
          for n=1:8
                dBoct(n) = fscanf(s,formatSpec);
                th(n).String = num2str(dBoct(n));
          end             
          bh1.YData = dBoct;
          drawnow
        end
    end
    
    disp 'closing serial connection'
    fclose(s);
    clear s
    disp 'closed'
    
    function myKeyPressFcn(hObject, event)
    global KEY_IS_PRESSED
    KEY_IS_PRESSED  = 1;
    disp('key is pressed')
    end

  5. #5
    Junior Member
    Join Date
    May 2019
    Posts
    7
    Here's the Matlab figure I use to visualize the octaveband SPL meter. Note the high noisefloor for the high freq bands. The high noisefloor is also present when using a software simulated sine signal .. how's that possible?

    Click image for larger version. 

Name:	teenst octave band SPL meter.jpg 
Views:	11 
Size:	65.5 KB 
ID:	16556

  6. #6
    Junior Member
    Join Date
    May 2019
    Posts
    7
    Well, I found out through some measurement of raw spectra that is putout by the AudioAnalyzeFFT1024 , that it puts out a 16bit value. Now I understand that the ADC uses 16bit data, but why would the output of an FFT not be a float? Since a 1024 point FFT spreads the energy over 512 frequency bins, and the broadbandinput it 16bit, atleast 16+9=25bits are needed to avoid throwing away usefull resolution.

    can the output of AudioAnalyzeFFT1024 be set to float?

  7. #7
    Junior Member
    Join Date
    May 2019
    Posts
    7
    Looking into the .cpp file that is called from the library, I see that the output of the CMSIS fft is a UNIT32, but it is squarerooted just before assigning it to the output. If I am not mistaken, if you squareroot a 32bit interger, you are left with 16bit.. hence the 16bit resolution of the AudioAnalyzeFFT1024

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •