1

我正在尝试将“实时”(缓冲)音频数据编码为 OggVorbis 格式,但它对我不起作用。无论我做什么,输出流都只包含 Vorbis 标头(没有 Ogg 数据)。

我已经成功地使用 libLAME 以相同的方式编码到 MP3 流(显然用 LAME 替换了 ogg 函数)。

我已经包含了用于检索 PCM 数据、将其提供给 libOgg 并检索输出并对其进行缓冲的代码。目前我正在“缓冲区溢出”阶段中断并使用 Xcode 查看 outputBuffer 中包含的内存。

正如我上面所说,这适用于使用 libLAME 的 MP3,所以我知道我离得不远了。如果我查看 ogg.header 和 ogg.body,它们包含数据,ogg.header_length 是 282,ogg.body_length 是 255。

如果需要,我可以将 outputBuffer 粘贴到 bin 供人们查看。

    UInt32 ioLengthInFrames = 256;//ioBufferDuration * self.audioFormat->mSampleRate;
    AudioBufferList *ioData = AllocateABL(self.audioFormat->mChannelsPerFrame, self.audioFormat->mBytesPerFrame, NO, ioLengthInFrames);
    AudioBufferList *floatData = AllocateABL(self.audioFormat->mChannelsPerFrame, self.audioFormat->mBytesPerFrame, NO, ioLengthInFrames);

    UInt32 retVal = TPCircularBufferPeek(inputBuffer, NULL, self.audioFormat);
    if (!retVal > 0)
        return;

    //NSLog (@"Frames Available:  %ld", retVal);

    TPCircularBufferDequeueBufferListFrames(inputBuffer, &ioLengthInFrames, ioData, NULL, self.audioFormat);
    AEFloatConverterToFloatBufferList(self.floatConverter, ioData, floatData, ioLengthInFrames);

    if (ioLengthInFrames <= 0)
    {
        NSLog(@"Not enough frames");
        return;
    }

    float **buffer = vorbis_analysis_buffer(&vd, ioLengthInFrames * self.audioFormat->mBytesPerFrame);

    buffer[0] = floatData->mBuffers[0].mData;
    buffer[1] = floatData->mBuffers[1].mData;

    checkresult (vorbis_analysis_wrote(&vd, ioLengthInFrames * self.audioFormat->mBytesPerFrame), @"Analysis Wrote");

    int wrote = 0;

    while (vorbis_analysis_blockout(&vd, &vb) == 1)
    {
        NSLog(@"Block Out");

        checkresult (vorbis_analysis(&vb, NULL), @"Analysis");
        checkresult (vorbis_bitrate_addblock(&vb), @"BitRate AddBlock");

        while (vorbis_bitrate_flushpacket(&vd, &op))
        {
            NSLog(@"Flush Packet");

            ogg_stream_packetin(&os, &op);

            bool eos = false;
            while (!eos)
            {
                NSLog(@"EOS");
                int result = ogg_stream_pageout(&os, &og);
                if (result==0)break;
                NSLog(@"EOS 2");

                int availableBytes;
                unsigned char* head = TPCircularBufferHead(&outputBuffer, &availableBytes);
                if (availableBytes < og.header_len + og.body_len)
                {
                    return;
                    // Buffer Full
                }
                memcpy(head, og.header, og.header_len);
                memcpy(head+og.header_len, og.body, og.body_len);
                TPCircularBufferProduce(&outputBuffer, og.header_len + og.body_len);

                wrote += og.header_len + og.body_len;

                if (ogg_page_eos(&og))eos=true;
            }
        }
    }

    NSLog(@"Rendering OggVorbis: %d bytes written", wrote);
4

1 回答 1

0

最后我得到了它的工作。我必须使用 memcpy 来填充 libOgg 输入缓冲区,并且我必须修复我传入的值,以便复制到缓冲区的样本数量。

请参阅下面的工作代码:

    UInt32 ioLengthInFrames = 256;//ioBufferDuration * self.audioFormat->mSampleRate;
    AudioBufferList *ioData = AllocateABL(self.audioFormat->mChannelsPerFrame, self.audioFormat->mBytesPerFrame, NO, ioLengthInFrames);
    AudioBufferList *floatData = AllocateABL(self.audioFormat->mChannelsPerFrame, self.audioFormat->mBytesPerFrame, NO, ioLengthInFrames);

    UInt32 retVal = TPCircularBufferPeek(inputBuffer, NULL, self.audioFormat);
    if (!retVal > 0)
        return;

    TPCircularBufferDequeueBufferListFrames(inputBuffer, &ioLengthInFrames, ioData, NULL, self.audioFormat);
    AEFloatConverterToFloatBufferList(self.floatConverter, ioData, floatData, ioLengthInFrames);

    if (ioLengthInFrames <= 0)
    {
        NSLog(@"Not enough frames");
        return;
    }

    float **buffer = vorbis_analysis_buffer(&vd, ioLengthInFrames);

    memcpy(buffer[0], floatData->mBuffers[0].mData, floatData->mBuffers[0].mDataByteSize);
    memcpy(buffer[1], floatData->mBuffers[1].mData, floatData->mBuffers[1].mDataByteSize);

    checkresult (vorbis_analysis_wrote(&vd, ioLengthInFrames), @"Analysis Wrote");

    int wrote = 0;

    while (vorbis_analysis_blockout(&vd, &vb) == 1)
    {
        checkresult (vorbis_analysis(&vb, NULL), @"Analysis");
        checkresult (vorbis_bitrate_addblock(&vb), @"BitRate AddBlock");

        while (vorbis_bitrate_flushpacket(&vd, &op))
        {
            //NSLog(@"Flush Packet");

            ogg_stream_packetin(&os, &op);

            bool eos = false;
            while (!eos)
            {
                int result = ogg_stream_pageout(&os, &og);
                if (result==0)break;

                int size = og.header_len + og.body_len;

                int availableBytes;
                unsigned char* head = TPCircularBufferHead(&outputBuffer, &availableBytes);

                if (availableBytes < size)
                {
                    NSLog(@"Buffer Full");
                    return;
                }

                memcpy(head, og.header, og.header_len);
                memcpy(head+og.header_len, og.body, og.body_len);
                TPCircularBufferProduce(&outputBuffer, size);

                wrote += size;

                if (ogg_page_eos(&og))eos=true;
            }
        }
    }

    NSLog(@"Rendering OggVorbis: %d bytes written", wrote);
于 2013-12-17T10:40:59.990 回答