pschatzmann / arduino-audio-tools

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

recording WAV to SD is not working with ADPCM #1690

Closed ffaerber closed 2 months ago

ffaerber commented 2 months ago

Problem Description

i try this example https://www.pschatzmann.ch/home/2023/05/21/adpcm-and-wav-files/ and this https://github.com/pschatzmann/arduino-audio-tools/blob/main/tests-cmake/codec/wav/wav.cpp but its not working. if i record a wav with ADPCM. the wav file is only containing silence with some cracking noises.

Device Description

xiao esp32s3 sense

Sketch

SdFs SD;
AudioInfo info(16000, 1, 16);
I2SStream microphone;
SdFile wavFile;
ADPCMEncoder adpcm_encoder(AV_CODEC_ID_ADPCM_IMA_WAV); 
EncodedAudioStream wavEncoderToFile(&wavFile, new WAVEncoder(adpcm_encoder, AudioFormat::ADPCM));
VolumeStream vol(wavEncoderToFile);
StreamCopy micToFileCopier(wavEncoderToFile, microphone);

I2SStream speaker;
MP3DecoderHelix mp3Decoder;
EncodedAudioStream mp3DecoderToSpeaker(&speaker, &mp3Decoder);
URLStream url;
StreamCopy urlToSpeakerCopier(mp3DecoderToSpeaker, url);

void recorder(void *pvParameters) {
  int randomNumber = random(1000, 10000);
  sprintf(filename, "/%04d.wav", randomNumber);
  if (SD.begin(21)) {
    if (wavFile.open(filename, O_WRONLY | O_CREAT )) {
      Serial.println("wavFile is open");
    }else{
      Serial.println("error open wavFile");
    }
  }
  wavEncoderToFile.begin();
  while (1) {
    if (recording) {
      micToFileCopier.copy();
    } else {
      wavEncoderToFile.end();
      Serial.println("record Stop");
      wavFile.close();
      sendNotification(xHttpControllerHandle, UPLOAD_VOICE_RECORD);
      vTaskDelete(NULL);
    }
  }
}

void player(void *pvParameters) {
  playing = true;
  String apiUrl = String(apiProtocol) + String(apiHostname) + String(":") + String(apiPort);
  String _messageAudioUrl = apiUrl + String("/messages/") + messageId + String("/audio");
  const char* messageAudioUrl = _messageAudioUrl.c_str();
  url.begin(messageAudioUrl, "audio/mp3");
  mp3DecoderToSpeaker.begin();
  urlToSpeakerCopier.copyAll();
  mp3DecoderToSpeaker.end();
  playing = false;
  vTaskDelete(NULL);
}

void audioController(void *pvParameter) {
  uint32_t ulNotificationValue;
  const TickType_t xTicksToWait = portMAX_DELAY;
  TaskHandle_t xRecorderHandle = NULL;
  TaskHandle_t xPlayerHandle = NULL;

  AudioLogger::instance().begin(Serial, AudioLogger::Warning);

  auto microphone_cfg = microphone.defaultConfig(RX_MODE);
  microphone_cfg.copyFrom(info);
  microphone_cfg.signal_type = PDM;
  microphone_cfg.i2s_format = I2S_PCM;    
  microphone_cfg.pin_bck = I2S_PIN_NO_CHANGE;
  microphone_cfg.pin_ws = 42;
  microphone_cfg.pin_data = 41;
  microphone_cfg.port_no = 0;

  auto vol_cfg = vol.defaultConfig();
  vol_cfg.copyFrom(info);
  vol_cfg.allow_boost = true;
  vol.begin(vol_cfg);
  vol.setVolume(12);

  auto speaker_cfg = speaker.defaultConfig(TX_MODE);
  speaker_cfg.copyFrom(info); 
  speaker_cfg.i2s_format = I2S_STD_FORMAT;
  speaker_cfg.port_no = 1;
  speaker_cfg.pin_bck = 4; // BCLK
  speaker_cfg.pin_ws = 43; // LRC
  speaker_cfg.pin_data = 3; // DIN - Data Input
  speaker_cfg.port_no = 1;
  speaker.begin(speaker_cfg);

  microphone.begin(microphone_cfg);
  wavEncoderToFile.begin(info);
  mp3DecoderToSpeaker.begin();

  while (true) {
    if (xTaskNotifyWait(pdFALSE, ULONG_MAX, &ulNotificationValue, xTicksToWait) == pdPASS) {
      EventCode currentEvent = static_cast<EventCode>(ulNotificationValue);

      switch (currentEvent) {

        case START_VOICE_RECORD:
          Serial.println("START_VOICE_RECORD");
          recording = true;
          xTaskCreatePinnedToCore(recorder, "recorder", 12*1024, NULL, 1, &xRecorderHandle, APP_CPU);
          break;

        case STOP_VOICE_RECORD:
          Serial.println("STOP_VOICE_RECORD");
          recording = false;
          sendNotification(xMqttControllerHandle, PUBLISH_APP_STATE);
          break;

        case START_PLAY:
          Serial.println("START_PLAY");
          xTaskCreatePinnedToCore(player, "player", 24*1024, NULL, 1, &xPlayerHandle, APP_CPU);
          break;

        default:
          Serial.println("Unknown event in microphone");
          break;
      }
    } else {
      Serial.println("Failed to receive from appEventQueue");
    }

    vTaskDelay(100 / portTICK_PERIOD_MS);
  }
}

Other Steps to Reproduce

recording to SD without ADPCMEncoder works fine.

What is your development environment

Arduino

I have checked existing issues, discussions and online documentation

pschatzmann commented 2 months ago

The adpcm test case was passing successfully. The WAV codec was indeed broken: I committed a correction and added a corresponding test case

image