2013-01-23 42 views
3

当我绕过speex编码/解码步骤时,原始音频输出是正确的。我想要的是从录音回放中捕获的整个缓冲区被编码,解码并发送回播放循环。在几个项目我不确定的是:Speex编码/解码导致嘶嘶声噪声(Objective-c)

  1. 什么大小来分配的enc_buffer和dec_buffer
  2. 在speex_bits_read_from(SpeexBits *位字符*字节,INT LEN)
  3. 指定什么长什么最大尺寸指定INT speex_bits_write(SpeexBits *位字符*字节,INT MAX_LEN)

这里是我的Speex编解码器的初始化:

#define SAMPLE_RATE 8000 
#define MAX_FRAMES 100 
#define FRAME_SIZE 160 

enc_state = speex_encoder_init(&speex_nb_mode); 
dec_state = speex_decoder_init(&speex_nb_mode); 

spx_int32_t tmp; 
tmp=5; 
speex_encoder_ctl(enc_state, SPEEX_SET_QUALITY, &tmp); 
tmp=1; 
speex_encoder_ctl(enc_state, SPEEX_SET_COMPLEXITY, &tmp); 

speex_encoder_ctl(enc_state, SPEEX_GET_FRAME_SIZE, &enc_frame_size); 
speex_decoder_ctl(dec_state, SPEEX_GET_FRAME_SIZE, &dec_frame_size); 

tmp = SAMPLE_RATE; 

speex_encoder_ctl(enc_state, SPEEX_SET_SAMPLING_RATE, &tmp); 
speex_decoder_ctl(dec_state, SPEEX_SET_SAMPLING_RATE, &tmp); 

speex_bits_init(&enc_bits); 
speex_bits_init(&dec_bits); 

//Unsure of this allocation size 
enc_buffer = (char*)malloc(sizeof(char)*enc_frame_size*MAX_FRAMES); 
dec_buffer = (spx_int16_t*)malloc(sizeof(spx_int16_t)*dec_frame_size*MAX_FRAMES); 

我的编码/解码方法:

-(char*)encodeAudioBuffer:(spx_int16_t*)audioBuffer withByteSize:(int)numberOfFrames andWriteSizeTo:(int*)inSize{ 
    speex_bits_reset(&enc_bits); 
    speex_encode_int(enc_state, audioBuffer, &enc_bits); 

    //Unsure of this third argument. 'numberOfFrames' is the stored number of input frames from my recording callback. 
    *inSize = speex_bits_write(&enc_bits, enc_buffer, numberOfFrames*enc_frame_size); 

    return enc_buffer; 
} 
-(spx_int16_t*)decodeSpeexBits:(char*)encodedAudio withEncodedSize:(int)encodedSize andDecodedSize:(int)decodedSize{ 

    //Unsure of this third argument. 'encodedSize' is the number written to *inSize in the encode method 
    speex_bits_read_from(&dec_bits, encodedAudio, encodedSize*dec_frame_size); 

    speex_decode_int(dec_state, &dec_bits, dec_buffer); 
    return dec_buffer; 
} 

而且他们被称为是这样的:

- (void)encodeBufferList:(AudioBufferList*)bufferList withNumberOfFrames:(int)numberOfFrames{ 
    AudioBuffer sourceBuffer = bufferList->mBuffers[0]; 
    int speexSize = 0; 
    char* encodedAudio = [speexCodec encodeAudioBuffer:(spx_int16_t*)sourceBuffer.mData withByteSize:numberOfFrames andWriteSizeTo:&speexSize]; 
    spx_int16_t* decodedAudio = [speexCodec decodeSpeexBits:encodedAudio withEncodedSize:speexSize andDecodedSize:sourceBuffer.mDataByteSize]; 
    memcpy(audioBuffer.mData, sourceBuffer.mData, numberOfFrames * sizeof(SInt32)); 
} 

其中 “bufferList” 是从我录制/播放回调返回。有人可以确认我正在填充缓冲区吗?我看到报道here类似的问题,但不能看到在我的代码我可以做一个错误:

static OSStatus recordingCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) 
{ 
    AudioBuffer buffer; 
    OSStatus status; 
    AudioStreamer *input = (__bridge AudioStreamer*) inRefCon; 

    buffer.mDataByteSize = inNumberFrames * sizeof(SInt16); 
    buffer.mNumberChannels = 1; 
    buffer.mData = malloc(inNumberFrames * sizeof(SInt16)); 

    AudioBufferList bufferList; 
    bufferList.mNumberBuffers = 1; 
    bufferList.mBuffers[0] = buffer; 

    status = AudioUnitRender([input rioAUInstance], ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList); 
    [input encodeBufferList:&bufferList withNumberOfFrames:inNumberFrames]; 
    return noErr; 
} 

static OSStatus playbackCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) 
{ 
    AudioStreamer* input = (__bridge AudioStreamer*)inRefCon; 
    UInt32 size = MIN(ioData->mBuffers[0].mDataByteSize, [input audioBuffer].mDataByteSize); 
    memcpy(ioData->mBuffers[0].mData, input.audioBuffer.mData, size); 
    return noErr; 
} 

通过编码/解码,因为它代表产生的噪声是一种颗粒感静态的嘶嘶声,但它不是完全随机的信息 - 当我吹进麦克风时,我可以在噪音背后听到它。

任何帮助把这个问题睡在床上将不胜感激。一旦我把所有东西都整理出来,我很可能最终会写博客,似乎很多人都遇到了设置此编解码器的各种小问题。

+0

现在这个工作吗?我面临同样的问题 – GauravSTomar

回答

1

所以这是一个编码/解码功能的问题,我需要在多个帧上调用speex_encode_int,因为它似乎一次只处理1帧,然后将它们写入编码缓冲区,如下所示:

-(char*)encodeAudioBuffer:(spx_int16_t*)audioBuffer withNumberOfFrames:(int)numberOfFrames andWriteSizeTo:(int*)inSize{ 
    speex_bits_reset(&enc_bits); 
    for(int i = 0; i < numberOfFrames; ++i){ 
     speex_encode_int(enc_state, audioBuffer+i, &enc_bits); 
    } 
    *inSize = speex_bits_write(&enc_bits, enc_buffer, numberOfFrames); 
    return enc_buffer; 
} 

同样地,对于解码,speex_bits_read_from编码的缓冲区,然后在整个dec_bits遍历每个帧,写入解码缓冲器

-(spx_int16_t*)decodeSpeexBits:(char*)encodedAudio withEncodedSize:(int)encodedSize andNumberOfFrames:(int)numberOfFrames{ 
    speex_bits_read_from(&dec_bits, encodedAudio, encodedSize); 
    for(int i = 0; i < numberOfFrames; ++i){ 
     speex_decode_int(dec_state, &dec_bits, dec_buffer+i); 
    } 
    return dec_buffer; 
} 

这仍然运行很慢,我。即使在配置speex库以使用定点计算而不是浮点计算之后,它仍然比我的音频循环运行得慢(导致新的不连续性)。任何导致如何让这个运行更快?

两个循环语句你传递音频缓冲,但考虑不采取帧大小的
0

for(int i = 0; i < numberOfFrames; ++i){ 
    speex_encode_int(enc_state, audioBuffer+i, &enc_bits); 
} 

,它应该是:

for(int i = 0; i < numberOfFrames; ++i){ 
    speex_encode_int(enc_state, audioBuffer + (i * enc_frame_size), &enc_bits); 
} 

希望帮助。