Unwanted playback speed change #1751
-
Problem DescriptionThis sketch records into the SPIFF from an i2s microphone and plays back what was recorded. Then it plays back a text from TTS Device DescriptionXIAO ESP32-S3 - INMP441 - MAX98357 Sketch#include "AudioTools.h"
#include <LittleFS.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "AudioTools/AudioCodecs/CodecMP3Helix.h"
#define SPK_PIN_I2S_BCK 7
#define SPK_PIN_I2S_WS 8
#define SPK_PIN_I2S_DIN 44
#define MIC_PIN_I2S_BCK 1
#define MIC_PIN_I2S_WS 2
#define MIC_PIN_I2S_DIN 3
#define BUTTON_PIN 9 // Pin para el botón
float RecordVolume=15.0; // set the recording playback volume (float)
float TTSVolume=5.0; // set the TTS Voice volume (float)
#define WIFI_SSID "YourSDID" // your Wifi SSID
#define WIFI_PASSWORD "YourPASSWD" // your WIfi password
const char file_name[] = "/rec.wav";
bool isRecording = false;
bool playing = false;
bool isDecoding=false;
static unsigned long lastTime = 0;
// Audio Setup
AudioInfo info(16000, 1, 16);
I2SStream out;
I2SStream in;
VolumeMeter volumeMic(in);
VolumeStream volume(out);
VolumeStream volumeTTS(out);
WAVDecoder wav;
File file; // final output stream
EncodedAudioStream SavetoSPIFF(&file, new WAVEncoder());
EncodedAudioStream PlayWav(&volume, &wav); // Decoding stream
EncodedAudioStream Mp3Decoder(&volumeTTS, new MP3DecoderHelix());
StreamCopy copier;
StreamCopy ttsCopier; // StreamCopy TTS
URLStream urlStream(WIFI_SSID, WIFI_PASSWORD);
StrExt query("http://translate.google.com/translate_tts?ie=UTF-8&tl=%1&client=tw-ob&ttsspeed=%2&q=%3");
bool ttsPlaying = false;
void playTTS(String text, const char* lang = "en", const char* speed = "1") {
String part = "";
int maxLength = 200; // Máximo de caracteres por solicitud
int textLength = text.length();
int start = 0;
while (start < textLength) {
int end = start + maxLength;
if (end < text.length()) {
while (end > start && text[end] != ' ' && text[end] != '.' && text[end] != ',') {
end--;
}
}
if (end == start) {
end = start + maxLength;
}
part = text.substring(start, end);
StrExt query("http://translate.google.com/translate_tts?ie=UTF-8&tl=%1&client=tw-ob&ttsspeed=%2&q=%3");
query.replace("%1", lang);
query.replace("%2", speed);
StrExt encodedText(part.c_str());
encodedText.urlEncode();
query.replace("%3", encodedText.c_str());
const char* url_str = query.c_str();
urlStream.end();
urlStream.setReadBufferSize(256);
urlStream.begin(url_str, "audio/mp3");
Mp3Decoder.begin();
ttsCopier.begin(Mp3Decoder, urlStream);
ttsPlaying = true;
while (ttsCopier.copy()) {
delay(10);
}
Serial.println("TTS fragment finished");
ttsPlaying = false;
Mp3Decoder.end();
urlStream.end();
PlayWav.begin();
SavetoSPIFF.begin();
start = end + 1;
}
}
String urlEncode(String str) {
String encodedString = "";
char c;
char code0;
char code1;
for (int i = 0; i < str.length(); i++) {
c = str.charAt(i);
if (c == ' ') {
encodedString += "+";
} else if (isalnum(c)) {
encodedString += c;
} else {
code1 = (c & 0xf) + '0';
if ((c & 0xf) > 9) {
code1 = (c & 0xf) - 10 + 'A';
}
code0 = ((c >> 4) & 0xf) + '0';
if (((c >> 4) & 0xf) > 9) {
code0 = ((c >> 4) & 0xf) - 10 + 'A';
}
encodedString += '%';
encodedString += code0;
encodedString += code1;
}
}
return encodedString;
}
void initI2S(){
auto config_out = out.defaultConfig(TX_MODE);
config_out.copyFrom(info);
config_out.port_no = 1;
config_out.pin_data = SPK_PIN_I2S_DIN;
config_out.pin_ws = SPK_PIN_I2S_WS;
config_out.pin_bck = SPK_PIN_I2S_BCK;
config_out.channel_format = I2SChannelSelect::Right;
auto config_in = in.defaultConfig(RX_MODE);
config_in.copyFrom(info);
config_in.i2s_format = I2S_STD_FORMAT;
config_in.is_master = true;
config_in.port_no = 0;
config_in.channel_format = I2SChannelSelect::Right;
config_in.pin_data = MIC_PIN_I2S_DIN;
config_in.pin_bck = MIC_PIN_I2S_BCK;
config_in.pin_ws = MIC_PIN_I2S_WS;
auto configvol = volume.defaultConfig();
configvol.allow_boost = true;
auto configvol_TTS = volumeTTS.defaultConfig();
configvol_TTS.allow_boost = true;
in.begin(config_in);
SavetoSPIFF.begin(info);
out.begin(config_out);
volumeMic.begin(info);
volume.begin(configvol);
volume.setVolume(RecordVolume);
volumeTTS.begin(configvol_TTS);
volume.setVolume(TTSVolume);
// PlayWav.addNotifyAudioChange(out);
// copier.setSynchAudioInfo(true); // alternative way
}
// Arduino Setup
void setup(void) {
// Open Serial
const int limit = 1000000;
heap_caps_malloc_extmem_enable(limit);
Serial.begin(115200);
//AudioLogger::instance().begin(Serial, AudioLogger::Warning);
AudioLogger::instance().begin(Serial, AudioLogger::Debug);
if(psramInit()){
Serial.println("\nThe PSRAM is correctly initialized");
}else{
Serial.println("\nPSRAM does not work");
}
pinMode(BUTTON_PIN, INPUT_PULLUP);
AudioLogger::instance().begin(Serial, AudioLogger::Warning);
connectToWiFi();
initI2S();
if (!LittleFS.begin()) {
Serial.println("Initialization failed!");
stop();
}
Serial.println("I2S started...");
}
void record() {
// Reset streams
urlStream.end();
Mp3Decoder.end();
ttsCopier.end();
in.flush();
out.flush();
SavetoSPIFF.begin(info);
volumeMic.begin(info);
// Start recording
Serial.println(F("Starting to record"));
if (LittleFS.exists(file_name)) {
LittleFS.remove(file_name);
}
file = LittleFS.open(file_name, FILE_WRITE);
if (!file) {
Serial.println("File failed to open!");
stop();
}
SavetoSPIFF.begin(info);
copier.begin(SavetoSPIFF, volumeMic);
isRecording = true;
}
void stopRecording() {
// Finish recording
if (file) {
file.flush();
Serial.print("File has ");
Serial.print(file.size());
Serial.println(" bytes");
SavetoSPIFF.end();
file.close();
}
isRecording = false;
}
void play() {
// Reset stream states before playing
in.flush();
out.flush();
Mp3Decoder.end();
ttsCopier.end();
volumeMic.begin(info);
PlayWav.begin(info);
// Open File to play
file = LittleFS.open(file_name);
if (!file) {
Serial.println(F("Failed to open file for playback!"));
stop();
}
copier.begin(PlayWav, file);
}
// Arduino loop
void loop() {
int buttonState = digitalRead(BUTTON_PIN);
if (buttonState == LOW && !isRecording) {
record();
}
if (buttonState == HIGH && isRecording) {
stopRecording();
playing = true;
play();
}
if (isRecording) {
copier.copy();
}
if (playing) {
//copier.copy();
bool isCopying = copier.copy();
if (!isCopying) {
Serial.println(F("Playback finished"));
playing = false;
file.close();
// sendToDeepgram(file_name);
playTTS("recording finished successfully","en");
}
}
}
void connectToWiFi() {
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.println(F("Connecting to WiFi..."));
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.println(F("Connected to WiFi..."));
} Other Steps to ReproduceNo response What is your development environmentArduino IDE I have checked existing issues, discussions and online documentation
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
Please use issues only to report bugs in my software and not the bugs that you produce in your sketch. As an alternative you can standardize the sample rate across all your data sources by up or downsampling. |
Beta Was this translation helpful? Give feedback.
-
Thanks Phil ! I really appreciate your work, it's amazing |
Beta Was this translation helpful? Give feedback.
Please use issues only to report bugs in my software and not the bugs that you produce in your sketch.
If you change the data source, you need to manage the sample rate with the help of getAudioInfo() and setAudioInfo().
Make sure that you call setAudioInfo() on i2s with the rate and number of channels that you are using.
As an alternative you can standardize the sample rate across all your data sources by up or downsampling.