【问题标题】:How to save 16khz audio sampling from Arduino nano 33 BLE?如何从 Arduino nano 33 BLE 保存 16khz 音频采样?
【发布时间】:2022-07-14 03:30:50
【问题描述】:

我正在做一个需要从 Arduino NANO 33 BLE 保存音频文件的项目,以使用 EdgeImpulse 创建数据集,首先,我不能使用集成的 webUSB 直接在 EdgeImpulse 上保存音频,因为我需要关联它音频文件到本地保存的视频,然后我分析视频以将音频与基于视频的特定类相关联。

我的第一次尝试是使用示例文件(PDMSerialPlotter)来保存采样,但是如果我使用这个python函数保存终端接收到的采样:

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()

要运行这个脚本,它应该持续 5 秒,因为麦克风采样是 16khz 并且样本变量是 16k * 5 但脚本运行了大约 22 秒(这次我从 1 计数到 22),用于上传我在 EdgeImpulse 上将采样率设置为 16khz,音频长度为 5 秒,但音频加快了。

所以我认为 Serial.print() 速度不够快,无法保存 16khz 采样(16 位)

在网上搜索发现,函数Serial.print()将数据转换成ASCII码发送,这个过程会浪费一些时间,所以我做了一个简单的Arduino代码,用Serial.write( ) 函数(不应该转换数据,但可以只打磨 1 个字节)这段代码:

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

byte value = 255;

void loop() {

  Serial.write(value);

}

我使用读取 2 个字节(16 位)的 Python 脚本分析了 Serial 并将其保存在文件中,并计算一秒钟内保存了多少样本: 导入序列号 进口时间

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)

如果我在 1 秒内占用 2 个字节,则可以节省 [5700-5800] 个样本,但我需要 16000 个。

我的第二次尝试是在 Arduino 上本地保存样本,然后一次全部传输,问题是我无法保存长度超过 6 秒的音频,因为我填满了 Arduino 内存,而我的项目需要更长的音频超过 6 秒,可能我想连续录制音频或至少 30-60 分钟

请帮帮我!

【问题讨论】:

  • 1) 您需要提高您的串行通信速度,115200bps 最多是 115200/10 = 11520 字节数据/秒。 2)如果您将数据作为原始二进制文件发送,为什么要将其转换为 str 以保存它?只需使用open("audio/file.txt","wb" 将其保存为原始二进制数据即可。 3)您可能还想考虑将数据读入字节数组,仅在字节数组填满时才将其写入文件。
  • 我尝试使用一些不同的波特率,但这不会影响我一秒钟可以记录的样本数量,我现在用 2000000 进行了测试(在 Arduino 和 Python 脚本上进行了更改)我设置了open("audio/file.txt","wb"),所以在保存文件之前没有转换为str,结果与[5700-5900]样本之前的几秒钟相同。我认为 Python 脚本足够快,因为如果我在不等待串行通信的情况下打印文件,我可以在几秒钟内编写 650000 个样本,因此限制速度的串行通信也是如此。

标签: python arduino sampling arduino-nano


【解决方案1】:

我找到了方法! 只需将数据保存在缓冲区中,缓冲区必须是 uint8_t 类型,因此在 1 Byte 处,对于我来说,我只是将缓冲区滚动到 2 Bytes 并使用此代码来划分数据:

  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 ++;

  }

通过这种方式,我可以使用下面的代码来发送一个数据数组,该数组必须同时为 8 位(1 个字节)

SerialUSB.write(sampleBuffer_8bit,sb_index);

我使用了 SerialUSB,但我认为 Serial 应该可以正常工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-28
    • 1970-01-01
    • 2020-12-24
    • 2022-07-03
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    相关资源
    最近更新 更多