Конфигурация для получения и воспроизведения ALSA Raw PCM на аналоговом выходе Raspberry Pi

Я успешно воспроизвел аудио на аналоговом выходе наушников 3,5 мм на Raspberry Pi, используя PulseAudio и QAudioOutput Qt5.4. Звук успешно передается с удаленного микрофона по каналу XBee с частотой 8 кГц с 8-битными сэмплами.

У PulseAudio была огромная задержка, поэтому я решил подключиться к libasound (ALSA) и воспроизвести аудио напрямую. Мой код находится ниже и успешно открывается и воспроизводит звук, но он почти неузнаваем, в нем много трещин и скрипов. Если я говорю в удаленный микрофон, я очень быстро слышу повышенное царапание и скрип в наушниках от Pi (но это не очень хороший звук). Я думаю, что мои параметры испорчены.

1.) Данные передаются в BigEndian — QAudioOutput позволяет вам сообщить ему, что образцы являются BigEndian. Но это образцы U8, так что мне нужно беспокоиться о порядке байтов?
2.) Можете ли вы увидеть что-то не так с моей конфигурацией ниже?
3.) Как определить размер фрагмента для ALSA для вывода на Pi?
4.) Может кто-нибудь объяснить, как мне записать свой буфер на аудиоустройство?

Спасибо!

Вот мой код:

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_near (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;
for (int i = 0; i < 10; ++i) {
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++;

}

1

Решение

  1. Нет.
  2. snd_pcm_hw_params_set_rate_near() изменит ставку на ближайшую поддерживаемую ставку. Вы, вероятно, не хотите этого.
  3. У ALSA нет размера фрагмента.

    Имеет размер буфера и периода; Вы должны установить их в соответствии с вашими требованиями к времени (см. ALSA: отношение размера периода динамика и микрофона).

  4. Вы не можете просто вывести полученные образцы; Вы должны повторно сэмплировать их со скоростью устройства воспроизведения (которое не является точно таким же, даже если оно использует ту же номинальную частоту дискретизации).
2

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector