私の質問のタイトルがひどい場合は、私に許してください。私の妻はいつも私は物事を表現することがうまくいかないと私に言っています。オーディオをデコードした後にsnd_pcm_writeiをブロックすると奇妙な再生が発生しますか?
別のスレッドで満たされたバッファを読み取るコードを記述しました。バッファには、opusコーデックでエンコードされたオーディオデータが格納されます。 VoIPデータはリモート側から20msずつ受信されます。できるだけ早くオーディオを再生しようとすると、バッファから一度に20ミリ秒分のデータを取り出し、それをデコードして直ちに送信してsnd_pcm_writeiを再生します。
私は、以前にエンコードされたオーディオでsnd_pcm_writeiを使用して他の人がどのようにしているかを確認するためのいくつかの例をGoogleで見てきました。私は多くの運がなかった。
私はミューテックスを待ってエンコーディングを待っていると、オーディオが論理的に「滑らか」であるとは思えません。私は各20msのフレームの間に、音声がスピーカーに送られていない時間のギャップがあると思います。これが不完全なオーディオを作成する可能性があるという私の疑惑は正しいのでしょうか?これに関連し
私のコード:20ミリ秒のチャンクを書き込むまでの時間が正確に20msである場合は、新しいチャンクを書いているとき
while(true)
{
// We need a positive lock
if(!buffer_lock)
buffer_lock.lock();
LOG_DEBUG(*logger_) << "After the mutex lock.";
LOG_DEBUG(*logger_) << "Buffer size: " << current_audio->buffer_size_;
LOG_DEBUG(*logger_) << "Read pointer: " << current_audio->read_pointer_;
opus_int32 payload_size;
LOG_DEBUG(*logger_) << "calling audioCanDecodeChunk()";
// Now fisticuffs do we have enouffs?
if(audioCanDecodeChunk(current_audio, payload_size))
{
LOG_DEBUG(*logger_) << "We have enough current_audio buffer.";
// Are we dank?
if(payload_size<0 or payload_size>MAX_PACKET)
{
LOG_ERROR(*logger_) << "Decoding error, payload size (" << payload_size << ") is outsize range.";
break; // Terminal
}
// We have enough!
// Advance the read pointer
current_audio->read_pointer_+= 4;
// Copy it out
memcpy(payload_buffer, current_audio->buffer_+current_audio->read_pointer_, payload_size);
// Release it
buffer_lock.unlock();
// Now thingify it
int samples_decoded = opus_decode(opus_decoder_,
(const unsigned char *)payload_buffer,
payload_size,
(opus_int16 *)pcm_buffer,
MAX_FRAME_SIZE,
0);
// How did we do?
if(samples_decoded<0)
{
// What hap?
LOG_ERROR(*logger_) << "Error decoding samples: " << opus_strerror(samples_decoded);
break;
}
else
{
// Now we have our PCM!
int bytes_decoded = current_audio->recording_.channels*sizeof(opus_int16)*samples_decoded;
LOG_DEBUG(*logger_) << "We have decoded " << bytes_decoded << " bytes payload: " << payload_size;
// Now write
if((error = snd_pcm_writei(playback_handle_, pcm_buffer, samples_decoded))!=samples_decoded)
{
LOG_ERROR(*logger_) << "snd_pcm_writei error: " << snd_strerror(error);
}
}
// Advance pointer
current_audio->read_pointer_+= payload_size;
} // If we don't have enough let it slide and unlock
else if(current_audio->done_) // Were we issued a flush?
{
LOG_DEBUG(*logger_) << "We are done.";
// We are done with this loop
break;
}
else
{
// Wait for it (an update)
LOG_DEBUG(*logger_) << "Before wait_buffer wait. Done: " << (current_audio->done_ ? "true" : "false") <<
"Size: " << current_audio->buffer_size_
<< ", Read: " << current_audio->read_pointer_;
current_audio->wait_buffer_.wait(buffer_lock);
LOG_DEBUG(*logger_) << "After wait_buffer wait";
}
} // End while(true)
PCMデバイスのバッファが20ミリ秒を超えていますか? –
はい。なぜ私がこれをやっているのか言及しなかったのかもしれません。私は私の質問も編集します。これは、データが一度に20ms受信されるVoIPタイプのアプリケーション用です。だから私はできるだけ早くそれを再生しようとしています。 –
送信者の時計とデバイスの時計は同期していませんか? –