2

libogg と libogg を使用しています。これらのライブラリを iPhone xCode プロジェクトに追加し、Speex で音声をエンコードすることに成功しました。問題は、これらのオーディオ パケットを ogg でパックする方法がわからないことです。誰かがその種のパケットがどのように見えるべきか、または私が使用できる参照コードを持っているか知っていますか.

Javaでは非常に単純であることは知っていますが(そのための専用関数があります)、iOSではそうではありません。助けてください。

4

1 に答える 1

5

UPD 10.09.2013:デモ プロジェクトを参照してください。これは、基本的には wave コンテナーから pcm オーディオデータを取得し、speex コーデックでエンコードし、すべてを ogg コンテナーにパックします。たぶん後で、IOS 上のすべての Speex ルーチン用の本格的なライブラリ/フレームワークを作成する予定です。

UPD 16.02.2015: デモ プロジェクトがGitHubで再公開されました。


私はまた、最近 iOS で Speex を試していて、さまざまな成功を収めていますが、ここに私が見つけたものがあります。基本的に、speex でエンコードされた音声を ogg ファイルにパックする場合は、3 つの手順に従う必要があります (libogg と libspeex が既にコンパイルされ、プロジェクトに追加されていると仮定します)。

1) Speex ヘッダーを含む最初の ogg ページを追加します。libspeex はそのための組み込みツールを提供します (以下のコードは私のプロジェクトからのもので、例として最適ではありません):

// 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) Vorbis コメント付きの 2 番目の ogg ページを追加します。

// 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)

それでおしまい。それが役立つことを願っています。修正や質問は大歓迎です。

于 2013-04-05T11:26:39.507 に答える