Как восстановить звук из серии аналоговых целочисленных входов?
Я пытаюсь научиться передавать потоковое аудио с контакта A0 платы ESP8266 NodeMCU через соединение сокета UDP на другой компьютер с Windows, который использует pyaudio для его воспроизведения. На данный момент все, что я слышу на компьютере с Windows, — это серия «хлопающих» звуков, каждый из которых происходит с интервалом примерно в полсекунды.
Я новичок в работе с такими типами секционных плат, поэтому нашел онлайн-проект, который использую в качестве отправной точки:
Потоковая передача звука из ESP8266 в pyaudio, работающая в Arduino IDE
Я полагаю, что начну устранять проблему с треском звука, проверяя UDP-пакеты моего кода ESP8266. Ниже приведен исходный код, над которым я работаю:
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
const char* ssid = "change this";
const char* password = "change this";
int contconexion = 0;
WiFiUDP Udp;
void setup()
{
Serial.begin(115200);
Serial.println();
pinMode(5, OUTPUT); //D1 Led de estado
digitalWrite(15, LOW);
WiFi.mode(WIFI_STA); //чтобы не запускать SoftAP в обычном режиме
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED and contconexion <50) { //Cuenta hasta 50 si no se puede conectar lo cancela
++contconexion;
delay(250);
Serial.print(".");
digitalWrite(5, HIGH);
delay(250);
digitalWrite(5, LOW);
}
if (contconexion <50) {
//для использования с IP-адресом
IPAddress Ip(192,168,1,180);
IPAddress Gateway(192,168,0,1);
IPAddress Subnet(255,255,255,0);
WiFi.config(Ip, Gateway, Subnet);
Serial.println("");
Serial.println("WiFi conectado");
Serial.println(WiFi.localIP());
//digitalWrite(5, ВЫСОКИЙ);
}
else {
Serial.println("");
Serial.println("Error de conexion");
//digitalWrite(15, LOW);
}
}
void loop()
{
Udp.beginPacket("192.168.0.26", 1234);
for(int i=0; i<1024;i++){
int old=micros();
float analog = analogRead(A0);
if (analog > 255) {
analog = 255;
}
else if (analog < 0){
analog = 0;
}
Udp.write(int(analog));
Serial.print(int(analog));
Serial.print(",");
while(micros()-old<87); // 90 мксек = 1 с/11111 Гц - 3 мксек для других процессов
}
Serial.print(";;;;;");
Udp.endPacket();
delay(5);
}
Обратите внимание, что в нижней части файла я распечатываю каждое аналоговое значение, разделенное запятой, и каждый пакет данных, разделенный пятью точками с запятой.
Может ли кто-нибудь предложить мне способ воссоздать эти серии целых чисел в звуковой файл, который я смогу проверить, прослушав собственными ушами? Тогда я смогу определить, полны ли отправляемые звуковые данные? Или дайте мне знать, есть ли лучший способ проверить правильность отправки всех пакетов данных.
ОБНОВЛЕНИЕ
Я пытался создать wav-файл, выполнив следующие действия:
- Возьмите список всех целых чисел из
Serial.print(int(analog))
и вставьте его в файл. Я проверяю, что все целые числа разделены пробелами (т. е. больше нет запятых и точек с запятой). - Я скопировал файл на компьютер с Linux, на котором был установлен ffmpeg.
- Я выполнил команду
ffmpeg -f u8 -ar 11111 -ac 1 -i myfileofintegers -y test.wav
Когда я слушаю файл test.wav, я слышу лишь серию частых хлопков. Не уверены, правильно ли я создал wav-файл?
@John, 👍1
Обсуждение1 ответ
Лучший ответ:
Я пытаюсь научиться передавать потоковое аудио с контакта A0 платы ESP8266 NodeMCU через соединение сокета UDP на другой компьютер с Windows, который использует pyaudio для его воспроизведения.
Вы описали несколько проблем; нужно разбивать большие проблемы на маленькие:
- Пример аудио
- Отправить на другой компьютер
- Декодирование и воспроизведение звука
На данный момент все, что я слышу на компьютере под управлением Windows, — это серия «хлопающих» звуков, каждый из которых происходит с интервалом примерно в полсекунды.
Похоже, что у вас перепутаны временные рамки; вполне вероятно, что вы записываете недостаточно данных или воспроизводите их неправильно. Обратите внимание, похоже, что вы записываете ~92 мс аудиоданных в каждом «пакете», и если вы получаете серию хлопков с частотой 2 Гц, вы, вероятно, воспроизводите менее 1/10 секунды звука в течение 5/10 времени, так что ваш говорящий движется на 1/10 секунды, затем остается на месте на 4/10 секунды и повторяет; это создает хлопающие звуки частотой 2 Гц.
В вашем коде есть и другие проблемы:
- Serial.print() работает медленно! Не используйте его там, где важна производительность!
- Объединение выборки и отправки
- Неправильное масштабирование аналоговых показаний.
- 11,1 кГц позволяет записывать только сигналы частотой до 5,5 кГц.
Начнем с семплирования звука. У нас есть какая-то аудиосхема, подающая сигнал на аналоговый вход, и нам нужно регулярно и равномерно его оцифровывать! Представленный код пытается выполнить выборку на частоте 11,1 кГц, но делает это только для 1024 выборок, прежде чем возникает разрыв. У нас нет специальной схемы, поэтому нам придется использовать схему АЦП на Arduino.
Первое, что вам нужно сделать, это обеспечить регулярный и непрерывный отбор проб. Для этого вам понадобится использовать прерывание на Arduino. Прерывание должно взять одну выборку из АЦП и добавить ее в буфер или сигнализировать основному циклу о ее чтении/буферизации.
Это прерывание должно срабатывать регулярно с частотой дискретизации, иначе данные будут испорчены.
Во-вторых, аудиосхема должна подготовить сигнал так, чтобы он находился в диапазоне 0–5 В со смещением ~ 2,5 В, при этом аппаратное обеспечение АЦП будет использоваться в полной мере.
так в псевдокоде:
// включаем любые библиотеки и т.д.
// устанавливаем переменные и т.д.
void interupt_sample();
// регистрируем и присоединяем прерывание
void setup() {
//выполняем настройку и т.д.
}
void loop() {
// if(new_sample) add_to_buffer(new_sample);
// if(buffer_full) send_and_flush_buffer();
}
Специально для преобразования списка целых чисел в аудиофайл я нашел решение здесь -целые числа в аудио/55288084, @John
- Сопряжение наушников TRRS с Arduino Uno
- Считать напряжение батареи и значение аналогового датчика с помощью NodeMCU ESP8266.
- Определение окончания воспроизведения MP3-файла с помощью библиотеки DFPlayerMini/DFRobotDFPlayerMini.h
- Контакты I2S не выводят звук в ESP8266
- Датчик углекислого газа MG 811
- Аналоговое чтение с шумом — Arduino Uno VS ESP12e
- Не удается заставить Wi-Fi модуль esp8266-12 всегда точно считывать входящее напряжение analogRead
- Сигнал времени. Определить наличие импульсов и их длительность
Вы можете преобразовать его в формат файла .wav. Самый простой доступный формат файла., @ratchet freak
Я только что обновил свой вопрос, чтобы показать свою попытку создать wav-файл. Правильно ли я сделал? Я слышу еще больше хлопков., @John
1) конвертировать что в wav? 2) печать требует времени 3) что подключено к A0? 4) диапазон аналогового чтения составляет 10 бит. вы сократили ввод до 255, @Juraj
@Juraj Чтобы ответить на ваши вопросы 1) Я хотел бы преобразовать список целых чисел, заданный
Serial.print(int(analog))
, в wav-файл. 3) А0 получает выходное напряжение электретного микрофона с предварительным усилением. Амплитуда напряжения колеблется от 0 мВ до 300 мВ., @JohnЯ так понимаю, потому что следовал тому же руководству. К сожалению, я не получаю никакого качественного звука, а только небольшие импульсы, микрофон, который используется в видео, сделан им же, я использовал два разных типа микрофонов: KY-038 и/или MAX4466 с тем же результатом. Мне нужно получить аудио, отправить его в UDP и сохранить в WAV. Может ли кто-нибудь нам помочь?, @Alessandro