私はC++プロジェクトで、独自のC++ APIを使用して、マイクアレイシステムから生のオーディオを読み込み/処理/再生しています。 QTを使ってソフトウェアをプログラミングしています。QT C++ QAudioOutputによるリアルタイムストリーミング
投稿者Real Time Streaming With QAudioOutput (QT)については、処理するのに約1000ms(1秒)かかる関数呼び出しからRaw Audioデータが得られた場合は、フォローアップを行い、何をすべきかアドバイスを求めたかったですか?リアルタイムのオーディオ再生をどうすれば達成できますか?
QIODevice :: QAudioFormat-> start()に書き込むときに読み込んでいたので、処理に約1秒かかりました。バッファのアンダーラン/オーバーランを防ぐためには、一定の期間のバイトを使用することをお勧めします。 http://cell0907.blogspot.sg/2012/10/qt-audio-output.html
QByteArrayとQDataStreamをセットアップして、関数呼び出しから受け取ったデータをストリーミングしました。
- API CcmXXX()
- は、マイクロホンアレイからデータを読み取って32ビット整数、32ビット整数、24ビットの分解能、8ビットLSBパディングゼロの
- の配列を返します。
- ブロックサイズ(1024サンプルに設定)x 40マイクロフォン
- 各チャンクは、書き込まれたバイト数がピリオド・サイズ/フリー・バイト量に近づくまで約1ブロックを書き込みます。
テスト済み:約50ミリ秒の通知に私のスロットを接続して、1ピリオド分のバイトを書き込みます。循環バッファー形式のQByteArray。読み込み/書き込み部分にmutexロック/アンロックを追加しました。
結果:実際に再生されたオーディオの非常に短い分割ms、ジッタの多いサウンドおよび録音されていないサウンドが多数あります。
私のコードを改善する方法についてのフィードバックを提供してください。
void MainWindow::slot_writedata(){
QMutex mutex;
mutex.lock();
read_frames();
mutex.unlock();
}
:
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();
}
スロット
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 /データストリーム0
フレーム読みするには、次のフレームを書き込むには
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
}
}
を:Qtの中
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());
}
}
はい、絶対に。ほとんどすべてのビデオ/オーディオはQtに関連していますが、QMediaPlayerでもFFmpegのようなものを使用するのではなく、OSの再生機能(!!!)を使用していても、あらゆる種類の問題につながります。特殊なライブラリ(GUIのためにQtを混ぜたもの)を使う方が良いでしょう。 – TheSHEEEP
コメントと提案いただきありがとうございます。私はそれらの図書館を試してみます!乾杯! – MrS05
dtechとTheSHEEEPこんにちは、他のAPIについてさらにお尋ねします。私はrtaudio APIを追加しようとしました。私はhttp://www.music.mcgill.ca/~gary/rtaudio/からファイルをダウンロードしました。私はその後、CMakeメイクファイルを作成してDLLを生成し、それからrtaudio DLLまたはlibファイルを生成するためにメイクファイルをMingw64メイクで実行する必要がありますか? – MrS05