QAudioOutputを使用したリアルタイムストリーミング

MrS05

私は、独自のC ++ APIを使用して、マイクアレイシステムから生のオーディオを読み取り/処理/再生するC ++プロジェクトに取り組んでいます。Qtを使用してソフトウェアをプログラムしています。

QAudioOutput(Qt)を使用したリアルタイムストリーミングに関するこの投稿から、生のオーディオデータが処理に約1000ミリ秒(1秒)かかる関数呼び出しからのものである場合の対処方法についてフォローアップしてアドバイスを求めたいと思いました。どうすればリアルタイムのオーディオ再生を実現できますか。

QIODevice :: QAudioFormat-> start();に書き込むときに読んだので、処理には約1秒かかります。バッファのアンダーラン/オーバーランを防ぐために、ピリオドに相当するバイトを使用することをお勧めします。http://cell0907.blogspot.sg/2012/10/qt-audio-output.html

関数呼び出しから受信したデータをストリーミングするようにQByteArrayとQDataStreamを設定しました。

  • APIはCcmXXX()です
  • マイクアレイからデータを読み取ると、32ビット整数の配列が返されます
  • 32ビット整数のうち、24ビットの解像度、8ビットのLSBが埋め込まれたゼロ。
  • ブロックサイズ(1024サンプルに設定)x40マイクで提供されます
  • 書き込まれるバイト数が期間サイズ/空きバイト数に近づくまで、各チャンクは約1ブロックを書き込みます。

テスト済み:スロットを約50ミリ秒の通知に接続して、1期間分のバイトを書き込みました。循環バッファスタイルのQByteArray。読み取り/書き込み部分にミューテックスロック/ロック解除を追加しました。

結果:実際に再生されたオーディオの非常に短いスプリットミリ秒、多くのジッターおよび録音されていないサウンド。

コードを改善する方法についてフィードバックを提供してください。

QAudioFormatの設定

void MainWindow::init_audio_format(){
            m_format.setSampleRate(48000); //(8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, 96000, 192000
            m_format.setByteOrder(QAudioFormat::LittleEndian);
            m_format.setChannelCount(1);
            m_format.setCodec("audio/pcm");
            m_format.setSampleSize(32); //(8, 16, 24, 32, 48, 64)
            m_format.setSampleType(QAudioFormat::SignedInt); //(SignedInt, UnSignedInt, Float)

            m_device = QAudioDeviceInfo::defaultOutputDevice();
            QAudioDeviceInfo info(m_device);
            if (!info.isFormatSupported(m_format)) {
                qWarning() << "Raw audio format not supported by backend, cannot play audio.";
                return;
            }
}

オーディオとQByteArray / Datastreamの初期化

void MainWindow::init_audio_output(){   
    m_bytearray.resize(65536);
    mstream = new QDataStream(&m_bytearray,QIODevice::ReadWrite);
    mstream->setByteOrder(QDataStream::LittleEndian);
    audio = new QAudioOutput(m_device,m_format,this);
    audio->setBufferSize(131072);
    audio->setNotifyInterval(50);
    m_audiodevice = audio->start();
    connect(audio,SIGNAL(notify()),this,SLOT(slot_writedata()));
    read_frames();
}

スロット:

void MainWindow::slot_writedata(){
    QMutex mutex;
    mutex.lock();
    read_frames();
    mutex.unlock();
}

フレームを読み取るには:

    void MainWindow::read_frames(){
        qint32* buffer;
        int frameSize, byteCount=0;
        DWORD tdFrames, fdFrames;
        float fvalue = 0;
        qint32 q32value;

        frameSize = 40 * mBlockSize; //40 mics 
        buffer = new int[frameSize];
        int periodBytes = audio->periodSize();
        int freeBytes = audio->bytesFree();
        int chunks = qMin(periodBytes/mBlockSize,freeBytes/mBlockSize);

        CcmStartInput();

        while(chunks){
            CcmReadFrames(buffer,NULL,frameSize,0,&tdFrames,&fdFrames,NULL,CCM_WAIT);
            if(tdFrames==0){
                break;
            }
            int diffBytes = periodBytes - byteCount;

            if(diffBytes>=(int)sizeof(q32value)*mBlockSize){
                for(int x=0;x<mBlockSize;x++){
                    q32value = (quint32)buffer[x]/256;
                   *mstream << (qint32)fvalue;
                    byteCount+=sizeof(q32value);
                }
            }
            else{
                for(int x=0;x<(diffBytes/(int)sizeof(q32value));x++){
                    q32value = (quint32)buffer[x]/256;
                    *mstream << (qint32) fvalue;
                    byteCount+=sizeof(q32value);
                }
            }
            --chunks;
        }
        CcmStopInput();
        mPosEnd = mPos + byteCount;
        write_frames();
        mPos += byteCount;
        if(mPos >= m_bytearray.length()){
              mPos = 0;
              mstream->device()->seek(0); //change mstream pointer back to bytearray start
        }
    } 

フレームを書き込むには:

void MainWindow::write_frames()
{
    int len = m_bytearray.length() - mPos;
    int bytesWritten = mPosEnd - mPos;

    if(len>=audio->periodSize()){
        m_audiodevice->write(m_bytearray.data()+mPos, bytesWritten);
    }
    else{

        w_data.replace(0,qAbs(len),m_bytearray.data()+mPos);
        w_data.replace(qAbs(len),audio->periodSize()-abs(len),m_bytearray.data());
       m_audiodevice->write(w_data.data(),audio->periodSize());
    }
}
dtech

Qtでのオーディオサポートは実際には非常に初歩的なものです。目標は、可能な限り低い実装および保守コストでメディアを再生することです。状況は特にWindowsで悪く、古代のMMEAPIがまだオーディオ再生に使用されていると思います。

その結果、QtオーディオAPIはリアルタイムとはほど遠いため、このようなアプリケーションには特に適していません。portaudioまたはrtaudioを使用することをお勧めします。これらは、必要に応じてQtスタイルのIOデバイスでラップできます。これにより、パフォーマンスの高いプラットフォームオーディオAPIにアクセスし、非常に低いレイテンシではるかに優れた再生パフォーマンスを実現できます。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

mysqlとストリーミングセンサーデータを使用したd3リアルタイムグラフプロット

分類Dev

UDPを介した低遅延のリアルタイムオーディオストリーミング

分類Dev

ストリーミングAPIを使用してリアルタイムのTwitter検索結果を取得する

分類Dev

検索ビューを使用したカスタムリストアイテムのフィルタリング

分類Dev

QAudioInputを使用したマイクからのリアルタイム再生でのQAudioOutputアンダーランの問題

分類Dev

Python:PyAudio(または何か他のもの)を使用したリアルタイムオーディオストリーミング?

分類Dev

リアルタイムセンサーデータをrethinkdbにストリーミングします

分類Dev

挿入されたデータをリアルタイム(またはほぼリアルタイム)でストリーミングするMongoDb

分類Dev

`と`を使用したTwittertweetinviストリーミングフィルタリング

分類Dev

カスタムストリーミングアプリを使用したWowzaのPlayReadyDRM

分類Dev

ブーストストリームとフィルタリングストリームを使用したアーカイブの解凍

分類Dev

リアルタイムグラフ化のためにmatplotlib.animationを使用して、動的に成長するリストからデータポイントを継続的にストリーミングするにはどうすればよいですか?

分類Dev

IFステートメントを使用したリアルタイム計算JQuery

分類Dev

JavaScriptを使用した大きなファイルのクライアント側のストリーミング

分類Dev

リアルタイムストリーミングデータの分析

分類Dev

Pythonでリアルタイムストリーミングデータをスクレイプする方法は?

分類Dev

socatを使用したリアルタイムライブストリームでの遅延なしのポートフォワーディングと高fps

分類Dev

WebRTCとPHPを使用したマルチクライアントビデオストリーミング

分類Dev

重大:GETの非同期タイムアウト[Spring MVC 4.3.x、Java 8、Tomcat 7を使用した巨大なデータのストリーミング]

分類Dev

ドロップダウンリストを使用したアイテムのフィルタリング

分類Dev

レイヤーリストの背景ドローアブルを使用したカスタムビューは、黒い画面をレンダリングします

分類Dev

Antデザインリストとラジオグループを使用したアイテムのフィルタリング

分類Dev

RESTを使用したデータのストリーミング

分類Dev

コルーチンを使用したFirebaseリアルタイムスナップショットリスナー

分類Dev

Golangおよびffmpegリアルタイムストリーミング入出力

分類Dev

ストリーミングh264リアルタイム800x600

分類Dev

WebAPIでのリアルタイムTweetinviストリーミング

分類Dev

リアルタイムのインテント認識のためにDialogFlowにオーディオをストリーミング

分類Dev

配列アイテムを使用したリストのフィルタリング

Related 関連記事

  1. 1

    mysqlとストリーミングセンサーデータを使用したd3リアルタイムグラフプロット

  2. 2

    UDPを介した低遅延のリアルタイムオーディオストリーミング

  3. 3

    ストリーミングAPIを使用してリアルタイムのTwitter検索結果を取得する

  4. 4

    検索ビューを使用したカスタムリストアイテムのフィルタリング

  5. 5

    QAudioInputを使用したマイクからのリアルタイム再生でのQAudioOutputアンダーランの問題

  6. 6

    Python:PyAudio(または何か他のもの)を使用したリアルタイムオーディオストリーミング?

  7. 7

    リアルタイムセンサーデータをrethinkdbにストリーミングします

  8. 8

    挿入されたデータをリアルタイム(またはほぼリアルタイム)でストリーミングするMongoDb

  9. 9

    `と`を使用したTwittertweetinviストリーミングフィルタリング

  10. 10

    カスタムストリーミングアプリを使用したWowzaのPlayReadyDRM

  11. 11

    ブーストストリームとフィルタリングストリームを使用したアーカイブの解凍

  12. 12

    リアルタイムグラフ化のためにmatplotlib.animationを使用して、動的に成長するリストからデータポイントを継続的にストリーミングするにはどうすればよいですか?

  13. 13

    IFステートメントを使用したリアルタイム計算JQuery

  14. 14

    JavaScriptを使用した大きなファイルのクライアント側のストリーミング

  15. 15

    リアルタイムストリーミングデータの分析

  16. 16

    Pythonでリアルタイムストリーミングデータをスクレイプする方法は?

  17. 17

    socatを使用したリアルタイムライブストリームでの遅延なしのポートフォワーディングと高fps

  18. 18

    WebRTCとPHPを使用したマルチクライアントビデオストリーミング

  19. 19

    重大:GETの非同期タイムアウト[Spring MVC 4.3.x、Java 8、Tomcat 7を使用した巨大なデータのストリーミング]

  20. 20

    ドロップダウンリストを使用したアイテムのフィルタリング

  21. 21

    レイヤーリストの背景ドローアブルを使用したカスタムビューは、黒い画面をレンダリングします

  22. 22

    Antデザインリストとラジオグループを使用したアイテムのフィルタリング

  23. 23

    RESTを使用したデータのストリーミング

  24. 24

    コルーチンを使用したFirebaseリアルタイムスナップショットリスナー

  25. 25

    Golangおよびffmpegリアルタイムストリーミング入出力

  26. 26

    ストリーミングh264リアルタイム800x600

  27. 27

    WebAPIでのリアルタイムTweetinviストリーミング

  28. 28

    リアルタイムのインテント認識のためにDialogFlowにオーディオをストリーミング

  29. 29

    配列アイテムを使用したリストのフィルタリング

ホットタグ

アーカイブ