Hellp, I’m trying to run in Arduino Studio the Seed Arduino mic→ mic serial recording example, with minor modifications, together with the supplied python script, to try to capture 3 seconds of audio at 8kHz. The sketch runs, the python script captures the output, but the issue is, the script seemingly does not respect the timing specified in the mic_config_t mic_config struct.
As it is, my main buffer is 24000 bytes long:
#define SAMPLES 8000*3
int16_t recording_buf[SAMPLES];
and the mic_config_t struct is like that:
mic_config_t mic_config{
.channel_cnt = 1,
.sampling_rate = 8000,
.buf_size = 1600,
.debug_pin = LED_BUILTIN
};
As far I understand, with these settings the ISR routine that transfer the captured samples from the internal buffer to my main buffer (which I will output to serial after capturing all samples) should take ~3 seconds to capture everything: for 8kHz, the ISR should be called 15 times: ((24000/8000) 1600), and each call should happen every 200ms ((1 sec / 8kHz) * 1600).
But it just finishes very quickly, in less than a second, and doesn’t capture all samples. It’s like its not respecting the interval to call the ISR (200ms between calls), filling the buffer almost instantly with noise.
Can someone please help to check the code (which is mainly Seeed’s code anyway), or have any experience with the <mic.h> library to see if there’s anything missing in the setup?
Thank you very much,
Luis.
Arduino sketch and python code supplied below.
Arduino:
#include <mic.h>
// Settings
#define DEBUG 1 // Enable pin pulse during ISR
#define SAMPLES 8000*3 // 3 seconds of audio @ 8kHz
// Define the DC Offset based on the ADC range (0 to 4000)
#define DC_OFFSET 1900
mic_config_t mic_config{
.channel_cnt = 1,
.sampling_rate = 8000,
.buf_size = 1600,
.debug_pin = LED_BUILTIN
};
MG24_ADC_Class Mic(&mic_config);
int16_t recording_buf[SAMPLES];
volatile static bool record_ready = false;
volatile static bool recording = false;
volatile static uint32_t idx = 0;
volatile static uint32_t vezes = 0;
volatile static unsigned long initialTime = 0;
volatile static unsigned long finalTime;
void setup() {
Serial.begin(115200);
while (!Serial) {delay(10);}
Mic.set_callback(audio_rec_callback);
if (!Mic.begin()) {
Serial.println("init_fail");
while (1);
}
Serial.println("init_ok");
}
void loop() {
// Wait for "init" command
while(Serial.readString() != "init\n") {
}
Serial.println("init_ok");
// Wait for "rec" command
while(Serial.readString() != "rec\n") {
}
idx = 0; // Reset index
recording = true; // Start the recording process
vezes = 0;
// Wait for the callback to finish filling the buffer
while(!record_ready) {
}
//Serial.print("Passed through record_ready=true "); Serial.print(vezes); Serial.print(" times in ");
//Serial.print(finalTime - initialTime); Serial.println(" ms.");
// Data transfer section
if (record_ready) {
Serial.println("rec_ok");
for (int i = 0; i < SAMPLES; i++) {
Serial.println(recording_buf[i]);
}
Serial.println("fi");
record_ready = false;
}
}
static void audio_rec_callback(uint16_t *buf, uint32_t buf_len) {
if (recording) {
vezes++;
if (initialTime == 0) { initialTime=millis(); }
for (uint32_t i = 0; i < buf_len; i++) {
recording_buf[idx] = (int16_t)((buf[i] - DC_OFFSET) * 16);
idx++;
if (idx >= SAMPLES) {
finalTime = millis();
initialTime = 0;
idx = 0;
record_ready = true;
recording = false;
break;
}
}
}
}
Python code:
import os, sys
import serial
import wave, struct
import logging
import argparse
logging.basicConfig(level=logging.INFO)
commands = [b"“, b"rec_ok”, b"init_ok", b"fi"]
sampleRate = 8000 # hertz
duration = 3 # seconds
def write_wav_data(raw_sound, filename):
logging.debug(raw_sound)
obj = wave.open(filename, 'w')
obj.setnchannels(1) # mono
obj.setsampwidth(2)
obj.setframerate(sampleRate)
for value in raw_sound:
data = struct.pack('<h', value)
obj.writeframesraw(data)
obj.close()
def main(args):
i = 1
ser = serial.Serial(args.port, args.baud_rate, timeout=1)
logging.info(‘Awaiting response from device’)
while True:
ser.write(b"init\n")
recv = ser.readline().rstrip()
print(recv)
if recv == b'init_ok':
logging.info('Device init successful')
break
if recv == b'init_fail':
logging.error('Device init failed')
sys.exit(0)
while True:
try:
logging.info('READY')
input("Press Enter to continue...")
ser.write(b"rec\n")
logging.info('RECORDING')
recv = ""
raw_sound = []
while True:
recv = ser.readline().rstrip()
if recv == b"rec_ok":
logging.info('RECORDING FINISHED')
if recv == b"fi":
logging.info('TRANSFER FINISHED')
break
if not recv in commands:
raw_sound.append(int(recv))
#print(int(recv))
#logging.debug(recv)
filename = args.filename + str(i) + ".wav"
write_wav_data(raw_sound, filename)
i += 1
except KeyboardInterrupt:
logging.info('Exiting script')
break
if name == ‘main’:
argparser = argparse.ArgumentParser(
description='Record and save sound from device')
argparser.add_argument(
'-p',
'--port',
help='port for connection to the device')
argparser.add_argument(
'-b',
'--baud_rate',
default=115200,
help='Connection baud rate')
argparser.add_argument(
'-n',
'--filename',
default='sound',
help='Prefix for sound files')
args = argparser.parse_args()
main(args)