Source separation on a microphone recording and a know generated signal

Status
Not open for further replies.
what distances do you try?
128 samples in delay correspond to max 3ms delay or 1 m distance
so if you are, say 50 cm distant you should see the peak at about 64 samples.

As the I2S input may also introduce 3 ms delay, so, you could try to increase max delay to say 256 or 512 to see if there are constant peaks
(you may need to increase Audio buffers)
 
I've tried from about 1 cm until about 1 meter.

I just tried to increase to 512 iterations (already did until 256).
Here are the values I'm getting after 6 tests where the microphone stay at 15 cm from the speaker :

- 0.34 ms
- 0.36
- 8.73
- 0.34
- 11.61
- 8.73

Does it make any sense to you ? I don't understand anything.

How can I increase the audio buffer wheareas it seems to be fixed at 128 with AUDIO_BLOCK_SAMPLES ?
 
I've tried from about 1 cm until about 1 meter.

How can I increase the audio buffer wheareas it seems to be fixed at 128 with AUDIO_BLOCK_SAMPLES ?

Sorry, I was referring to
AudioMemory(64); 64 or similar

Also, you need to use delay(100), or 100 or something similar value, instead of the while waits.

The wait for rms returns nearly immediately (after first buffer received, you will have a rms value)
In particular, while tonesweep is running, you receive already data, multiply and estimate the rms.
(you can check with microSeconds() call before and after the wait)
 
Hey mate !

Sorry for this late reply but I was in holiday !

Just tried what you suggested. It seems to get a more consistent value as it stays stable after 3 tests...BUT...it also returned the same value wheareas I put the speaker closer from the microphone, which is pretty incoherent.

I've also measured the CPU and memory usage as I sometime hear some glitches. It came out that the memory suddently climb from 4.4 to 233 without any reason... may be this could be the cause of the problem ? I can't increase the audiomemory to this high value I think so what could be the solution ?
 
Hey there,

I just tried your code again by increasing the delay to 200 and it always send me back the same value whatever the position. I still tried to use this delay and gain compensation but it doesn't work at all. I'm giving up this method for now.

What about your cross correlation idea ?
 
Sure mate,

Here it is :

PS : I used this 2 values in my main code, then used the derivative of the microphone corrected signal in order to see the peaks.

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

// GUItool: begin automatically generated code
AudioSynthToneSweep      tonesweep1;     //xy=139,238
AudioOutputI2S           i2s1;           //xy=339,97
AudioEffectDelay         delay2;         //xy=388,350
AudioInputI2S            i2s2;           //xy=469,98
AudioAnalyzeRMS          rmsMic;           //xy=637,92
AudioEffectMultiply      multiply2;      //xy=659,397
AudioAnalyzeRMS          rmsSigInt;           //xy=660,302
AudioAnalyzeRMS          rms1;           //xy=811,397
AudioConnection          patchCord1(tonesweep1, delay2);
AudioConnection          patchCord2(tonesweep1, 0, i2s1, 0);
AudioConnection          patchCord3(tonesweep1, 0, i2s1, 1);
AudioConnection          patchCord4(delay2, 0, multiply2, 1);
AudioConnection          patchCord5(delay2, 0, rmsSigInt, 0);
AudioConnection          patchCord6(i2s2, 0, multiply2, 0);
AudioConnection          patchCord7(i2s2, 0, rmsMic, 0);
AudioConnection          patchCord8(multiply2, rms1);
AudioControlSGTL5000     sgtl5000_1;     //xy=139,397
// GUItool: end automatically generated code

MedianFilter Median(10, 0);

const int myInput = AUDIO_INPUT_MIC;
float valMax = 0;
float delayCompens = 0;

float AttenuationFactor = 0;
float AttenuationFactorMedian = 0;

void ping(int idel)
{
  float fdel = idel * 1000.0f / AUDIO_SAMPLE_RATE_EXACT;
  AudioNoInterrupts();
  rmsMic.read();    // clear rms counter/accumulator
  rmsSigInt.read(); // clear rms counter/accumulator
  rms1.read();      // clear rms counter/accumulator
  delay2.delay(0, fdel); // delay in ms
  AudioInterrupts();
  tonesweep1.play(1.0, 500, 3000, 0.01);
  delay(200);
  float val2 = rmsSigInt.read() * 1000;
  float val3 = rmsMic.read() * 1000;
  float val = rms1.read() * 1000;
  if (val > valMax) {
    valMax = val;
    delayCompens = fdel;
  }

  AttenuationFactor = val2 / val3;
  Median.in(AttenuationFactor);
  AttenuationFactorMedian = Median.out();
  Serial.printf("%d %f %f %f %f\n\r", idel, fdel, val2, val3, val);
  Serial.println("  -----  ");
}

void setup() {
  // put your setup code here, to run once:
  AudioMemory(80);
  while (!Serial);
  Serial.println("TestShift");
  AudioNoInterrupts();
  // setup audio board
  sgtl5000_1.enable();
  // setup headphone
  sgtl5000_1.volume(0.8);
  sgtl5000_1.inputSelect(myInput);
  // setup microphone
  sgtl5000_1.micGain(50); // from 0 to 63
  for (int ii = 1; ii < 8; ii++) delay2.disable(ii);
  AudioInterrupts();
}

void loop() {
  static int idel = 1;
  if (idel < 0) return;
  ping(idel);
  idel++;
  if (idel > 512) {
    Serial.print("The Delay compensation is : ");
    Serial.println(delayCompens);
    Serial.print("The attenuation factor is : ");
    Serial.println(AttenuationFactor);
    idel = -1; // mark to stop
  }
}
 
I've tried from about 1 cm until about 1 meter.

I just tried to increase to 512 iterations (already did until 256).
Here are the values I'm getting after 6 tests where the microphone stay at 15 cm from the speaker :

- 0.34 ms
- 0.36
- 8.73
- 0.34
- 11.61
- 8.73

Does it make any sense to you ? I don't understand anything.

How can I increase the audio buffer wheareas it seems to be fixed at 128 with AUDIO_BLOCK_SAMPLES ?

Lets do the math
15 cm at 330m/s would result to about 0.45 ms, very close to the 3 values 0.34,0.36,0.34 ms.(which is effectively 11 cm)
So question is why are there values at higher delays. There are definitely spurious and could be coming in via microphone.

So we have now to tune the system
max distance is 1 m, right?
so max delay is 3 ms which is about 1 audio block.
Lets take 6 ms max delay and see if printout gets cleaner

for 6 ms max delay
- replace delay(200) in ping() by delay(6)
- replace 512 in loop by 128 (0 to 3 ms delay of replica)
- keep distance constant at 15 cm.

If you get a clean reading then OK,
Consequently one has to verify value. why it says 0.34 and not 0.45 for example.

BTW: we ARE doing cross correlation (of a received signal with a delayed signal). It is only done with the functions available in the audio library, so it is done with a delay loop and not inside a audio effect function.
 
Ok,
I just updated the code with this last settings. The microphone is at about 15cm from the speaker.
I execute the code 6 times and I got this result :
0.63
0.88
0.88
0.91
0.66
0.88

It seems that the most consistent value is 0.88 which would corresponds to 29,9cm, so the double.

Is that make sense to you ?

The new code is here :
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <MedianFilter.h>

// GUItool: begin automatically generated code
AudioSynthToneSweep      tonesweep1;     //xy=104,237
AudioOutputI2S           i2s1;           //xy=304,96
AudioEffectDelay         delay2;         //xy=353,349
AudioInputI2S            i2s2;           //xy=434,97
AudioEffectMultiply      multiply2;      //xy=624,396
AudioAnalyzeRMS          rms1;           //xy=776,396
AudioConnection          patchCord1(tonesweep1, delay2);
AudioConnection          patchCord2(tonesweep1, 0, i2s1, 0);
AudioConnection          patchCord3(tonesweep1, 0, i2s1, 1);
AudioConnection          patchCord4(delay2, 0, multiply2, 1);
AudioConnection          patchCord5(i2s2, 0, multiply2, 0);
AudioConnection          patchCord6(multiply2, rms1);
AudioControlSGTL5000     sgtl5000_1;     //xy=104,396
// GUItool: end automatically generated code


MedianFilter Median(10, 0);

const int myInput = AUDIO_INPUT_MIC;
float valMax = 0;
float delayCompens = 0;

void ping(int idel)
{
  float fdel = idel * 1000.0f / AUDIO_SAMPLE_RATE_EXACT;
  AudioNoInterrupts();
  delay2.delay(0, fdel); // delay in ms
  AudioInterrupts();
  tonesweep1.play(1.0, 500, 3000, 0.01);
  delay(6);
  float val = rms1.read() * 1000;
  if (val > valMax) {
    valMax = val;
    delayCompens = fdel;
  }
  Serial.printf("%d %f %f\n\r", idel, fdel, val);
  Serial.println("  -----  ");
}

void setup() {
  // put your setup code here, to run once:
  AudioMemory(80);
  while (!Serial);
  Serial.println("TestShift");
  AudioNoInterrupts();
  // setup audio board
  sgtl5000_1.enable();
  // setup headphone
  sgtl5000_1.volume(0.8);
  sgtl5000_1.inputSelect(myInput);
  // setup microphone
  sgtl5000_1.micGain(50); // from 0 to 63
  for (int ii = 1; ii < 8; ii++) delay2.disable(ii);
  AudioInterrupts();
}

void loop() {
  static int idel = 1;
  if (idel < 0) return;
  ping(idel);
  idel++;
  if (idel > 128) {
    Serial.print("The Delay compensation is : ");
    Serial.println(delayCompens);
    idel = -1; // mark to stop
  }
}
 
Last edited:
Sorry, didn't have time to check it out as I had other problems to solve.

What I can say is that I finally cut the microphone each time a sound is played, which is not ideal at all but does the job... I finally realised that the delay between internal signal and microphone could probably be something like 130 ms because of when the "isplaying" function return 0, the microphone still receives the sound of the soundfile for about 130 ms (I have a 10 ms delay in the loop and I counted 13 iteration before the signal falls down to the "normal" value of ambiant noise).

What is the meaning of that ? The value of RMS1 taken at the microphone output takes time to arrive to the teensy ?
 
Status
Not open for further replies.
Back
Top