2012-05-21 23 views
7

Amacım, * .wav dosyasını LAN ağı üzerinden geciktirmeksizin veya en az bir kere iletmektir.Qt'de Ethernet üzerinden ses akışı nasıl oynarım?

Ayrıca, mashin dosyasını 320 baytlık parçalarla da okuyoruz. Bundan sonra Udp ile paketler gönderiyoruz ve jitter-bufferda yazma alıyoruz. Jitter-buffer'ın boyutu 10'dur. Net ses için zamanlayıcılar üzerine ayarlamam gereken gecikmeler. Burada

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

alıcı ve oyuncu

edilir:

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

Kodunuza bakmadım çünkü Qt'ye aşina değilim, ancak sesleri lansmanla gönderme hakkında bazı genel açıklamalar: 1. Paket kaybı düşük olsa da, arada sırada paket kaybı için hazırlıklı olmalısınız. 2. Ben lans ile tonlarca deneyimim yok, ama tahminimce 100 ms gecikme süresi veya daha az olabilir. –

+0

100 ms ses akışı için çok yüksek bir gecikme ... Evet, paket kaybına hazırlanıyorum çünkü UDP kullanıyorum. Ama çıktıda net ses elde etmek istiyorum. arabelleğe alma verilerini kullanıyorum (örneğin, bu işlemin yapıldığı anda) – HoBBiT

+0

Ayrıca, şunu kullanırsam anlıyorum: sampleRate = 8000 kHz sampleSize = 8 bit ve dosyadan 320bytes okuma, sonra verilerde 5ms ses var Örneğin, jitter tamponunun boyutu 10 hücredir, daha sonra jitter tamponu + 5 ms paketlemede 5 * 10 ms gecikme var. Sonuçta 55ms toplam gecikme olacak. öyle değil mi Yanlış olup olmadığını bana bildirin. – HoBBiT

cevap

6

Bu sorun çözüldü burada

gönderen olduğunu. QAdioOutput'ın "itme" ve "çekme" olmak üzere iki modu vardır. QIODevice üzerinde işaretçi veriyorum ve bu konuda doğrudan veri yazdım. Çözüm:

UDP soketi okuma: UDP yuvasına yazma

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

:

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

olacak birileri sorun görünüyorsa, ben ona yardım etmeye çalışacaktır.

+0

Merhaba, 3 yıldan daha uzun bir süre önce olduğunu biliyorum, ancak hala tam proje kodunuz var mı? Kodu lütfen benimle paylaşır mısınız? Teşekkürler. –

İlgili konular