pschatzmann / arduino-audio-tools

Arduino Audio Tools (a powerful Audio library not only for Arduino)
GNU General Public License v3.0
1.55k stars 237 forks source link

High End Response #1198

Open Borgling opened 10 months ago

Borgling commented 10 months ago

Problem Description

Hey All,

Thanks for all your work on these tools, very awesome of you!

On both the 3.0a version and 2.0.11 of ESP32 Arduino. I'm getting very weird results.

For 2.0.11

To capture a up to 20khz frequency range I need to set the samples to 88400. Anything below that it starts turning higher frequencies into lower ones, like I was only capturing at 20khz (for 44100hz)

Even though playback is fine at the given sample rate. E.g. 44100, e.g. the file is the correct speed when played back as if it was a 44100 sample rate, it misses all the top ends.

But setting to 88400hz samples, I do get all required frequencies, but double the file size needed.

For 3.0a

All hell breaks loose!

1) Firstly, setting a sample rate above 70khz, does something weird to the ESP32.

It throws :

Guru Meditation Error: Core 1 panic'ed (Cache disabled but cached memory region accessed).

But even when I re-flash a sketch at lower hz, it still throws the error. But... leaving the ESP32 alone for 10 to 20 mins(?!), coming back to it, seems to resolve the problem, and the lower hz sketch starts working again.... I can't work it out, but I've replicated the issue 20 times now. Set to 80kz samples, and it's sort of half bricked until I leave it alone, so weird.

Even more weird, sometimes just letting it restart itself after a panic, maybe 20-30 times, it will start working by it's self and the sketch runs.

Note: in all occasions I am using wifi at the same time. But I have had the Guru Mediation Error, even with wifi disabled on 3.0 with the samples set above 80,000, but it's less frequent.

2) The results when using the 3.0a version, are a bit wild. See image below, we some strange behaviour at the high ends not seen with the older version. I'm not sure if this:

  1. Arduino audio tools issues?
  2. New continuous ADC issue?
  3. Something I need to do with the results of the new continuous ADC that I'm not doing?

3) The sample rate doesn't match the output sample rate. For example setting to 70khz seems to give an output of around 57500Hz.

Below is an image to highlight the issue.

Track1: Original source audio Track2: 2.11 Audio using I2S : sample rate 88400 -> imported sample rate 88400hz Track3: 3.0a Audio using continuous ADC : sample rate 70000 -> imported sample rate 57500hz

As you can see in track 3, it's picking up the high end frequency, but with strange amount of of banding(?) in there.

image

The issues are consistent across multiple chips I've tried, including one esp32 doit dev kit one. Although they are all older chips ESP32-D0WDQ6 rev1 chips.

Device Description

ESP32 wroom, on custom board.

Chip is ESP32-D0WDQ6 (revision v1.0) Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None

Sketch

AnalogAudioStream adc;

#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
  const int32_t max_buffer_len = 7000;
#else
  const int32_t max_buffer_len = 16384;
#endif
uint8_t buffer[max_buffer_len] = {0};

void sendData(WiFiClient *wifiClient, HTTPClient *httpClient, const char *url, uint8_t *bytes, size_t count)
{
   //send them off to the server
  httpClient->begin(*wifiClient, url);
  httpClient->addHeader("content-type", "application/octet-stream");
  httpClient->POST(bytes, count);
  httpClient->end();
}

auto adcConfig = adc.defaultConfig(RX_MODE);

// Arduino Setup
void setup(void) {

  delay(3000); // Give time to boot
  Serial.begin(115200);

  // Include logging to serial
 // AudioLogger::instance().begin(Serial, AudioLogger::Info); //Warning, Info
  Serial.println("ADC SETUP");

#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
    adcConfig.sample_rate =70000; // about 57500
    adcConfig.buffer_count = 50;
    adcConfig.buffer_size = 1024;
    adcConfig.adc_channels[0] = ADC_CHANNEL_7;
    //adcConfig.adc_bit_width = 12; // this will result in 16 bits_per_sample
#else
    adcConfig.sample_rate =88400; // about 88400 hz
    adcConfig.adc_pin  = 35;
    adcConfig.buffer_count = 48;
    adcConfig.buffer_size = 1024;

#endif

    adcConfig.channels = 1;

    WiFi.mode(WIFI_STA);
    WiFi.begin(SSID, PASSWORD);
    while (WiFi.waitForConnectResult() != WL_CONNECTED)
    {
      Serial.print(".");
      delay(1000);
    }

    Serial.println("Wifi Started");

   // setup the HTTP Client
   wifiClientADC = new WiFiClient();
   httpClientADC = new HTTPClient();

}

bool adcstarted = false;

void loop()
 {
    if(!adcstarted)
    {
      adc.begin(adcConfig);
      adcstarted = true;
      Serial.println("ADC STARTED");

    }

  size_t len = adc.readBytes(buffer, max_buffer_len); 
  sendData(wifiClientADC, httpClientADC, ADC_SERVER_URL, (uint8_t *)buffer, len * sizeof(uint8_t));

}

Other Steps to Reproduce

No response

What is your development environment

Arduino IDE.

I have checked existing issues, discussions and online documentation

pschatzmann commented 10 months ago

Not sure if it is a good idea to use the internal dac for this purpose: I would have used a proper audio dac for this! Are you sure that the Wifi is fast enough to handle these sampling rates properly?

With a sampling rate of 44100 you should be able to get frequencies up to 22050 hz. How did you test the receiving of high frequencies ?

Borgling commented 10 months ago

Hey thanks for the response.

I'm using a frequency sweep to test, 20hz to 20khz. If I run below 88400 in 2.11 (say 44100), I start seeing a drop off of at around 10khz instead of 20khz. By dropping off I mean it starts getting recorded as a signal at half the hz. If I FFT you'll see it bounce from one end and the peak starts moving backwards.

I was getting a lot of dropped packets, but upping the buffers sorted that out. I tested this with a lot of clicks at various bpms, then matching up the beats. If packets / samples are missing, they would go out of sync with the original. The current settings on wifi allow a consistent stream, occasional sample loss, but only after 30 mins recording. The file size and time also help with detecting loss of samples. Using both methods I'm confidant nothing is being lost in my short tests.

I forgot to mention the analog signal is coming from a max9814 microphone module.

Borgling commented 10 months ago

Here is an example: 2.0.11

Setting sample rates to the amount shown highlighted. (88400, 44100, 22050)

As you can see at 44100hz, is behaving like a lower sample rate where the higher freq start rebounding back on itself.

image

pschatzmann commented 10 months ago

Just out of curiosity: how does this compare if you do the recording directly in Audacity ? Can you share the sound generation: then I can provide you with the result that you would get with an AudioKit which is using a proper ES8388 ADC and DAC

Borgling commented 10 months ago

in my first post, if you take a look at the first image, the top was recorded directly in audacity from audio "desktop audio" , I'll see if I've got a mic somewhere to record line in into audacity. Or better yet, I'll rig up the MAX module I'm using to a line in on the pc.

https://www.youtube.com/watch?v=PAsMlDptjx8

here is the freq sweep I used, I added a couple of kick drums to the start and end for sync reasons.

pschatzmann commented 10 months ago

OK, here is a simple endless Arduino sweep sketch:

#include "AudioTools.h"
#include "AudioLibs/AudioKit.h"

AudioInfo info(44100, 1, 16);
SineWaveGenerator<int16_t> sineWave;                // subclass of SoundGenerator with max amplitude of 32000
GeneratedSoundStream<int16_t> sound(sineWave);             // Stream generated from sine wave
AudioKitStream out; 
StreamCopy copier(out, sound, 512);                             // copies sound into i2s
float freq = 20;

// Arduino Setup
void setup(void) {  
  // Open Serial 
  Serial.begin(115200);
  AudioLogger::instance().begin(Serial, AudioLogger::Warning);

  // start I2S
  Serial.println("starting I2S...");
  auto config = out.defaultConfig(TX_MODE);
  config.copyFrom(info); 
  out.begin(config);

  // Setup sine wave
  sineWave.begin(info, N_B4);
  Serial.println("started...");
}

void sweep(){
  freq += 20.0;
  if (freq > 20000) {
    freq = 20;
  }
  sineWave.setFrequency(freq);
}

// Arduino loop - copy sound to out 
void loop() {
  copier.copy();
  sweep();
}
Borgling commented 10 months ago

Hey thanks,

So, just to check, I should wire two esp32 together, one using i2s out to the other i2s inwards? Use that for testing, taking the mic out of the equation? If so that's a good idea, and probs help stop this headache I'm getting form listening to 15khz > at 50db all day lol

pschatzmann commented 10 months ago

No, I2S between two ESP32 is not working properly

pschatzmann commented 10 months ago

I was playing around with my sweep sketch above and Audacity (connecting the AudioKit with a cable); I left the sound generation at 44100.

Analyzing (in Audacity) with 44100 gives the following image

Analyzing with 48000 gives the following image

Analyzing with 48000 using speaker and PC microphones

image

Conclusion A sampling rate on the recording side of 44100 is sufficient to measure up to 20000 Hz, but 48000 is better... When going thru a speaker and a microphone, the consistency of the volume varies considerably

Borgling commented 10 months ago

Interesting, thanks for info.

What Chip versions of ESP32 are you trying with ?

pschatzmann commented 10 months ago

The AudioKit has a ESP32-A1S which comes with an ES8388 audio chip