Soru başlığım korkunçsa beni affet. Karım her zaman bana bir şeyler söylemede iyi olmadığımı söylüyor.Ses kodlarının çözülmesinden sonra bir snd_pcm_writei engellenmesi garip oynatmaya neden olur mu?
Başka bir iş parçacığı tarafından doldurulan bir arabellek okuyan bir kod yazdım. Tampon, opus codec tarafından kodlanan ses verileriyle doldurulur. VoIP verileri bir seferde 20ms uzak taraftan alınır. Sesi mümkün olduğu kadar çabuk çalmak için, bir döngüde, arabellek dışında bir anda 20 ms veri alır ve sonra kodu çözer, sonra snd_pcm_writei'de oynatmak için doğrudan gönderirim.
Başkalarının bunu nasıl yaptığını görmek için önceden kodlanmış ses içeren snd_pcm_writei kullanımıyla ilgili bazı örnekler için Google'da etrafa baktım. Çok şansım olmadı.
Düşüncem şu ki, eğer bir muteks üzerinde bekliyorum ve kodlamayı beklerken sesin "düzgün" olduğunu mantıksal olarak göremiyorum. Her 20ms frame arasında, hoparlörlere sesin gönderilmediği zaman aralıkları olduğunu hayal ediyorum. Şüphelerim, bunun muhtemelen kusurlu ses oluşturacağını düzeltir mi? Buna ilişkin
Kodum: yazma 20-ms parçalar arasındaki zaman tam 20 ms, yeni bir yığın yazarken sonra cihazın tampon boş olacaktır ise
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 aygıtının arabelleği 20 ms'den daha büyük değil mi? –
Evet. Bunu neden yaptığımı söyleyemedim. Sorumu da düzenlerim. Verilerin bir seferde 20 ms alındığı bir VoIP tipi uygulama içindir. Bu yüzden sadece en kısa zamanda oynamaya çalışıyorum. –
Böylece gönderenin saati ve cihazın saati senkronize edilmiyor mu? –