2012-05-21 10 views
7

Il mio obiettivo è quello di trasmettere * .wav file su rete LAN senza ritardo o con uno minimo.Come posso riprodurre lo streaming audio su Ethernet in Qt?

Inoltre, si legge il file sul server mashin di parti 320 byte entrambi. Dopodiché inviamo pacchetti da Udp e scriviamo ricevendo in jitter-buffer. La dimensione del jitter-buffer è 10. Quali ritardi dovrei impostare sui timer per un suono chiaro.

qui è mittente:

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."; 
} 

Ecco ricevitore e il lettore:

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

Non ho controllato il codice perché non ho familiarità con Qt, ma alcune considerazioni generali sull'invio di audio su lans: 1. Sebbene la perdita di pacchetti sia bassa, si dovrebbe comunque essere pronti per la perdita occasionale di pacchetti. 2. Non ho molta esperienza con lans, ma suppongo che potresti ottenere circa 100 ms di latenza o meno. –

+0

100 ms è così alta latenza per lo streaming audio ... Sì, mi preparo per la perdita di pacchetti, perché io uso UDP. Ma voglio ottenere un suono chiaro in uscita. utilizzo i dati di buffering (ad esempio su last.fm) – HoBBiT

+0

Inoltre, come ho capito se uso: sampleRate = 8000 kHz sampleSize = 8 bit e letto dal file di 320bytes, quindi ho 5ms di suono nei dati per esempio la dimensione del buffer di jitter è 10 celle, quindi ho un ritardo di 5 * 10 ms per il buffer di jitter + 5 ms sulla packetizzazione. in risultato avrò un ritardo totale di 55ms. non è vero? fammi sapere se è sbagliato. – HoBBiT

risposta

6

Questo problema è stato risolto. QAdioOutput ha due modalità: "push" e "pull". Fornisco un puntatore su QIODevice e scrivo i dati direttamente in questo. Soluzione:

lettura socket UDP:

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(); 
      } 
     } 

iscritto al socket UDP:

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); 
    } 
} 

Se qualcuno avrà sembra problema, cercherò di aiutarlo.

+0

Ciao, lo so che è più di 3 anni fa, ma hai ancora il codice completo del progetto? Potresti condividere il codice con me? Grazie. –