2015-02-08 81 views
7

我有2個Raspberry Pis,其中1個將音頻數據的UDP幀傳輸到另一個Raspberry Pi。收到的UDP數據包是每個160字節。發送樹莓派發送8KHz 8位單聲道採樣。接收Raspberry Pi使用Qt 5.4.0和QUDPSocket,並嘗試使用ALSA播放接收到的數據。代碼如下。每當字節到達接收樹莓派時「readyRead」信號被觸發,緩衝區就被寫入ALSA。接收機上的耳機插孔上出現了非常渾濁的聲音 - 但它是可識別的。所以它正在工作,但聽起來很糟糕。如何在Raspberry Pi上正確地將接收到的UDP音頻數據寫入ALSA,使用C++

  1. ALSA的配置下面有什麼明顯的錯誤嗎?
  2. 我應該如何使用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++; 

} 
+0

使用其他程序時可以更好地播放聲音嗎?某些(?)模型的插孔聲音(但不是HDMI)本身就很糟糕,獨立於軟件。 – deviantfan 2015-02-08 23:50:02

+0

感謝您的意見。但如果我使用ALSA實用程序的「aplay」程序,那麼音頻輸出聽起來很棒。我很確定這是一個配置問題。 – PhilBot 2015-02-09 00:29:19

+0

您仍然沒有設置緩衝區/週期大小。 – 2015-02-09 08:17:04

回答

0

我不理解代碼的「上限緩衝區大小」部分。如果傳入的數據大於您的任意NOMINAL_AUDIO_BUFFER_SIZE,那麼您將切斷傳入的數據。你有沒有嘗試刪除這段代碼?

相關問題