#import "OpusBridge.h" #import "opus.h" // 编码器结构体 typedef struct { OpusEncoder *encoder; int channels; int sampleRate; int frameSize; } OpusEncoderWrapper; // 解码器结构体 typedef struct { OpusDecoder *decoder; int channels; int sampleRate; } OpusDecoderWrapper; @implementation OpusBridge { OpusEncoderWrapper *_encoderWrapper; OpusDecoderWrapper *_decoderWrapper; } #pragma mark - 初始化和销毁 - (instancetype)init { self = [super init]; if (self) { _encoderWrapper = NULL; _decoderWrapper = NULL; } return self; } - (void)dealloc { [self disposeEncoder]; [self disposeDecoder]; } #pragma mark - 编码器方法 - (BOOL)createEncoderWithSampleRate:(int)sampleRate channels:(int)channels application:(int)application complexity:(int)complexity frameSize:(int)frameSize { // 先释放已有资源 [self disposeEncoder]; int error = OPUS_OK; OpusEncoder *encoder = opus_encoder_create(sampleRate, channels, application, &error); if (error != OPUS_OK || encoder == NULL) { NSLog(@"[OpusBridge] Failed to create encoder: %s", opus_strerror(error)); return NO; } // 设置编码器参数 opus_encoder_ctl(encoder, OPUS_SET_COMPLEXITY(complexity)); // 创建封装结构 _encoderWrapper = malloc(sizeof(OpusEncoderWrapper)); _encoderWrapper->encoder = encoder; _encoderWrapper->channels = channels; _encoderWrapper->sampleRate = sampleRate; _encoderWrapper->frameSize = frameSize; NSLog(@"[OpusBridge] Encoder created: sampleRate=%d, channels=%d", sampleRate, channels); return YES; } - (NSData *)encodePCMData:(NSData *)pcmData { if (_encoderWrapper == NULL || _encoderWrapper->encoder == NULL) { NSLog(@"[OpusBridge] Encoder not initialized"); return nil; } // 检查PCM数据大小是否匹配 int frameSize = _encoderWrapper->frameSize; int channels = _encoderWrapper->channels; // PCM数据大小 = 帧大小 * 声道数 * 每样本字节数(2字节) int frameBytes = frameSize * channels * 2; if (pcmData.length < frameBytes) { NSLog(@"[OpusBridge] PCM data too small: %lu bytes (need %d bytes)", (unsigned long)pcmData.length, frameBytes); return nil; } // 创建输出缓冲区 - 通常编码后的数据会小于PCM,可以用更小的缓冲区 // 但这里保守起见,使用相同大小的缓冲区 const int maxEncodedSize = (int)pcmData.length; unsigned char *encodedData = malloc(maxEncodedSize); // 编码 int encodedBytes = opus_encode( _encoderWrapper->encoder, (const opus_int16 *)[pcmData bytes], frameSize, encodedData, maxEncodedSize ); if (encodedBytes <= 0) { NSLog(@"[OpusBridge] Encoding failed: %s", opus_strerror(encodedBytes)); free(encodedData); return nil; } // 封装为NSData并返回 NSData *result = [NSData dataWithBytes:encodedData length:encodedBytes]; free(encodedData); NSLog(@"[OpusBridge] Encoded %d bytes", encodedBytes); return result; } - (void)disposeEncoder { if (_encoderWrapper) { if (_encoderWrapper->encoder) { opus_encoder_destroy(_encoderWrapper->encoder); _encoderWrapper->encoder = NULL; } free(_encoderWrapper); _encoderWrapper = NULL; NSLog(@"[OpusBridge] Encoder disposed"); } } #pragma mark - 解码器方法 - (BOOL)createDecoderWithSampleRate:(int)sampleRate channels:(int)channels { // 先释放已有资源 [self disposeDecoder]; int error = OPUS_OK; OpusDecoder *decoder = opus_decoder_create(sampleRate, channels, &error); if (error != OPUS_OK || decoder == NULL) { NSLog(@"[OpusBridge] Failed to create decoder: %s", opus_strerror(error)); return NO; } // 创建封装结构 _decoderWrapper = malloc(sizeof(OpusDecoderWrapper)); _decoderWrapper->decoder = decoder; _decoderWrapper->channels = channels; _decoderWrapper->sampleRate = sampleRate; NSLog(@"[OpusBridge] Decoder created: sampleRate=%d, channels=%d", sampleRate, channels); return YES; } - (NSData *)decodeOpusData:(NSData *)opusData frameSize:(int)frameSize { if (_decoderWrapper == NULL || _decoderWrapper->decoder == NULL) { NSLog(@"[OpusBridge] Decoder not initialized"); return nil; } // 准备输出缓冲区,frameSize * channels 个short类型 int outputSizeInSamples = frameSize * _decoderWrapper->channels; int outputSizeInBytes = outputSizeInSamples * sizeof(opus_int16); opus_int16 *outputBuffer = malloc(outputSizeInBytes); // 解码 int samplesPerChannel = opus_decode( _decoderWrapper->decoder, [opusData bytes], (int)[opusData length], outputBuffer, frameSize, 0 // 不使用FEC ); if (samplesPerChannel <= 0) { NSLog(@"[OpusBridge] Decoding failed: %s", opus_strerror(samplesPerChannel)); free(outputBuffer); return nil; } // 实际输出大小 int actualSamples = samplesPerChannel * _decoderWrapper->channels; int actualBytes = actualSamples * sizeof(opus_int16); // 封装为NSData并返回 NSData *result = [NSData dataWithBytes:outputBuffer length:actualBytes]; free(outputBuffer); NSLog(@"[OpusBridge] Decoded %d samples per channel", samplesPerChannel); return result; } - (void)disposeDecoder { if (_decoderWrapper) { if (_decoderWrapper->decoder) { opus_decoder_destroy(_decoderWrapper->decoder); _decoderWrapper->decoder = NULL; } free(_decoderWrapper); _decoderWrapper = NULL; NSLog(@"[OpusBridge] Decoder disposed"); } } @end