How to Properly Write Received UDP Audio Data to ALSA with C++
来源:互联网 发布:网络维护工程师 编辑:程序博客网 时间:2024/06/16 21:48
I have 2 Raspberry Pis and 1 of them transmits UDP frames of Audio data to the other Raspberry Pi. The UDP Packets received are 160 Bytes each. The transmitting Raspberry Pi is sending 8KHz 8-bit Mono samples. The receiving Raspberry Pi uses Qt 5.4.0 with QUDPSocket and tries to play the received data with ALSA. The code is below. Each time the "readyRead " signal is fired when bytes arrive on the receiving Raspberry Pi, the Buffer is written to ALSA. I have very Choppy and Glitchy sound coming out of the headphone Jack on the Receiving Pi - but it is recognizable. So it is working but sounds Terrible.
- Is there anything glaringly wrong with my configuration below for ALSA?
- How should I approach writing the received UDP packets to ALSA with snd_pcm_writei?
Thank you for any suggestions.
UdpReceiver::UdpReceiver(QObject *parent) : QObject(parent){ // Debug qDebug() << "Setting up a UDP Socket..."; // Create a socket m_Socket = new QUdpSocket(this); // Bind to the 2616 port bool didBind = m_Socket->bind(QHostAddress::Any, 0x2616); if ( !didBind ) { qDebug() << "Error - could not bind to UDP Port!"; } else { qDebug() << "Success binding to port 0x2616!"; } // Get notified that data is incoming to the socket connect(m_Socket, SIGNAL(readyRead()), this, SLOT(readyRead())); // Init to Zero m_NumberUDPPacketsReceived = 0;}void UdpReceiver::readyRead() { // When data comes in QByteArray buffer; buffer.resize(m_Socket->pendingDatagramSize()); QHostAddress sender; quint16 senderPort; // Cap buffer size int lenToRead = buffer.size(); if ( buffer.size() > NOMINAL_AUDIO_BUFFER_SIZE ) { lenToRead = NOMINAL_AUDIO_BUFFER_SIZE; } // Read the data from the UDP Port m_Socket->readDatagram(buffer.data(), lenToRead, &sender, &senderPort); // Kick off audio playback if ( m_NumberUDPPacketsReceived == 0 ) { qDebug() << "Received Data - Setting up ALSA Now...."; // Error handling int err; // Device to Write to char *snd_device_out = "hw:0,0"; if ((err = snd_pcm_open (&playback_handle, snd_device_out, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf (stderr, "cannot open audio device %s (%s)\n", snd_device_out, snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) { fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_any (playback_handle, hw_params)) < 0) { fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_access (playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf (stderr, "cannot set access type (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_format (playback_handle, hw_params, SND_PCM_FORMAT_U8)) < 0) { // Unsigned 8 bit fprintf (stderr, "cannot set sample format (%s)\n", snd_strerror (err)); exit (1); } uint sample_rate = 8000; if ((err = snd_pcm_hw_params_set_rate (playback_handle, hw_params, sample_rate, 0)) < 0) { // 8 KHz fprintf (stderr, "cannot set sample rate (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params_set_channels (playback_handle, hw_params, 1)) < 0) { // 1 Channel Mono fprintf (stderr, "cannot set channel count (%s)\n", snd_strerror (err)); exit (1); } if ((err = snd_pcm_hw_params (playback_handle, hw_params)) < 0) { fprintf (stderr, "cannot set parameters (%s)\n", snd_strerror (err)); exit (1); } snd_pcm_hw_params_free (hw_params); // Flush handle prepare for playback snd_pcm_drop(playback_handle); if ((err = snd_pcm_prepare (playback_handle)) < 0) { fprintf (stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror (err)); exit (1); } qDebug() << "Done Setting up ALSA...."; } // Grab the buffer m_Buffer = buffer.data(); // Write the data to the ALSA device int error; if ((error = snd_pcm_writei (playback_handle, m_Buffer, NOMINAL_AUDIO_BUFFER_SIZE)) != NOMINAL_AUDIO_BUFFER_SIZE) { fprintf (stderr, "write to audio interface failed (%s)\n", snd_strerror (error)); exit (1); } // Count up m_NumberUDPPacketsReceived++;}Can you play sounds better when using another program? The jack sound stuff (but not HDMI) of some(?) models just is terrible itself, independent from the software. – deviantfan Feb 8 at 23:50Thanks for the input. But if I use ALSA utilities' "aplay" program then the Audio output sounds great. I'm pretty sure this is a configuration problem. – PhilBot Feb 9 at 0:29You still are not setting buffer/period sizes. – CL. Feb 9 at 8:17You should process the incoming datagrams with a while inside the SLOT, as done for instance here to ensure that all the available data is processed with the current signal. – BaCaRoZzo Feb 9 at 10:381Set up your audio buffer to gather 1 full second and then play in chunks of 1 second buffers. See if quality gets better (it should). Change the design to have a listening thread that reads data and fills a buffer while another thread plays it with a delay of, let's say, 0.1 seconds by continuously feeding data. You have 8000 samples per second. 5 UDP messages means 800 samples, which is 0.1 seconds. So you can start with this. By feeding 160 samples in a run you play 0.02 seconds at a time. Then you stop playing, and on the same thread you read another UDP message. – Bogdan V. Feb 18 at 9:48
0 0
- How to Properly Write Received UDP Audio Data to ALSA with C++
- How to write/change EXIF data
- How to write GIMP plugin with OpenCV
- How To Read and Write BLOB Data by Using ADO.NET with Visual C# .NET
- How To Read and Write BLOB Data by Using ADO.NET with Visual C# .NET
- How to properly use 'dd' to benchmark the write speed of your disk?
- How to close resources properly
- How to properly unblock libusb_bulk_transfer
- how to wipe data with adb?
- how to write it in C++?
- How to properly convert SecureString to String
- How to write Bibliography
- how to write makefile
- How to write makefile
- How to write patent
- how to write Makefile
- DLL - How to Write
- how to write
- Codeforces551C:GukiZ hates Boxes(二分+贪心)
- 物化视图
- 如何放大查看浏览器内容中某一部分内容
- 上拉电阻大小选择
- JNI注册:手动注册(JNI_OnLoad)和自动注册(lookupSharedLibMethod)
- How to Properly Write Received UDP Audio Data to ALSA with C++
- 在JAVA中怎么比较Double类型数据的大小?
- MJRrfresh刷新注意
- goldengate director 安装配置
- Linux网络编程——I/O复用之poll函数
- Nginx 502 Bad Gateway错误的【ubutun系统】
- Lua lib 加载分析
- %.*lf控制输出长度
- 初学Laravel4常见的问题之一