问题描述
我在iOS上创建ogg opus音频文件时遇到问题,在下面的代码中,我能够将pcm音频编码为opus,然后添加到ogg容器中,最终结果中显示结果,但是当我尝试使用以下命令创建文件时此数据,文件为0秒,无法播放。有人可以帮我吗?
#define WATSONSDK_AUdio_FRAME_SIZE 160
#define WATSONSDK_AUdio_SAMPLE_RATE 8000.0
self.opushelper = [[OpusHelper alloc] init];
[self.opushelper createEncoder: WATSONSDK_AUdio_SAMPLE_RATE];
opusRef = self->_opushelper;
self.ogghelper = [[OggHelper alloc] init];
oggRef = self->_ogghelper;
NSMutableData *finaldata= [NSMutableData new];
NSData *headerdata =[[self ogghelper] getoggOpusHeader:WATSONSDK_AUdio_SAMPLE_RATE];
[finaldata appendBytes:headerdata.bytes length:headerdata.length];
if (pcmdata!=nil && [pcmdata length]!=0) {
NSUInteger length = [pcmdata length];
NSUInteger chunkSize = WATSONSDK_AUdio_FRAME_SIZE * 2;
NSUInteger offset = 0;
do {
NSUInteger thisChunkSize = length - offset > chunkSize ? chunkSize : length - offset;
NSData* chunk = [NSData dataWithBytesNocopy:(char *)[pcmdata bytes] + offset
length:thisChunkSize
freeWhenDone:NO];
// opus encode block
NSData *compressed = [opusRef encode:chunk frameSize:WATSONSDK_AUdio_FRAME_SIZE];
if(compressed != nil){
NSMutableData *audioData = [NSMutableData new];
audioData = [oggRef writePacket:compressed frameSize:WATSONSDK_AUdio_FRAME_SIZE];
if(audioData != nil)
{
[finaldata appendBytes:audioData.bytes length:audioData.length];
}
}
offset += thisChunkSize;
} while (offset < length);
}
这些是OpusHelper.h中使用的方法:
- (NSData*) encode:(NSData*) pcmData frameSize:(int) frameSize{
opus_int16 *data = (opus_int16*) [pcmData bytes];
uint8_t *outBuffer = malloc(pcmData.length * sizeof(uint8_t));
// The length of the encoded packet
opus_int32 encodedByteCount = opus_encode(_encoder,data,frameSize,outBuffer,(opus_int32)pcmData.length);
if (encodedByteCount < 0) {
NSLog(@"encoding error %@",[self opusErrorMessage:encodedByteCount]);
return nil;
}
// Opus data initialized with size in the first byte
NSMutableData *outputData = [[NSMutableData alloc] initWithCapacity:frameSize*2];
// Append Opus data
[outputData appendData:[NSData dataWithBytes:outBuffer length:encodedByteCount]];
return outputData;
}
这些是OGGHelper.h中使用的方法:
- (NSData *) getoggOpusHeader:(int) sampleRate{
packetCount = 0,granulePos = 0;
long headerSize = 19;
unsigned char opusHeader[headerSize];
int offset = 0;
// 0 - 7: OpusHead
writeString(opusHeader,offset + 0,(unsigned char *)"OpusHead",8);
// Version,MUST The version number MUST always be '1' for this version of the encapsulation specification.
opusHeader[offset + 8] = 1;
// Output Channel Count
opusHeader[offset + 9] = 1;
// Pre-skip
writeShort(opusHeader,offset + 10,0);
// Input Sample Rate (Hz)
writeInt(opusHeader,offset + 12,sampleRate);
// Output Gain (Q7.8 in dB),+/- 128 dB
writeShort(opusHeader,offset + 16,0);
// Mapping Family (For channel mapping family 0,this value defaults to C-1 (i.e.,0 for mono and 1 for stereo),and is not coded.)
opusHeader[offset + 18] = 0;
ogg_packet opusHeaderPacket;
opusHeaderPacket.packet = opusHeader;
opusHeaderPacket.bytes = headerSize;
opusHeaderPacket.b_o_s = 1;
opusHeaderPacket.e_o_s = 0;
opusHeaderPacket.granulepos = granulePos;
opusHeaderPacket.packetno = packetCount++;
ogg_stream_packetin(&streamState,&opusHeaderPacket);
ogg_stream_flush(&streamState,&oggPage);
NSMutableData *newData = [[NSMutableData alloc] initWithCapacity:0];
[newData appendBytes:oggPage.header length:oggPage.header_len];
[newData appendBytes:oggPage.body length:oggPage.body_len];
// NSLog(@"[Encoder] Ogg header,%ld bytes are written\n",opusHeaderPacket.bytes);
offset = 0;
Nsstring *comments = @"libopus";
int commentsLength = (int)[comments lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
// NSLog(@"Comments length=%d",commentsLength);
unsigned char opusComments[commentsLength + 28];
writeString(opusComments,offset,(unsigned char *)"OpusTags",8);
Nsstring *vendorString = @"IBM";
int vendorStringLength = (int) vendorString.length;
// vendor String Length
writeInt(opusComments,offset + 8,(int) vendorStringLength);
// vendor String
writeString(opusComments,(unsigned char*)[comments cStringUsingEncoding:NSUTF8StringEncoding],vendorStringLength);
// User Comment List Length
writeInt(opusComments,offset + 20,1);
// vendor comment size
writeInt(opusComments,offset + 24,commentsLength);
// vendor comment
writeString(opusComments,offset + 28,commentsLength);
ogg_packet opusCommentsPacket;
opusCommentsPacket.packet = opusComments;
opusCommentsPacket.bytes = commentsLength + 8;
opusCommentsPacket.b_o_s = 0;
opusCommentsPacket.e_o_s = 0;
opusCommentsPacket.granulepos = 0;
opusCommentsPacket.packetno = packetCount++;
ogg_stream_packetin(&streamState,&opusCommentsPacket);
ogg_stream_flush(&streamState,&oggPage);
[newData appendBytes:oggPage.header length:oggPage.header_len];
[newData appendBytes:oggPage.body length:oggPage.body_len];
// NSLog(@"[Encoder] Ogg comments,opusCommentsPacket.bytes);
return newData;
}
/**
* Write OggOpus packet
*
* @param data Opus data
* @param frameSize Frame size
*
* @return NSMutableData instance or nil
*/
- (NSMutableData *) writePacket: (NSData*) data frameSize:(int) frameSize{
ogg_packet packet;
packet.packet = (unsigned char *)[data bytes];
packet.bytes = (long)([data length]);
packet.b_o_s = 0;
packet.e_o_s = 0;
granulePos += (frameSize * 2);
packet.granulepos = granulePos;
packet.packetno = packetCount++;
ogg_stream_packetin(&streamState,&packet);
if (ogg_stream_pageout(&streamState,&oggPage)) {
NSMutableData *newData = [NSMutableData new];
[newData appendBytes:oggPage.header length:oggPage.header_len];
[newData appendBytes:oggPage.body length:oggPage.body_len];
return newData;
}
return nil;
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)