Synchronizing ADC object and Audio library

Status
Not open for further replies.

josechow

Well-known member
Hey All,

I wanted to know how to synchronize the ADC and audio libraries so they can operate at the same time without interfering with each other? I couldn't find it online, sorry for double post if this is already answered

Currently, as best my research and testing could come up with, my ADC object (using ADC_1 on pin A2) running at ~48Khz conflicts with the audio passthrough function running at the standard 44khz (using ADC_0 on pin A3). When testing, the audio library wins the fight and works flawlessly while my ADC objects (adc1_isr) gets crippled and can't perform correctly. The program doesn't crash, the ISR obviously gets trampled with the other ISR.

So I was thinking, if I was able to force the ADC object to work in parallel with the audio library, offset by half a cycle, they would both work and only collide if either ISR used more than 50% of cpu usage. Can this be done?

The other way, is if I can get direct access to the samples coming from the audio library when a conversion is complete, but I haven't looked that up yet.

Thanks!
 
Doesn't the audio library allow to adapt the sample rate? I remember that in its early beta days, it was fixed to 44100Hz. Its a little time that I looked into it, but this has most probably evolved in the meantime.
 
Doesn't the audio library allow to adapt the sample rate? I remember that in its early beta days, it was fixed to 44100Hz. Its a little time that I looked into it, but this has most probably evolved in the meantime.

From what I read in multiple of Pauls posts is that the Audio Library is hardcoded to 44.1 kHz. (and it seemed pretty harder to change since everything was designed around that number).

Well anyway, here is my code. I could achieve my goals with just getting the DMA data as the ADC_0 data comes in. I am just a little scared trying to pry into the library since I have never done it before.

Code:
// Audio Library Setup
// These must always be after the ADC object
  AudioInputAnalog         audio_passthrough(A3);           
  AudioOutputAnalog        dac1;          
  AudioConnection          patchCord1(audio_passthrough, dac1);


//**************************************************************************************************
///////////////////////////////////////  ADC SETUP ROURTINE  ///////////////////////////////////////
//**************************************************************************************************
void adc_setup() {

  //Set input pin to be used as input
    pinMode(A2, INPUT);

  //// ADC0 ////
  // Will be used by the audio library
  
  ///// ADC1 ////
  // reference can be ADC_REF_3V3, ADC_REF_1V2 (not for Teensy LC) or ADC_REF_EXT.
  // ADC_REF_3V3 is the default reference
  //adc->setReference(ADC_REF_3V3, ADC_1); // change all 3.3 to 1.2 if you change the reference to 1V2
  
    adc->setAveraging(4, ADC_1);   // set number of averages
    adc->setResolution(16, ADC_1); // set bits of resolution
  
  // it can be ADC_VERY_LOW_SPEED, ADC_LOW_SPEED, ADC_MED_SPEED, ADC_HIGH_SPEED or ADC_VERY_HIGH_SPEED
  // refer to above speed charts
    adc->setConversionSpeed(ADC_MED_SPEED, ADC_1); // change the conversion speed
    adc->setSamplingSpeed(ADC_MED_SPEED, ADC_1);   // change the sampling speed
  
  // If you enable interrupts, notice that the isr will read the result, so that isComplete() will return false (most of the time)
    adc->enableInterrupts(ADC_1);
    adc->startContinuous(A2, ADC_1);
  
  delay(500);
}


//**************************************************************************************************
////////////////////////////////////////// ADC  INTERRUPT //////////////////////////////////////////
//**************************************************************************************************
void adc1_isr(void) {

  int read_input = (uint16_t)adc->analogReadContinuous(ADC_1);  //Grab the data
  window_sample[pointer] = read_input - dc_offset;              //dc offset the sample
  dc_sum += read_input;                                         //Add up input samples to calculate dc offset
  power_calc += abs(window_sample[pointer]);                    //Add up input samples to calculate power

//  int out_dac = (read_input) >> 4;
//  analogWrite(A14,out_dac);

  //Process the amdf when enough results are in
    int temp_result = 0;
    int temp_shift  = pointer - amdf_window_size;
    if(pointer >= min_amdf + amdf_window_size){
      for(int i = 0; i < amdf_window_size; i++){
        temp_result += abs(window_sample[i] - window_sample[ i + temp_shift ]);
      }
      amdf[temp_shift] = temp_result;
    }

  //Advance pointer for next data input
    pointer++;

  //Once the AMDF is complete, perform wrap up routines to send it to HPS calculation
    if(pointer >= max_amdf + amdf_window_size){
  
      // Copy amdf into HPS working array, update results availability
      // Block any subsequent update until the old data is processed
        if(hps_amdf_release == true){
          for(int a = min_amdf; a < max_amdf; a++){
            hps_amdf[a] = amdf[a];
          }
          hps_amdf_release = false;
          input_power_array[input_power_array_pointer] = sqrt(power_calc);
        }//end if
  
      //reset power var and collection point
        power_calc = 0;
        pointer = 0;
  
      //adjust dc offset calculation with averaging
        dc_offset_array[dc_offset_array_pointer] = dc_sum / (max_amdf + amdf_window_size);
        dc_sum = 0;
        dc_offset = (dc_offset_array[0] + dc_offset_array[1] +
                     dc_offset_array[2] + dc_offset_array[3] +
                     dc_offset_array[4] + dc_offset_array[5] +
                     dc_offset_array[6] + dc_offset_array[7] )/8; 
        dc_offset_array_pointer++;
        if(dc_offset_array_pointer > 7){ dc_offset_array_pointer = 0; } 
    }// end if
  
}// end adc_isr
 
After a little more digging into the Audio library I found that I could grab the DMA data directly in chunks using readBuffer()

Code:
      uint16_t buffer[256];
      memcpy(buffer, amdf_samples.readBuffer(), 128);
      amdf_samples.freeBuffer();
      memcpy(buffer+256, amdf_samples.readBuffer(), 128);
      amdf_samples.freeBuffer();

Since the signal I need for both the ADC and AUDIO are the same this will suffice. I just need to modify my AMDF code a little bit to accommodate chunks of data instead of doing a calculation every sample cycle. My previous method distributed the code a little bit more, but this should overall work better since the audio library works flawlessly (whereas the ADC library using analogWrite produced harmonics).

I will report back my findings when I get it running.
 
... the Audio Library is hardcoded to 44.1 kHz. (and it seemed pretty harder to change since everything was designed around that number).

It is designed for only 44.1 kHz.

But several people have managed to get it running at other speeds, like 192 kHz. It's been discussed at least a few times on the forum, so maybe you can find those messages with enough searching?

In a nutshell, you edit AudioStream.h to change the speed. Almost all the library will adapt. However, the input and output objects have hard-coded numbers for the I2S clock or timers/hardware they use. Ideally all that code would automatically adapt too, but doing so is not as simple as it sounds. Anyone who wants to improve it is welcome to do so and send a pull request on github. So far, everyone who's altered the sample rate has just plugged in different constants in those few places that don't automatically adapt from the main sample rate setting in AudioStream.h.

Edit: the other part the library that's hard-coded is the WAV file parser, which looks for 44100 in the WAV file header to know if it's able to play the file. Not an issue for you, but worth mentioning if anyone who wants to try other sample rates finds this message...
 
Last edited:
josechow,
I'm interested in the code you used, please post it!
I tested the ADC and Audio libraries together some time ago, but not too much. It should be possible to use ADC_1 when the Audio is using ADC_0.
 
josechow,
I'm interested in the code you used, please post it!

To which one where you referring? The ADC object running in conjunction with the AUDIO library or my soon to be revision? I can concatenate the relevant pieces if you want to try it. Ill upload that for interested parties.

I tested the ADC and Audio libraries together some time ago, but not too much. It should be possible to use ADC_1 when the Audio is using ADC_0.

Yeah, it was working, but the problem was that my adc1_isr wasn't allowed to complete fully most of the time because the AUDIO library trampled it mid-way through. Atleast, thats the only way I could describe what was happening when garbage came out of the algorithm in the isr. It might be because the isr is doing too much; since I have about 200+ integer additions a few tens of divisions/multiplications, etc. every isr. Though I thought I was safe with the speedy teensy 3.2
 
josechow,
I'm interested in the code you used, please post it!.

Here's the full code with the Audio object commented out. Uncommenting it back into the code you'll see a funny thing happen with the samples in the "All reduced time operations" if statement of the main loop

Code:
//**************************************************************************************************
///////////////////////////////    SPECTRA EXTERNAL CONTROLLER     /////////////////////////////////
/***************************************************************************************************

Created by: David Deininger
Created: December 7, 2015
Last Modified: January 16, 2016
Revision 5
Thanks to:  Arduino! For an awesome electornics learning platform
              http://www.arduino.cc/
*/

// Dependent Libraries and files
  #include <avr/pgmspace.h>
  #include <ADC.h>
  #include <Audio.h>
  
  
// Timing Constants and variables
  const int standard_heart_beat = 10;    //the interval time of timed operations in milliseconds
  int  heart_beat_start = 0;   


// AMDF Variables
  ADC *adc = new ADC(); // adc object
  const int min_amdf = 30;
  const int max_amdf = 260;
  const int amdf_window_size = 100;
  const int max_power_value = 3000;
  int       amdf[max_amdf];
  int       dc_sum = 0;
  int       dc_offset_array[8]= {0,0,0,0,0,0,0,0};
  int       dc_offset_array_pointer = 0;
  int       dc_offset = 0;
  int       power_calc = 0;

// HPS_AMDF Variables
  int       power_input_limit = 400;
  boolean   hps_amdf_release = true;
  int       hps_amdf[max_amdf];
  int       input_power = 0;
  int       input_power_array[4] = {0,0,0,0};
  int       input_power_array_pointer = 0;
  int       peak_average = 0;
  int       peak_current = 0;
  int       peak_index[8]= {0,0,0,0,0,0,0,0};
  int       peak_index_pointer = 0;
  int       pointer = min_amdf;
  boolean   test_sample_release = true;
  int       window_sample[max_amdf + amdf_window_size];

// Audio Library Setup
// These must always be after the ADC object
//  AudioInputAnalog         audio_passthrough(A3);           
//  AudioOutputAnalog        dac1;          
//  AudioConnection          patchCord1(audio_passthrough, dac1);


//**************************************************************************************************
/////////////////////////////////////////////  SETUP  //////////////////////////////////////////////
//**************************************************************************************************
void setup(){

  //Setup the ADC
    pinMode(A2, INPUT);
    adc->setReference(ADC_REF_3V3, ADC_1);
    adc->setAveraging(4, ADC_1);   // set number of averages
    adc->setResolution(16, ADC_1); // set bits of resolution
    adc->setConversionSpeed(ADC_MED_SPEED, ADC_1); // change the conversion speed
    adc->setSamplingSpeed(ADC_MED_SPEED, ADC_1);   // change the sampling speed
    adc->enableInterrupts(ADC_1);
    adc->startContinuous(A2, ADC_1);

  //just because
    delay(500);

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
    AudioMemory(20);

  Serial.begin(115200);

}//end setup()



//**************************************************************************************************
//////////////////////////////////////////  Main Program  //////////////////////////////////////////
//**************************************************************************************************
void loop(){
    
  //Hearbeat Counter 
    boolean   heart_beat = false;
    int       heart_beat_end = millis();
    if(heart_beat_end - heart_beat_start >= standard_heart_beat){
      heart_beat_start = heart_beat_end;
      heart_beat = true;
    }

  /*Calculate the HPS result in the following Manner (in order):     
  - Takes the Current AMDF calculation from ADC0_ISR
  - Invert the spectrum
  - Performs harmonic product spectrum on result
  - Performs level clipping
  - Performs convolution on the result
  - Detects the max peak
  - Averages the result over 4 previous results */
    hps_amdf_result();

  /* All reduced time operations */
    if(heart_beat == true){

      //Serial.println(input_power);            // print out the power (approximately 3000 - 0)
      
      Serial.println(window_sample[0]);       // print out a sample
      
//      if(input_power > power_input_limit)
//        Serial.println(48250/peak_average);     // print out the estimated frequency in hz
//      else
//        Serial.println(0);
      
    }//end print outputs

}//end loop()


//**************************************************************************************************
////////////////////////////////////////// ADC  INTERRUPT //////////////////////////////////////////
//**************************************************************************************************
void adc1_isr(void) {

  int read_input = (uint16_t)adc->analogReadContinuous(ADC_1);  //Grab the data
  window_sample[pointer] = read_input - dc_offset;              //dc offset the sample
  dc_sum += read_input;                                         //Add up input samples to calculate dc offset
  power_calc += abs(window_sample[pointer]);                    //Add up input samples to calculate power

  //Process the amdf when enough results are in
    int temp_result = 0;
    int temp_shift  = pointer - amdf_window_size;
    if(pointer >= min_amdf + amdf_window_size){
      for(int i = 0; i < amdf_window_size; i++){
        temp_result += abs(window_sample[i] - window_sample[ i + temp_shift ]);
      }
      amdf[temp_shift] = temp_result;
    }

  //Advance pointer for next data input
    pointer++;

  //Once the AMDF is complete, perform wrap up routines to send it to HPS calculation
    if(pointer >= max_amdf + amdf_window_size){
  
      // Copy amdf into HPS working array, update results availability
      // Block any subsequent update until the old data is processed
        if(hps_amdf_release == true){
          for(int a = min_amdf; a < max_amdf; a++){
            hps_amdf[a] = amdf[a];
          }
          hps_amdf_release = false;
          input_power_array[input_power_array_pointer] = sqrt(power_calc);
        }//end if
  
      //reset power var and collection point
        power_calc = 0;
        pointer = 0;
  
      //adjust dc offset calculation with averaging
        dc_offset_array[dc_offset_array_pointer] = dc_sum / (max_amdf + amdf_window_size);
        dc_sum = 0;
        dc_offset = (dc_offset_array[0] + dc_offset_array[1] +
                     dc_offset_array[2] + dc_offset_array[3] +
                     dc_offset_array[4] + dc_offset_array[5] +
                     dc_offset_array[6] + dc_offset_array[7] )/8; 
        dc_offset_array_pointer++;
        if(dc_offset_array_pointer > 7){ dc_offset_array_pointer = 0; } 
    }// end if
  
}// end adc_isr


//**************************************************************************************************
///////////////////////////////////  HARMONIC PRODUCT SPECTRUM  ////////////////////////////////////
//**************************************************************************************************
void hps_amdf_result(){

  //Allow HPS to work on AMDF if new data is available
  if(hps_amdf_release == false){

    //calculate the new power
      input_power = ( input_power_array[0] + input_power_array[1] + input_power_array[2] + input_power_array[3] ) / 4;
      input_power_array_pointer++;
      if(input_power_array_pointer > 3) input_power_array_pointer = 0;
    
    //if input power is above limit, process the array
      if(input_power >= power_input_limit){
  
        //find the maximum value of the amdf result
          int temp_max = 0;
          int temp_min = 123456;
          for(int i = min_amdf; i < max_amdf; i++){
            if(hps_amdf[i] > temp_max){ temp_max = hps_amdf[i]; }
            if(hps_amdf[i] < temp_min){ temp_min = hps_amdf[i]; }
          }
    
        //ensure values below min_amdf are neglected
          for(int i = 0; i < min_amdf + 3; i++){ hps_amdf[i] = temp_max; }
        
        //normalize and invert the result array, allow high correlation to pass
          int strong_correlation = (int)((float)(temp_max - temp_min) * 0.75);
          for(int i = 0 ; i < max_amdf; i++){
            hps_amdf[i] = temp_max - hps_amdf[i];
            if(hps_amdf[i] < strong_correlation){ hps_amdf[i] = 0; }
          }
    
        //perform partial harmonic spectrum (HPS) analysis on amdf result
          float norm_fact        = 1.00;
          float first_harm_fact  = 0.10;
          float second_harm_fact = 0.10;
          float third_harm_fact  = 0.10;
          for(int i = min_amdf; i < max_amdf-1; i++){
            if(i*2 < max_amdf){
              hps_amdf[i]  = hps_amdf[i]     * norm_fact;
              hps_amdf[i] += (hps_amdf[i*2]   * first_harm_fact + 
                              hps_amdf[i*2-1] * first_harm_fact + 
                              hps_amdf[i*2+1] * first_harm_fact); }
            if(i*3 < max_amdf){
              hps_amdf[i]  = hps_amdf[i]     * norm_fact;
              hps_amdf[i] += (hps_amdf[i*3]   * second_harm_fact + 
                              hps_amdf[i*3-1] * second_harm_fact + 
                              hps_amdf[i*3+1] * second_harm_fact);}
            if(i*4 < max_amdf){
              hps_amdf[i]  = hps_amdf[i]     * norm_fact;
              hps_amdf[i] += (hps_amdf[i*4]   * third_harm_fact + 
                              hps_amdf[i*4-1] * third_harm_fact + 
                              hps_amdf[i*4+1] * third_harm_fact); }
          }//end if


        //perform 11 digit wide square convolution on the HPS spectrum if less than half
        if(peak_average >= max_amdf/2){
          int temp_hps[max_amdf];
          temp_max = 0;
          for(int i = 0; i<max_amdf; i++){ temp_hps[i] = 0; }
          for(int i = 5; i < max_amdf-5; i++){
            temp_hps[i] = 0;
            for(int j = -5; j<6 ; j++){ temp_hps[i] += hps_amdf[i-j]; }
            if(temp_hps[i] > temp_max){ temp_max = temp_hps[i]; }
          }
          for(int i = 0; i<max_amdf; i++){ hps_amdf[i] = temp_hps[i]; }
        }
    
        //Find the max of the resulting HPS spectrum
          temp_max = 0;
          int temp_peak_index = 0;
          for(int i = 0; i < max_amdf; i++){
            if(hps_amdf[i] > temp_max){
              temp_max = hps_amdf[i];
              temp_peak_index = i; }
          }
        
        //Pass peak value to the averaging value output
          peak_index[peak_index_pointer] = temp_peak_index;
          peak_current = temp_peak_index;
          peak_average = 0;
          for(int i = 0; i < 4; i++){
            peak_average += peak_index[i];
          }
          peak_average = peak_average / 4;

    }else{
      //Update for too low of an input to prevent spurious results
        peak_current = 0;      
    }//end power limitation if statement

  
    //Update the average pointer and average value
      peak_index_pointer++;
      if(peak_index_pointer > 3){ peak_index_pointer = 0; }

    //Release the HPS to gather another AMDF result
      hps_amdf_release = true;
      
  }//end hps amdf release if statement

}//Harmonic product spectrum
 
fixed.

Below is my example code showing how I grabbed the AUDIO library data using bufferRead() and I processed the data using AMDF (autocorrelation magnitude difference function) and HPS (Harmonic spectrum) to estimate the psuedo harmonic frequency of a instrument being played. Only works when a single note is being played.

Code:
//**************************************************************************************************
/////////////////////////////////    AMDF_WITH_AUDIO_EXAMPLE      //////////////////////////////////
/***************************************************************************************************

Created by: David Deininger
Created: December 7, 2015
Last Modified: January 19, 2016
Revision 5
Thanks to:  Arduino! For an awesome electornics learning platform
              http://www.arduino.cc/
*/

// Dependent Libraries and files
  #include <avr/pgmspace.h>
  #include <Audio.h>
  
// Timing Constants and variables
  const int standard_heart_beat = 20;    //the interval time of timed operations in milliseconds
  int       heart_beat_start = 0;   

// AMDF Variables
  const int min_amdf = 30;
  const int max_amdf = 240;
  const int amdf_window_size = 120;
  const int max_power_value = 3000;
  const int num_of_blocks = ( max_amdf + amdf_window_size ) / 128 + 1;
  int  power_input_limit = 150;
  int  input_power = 0;
  int  input_power_array[4] = {0,0,0,0};
  int  input_power_array_pointer = 0;
  int  peak_average = 0;
  int  peak_current = 0;
  int  peak_index[8]= {0,0,0,0,0,0,0,0};
  int  peak_index_pointer = 0;

// Audio Library Setup
// These must always be after the ADC object
  AudioInputAnalog         audio_in(A3);
  AudioRecordQueue         amdf_samples;       
  AudioOutputAnalog        dac1;          
  AudioConnection          patchCord1(audio_in, dac1);
  AudioConnection          patchCord2(audio_in, amdf_samples);


//**************************************************************************************************
/////////////////////////////////////////////  SETUP  //////////////////////////////////////////////
//**************************************************************************************************
void setup(){

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
    AudioMemory(60);
    amdf_samples.begin();

  Serial.begin(115200);

}//end setup()



//**************************************************************************************************
//////////////////////////////////////////  Main Program  //////////////////////////////////////////
//**************************************************************************************************
void loop(){
    
  //Hearbeat Counter 
    boolean   heart_beat = false;
    int       heart_beat_end = millis();
    if(heart_beat_end - heart_beat_start >= standard_heart_beat){
      heart_beat_start = heart_beat_end;
      heart_beat = true;
    }

  /*Calculate the HPS result in the following Manner (in order):     
  - Takes the Current AMDF calculation from ADC0_ISR
  - Invert the spectrum
  - Performs harmonic product spectrum on result
  - Performs level clipping
  - Performs convolution on the result
  - Detects the max peak
  - Averages the result over 4 previous results */
    amdf_result();

  /* All reduced time operations */
    if(heart_beat == true){

//      Serial.print(input_power);            // print out the power (approximately 3000 - 0)
//      Serial.print("  ");
      
      if(input_power > power_input_limit)
        Serial.println(44100/peak_average);     // print out the estimated frequency in hz
      else
        Serial.println(0);
      
    }//end print outputs

}//end loop()


//**************************************************************************************************
///////////  AUTOCORRELATION MAGNITUDE DIFFERNCE FUNCTION w/ HARMONIC PRODUCT SPECTRUM /////////////
//**************************************************************************************************
void amdf_result(){

  //check if enough bins are available
  if (amdf_samples.available() >= num_of_blocks) {

    //////SETUP
    //////Setup all the variables for AMDF and HPS
    //////
      byte buff[num_of_blocks*256];
      int16_t samples[num_of_blocks*128];
      int power_calc = 0;
      int amdf[max_amdf];
      int temp_result = 0;

    //////COPY
    //////Fetch DMA blocks from the audio library and copy into a buffer
    //////Also, form all the 16bit signed numbers from the buffer bytes
    //////Additionally, collect samples to sum up the power to validate output
    //////
      for(int i = 0; i < num_of_blocks;i++){
        int index_shift = i*256;
        memcpy(buff + index_shift, amdf_samples.readBuffer(), 256);
        amdf_samples.freeBuffer();
      }
      for(int i = 0; i < num_of_blocks * 128; i++){
        samples[i] = buff[i*2] | (buff[i*2+1] << 8);  
        power_calc += abs(samples[i]);    
      }
    
    //////Power Average Update
    //////Update the power array by taking the last 4 averages
    //////
      power_calc = sqrt(power_calc);
      input_power_array[input_power_array_pointer] = power_calc;
      input_power_array_pointer++;
      if(input_power_array_pointer > 3) input_power_array_pointer = 0;
      input_power = ( input_power_array[0] + input_power_array[1] + 
                      input_power_array[2] + input_power_array[3] ) / 4;

    //////HPS on AMDF
    //////If power is above limit, go ahead and perform the AMDF and HPS
    //////
      if(input_power >= power_input_limit){

        //Perform AMDF
        for(int i = 0; i< max_amdf; i++){ amdf[i] = 0; }
        for(int point = min_amdf; point < max_amdf; point++){
          temp_result = 0;
          for(int i = 0; i < amdf_window_size; i++){
            temp_result += abs(samples[i] - samples[ i + point ]);
          }
          amdf[point] = temp_result;
        }
          
        //Find the maximum value of the amdf result
        int temp_max = 0;
        int temp_min = 123456;
        for(int i = min_amdf; i < max_amdf; i++){
          if(amdf[i] > temp_max){ temp_max = amdf[i]; }
          if(amdf[i] < temp_min){ temp_min = amdf[i]; }
        }
    
        //ensure values below min_amdf are neglected
        for(int i = 0; i < min_amdf + 3; i++){ amdf[i] = temp_max; }
        
        //normalize and invert the result array, allow high correlation to pass
        int strong_correlation = (int)((float)(temp_max - temp_min) * 0.75);
        for(int i = 0 ; i < max_amdf; i++){
          amdf[i] = temp_max - amdf[i];
          if(amdf[i] < strong_correlation){ amdf[i] = 0; }
        }
    
        //perform partial harmonic spectrum (HPS) analysis on amdf result
        float norm_fact        = 1.00;
        float first_harm_fact  = 0.10;
        float second_harm_fact = 0.10;
        float third_harm_fact  = 0.10;
        for(int i = min_amdf; i < max_amdf-1; i++){
          if(i*2 < max_amdf){
            amdf[i]  =      amdf[i]     * norm_fact;
            amdf[i] += (    amdf[i*2]   * first_harm_fact + 
                            amdf[i*2-1] * first_harm_fact + 
                            amdf[i*2+1] * first_harm_fact); }
          if(i*3 < max_amdf){
            amdf[i]  =      amdf[i]     * norm_fact;
            amdf[i] += (    amdf[i*3]   * second_harm_fact + 
                            amdf[i*3-1] * second_harm_fact + 
                            amdf[i*3+1] * second_harm_fact);}
          if(i*4 < max_amdf){
            amdf[i]  =      amdf[i]     * norm_fact;
            amdf[i] += (    amdf[i*4]   * third_harm_fact + 
                            amdf[i*4-1] * third_harm_fact + 
                            amdf[i*4+1] * third_harm_fact); }
        }

        //perform 11 digit wide square convolution on the HPS spectrum if less than half
        if(peak_average >= max_amdf/2){
          int temp_hps[max_amdf];
          temp_max = 0;
          for(int i = 0; i<max_amdf; i++){ temp_hps[i] = 0; }
          for(int i = 5; i < max_amdf-5; i++){
            temp_hps[i] = 0;
            for(int j = -5; j<6 ; j++){ temp_hps[i] += amdf[i-j]; }
            if(temp_hps[i] > temp_max){ temp_max = temp_hps[i]; }
          }
          for(int i = 0; i<max_amdf; i++){ amdf[i] = temp_hps[i]; }
        }
    
        //Find the max of the resulting HPS spectrum
        temp_max = 0;
        int temp_peak_index = 0;
        for(int i = 0; i < max_amdf; i++){
          if(amdf[i] > temp_max){
            temp_max = amdf[i];
            temp_peak_index = i; }
        }
        
        //Pass peak value to the averaging value output
        peak_index[peak_index_pointer] = temp_peak_index;
        peak_current = temp_peak_index;
        peak_average = 0;
        for(int i = 0; i < 4; i++){
          peak_average += peak_index[i];
        }
        peak_average = peak_average / 4;

    }else{
      
      //Update for too low of an input to prevent spurious results
      peak_current = 0; 
           
    }//end power limitation if statement

  
    //Update the average pointer and average value
    peak_index_pointer++;
    if(peak_index_pointer > 3){ peak_index_pointer = 0; }

  }//end amdf_samples 
}// end amdf hps algorithm
 
Status
Not open for further replies.
Back
Top