簡體   English   中英

使用c ++和qt在哪里將Wav標頭添加到實時音頻服務器中的數據?

[英]Where to add the Wav header to data in a live audio server using c++ and qt?

我知道這是一個很長的問題,但是我真的希望您有耐心地閱讀它,對我有幫助,因為我似乎在這里已死胡同。

我對c ++客戶端服務器和Qt多媒體開發方面非常陌生。 我正在嘗試創建一個服務器,該服務器允許使用Qt將音頻流傳輸到客戶端。

通過使用Qt的QAudioInput, QAudioDeviceInfo, QAudioFormat類,我學會了如何錄制音頻,這與QAudioRecorder示例中給出的非常不同。 我還學習了如何將wav標頭添加到原始音頻數據中並使音頻可播放。 我用來向音頻添加wav標頭的函數如下:

void Server::rawToWavQT(QByteArray* arr, long samplingRate, long bytes)
{
    long chunksize=0x10;
    struct
    {
        unsigned short    wFormatTag;
        unsigned short    wChannels;
        unsigned long     dwSamplesPerSec;
        unsigned long     dwAvgBytesPerSec;
        unsigned short    wBlockAlign;
        unsigned short    wBitsPerSample;
    } fmt;

    long samplecount = bytes/2;
    long riffsize    = samplecount*2+0x24;
    long datasize    = samplecount*2;

    arr->append("RIFF");//    fwrite( "RIFF",     1, 4, wav );
    arr->append(QByteArray((const char*)&riffsize, 4));//    fwrite( &riffsize,  4, 1, wav );
    arr->append("WAVEfmt ");//    fwrite( "WAVEfmt ", 1, 8, wav );
    arr->append(QByteArray((const char*)&chunksize, 4));//    fwrite( &chunksize, 4, 1, wav );

    int bitsPerSample = 16;
    int bytesPerSample = bitsPerSample/8;
    int channel = 2;

    fmt.wFormatTag = 1;      // PCM
    fmt.wChannels  = channel;      // MONO
    fmt.dwSamplesPerSec  = samplingRate;
    fmt.dwAvgBytesPerSec = samplingRate*channel*bytesPerSample; // 16 bit
    fmt.wBlockAlign      = channel*bytesPerSample;
    fmt.wBitsPerSample   = bitsPerSample;

    arr->append(QByteArray((const char*)&fmt, sizeof(fmt)));//    fwrite( &fmt,      sizeof(fmt), 1, wav );
    arr->append("data");//    fwrite( "data",    1,           4, wav );
    arr->append(QByteArray((const char*)&datasize, 4));//    fwrite( &datasize, 4,           1, wav );
}

我還得到了一個有關如何使用Qt進行簡單的服務器-客戶端通信的示例 通過該項目,我了解了如何使用Qt服務器和套接字模塊開發客戶端與服務器之間的通信。

服務器的主窗口類如下所示:

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setFixedSize(size());
}

void MainWindow::on_pushButton_clicked()
{
    QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
    QAudioDeviceInfo devinfo = devices.at(0);
    input = new AudioInput(devinfo, this);
    quint16 port = ui->lineEdit->text().toInt();
    server = new Server(port, this);
    connect(input, SIGNAL(dataReady(QByteArray)), server, SLOT(writeData(QByteArray)));

    ui->comboBox->setEnabled(false);
    ui->lineEdit->setEnabled(false);
    ui->pushButton->setEnabled(false);
}

音頻數據提供程序類如下:

AudioInput::AudioInput(QAudioDeviceInfo devinfo, QObject *parent) : QObject(parent)
{
    QAudioFormat format;
    format.setChannelCount(1);
    format.setSampleRate(8000);
    format.setSampleSize(8);
    format.setCodec("audio/pcm");
    format.setByteOrder(QAudioFormat::LittleEndian);
    format.setSampleType(QAudioFormat::UnSignedInt);

    audio = new QAudioInput(devinfo, format, this);
    audio->setBufferSize(8192);

    device = audio->start();
    connect(device, SIGNAL(readyRead()), SLOT(readyRead()));
}

void AudioInput::readyRead()
{
    QByteArray data;

    //Check the number of samples in input buffer
    qint64 len = audio->bytesReady();

    //Read sound samples from input device to buffer
    if (len > 0)
    {
        data.resize(len);
        device->read(data.data(), len);
    }

    emit dataReady(data);
}

服務器類如下:

Server::Server(quint16 port, QObject *parent) : QObject(parent)
{
    socket = 0;
    server = new QTcpServer(this);
    connect(server, SIGNAL(newConnection()), SLOT(newConnection()));
    server->listen(QHostAddress::Any, port);
}

void Server::newConnection()
{
    socket = server->nextPendingConnection();
    connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
    connect(socket, SIGNAL(destroyed()), SLOT(zeropointer()));
}

void Server::zeropointer()
{
    socket = 0;
}

void Server::writeData(QByteArray data)
{
    if (socket)
        socket->write(data);
}

我現在面臨的問題是在寫入數據以在服務器中服務時找到合適的階段來添加wav標頭。 我已經嘗試通過使用rawToWavQT函數將標頭添加到writeData函數中,如上所示,但是在客戶端,它工作不正常,我在那里聽不到任何正確的聲音。 我什至嘗試將在客戶端接收到的音頻數據另存為wav文件,但是將其保存后,我無法生成任何可播放的音頻文件,並且與通常的.wav文件相比,文件本身很小。

謝謝你的耐心。

我是您在問題中使用的項目的所有者,我對此進行了一些更改。 修改內容包括錯誤修復,連接到服務器的多個客戶端,客戶端協商音頻設置和音頻記錄。

在這里看到它

服務器是一個非常基本的實現,我從互聯網上的一些閱讀中學到了一些東西,從這些閱讀中了解了一些東西,以及在Qt附帶的多媒體示例中看到的其他一些東西。 不僅僅是一個來源!

希望有幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM