微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

iOS创建OGG可播放的音频文件

如何解决iOS创建OGG可播放的音频文件

我在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 举报,一经查实,本站将立刻删除。