2013-03-07 8 views
2

libogg 및 libogg를 사용 중이며,이 라이브러리를 iPhone xCode 프로젝트에 추가하고 Speex로 음성을 인코딩하는 데 성공했습니다. 문제는 오디오 패킷을 ogg로 묶는 방법을 알 수 없다는 것입니다. 어떤 종류의 패킷이 어떻게 보일 지 또는 내가 사용할 수있는 참조 코드가 있어야 하는지를 누군가가 알고 있는가?iOS에 Ogg가 포함 된 Speex를 포장하십시오.

나는 자바에서 꽤 알고있다. (당신은 그것에 대한 전용 기능이 있지만) iOS에는 없다. 도와주세요.

답변

5

UPD 10.09.2013 : demo project을 참조하십시오. 기본적으로 웨이브 컨테이너에서 pcm audiodata를 취하고, speex 코덱으로 인코딩 한 다음 모든 것을 ogg 컨테이너에 넣습니다. 어쩌면 나중에 IOS의 모든 speex 루틴을위한 완전한 라이브러리/프레임 워크를 만들 것입니다.

UPD 16.02.2015 : GitHub의 데모 프로젝트는 republished입니다.

나는 최근에 다양한 성공을 거둔 iOS에서 Speex를 실험 해 왔지만, 여기에 내가 발견 한 것이있다. 기본적으로 speex로 인코딩 된 음성을 ogg 파일에 압축하려면 다음 세 단계를 수행해야합니다 (libogg 및 libspeex가 이미 컴파일되어 프로젝트에 추가되었다고 가정).

1) Speex 헤더가있는 첫 번째 ogg 페이지를 추가하십시오. libspeex이 내장되어 제공에 대한 tools (아래 코드는 단지 예를 위해, 내 프로젝트, 최적이 아닌 출신) :

// 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 comment와 두 번째 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 페이지에 갖고 싶어 얼마나 많은 프레임 오디오 데이터와 결정 (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) 

그게 전부입니다. 희망이 도움이 될 것입니다. 모든 수정이나 질문은 환영합니다.

+0

어디에서 어떻게 선언 할 수 있습니까? 특히 _ogg 파일 유형은 무엇입니까? – Idan

+0

@ 이단, 늦어서 대단히 반갑습니다. 최근에 많은 일을했습니다. 귀하의 질문에 관한 : _oggFile은 NSMutableData 개체이지만 이름이 혼란스럽게 들릴 수 있습니다. 매우 기본적인 샘플 프로젝트를 만들어 모든 프로젝트가 잘 진행된다면 이번 주말에 게시하려고 노력할 것입니다. – mikejd

+1

데모 프로젝트가 여기에 있습니다. 답변 본문의 업데이트를 참조하십시오. – mikejd