Problem with noise harmonics at higher sgtl5000.volume(X) settings

Status
Not open for further replies.
Hello,
That should be something simple but looks strange.
I have a simple idea to test the simultaneous generation of 20 tones. For that I use a Teensy 3.2 and a Teensy Audio board.
I have drawn in the web GUI a simple scheme where I have 20 x AudioSynthWaveform objects connected to 5 x AudioMixer objects and those in turn are connected to 2 x AudioMixer and finally we go into a AudioOutputI2S.

Then I initiate the 20 x AudioSynthWaveform with Waveform.amplitude(1.0/20); so that the summ of all the 20 amplitudes is always <= 1.0 and the Waveform_N.frequency(F0 + F0*N); . All the AudioMIxers are set to linear summ of the inputs - mixer1.gain(0,1.0); . To control the volume I use the sgtl5000_1.volume(X); , I know that there is also the sgtl5000_1.dacVolume(Y); but I did not get how it relates to the .volume(X) , so I simply did not use it.
The Problem:
If I start with a low sgtl5000_1.volume(0.2) I get a nice output of the Waveforms (here 10 but identical with 20): 20_percent_sgt5000_vol.png

At sgtl5000_1.volume(0.3) it is still working (but actually is too quite to listen):
30_percent_sgt5000_vol.png

But anything higher than ~0.33 in the main volume setting gives:
40_percent_sgt5000_vol.png

Actually if I use a potentiometer to change live the sgtl5000_1.volume(X); I get a very net change of the behavior at that volume setting.
I think that I do something wrong in how I control the volume, but did not find the solution yet.

The code below is for 10 tones but for me it is working exactly the same as for 20. After the code is loaded one need to use the serial terminal to press 0 -9 value that will switch on/off the respective tone and the main volume is to be changed in the code before the compilation.

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthWaveform       waveform6;      //xy=96,558
AudioSynthWaveform       waveform7;      //xy=108,607
AudioSynthWaveform       waveform8;      //xy=109,653
AudioSynthWaveform       waveform5;      //xy=110,516
AudioSynthWaveform       waveform9;      //xy=113,707
AudioSynthWaveform       waveform10;     //xy=115,754
AudioSynthWaveform       waveform1;      //xy=118,325
AudioSynthWaveform       waveform2;      //xy=118,370
AudioSynthWaveform       waveform4;      //xy=119,464
AudioSynthWaveform       waveform3;      //xy=120,416
AudioMixer4              mixer1;         //xy=357,388
AudioMixer4              mixer2;         //xy=359,562
AudioMixer4              mixer3;         //xy=361,741
AudioMixer4              mixer4;         //xy=596,540
AudioOutputI2S           i2s1;           //xy=806,525

AudioConnection          patchCord1(waveform6, 0, mixer2, 1);
AudioConnection          patchCord2(waveform7, 0, mixer2, 2);
AudioConnection          patchCord3(waveform8, 0, mixer2, 3);
AudioConnection          patchCord4(waveform5, 0, mixer2, 0);
AudioConnection          patchCord5(waveform9, 0, mixer3, 0);
AudioConnection          patchCord6(waveform10, 0, mixer3, 1);
AudioConnection          patchCord7(waveform1, 0, mixer1, 0);
AudioConnection          patchCord8(waveform2, 0, mixer1, 1);
AudioConnection          patchCord9(waveform4, 0, mixer1, 3);
AudioConnection          patchCord10(waveform3, 0, mixer1, 2);
AudioConnection          patchCord11(mixer1, 0, mixer4, 0);
AudioConnection          patchCord12(mixer2, 0, mixer4, 1);
AudioConnection          patchCord13(mixer3, 0, mixer4, 2);
AudioConnection          patchCord14(mixer4, 0, i2s1, 0);
AudioConnection          patchCord15(mixer4, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=614,187
// GUItool: end automatically generated code

int inByte = 0;
int call_N = 0;
const int N_waves = 10;

AudioSynthWaveform * Waves[N_waves] = 
{
  &waveform1, &waveform2, &waveform3, &waveform4, &waveform5, &waveform6, &waveform7, &waveform8, &waveform9, &waveform10
}; 

float Note_list[][N_waves] = 
{
  {587.33 , 1174.66 , 1761.99 , 2349.32 , 2936.65 , 3523.98 , 4111.31 , 4698.64 , 5285.97 , 5873.3},
  {739.99 , 1479.98 , 2219.97 , 2959.96 , 3699.95 , 4439.94 , 5179.93 , 5919.92 , 6659.91 , 7399.9},
  {830.61 , 1661.22 , 2491.83 , 3322.44 , 4153.05 , 4983.66 , 5814.26 , 6644.88 , 7475.49 , 8306.1},
  {987.77 , 1975.54 , 2963.31 , 3951.08 , 4938.85 , 5926.62 , 6914.39 , 7902.16 , 8889.93 , 9877.7}
};

float Tone_state[N_waves] = {0};

int set_note(int N_note)
{
  AudioNoInterrupts();
  
  for(int i=0; i < N_waves; ++i)
  {
    Tone_state[i] = 0.1;
    Waves[i]-> frequency(Note_list[N_note][i]);
    Waves[i]-> amplitude( Tone_state[i] );
    Waves[i]-> phase(0.0);
  }

  AudioInterrupts(); 

  for(int i=0; i < N_waves; ++i)
  {
    Waves[i]-> begin(WAVEFORM_SINE);
  }

  Serial.print("Reproducing the note N-");
  Serial.println(N_note);

  return 0;  
}

int toggle_tone(int N_tone)
{

  if(Tone_state[N_tone] == 0)
  {
    Tone_state[N_tone] = 0.1;
  }
  else
  {
    Tone_state[N_tone] = 0.0;
  }
  
  AudioNoInterrupts();
  
  Waves[N_tone]-> amplitude(Tone_state[N_tone]);

  AudioInterrupts();

  Serial.print("Tone N-");
  Serial.print(N_tone);
  Serial.print(", changing volume to ");
  Serial.println(Tone_state[N_tone]);
  
  return 0;  
}

void setup() {
 
  Serial.begin(9600);

  while (!Serial && millis() < 2500) ; // wait

  establishContact();
  
  Serial.println("Ready!");
  
  AudioMemory(20);
  analogReference(INTERNAL);   

  mixer1.gain(0,1.0);
  mixer1.gain(1,1.0);
  mixer1.gain(2,1.0);
  mixer1.gain(3,1.0);

  mixer2.gain(0,1.0);
  mixer2.gain(1,1.0);
  mixer2.gain(2,1.0);
  mixer2.gain(3,1.0);

  mixer3.gain(0,1.0);
  mixer3.gain(1,1.0);

  mixer4.gain(0,1.0);
  mixer4.gain(1,1.0);
  mixer4.gain(2,1.0);
  mixer4.gain(3,1.0);

  set_note(0);

  sgtl5000_1.enable();
  sgtl5000_1.volume(0.2);     // set the main volume...
  sgtl5000_1.adcHighPassFilterDisable();
//  sgtl5000_1.dacVolume(0.5);    // set the "dac" volume (extra control)
//  sgtl5000_1.dacVolumeRampDisable();

}

void loop() {

 if (Serial.available() > 0)
  {
    inByte = Serial.read() - 48;
    Serial.print(inByte);
    Serial.print(" Call N-");
    Serial.println(call_N);

    ++call_N;

    if(inByte >= 0 && inByte <= 9)
    {
      
      toggle_tone(inByte);
      
    }
    else if(inByte == 65 || inByte == 71 || inByte == 53 || inByte == 66)
    {
      if(inByte == 65)
      {
        set_note(0);
      }
      else if(inByte == 71)
      {
        set_note(1);
      }
      else if(inByte == 53)
      {
        set_note(2);
      }
      else if(inByte == 66)
      {
        set_note(3);
      }
      
    }
    else if(inByte == 67)
    {
      
    }
    else
    {
      Serial.println("Wrong argument");
    }
   
    delay(300);

  }

}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    delay(300);
  }
}

Any suggestion is welcome. Thanks.
 
My initial reaction is to turn the mixer gains down to .7 rather than 1.0, and actually increase the amplitude of each oscillator a bit, so you have a little more dynamic range in the calculations.

Really though, take it stage by stage: 4 oscillators into 1 mixer, then connect that directly to the I2S output. Does that work as expected or not? Okay, move on by adding another 4 oscillators and another layer of mixers. That is basically the approach we would have to take to debug.

Two other things to think about: enable USB audio so you can capture directly and eliminate any analog weirdness that's going on, also try leaving the high pass filter in place.
 
Status
Not open for further replies.
Back
Top