Open Bartvelp opened 2 years ago
By the magic of adding Serial prints to the source I've further pinpointed the issue to analyse_one_frame
But now it triggers a stackoverflow detection?
14:17:23.580 -> analyse_one_frame -1
14:17:23.580 -> analyse_one_frame 0
14:17:23.580 -> analyse_one_frame 0.5
14:17:23.580 -> analyse_one_f***ERROR*** A stack overflow in task loopTask has been detected.
By the code:
void analyse_one_frame(struct CODEC2 *c2, MODEL *model, short speech[])
{
serialLog("analyse_one_frame -1");
COMP Sw[FFT_ENC];
COMP Sw_[FFT_ENC];
COMP Ew[FFT_ENC];
float pitch;
int i;
PROFILE_VAR(dft_start, nlp_start, model_start, two_stage, estamps);
serialLog("analyse_one_frame 0");
/* Read input speech */
for(i=0; i<M-N; i++)
c2->Sn[i] = c2->Sn[i+N];
serialLog("analyse_one_frame 0.5");
for(i=0; i<N; i++)
c2->Sn[i+M-N] = speech[i];
serialLog("analyse_one_frame 1");
PROFILE_SAMPLE(dft_start);
dft_speech(c2->fft_fwd_cfg, Sw, c2->Sn, c2->w);
PROFILE_SAMPLE_AND_LOG(nlp_start, dft_start, " dft_speech");
serialLog("analyse_one_frame 2");
I'm no C guru and have no idea what is happening.
EDIT: I tried running a reduced version of your sketch and that seems to be working, probably something in my code then. What is wrong with my initial code snippet?
I am fairly sure there is some bug in the codec2 causing stack overflow warnings and the like, apperently when using a FreeRTOS task, the code doesn't crash. This is a suboptimal solution I've come up with in the mean time
#include <codec2.h>
struct CODEC2* codec2_state;
int16_t sine1KHz[8] = { -21210 , -30000, -21210, 0 , 21210 , 30000 , 21210, 0 };
int16_t audioBuf[320];
uint8_t c2Buf[8];
boolean flagEncodeAudioBuf = false;
boolean flagDecodeC2Buf = false;
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("Started codec2 sample");
// Set bitrate
codec2_state = codec2_create(CODEC2_MODE_1600);
// Set some tuning parameters
codec2_set_lpc_post_filter(codec2_state, 1, 0, 0.8, 0.2);
xTaskCreate(&codec2_watcher, "codec2_watcher_task", 30000, NULL, 5, NULL);
// Encode a (fixed size) input buffer of type int16_t to a (fixed size) output buffer
// CODEC2_MODE_1600 encodes 320 speech samples (320 * 2 = 640 bytes / 40ms of speech) into 8 bytes (64 bits)
// Fill buffer with a sine wave
for (int i = 0; i < 320; i++) audioBuf[i] = sine1KHz[i % 8];
for (int i = 0; i < 320; i++) Serial.print(String(audioBuf[i], DEC) + " ");
Serial.println();
int startTimeEncode = millis();
c2_encode();
Serial.println("Done encoding, took ms: " + String(millis() - startTimeEncode));
for (int i = 0; i < 8; i++) Serial.print(String(c2Buf[i], DEC) + " ");
Serial.println();
int startTimeDecode = millis();
c2_decode();
Serial.println("Done decoding, took ms: " + String(millis() - startTimeDecode));
for (int i = 0; i < 320; i++) Serial.print(String(audioBuf[i], DEC) + " ");
Serial.println();
}
void loop() {
}
void c2_encode() {
flagEncodeAudioBuf = true;
while (flagEncodeAudioBuf) delay(1); // Wait for the codec2_watch
}
void c2_decode() {
flagDecodeC2Buf = true;
while (flagDecodeC2Buf) delay(1); // Wait for the codec2_watch
}
void codec2_watcher(void* parameter) {
while (true) {
// yield() DOES NOT work, that trips the WDT every 5 secs
// delay(1) is VITAL
delay(1);
if (flagEncodeAudioBuf) { // We have some work to do
codec2_encode(codec2_state, c2Buf, audioBuf);
flagEncodeAudioBuf = false; // Notify encode()
}
if (flagDecodeC2Buf) { // We have some work to do
codec2_decode(codec2_state, audioBuf, c2Buf);
flagDecodeC2Buf = false; // Notify decode()
}
}
}
It currently takes 14 ms to encode 40 ms of data, and 24 ms to decode, definitely not insignificant.
I did never test it without a FreeRTOS task. The codec and decode tasks are very heavy, but as long as you can encode or decode in less than 40ms everything should be OK. For encoding the idea is to take a 40ms audio sample and encode it before arrive the next 40ms sample of audio. For decoding you need to decoding in less than the 40ms of the audio your are currently playing from the previous decoded. You did a great work!. Thanks!
Thanks for your reply, I agree, as long as decoding and encoding takes less than realtime, it is fine. Still I think there is some bug in this library causing the errors, it should be callable from outside a dedicated Task.
Hi, Thanks for your work porting codec2, I'm trying to use your library, and it succesfully compiles. The following code produces hangs on the line executing
codec2_encode
maybe I am overlooking something but what exactly?EDIT: it can also throw: