Декодируйте и воспроизводите фрагменты двоичных данных Opus, используя AudioQueue AudioToolbox - PullRequest
0 голосов
/ 10 мая 2019

Мы переносим нашу базу данных аудио из 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);  
}  
...