我上篇文章有交大家如何編譯Opus庫
不多說直接貼代碼了
opusCodec.h
#import <Foundation/Foundation.h>
@interface opusCodec : NSObject
-(void)opusInit;
-(NSData*)encodePCMData:(NSData*)data;
-(NSData*)decodeOpusData:(NSData*)data;
-(void)destroy;
@end
opusCodec.m
#import "opusCodec.h"
#import "opus.h"
#define kDefaultSampleRate 8000
#define WB_FRAME_SIZE 320
@implementation opusCodec
{
OpusEncoder *enc;
OpusDecoder *dec;
unsigned char opus_data_encoder[40];
}
-(void)opusInit
{
int error;
enc = opus_encoder_create(kDefaultSampleRate, 1, OPUS_APPLICATION_VOIP, &error);//(采樣率,聲道數(shù),,)
dec = opus_decoder_create(kDefaultSampleRate, 1, &error);
opus_encoder_ctl(enc, OPUS_SET_BITRATE(kDefaultSampleRate));//比特率
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_AUTO));//OPUS_BANDWIDTH_NARROWBAND 寬帶窄帶
opus_encoder_ctl(enc, OPUS_SET_VBR(0));
opus_encoder_ctl(enc, OPUS_SET_VBR_CONSTRAINT(1));
opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(8));//錄制質(zhì)量 1-10
opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(0));
opus_encoder_ctl(enc, OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));//信號
}
- (NSData *)encode:(short *)pcmBuffer length:(NSInteger)lengthOfShorts
{
// NSLog(@"--->>lengthOfShorts = %ld size -= %lu",(long)lengthOfShorts,sizeof(short));
int frame_size = (int)lengthOfShorts / sizeof(short);//WB_FRAME_SIZE;
short input_frame[frame_size];
opus_int32 max_data_bytes = 2 * WB_FRAME_SIZE ;//隨便設(shè)大,此時為原始PCM大小
memcpy(input_frame, pcmBuffer, lengthOfShorts );//frame_size * sizeof(short)
int encodeBack = opus_encode(enc, input_frame, frame_size, opus_data_encoder, max_data_bytes);
// NSLog(@"encodeBack===%d",encodeBack);
if (encodeBack > 0)
{
NSData *decodedData = [NSData dataWithBytes:opus_data_encoder length:encodeBack];
return decodedData;
}
else
{
return nil;
}
}
//int decode(unsigned char* in_data, int len, short* out_data, int* out_len) {
-(int)decode:(unsigned char *)encodedBytes length:(int)lengthOfBytes output:(short *)decoded
{
int frame_size = WB_FRAME_SIZE;
unsigned char cbits[frame_size*2];
memcpy(cbits, encodedBytes, lengthOfBytes);
int pcm_num = opus_decode(dec, cbits, lengthOfBytes, decoded, frame_size, 0);
// NSLog(@"解壓后長度=%d",pcm_num);
return frame_size;
}
-(NSData *)encodePCMData:(NSData*)data
{
// NSLog(@"原始數(shù)據(jù)長度--->>%lu",(unsigned long)data.length);
return [self encode:(short *)[data bytes] length:[data length]];
}
-(NSData *)decodeOpusData:(NSData*)data
{
int len = (int)[data length];
Byte *byteData = (Byte*)malloc(len);
memcpy(byteData, [data bytes], len);
int frame_size = WB_FRAME_SIZE;
short decodedBuffer[frame_size ];
int nDecodedByte = sizeof(short) * [self decode:byteData length:len output:decodedBuffer];
NSData *PCMData = [NSData dataWithBytes:(Byte *)decodedBuffer length:nDecodedByte];
return PCMData;
}
-(void)destroy
{
opus_encoder_destroy(enc);
opus_decoder_destroy(dec);
}
@end
使用方法
首先 使用audioqueue 來錄制音頻數(shù)據(jù) 生成NSdata 類型的數(shù)據(jù)流
注意:使用audioqueue錄制音頻的大小最好設(shè)置為320
然后使用我上面的方法 opusInit 初始化 opus 編碼器使用-(NSData)encodePCMData:(NSData)data;
編碼數(shù)據(jù)流
然后通過socket 上傳服務(wù)器 通過服務(wù)器分發(fā)到手機(jī)上手機(jī)收到服務(wù)器分發(fā)的數(shù)據(jù)使用
-(NSData)decodeOpusData:(NSData)data;
解碼數(shù)據(jù)流
得到 可以播放的音頻數(shù)據(jù)流
然后使用audio queue 來播放使用完以后記得使用-(void)destroy 來銷毀