earlephilhower / ESP8266Audio

Arduino library to play MOD, WAV, FLAC, MIDI, RTTTL, MP3, and AAC files on I2S DACs or with a software emulated delta-sigma DAC on the ESP8266 and ESP32
GNU General Public License v3.0
2.03k stars 434 forks source link

Description for the repeated playing of files. #67

Open JohannesMTC opened 6 years ago

JohannesMTC commented 6 years ago

Dear Earl!

May I ask you to describe exactly what to close and reopen when repeatedly outputting a file?

Have some problems with the following sketch:

#include <Arduino.h>
#include <WiFi.h>
#include "AudioFileSourceSPIFFS.h"
#include "AudioGeneratorWAV.h"
#include "AudioOutputI2S.h"
#include "AudioOutputMixer.h"
#include "SPIFFS.h"

AudioGeneratorWAV *wav[2];
AudioFileSourceSPIFFS *file[2];
AudioOutputI2S *out;
AudioOutputMixer *mixer;
AudioOutputMixerStub *kanal[2];

static uint32_t start = 0;

void setup() {
  WiFi.mode(WIFI_OFF);
  Serial.begin(115200);
  delay(1000);

  SPIFFS.begin();

  out = new AudioOutputI2S();
  mixer = new AudioOutputMixer(32, out);
  wav[0] = new AudioGeneratorWAV();
  wav[1] = new AudioGeneratorWAV();
  kanal[0] = mixer->NewInput();
  kanal[0]->SetGain(0.3);
  kanal[1] = mixer->NewInput();
  kanal[1]->SetGain(0.4);

  file[0] = new AudioFileSourceSPIFFS("/engine1.wav");
  wav[0]->begin(file[0], kanal[0]);

  start = millis();
}

void loop() {

  if (wav[0]->isRunning()) {
    if (!wav[0]->loop()) {
      wav[0]->stop();
      kanal[0]->stop();
      file[0] = new AudioFileSourceSPIFFS("/engine1.wav");
      wav[0]->begin(file[0], kanal[0]);
    }
  }
  if (wav[1]->isRunning()) {
    if (!wav[1]->loop()) {
      wav[1]->stop();
      kanal[1]->stop();
    }
  }

  if (millis() - start > 10000) {
    start = millis();
    file[1] = new AudioFileSourceSPIFFS("/makrofon.wav");
    wav[1]->begin(file[1], kanal[1]);
  }
  delay(1);
}
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
  Serial.printf("Listing directory: %s\n", dirname);

  File root = fs.open(dirname);
  if (!root) {
    Serial.println("Failed to open directory");
    return;
  }

The play goes so far quite well. Only "channel [0]" rushes and barks loudly. Whereby the noise sounds a bit different with every run and calms down in the course of the playback process. A general LOOP function is probably not intended, in which the respective file simply starts again and again?

Suppose that the error lies with me?

earlephilhower commented 6 years ago

I'm just eyeballing this as I'm running a long term test on SSL, but here's what I can see: . You'll want to delete and re-new the WAV component for each new playback. . You also need to delete the old file[] before generating a new one

Basically you're filling up RAM with old file[] entries and things fall over. IF you new something, you need to delete it or you'll end up this way...

JohannesMTC commented 6 years ago

I found the mistake today. (The fault was with the DAC, where I now connected the gain to ground.) On the osizloscope I realized that this input is disturbed by the CLK signal and thus the gain changes constantly. So nothing has to do with your Libery anymore. Sketch described above is about 3 hours error-free.

Since the individual wave sequences are only 20 ms long, I only switch the individual wave files when they have expired. Accordingly, there is nothing left in the memory. Hope that this then synonymous in operation runs error-free. The entire Sond loop is pinned to the Core 0, and is thus never interrupted. The remaining processes are held on Core 1. Hopefully that should work then.

In any case, thank you for this Libery. This is how it becomes possible to equip old H0 models with digital control and sound. I have only about 2 cm³ space. The switching power supply, the ESP32, the motor driver and the DAC with loudspeakers have to fit in there. For an MP3 or SD card module there is really no room left.

Since I will work on the project even longer, I keep the project "ESP8266audio" under observation.

What I still lack: (Please do not consider this as a criticism, but as a possible suggestion!)

The speed with which a wave is played to be able to control. For the simmulation of operating noise depending on the tempo.   A LOOP function that causes the Wave Generator to play the same file in a circle until you load something else.

The mixer did not come until later, after a model maker suggested it.

earlephilhower commented 6 years ago

Wow, that's one noisy ground if a direct connection is bouncing during playback. Good catch!

There is already a way to change the speed of a waveform (well, speed it up), but it's not so obvious. The FilterDecimate object implements a FIR as well as decimation stage. I used it to test some issues we thought we had @48KHz by resampling and LPF'ing to 44KHz (and hard-setting).

Probably breaking this into a general-purpose "AudioGeneratorTempo()" filter would make it more approachable. It's simple enough assuming you don't care about aliasing and just add or drop samples according to the speed change ratio...