Мы переносим нашу базу данных аудио из Speex в Opus. База данных в формате .pdb, записи представляют собой двоичные фрагменты. Раньше аудио кодировалось в формат Speex и помещалось в базу данных. В приложении фрагменты со звуком были декодированы / преобразованы в PCM и воспроизведены с помощью AudioToolbox AudioQueue для iOS.
Теперь аудиофайлы кодируются в формате Opus и успешно добавляются в базу данных на месте. Мне нужно использовать ту же логику, что и раньше, чтобы декодировать двоичные фрагменты данных и воспроизводить аудио. Файлы довольно маленькие - 1-5 КБ. Преобразование кода, казалось, шло хорошо, пока я не достиг изменения функции AudioQueueOutputCallback.
В Speex есть структура SpeexBits, которую можно использовать для чтения частей двоичных данных и подачи их в очередь (функции обратного вызова, показанные ниже).
Однако я, похоже, не нахожу прямой способ сделать то же самое с Opus. Я не верю, что на самом деле нет способа сделать что-то подобное без усилий изменить все остальное.
Есть идеи, как это можно сделать? Примеры кода были бы великолепны.
Кроме этого, но связанного - двоичное представление файла Opus, кажется, начинается с части заголовка, я должен обойти это и как?
Я пытался следовать примерам декодирования Opus, но ни один из них не подходит для конкретного случая.
Speex way:
void OutputCallback( AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
{
if(m_nDecodedData>=m_nDataLen)
{
AudioQueueStop(inAQ, false);
m_bComplete= true;
return;
}
unsigned count= ((unsigned char*) m_pData)[m_nDecodedData++];
if(m_nDecodedData + count>m_nDataLen)
count= (unsigned)(m_nDataLen - m_nDecodedData);
SpeexBits bits;
speex_bits_init(&bits);
speex_bits_read_from(&bits, m_pData+ m_nDecodedData, count);
m_nDecodedData+=count;
speex_decode_int(m_pSpeexState, &bits, (spx_int16_t*)inBuffer->mAudioData);
inBuffer->mAudioDataByteSize= m_nFrameSize*2;
AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
speex_bits_destroy(&bits);
}
OPUS way?:
void OutputCallback(AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
if(m_nDecodedData>=m_nDataLen) {
AudioQueueStop(inAQ, false);
m_bComplete= true;
return;
}
unsigned count= ((unsigned char*) m_pData)[m_nDecodedData++];
if(m_nDecodedData + count>m_nDataLen)
count= (unsigned)(m_nDataLen - m_nDecodedData);
// HOW TO PROCEED FROM HERE ON WITH NEXT CHUNK OF AUDIO DATA
//SpeexBits bits;
//speex_bits_init(&bits);
//speex_bits_read_from(&bits, m_pData+ m_nDecodedData, count);
m_nDecodedData+=count;
int frame_size = opus_decode(m_pOpusState, (unsigned char*)m_pData, 2, (opus_int16*)inBuffer->mAudioData, MAX_FRAME_SIZE, 0);
if(frame_size<0) {
return;
}
inBuffer->mAudioDataByteSize = m_nFrameSize*2;
AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
}