I'm trying to learn how to stream audio from the A0 pin of an ESP8266 NodeMCU board via UDP socket connection over to another windows computer that uses pyaudio to play it. At the moment, all I get on the windows computer are a series of "popping" sounds each spaced about half a second apart.
I'm new to working with these types of break out boards, so I found an online project that I'm using as a starting point:
Streaming audio from ESP8266 to pyaudio working in Arduino IDE
I figure I start troubleshooting my popping sound issue by inspecting the UDP packets my ESP8266 code. Below is the source code I'm working from:
#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); //para que no inicie el SoftAP en el modo normal
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) {
//para usar con ip fija
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, HIGH);
}
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); // 90uSec = 1Sec/11111Hz - 3uSec para los otros procesos
}
Serial.print(";;;;;");
Udp.endPacket();
delay(5);
}
Notice near the bottom of the file, I print out each analog value separated by a comma, and each data packet separated by five semicolons.
Can someone suggest a way for me to re-construct these series of integers into a sound file that I can inspect via listening with my own ears? Then I can tell if the sound data being sent is complete? Or let me know if there's a better way to test if all the data packets are being sent correctly.
UPDATE
I tried to create a wav file by doing this:
- Take the list of all integers from
Serial.print(int(analog))
and paste it into a file. I make sure all integers are space delimited (ie. no more commas or semicolons) - I copied the file over to a linux machine that had ffmpeg installed
- I ran the command
ffmpeg -f u8 -ar 11111 -ac 1 -i myfileofintegers -y test.wav
When I listen to the test.wav file, I just hear a series of rapid popping noises. Not sure if I created the wav file properly?
1 Answer 1
I'm trying to learn how to stream audio from the A0 pin of an ESP8266 NodeMCU board via UDP socket connection over to another windows computer that uses pyaudio to play it.
You have described several problems; one needs to break big problems into small problems:
- Sample the audio
- Send it to another computer
- Decode and playback the sound
At the moment, all I get on the windows computer are a series of "popping" sounds each spaced about half a second apart.
This sounds like you have got your timebases messed up; it is likely that you aren't recording enough data or playing it back incorrectly. N.b. it looks like you are recording ~92ms of audio data each 'packet' and if you get a series of pops at 2hz you are likely playing less than 1/10 of a second of audio for ever 5/10 of time, so your speaker moves for 1/10th of a second then stays still for 4/10ths and repeats; this produces your 2hz popping noises.
Your code has some other problems as well:
- Serial.print() is Slow! Don't use it where performance matters!
- Intertwining sampling and sending
- Incorrectly scaling the analog reading
- 11.1khz can only record signals up to 5.5khz
Lets start with the audio sampling. We have some sort of audio circuitry presenting a signal to an analog input, we need to sample it regularly and uniformly! The code presented is trying to sample at 11.1 kHz, but only does so for 1024 samples before hitting a discontinuity. We do not have circuitry dedicated to this so we will have to use the ADC circuitry on the Arduino.
First thing you will want to get you sampling regular and continuous. You will want to use an interrupt on the Arduino for this. The interrupt should take a single sample from the ADC and add it to a buffer or signal the main loop to read/buffer it.
This interrupt will need to fire regularly at the sample rate or the data will be ruined.
Second the audio circuitry should prepare the signal so that it is between 0-5v with a ~2.5v bias, this will use the ADC hardware to its fullest.
so in Pseudo code:
// include any libs etc.
// set up variables ect.
void interupt_sample();
// register and attach interrupt
void setup() {
//do your setup etc.
}
void loop() {
// if(new_sample) add_to_buffer(new_sample);
// if(buffer_full) send_and_flush_buffer();
}
-
Specific to converting a list of integers to an audio file, I found a solution here stackoverflow.com/questions/55286149/…learningtech– learningtech2019年03月21日 19:36:40 +00:00Commented Mar 21, 2019 at 19:36
Serial.print(int(analog))
to a wav file. 3) A0 receives the output voltage of a pre-amplified electret microphone. The voltage amplitude seems to range between 0mv and 300mv.