2012-05-21 7 views
7

Mein Ziel ist es, * .wav Datei über LAN-Netzwerk ohne Verzögerung oder mit minimalen zu übertragen.Wie kann ich Streaming-Audio über Ethernet in Qt abspielen?

Auch lesen wir Datei auf Server Mashin von Teilen 320 Bytes beide. Danach senden wir Pakete per Udp und schreiben im Jitter-Puffer. Größe des Jitter-Puffers ist 10. Welche Verzögerungen sollte ich auf Timer für klaren Sound einstellen.

hier Absender:

void MainWindow::on_start_tx_triggered() 
{ 
    timer1 = new QTimer (this); 
    udpSocketout = new QUdpSocket(this); 
    qDebug()<<"Start"; 
    for (int i = 0; i < playlist.size(); ++i) 
    { 
     inputFile.setFileName(playlist.at(i)); 
     qDebug()<<inputFile.fileName(); 
     if (!inputFile.open(QIODevice::ReadOnly)) 
     { 
      qDebug()<< "file not found;"; 
     } 
    } 
    connect(timer1, SIGNAL(timeout()),this, SLOT(writeDatagrams())); 
    timer1->start(5); 
} 

void MainWindow::writeDatagrams() 
{  
    if(!inputFile.atEnd()){ 
     payloadout = inputFile.read(320); 
    } 
    qDebug()<<payloadout; 
    QDataStream out(&datagramout, QIODevice::WriteOnly); 
    out.setVersion(QDataStream::Qt_4_7); 
    out << qint64(0); 
    out << payloadout; 
    out.device()->seek(qint64(0)); 
    out << qint64(datagramout.size() - sizeof(qint64)); 
    qint64 writtenBytes = udpSocketout->writeDatagram(datagramout, remoteHOST, remotePORT); 
    qDebug() << "Sent " << writtenBytes << " bytes."; 
} 

hier Empfänger und Spieler:

void MainWindow::on_start_rx_triggered() 
{ 
    udpSocketin = new QUdpSocket(this); 
    udpSocketin->bind(localHOST, localPORT); 
    connect(udpSocketin, SIGNAL(readyRead()), 
      this, SLOT(readDatagrams())); 
    QDataStream out(&datagramout, QIODevice::WriteOnly); 
    out.setVersion(QDataStream::Qt_4_7); 
    timer2 = new QTimer (this); 
    connect(timer2, SIGNAL(timeout()),this, SLOT(playbuff())); 
    timer2->start(50); 
    audioout = new QAudioOutput(format, this); 
} 

void MainWindow::readDatagrams() 
{ 
    datagramin.resize(udpSocketin->pendingDatagramSize()); 
    qint64 receiveBytes = udpSocketin->readDatagram(datagramin.data(),datagramin.size()); 
    qDebug() << "Receive " << receiveBytes << " bytes."; 
    QDataStream in(&datagramin, QIODevice::ReadOnly); 
    in.setVersion(QDataStream::Qt_4_7); 
    quint64 size = 0; 
    if(in.device()->size() > sizeof(quint64)) 
    { 
     in >> size; 
    } 
    else return; 
    if(in.device()->size() < size) return; 
    in >> payloadin; 
    qDebug()<<payloadin.size(); 
    emit jitterbuff(); 
} 

void MainWindow::jitterbuff() 
{ 
    if (buff_pos < SIZE_OF_BUF) 
    { 
     QDataStream out(&buffered, QIODevice::WriteOnly); 
     out.setVersion(QDataStream::Qt_4_7); 
     out << payloadin; 
     buff_pos++; 
    } 
    else buff_pos=0; 
} 

void MainWindow::playbuff() 
{ 
    qDebug()<<"YES!!!"; 
    buffer = new QBuffer(&buffered); 
    buffer->open(QIODevice::ReadOnly); 
    audioout->start(buffer); 
    QEventLoop loop; 
    QTimer::singleShot(50,&loop,SLOT(quit())); 
    loop.exec(); 
    buffer->close(); 
} 
+0

Ich habe mir den Code nicht angesehen, da ich mit Qt nicht vertraut bin, aber einige allgemeine Bemerkungen zum Senden von Audio über LANs: 1. Obwohl der Paketverlust gering ist, sollten Sie dennoch auf gelegentlichen Paketverlust vorbereitet sein. 2. Ich habe nicht viel Erfahrung mit Lans, aber ich würde schätzen, dass Sie etwa 100 ms Latenz oder weniger bekommen könnten. –

+0

100 ms ist es so hohe Latenz für Streaming-Audio ... Ja, ich bereite mich auf Paketverlust vor, weil ich UDP verwende. Aber ich möchte einen klaren Ton bei der Ausgabe bekommen. Ich benutze Pufferung Daten (zum Beispiel auf last.fm dies tun) – HoBBiT

+0

Auch, wie ich verstehe, wenn ich verwende: sampleRate = 8000 kHz sampleSize = 8 Bit und lesen von Datei von 320bytes, dann habe ich 5ms Sound in Daten zum Beispiel Größe des Jitter-Puffers ist 10 Zellen, dann habe ich 5 * 10 ms Verzögerung für Jitter-Puffer + 5 ms auf Paketierung. Im Ergebnis habe ich insgesamt 55ms Verzögerung. nicht wahr? lassen Sie mich wissen, wenn es falsch ist. – HoBBiT

Antwort

6

Dieses Problem wurde gelöst. QAdioOutput hat zwei Modi "Push" und "Pull". Ich gebe Zeiger auf QIODevice und schreibe Daten direkt in diese. Lösung:

UDP Socket zu lesen:

void MainWindow::on_start_rx_triggered() 
{ 
    udpSocketin = new QUdpSocket(this); 
    udpSocketin->bind(localPORT); 
    connect(udpSocketin, SIGNAL(readyRead()),this, SLOT(readDatagrams())); 
    QDataStream out(&datagramout, QIODevice::WriteOnly); 
    out.setVersion(QDataStream::Qt_4_7); 
    timer2 = new QTimer (this); 
    connect(timer2, SIGNAL(timeout()),this, SLOT(playbuff())); 
    timer2->setInterval(15*9); 
    audioout = new QAudioOutput(format, this); 
    input = audioout->start(); 
    } 
void MainWindow::readDatagrams() 
    { 
     if (udpSocketin->hasPendingDatagrams()){ 
     datagramin.resize(udpSocketin->pendingDatagramSize()); 
     qint64 receiveBytes = udpSocketin->readDatagram(datagramin.data(),datagramin.size()); 
     if (receiveBytes<=0) 
     { 
      msg.warning(this,"File ERROR","The end!",QMessageBox::Ok); 
      emit on_stop_rx_triggered(); 
     } 
     QDataStream in(&datagramin, QIODevice::ReadOnly); 
     in.setVersion(QDataStream::Qt_4_7); 
     quint64 size = 0; 
     if(in.device()->size() > sizeof(quint64)) 
     { 
      in >> size; 
     } 
     else return; 
     in >> rxfilename; 
     in >> name; 
     in >> payloadin; 
    emit jitterbuff(); 
    } 
    void MainWindow::jitterbuff() 
     { 
      if (buff_pos < SIZE_OF_BUF) 
      { 
       buffered.append(payloadin); 
       buff_pos++; 
      } 
      else 
      { 
       timer2->start(); 
       buffered.clear(); 
       buff_pos=0; 
      } 
     } 

     void MainWindow::playbuff() 
     { 
      if (!buffered.isEmpty()) 
      { 
       buffer = new QBuffer(&buffered); 
       buffer->open(QIODevice::ReadOnly); 
       input->write(buffered); 
       buffer->close(); 
      } 
     } 

schriftlich an UDP-Sockets: haben

void MainWindow::on_start_tx_triggered() 
{ 
    timer1 = new QTimer (this); 
    udpSocketout = new QUdpSocket(this); 
    inputFile.setFileName(playlist.at(playIDfile)); 
     if (!inputFile.open(QIODevice::ReadOnly)) 
     { 
      msg.warning(this,"File ERROR","File not found!",QMessageBox::Ok); 
      return; 
     } 
    fileinfo = new QFileInfo (inputFile); 
    txfilename = fileinfo->fileName(); 
    ui->playedFile->setText("Now played: " + txfilename); 
    connect(timer1, SIGNAL(timeout()),this, SLOT(writeDatagrams())); 
    timer1->start(15); 
} 
void MainWindow::writeDatagrams() 
{ 

    if(!inputFile.atEnd()){ 
     payloadout = inputFile.read(SIZE_OF_SOUND); 
     QDataStream out(&datagramout, QIODevice::WriteOnly); 
     out.setVersion(QDataStream::Qt_4_7); 
     out << qint64(0); 
     out << txfilename; 
     out << name; 
     out << payloadout; 
     out.device()->seek(qint64(0)); 
     out << qint64(datagramout.size() - sizeof(qint64)); 
     qint64 writtenBytes = udpSocketout->writeDatagram(datagramout, remoteHOST, remotePORT); 
    } 
} 

Wenn jemand Problem scheint, werde ich versuchen, ihm zu helfen.

+0

Hallo, ich weiß es ist vor mehr als 3 Jahren, aber hast du noch den vollen Projektcode? Könntest du bitte den Code mit mir teilen? Danke. –

Verwandte Themen