如何在Raspberry Pi上用C++将接收到的UDP音频数据正确写入ALSA
How to Properly Write Received UDP Audio Data to ALSA with C++ on Raspberry Pi
我有两个树莓派,其中一个将音频数据的UDP帧传输到另一个树莓皮。接收到的UDP数据包每个为160字节。发送Raspberry Pi正在发送8KHz 8位Mono样本。接收Raspberry Pi使用Qt 5.4.0和QUDPSocket,并尝试用ALSA播放接收到的数据。代码如下。当字节到达接收Raspberry Pi时,每次触发"readyRead"信号时,缓冲区都会写入ALSA。接收Pi上的耳机插孔发出的声音非常清脆,但很容易辨认。所以它是有效的,但听起来很可怕。
- 我下面的ALSA配置有什么明显的错误吗
- 我应该如何使用snd_pcm_writei将接收到的UDP数据包写入ALSA
谢谢你的建议。
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++;
}
我不理解代码中的"限制缓冲区大小"部分。如果传入数据大于您任意的NOMINAL_AUDIO_BUFFER_SIZE,则您正在截断该传入数据。你试过删除那部分代码吗?
相关文章:
- FFmpeg av_read_frame从音频流返回数据包
- 捕获音频数据并保存到AudioFlinger中的原始PCM文件
- 如何将 cdparanoia 读取的 CD 音频数据移交给 ALSA 播放器?
- 如何将静默音频数据写入音频流
- 如何在SDL2音频流数据上执行实时FFT
- 使用FFMPEG编写多线程视频和音频数据包
- 数据包大小(每数据包 mBytes)或核心音频中 AAC 文件的比特率
- 以选定的比特率发送音频数据 - 喊播
- 使用C 中的套接字通过网络发送音频数据
- C++将音频数据发送到Linux和Mac OS X上的扬声器输出
- 使用C++(基于C#程序)保存wav文件时,音频数据不正确
- FFmpeg:编码PCM 16音频数据分配错误
- 如何在Raspberry Pi上用C++将接收到的UDP音频数据正确写入ALSA
- 实时录制/转换音频数据到WAV
- 端口音频遍历音频数据
- 在 C++ 中使用 libsndfile 从 WAV 文件中提取原始音频数据
- 如何用音频数据填充AVFrame
- 如何获取 mp3 音频数据包以在 C/C++ 中流式传输
- OpenAL回放捕获的音频数据c++
- 在哪里使用c++和qt将Wav标头添加到实时音频服务器中的数据