ios – 如何使用opus对音频进行编码和解码

ios – 如何使用opus对音频进行编码和解码,第1张

概述我正在尝试将opus集成到我的应用程序中,编码解码函数返回正值,这意味着成功,但输出音频无法播放.原始音频数据也可以播放. 这是我编码数据的方式.我使用4字节前缀来分隔每个数据包. self.encoder = opus_encoder_create(24000, 1, OPUS_APPLICATION_VOIP, &opusError);opus_encoder_ctl(self.encod 我正在尝试将opus集成到我的应用程序中,编码和解码函数返回正值,这意味着成功,但输出音频无法播放.原始音频数据也可以播放.
这是我编码数据的方式.我使用4字节前缀来分隔每个数据包.

self.encoder = opus_encoder_create(24000,1,OPUS_APPliCATION_VOIP,&opusError);opus_encoder_ctl(self.encoder,OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_SUPERWIDEBAND));- (voID) encodeBufferList:(audiobufferlist *)bufferList {    BOol success = TPCircularBufferProduceBytes(_circularBuffer,bufferList->mBuffers[0].mData,bufferList->mBuffers[0].mDataByteSize);    if (!success) {        NSLog(@"insufficIEnt space in circular buffer!");    }    if (!_enCoding) {            _enCoding = YES;            dispatch_async(self.processingQueue,^{                [self startEnCodingLoop];            });    }}-(voID)startEnCodingLoop{    int32_t availableBytes = 0;    opus_int16 *data = (opus_int16*)TPCircularBufferTail(_circularBuffer,&availableBytes);    int availableSamples = availableBytes / _inputASBD.mBytesPerFrame;    /*!     *  Use dynamic duration     *///    int valIDSamples[6] = {2.5,5,10,20,40,60}; // in milisecond//    int esample = valIDSamples[0] * self.sampleRate / 1000;//    for (int i = 0; i < 6; i++) {//        int32_t samp = valIDSamples[i] * self.sampleRate / 1000;//        if (availableSamples < samp) {//            break;//        }//        esample = samp;//    }    /*!     *  Use 20ms     */    int esample = 20 * self.sampleRate / 1000;    if (availableSamples < esample) {        /*!         *  Out of data. Finish enCoding         */        self.enCoding = NO;        [self.eDelegate dIDFinishEncode];        return;    }//    printf("raw input value for packet \n");//    for (int i = 0; i < esample * self.numberOfChannels; i++) {//        printf("%d :",data[i]);//    }    int returnValue = opus_encode(_encoder,data,esample,_encoderOutputBuffer,1000);    TPCircularBufferConsume(_circularBuffer,esample * sizeof(opus_int16) * self.numberOfChannels);//    printf("output encode \n");//    for (int i = 0; i < returnValue; i++) {//        printf("%d :",_encoderOutputBuffer[i]);//    }    NSMutableData *outputData = [NSMutableData new];    NSError *error = nil;    if (returnValue <= 0) {        error = [OKUtilitIEs errorForOpusErrorCode:returnValue];    }else {        [outputData appendBytes:_encoderOutputBuffer length:returnValue * sizeof(unsigned char)];        unsigned char int_fIEld[4];        int_to_char(returnValue,int_fIEld);        NSData *header = [NSData dataWithBytes:&int_fIEld[0] length:4 * sizeof(unsigned char)];        if (self.eDelegate) {            [self.eDelegate dIDEncodeWithData:header];        }    }    if (self.eDelegate) {        [self.eDelegate dIDEncodeWithData:outputData];    }    [self startEnCodingLoop];}

这里是解码功能:

self.decoder = opus_decoder_create(24000,&opusError);opus_decoder_ctl(self.decoder,OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));opus_decoder_ctl(self.decoder,OPUS_SET_GAIN(10));-(voID)startParseData:(unsigned char*)data remainingLen:(int)len{    if (len <= 0) {        [self.dDelegate dIDFinishDecode];        return;    }    int headLen = sizeof(unsigned char) * 4;    unsigned char h[4];    h[0] = data[0];    h[1] = data[1];    h[2] = data[2];    h[3] = data[3];    int packetLen = char_to_int(h);    data += headLen;    packetLen = packetLen * sizeof(unsigned char) * self.numberOfChannels;    [self decodePacket:data length:packetLen remainingLen:len - headLen];}-(voID)decodePacket:(unsigned char*)inputData length:(int)len remainingLen:(int)rl{    int bw = opus_packet_get_banDWIDth(inputData); //TEST: return OPUS_BANDWIDTH_SUPERWIDEBAND here    int32_t decodedSamples = 0;//    int valIDSamples[6] = {2.5,60}; // in milisecond    /*!     *  Use 60ms     */    int esample = 60 * self.sampleRate / 1000;//    printf("input decode \n");//    for (int i = 0; i < len; i++) {//        printf("%d :",inputData[i]);//    }    _decoderBufferLength = esample * self.numberOfChannels * sizeof(opus_int16);    int returnValue = opus_decode(_decoder,inputData,len,_outputBuffer,1);    if (returnValue < 0) {        NSError *error = [OKUtilitIEs errorForOpusErrorCode:returnValue];        NSLog(@"decode error %@",error);        inputData += len;        [self startParseData:inputData remainingLen:rl - len];        return;    }    decodedSamples = returnValue;    NSUInteger length = decodedSamples * self.numberOfChannels;//    printf("raw decoded data \n");//    for (int i = 0; i < length; i++) {//        printf("%d :",_outputBuffer[i]);//    }    NSData *audioData = [NSData dataWithBytes:_outputBuffer length:length * sizeof(opus_int16)];    if (self.dDelegate) {        [self.dDelegate dIDDecodeData:audioData];    }    inputData += len;    [self startParseData:inputData remainingLen:rl - len];}

请帮我指出我错过的东西.一个例子就是很棒.

解决方法 我认为问题出在解码方面:

>您将1作为fec参数传递给opus_decode().这要求解码器从当前数据包中的纠错数据生成完整数据包持续时间的数据.我没有在您的代码中看到任何丢失的数据包跟踪,因此应该传递0.通过该更改,您的输入和输出持续时间应匹配.>您为单声道输出配置解码器,但稍后在长度计算中使用self.numberOfChannels.那些应该匹配,否则你可能会出现意外行为.> OPUS_SET_SIGNAL在opus_decoder_ctl()中不执行任何 *** 作,但它只会返回OPUS_UNIMPLEMENTED而不会影响行为.> Opus数据包的持续时间最长可达120毫秒,因此60毫秒的限制可能无法解码某些流.如果你只是跟你自己的应用程序说话而不会像你配置它那样引起问题,因为libopus默认为20ms帧.

总结

以上是内存溢出为你收集整理的ios – 如何使用opus对音频进行编码和解码全部内容,希望文章能够帮你解决ios – 如何使用opus对音频进行编码和解码所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1077370.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-26
下一篇2022-05-26

发表评论

登录后才能评论

评论列表(0条)

    保存