Я использую плату разработки ESP8266 NodeMCU 12-E для захвата звука с электретного микрофона с предварительным усилением, а затем загружаю его в Интернет, где он будет преобразован в файл wav. Моей первой мыслью было преобразовать целочисленные значения analogRead(A0)
на ESP8266 в тип String
, а затем объединить их в более длинную строку полезной нагрузки, которую я могу опубликовать у брокера MQTT.
Подписчики моего клиента MQTT, похоже, не получали надлежащие звуковые файлы, потому что все, что я слышал, было серией ритмичных хлопков.
Я решил проверить, правильно ли записывает мой код на плате ESP8266. Я сократил код до этих нескольких строк, которые, кажется, вызывают проблемы:
#include <ESP8266WiFi.h>
const char *ssid = "____"; // Change it
const char *pass = "____"; // Change it
void setup()
{
Serial.begin(115200);
Serial.println(0); //start
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
}
void loop()
{
int analog = analogRead(A0);
if (analog > 255) {
analog = 255;
}
else if (analog < 0){
analog = 0;
}
Serial.print(String(analog));
Serial.print(" ");
}
Вот как я использую приведенный выше код для создания wav-файла, чтобы проверить, соответствует ли звук тому, что я ожидаю:
- I start up the ESP8266 development board
- I turn on the Serial Monitor and clear all previous output
- I power up my electret microphone and speak into it
- I power down my electret microphone
- I copy the contents of the Serial Monitor (which is a series of integers) into a text file called `audio.raw`
- I copy `audio.raw` to a linux machine that has ffmpeg installed
- I issue the command `ffmpeg -f u8 -ar 11111 -ac 1 -i audio.raw -y audio.wav` on the linux machine
Когда я слушаю файл audio.raw, я слышу свой голос, но скорость может быть в 5-10 раз выше, чем обычно. (Я также получаю много шума и искажений, но это может быть отдельная проблема с качеством входного сигнала.)
Затем я попытался изменить эту строку кода Serial.print(String(analog))
на Serial.print(analog)
. Затем я повторил шаги, описанные выше. Но на этот раз мой голос звучит примерно в 2 раза быстрее, чем обычно.
Почему изменение этой строки с Serial.print(String(analog))
на Serial.print(analog)
имеет такое большое значение?
Не потому ли, что функция String()
— очень дорогая операция, занимающая много времени? А когда сценарию требуется больше времени для обработки каждой строки кода, у него остается меньше времени для сбора достаточного количества analogRead(A0)
точек данных? И если я запущу ту же команду ffmpeg
, используя все те же флаги, то ffmpeg попытается выполнить требование -ar 11111
, ускорив воспроизведение звука? Что означает, что моя частота дискретизации зависит от скорости выполнения моего скрипта? Что означает, что я должен учитывать переменную скорость выполнения на других платах той же модели из-за различий в точности изготовления, температуре окружающей среды и т. д.?