Как восстановить звук из серии аналоговых целочисленных входов?

Я пытаюсь научиться передавать потоковое аудио с контакта 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-файл?

, 👍1

Обсуждение

Вы можете преобразовать его в формат файла .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


1 ответ


Лучший ответ:

1

Я пытаюсь научиться передавать потоковое аудио с контакта A0 платы ESP8266 NodeMCU через соединение сокета UDP на другой компьютер с Windows, который использует pyaudio для его воспроизведения.

Вы описали несколько проблем; нужно разбивать большие проблемы на маленькие:

  1. Пример аудио
  2. Отправить на другой компьютер
  3. Декодирование и воспроизведение звука

На данный момент все, что я слышу на компьютере под управлением 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