Francesco Maccantelli
Francesco Maccantelli

Reputation: 11

How to save 16khz audio sampling from Arduino nano 33 BLE?

I'm working on a project that requires saving audio files from Arduino NANO 33 BLE, to create a dataset with EdgeImpulse, first of all, I can not use integrated webUSB to save audio directly on EdgeImpulse because I need to associate that audio file to a video that save locally, after that I analyze the video for associate the audio with a specific class based on the video.

My first try was to use the example file (PDMSerialPlotter) to save sampling, but if I saves the sampling received by the terminal using this python function:

def serial_import_from_arduino(time_str,serial_port_name):

    ser = serial.Serial(serial_port_name, 115200)     # Create Serial link
    
    prefisso = "audio/"
    file_name = prefisso + time_str + ".json"
    file = open(file_name,"w")

    for x in range(sample):       # sample = # of samples to save
          cc=str(ser.readline())
          print(cc)
          file.write(cc[2:][:-5])
          file.write(",")
    
    file.close()

to run this script it should have lasted 5 seconds because the microphone sampling is 16khz and the sample variable is 16k * 5 but the script runs for about 22 seconds(in this time I counted from 1 to 22), for the upload I set the sampling rate at 16khz on EdgeImpulse the audio length is 5 seconds but the audio is speeded up.

So my opinion is that the Serial.print() is not fast enough to save 16khz sampling (16bit)

Searching online I found that, the function Serial.print() converts the data to ASCII code and send it, this process can waste some time, so I made a simple Arduino code that sends just a number with Serial.write() function (that should not convert data, but can sand just 1 byte for times) this code:

void setup() {
 Serial.begin(115200);
 while(!Serial);
}

byte value = 255;

void loop() {

  Serial.write(value);

}

And I analyzed the Serial with a Python script that reads 2 bytes (16bit) save it on a file, and count how many sample save in a second: import serial import time

ser = serial.Serial("COM3", 115200)     # Create Serial link
value = 0
file = open("audio/file.txt","w")
start_time = time.time()
print(start_time)
while(time.time()-start_time < 1 ):
    value = value + 1
    file.write(str(ser.read(1)))
    file.write(",")
file.close()
print(value)

If I take 2 bytes in 1 secods saves [5700-5800] samples, but I need 16000 in a second.

My second attempt was to save samples locally on Arduino and transfer them later all at once, the problem is that I cannot save audio with a length longer than about 6 seconds because I fill the Arduino memory, and my project requires audio longer than 6 seconds, possibly I would like to record audio continuously or at least for 30-60 min

please help me!

Upvotes: 0

Views: 749

Answers (1)

Francesco Maccantelli
Francesco Maccantelli

Reputation: 11

I found a way! Just save data in a buffer, a buffer that must be uint8_t type, so at 1 Byte, for my case, I just scroll my buffer at 2 Bytes and use this code to divide the data:

  if (samplesRead) {

    for (int i = 0; i < samplesRead; i=i+1) {

      sampleBuffer_8bit[sb_index] = (sampleBuffer[i] >> 8) & 0xFF;
      sb_index ++;  
      sampleBuffer_8bit[sb_index] = (sampleBuffer[i] & 0xFF);
      sb_index ++;

  }

in this way I can use the code that follows to send an array of data, that must be at 8 bit (1 byte) all at once

SerialUSB.write(sampleBuffer_8bit,sb_index);

I used SerialUSB but also Serial should work fine, I think.

Upvotes: 1

Related Questions