【问题标题】:libOgg / libVorbis and AudioBufferListlibOgg / libVorbis 和 AudioBufferList
【发布时间】:2014-01-04 17:41:23
【问题描述】:

我正在尝试将“实时”(缓冲)音频数据编码为 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);

【问题讨论】:

    标签: objective-c core-audio oggvorbis


    【解决方案1】:

    最后我得到了它的工作。我必须使用 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);
    

    【讨论】:

      猜你喜欢
      • 2011-11-11
      • 2019-04-04
      • 2014-03-25
      • 1970-01-01
      • 2011-04-05
      • 1970-01-01
      • 2012-07-27
      • 1970-01-01
      • 2014-02-13
      相关资源
      最近更新 更多