gpt4 book ai didi

ogg - 在 iOS 上用 Ogg 打包 Speex

转载 作者:行者123 更新时间:2023-12-02 22:11:18 30 4
gpt4 key购买 nike

我正在使用 libogg 和 libogg,我已成功将这些库添加到我的 iPhone xCode 项目并使用 Speex 对我的声音进行编码。问题是我不知道如何用 ogg 打包这些音频数据包。有人知道那种数据包应该是什么样子,或者有我可以使用的引用代码。

我知道在 Java 中它非常简单(您有一个专门的函数)但在 iOS 上则不然。请帮忙。

最佳答案

UPD 10.09.2013:请参阅 demo project ,它基本上从 wave 容器中获取 pcm 音频数据,使用 speex 编解码器对其进行编码,然后将所有内容打包到 ogg 容器中。也许稍后我会为 IOS 上的所有 speex 例程创建一个成熟的库/框架。

UPD 16.02.2015:演示项目是 republished在 GitHub 上。


我最近也在 iOS 上尝试使用 Speex,取得了不同程度的成功,但我发现了一些东西。基本上,如果您想将一些 speex 编码的语音打包到一个 ogg 文件中,您需要执行以下三个步骤(假设 libogg 和 libspeex 已经编译并添加到项目中)。

1) 添加带有Speex header的第一个ogg页面; libspeex 提供内置 tools为此(下面的代码来 self 的项目,不是最优的,只是为了举例):

// create speex header 
SpeexHeader spxHeader;
SpeexMode spxMode = speex_wb_mode;
int spxRate = 16000;
int spxNumberOfChannels = 1;
speex_init_header(&spxHeader, spxRate, spxNumberOfChannels, &spxMode);

// set audio and ogg packing parameters
spxHeader.vbr = 0;
spxHeader.bitrate = 16;
spxHeader.frame_size = 320;
spxHeader.frames_per_packet = 1;

// wrap speex header in ogg packet
int oggPacketSize;
_oggPacket.packet = (unsigned char *)speex_header_to_packet(&spxHeader, &oggPacketSize);
_oggPacket.bytes = oggPacketSize;
_oggPacket.b_o_s = 1;
_oggPacket.e_o_s = 0;
_oggPacket.granulepos = 0;
_oggPacket.packetno = 0;

// submit the packet to the ogg streaming layer
ogg_stream_packetin(&_oggStreamState, &_oggPacket);
free(_oggPacket.packet);

// form an ogg page
ogg_stream_flush(&_oggStreamState, &_oggPage);

// write the page to file
[_oggFile appendBytes:&_oggStreamState.header length:_oggStreamState.header_fill];
[_oggFile appendBytes:_oggStreamState.body_data length:_oggStreamState.body_fill];

2) 添加第二个 ogg 页面 Vorbis comment :

// form any comment you like (I use custom struct with all fields)
vorbisCommentStruct *vorbisComment = calloc(sizeof(vorbisCommentStruct), sizeof(char));
...

// wrap Vorbis comment in ogg packet
_oggPacket.packet = (unsigned char *)vorbisComment;
_oggPacket.bytes = vorbisCommentLength;
_oggPacket.b_o_s = 0;
_oggPacket.e_o_s = 0;
_oggPacket.granulepos = 0;
_oggPacket.packetno = _oggStreamState.packetno;

// the rest should be same as in previous step
...

3) 以类似方式添加带有 speex 编码音频的后续 ogg 页面。

首先决定你想在每个ogg页面上有多少帧音频数据(0-255;我选择79很随意):

_framesPerOggPage = 79;

然后对于每一帧:

// calculate current granule position of audio data within ogg file 
int curGranulePos = _spxSamplesPerFrame * _oggTotalFramesCount;

// wrap audio data in ogg packet
oggPacket.packet = (unsigned char *)spxFrame;
oggPacket.bytes = spxFrameLength;
oggPacket.granulepos = curGranulePos;
oggPacket.packetno = _oggStreamState.packetno;
oggPacket.b_o_s = 0;
oggPacket.e_o_s = 0;

// submit packets to streaming layer until their number reaches _framesPerOggPage
...

// if we've reached this limit, we're ready to create another ogg page

ogg_stream_flush(&_oggStreamState, &_oggPage);

[_oggFile appendBytes:&_oggStreamState.header length:_oggStreamState.header_fill];
[_oggFile appendBytes:_oggStreamState.body_data length:_oggStreamState.body_fill];

// finally, if this is the last frame, flush all remaining packets,
// which have been created but not packed into a page, to the last page
// (don't forget to set oggPacket.e_o_s to 1 for this frame)

就是这样。希望它会有所帮助。欢迎任何更正或问题。

关于ogg - 在 iOS 上用 Ogg 打包 Speex,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15277361/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com