How to resemple pcm data in iOS

436 views Asked by At

I want to use AudioConverterFillComplexBuffer to convert sample rate for a pcm buffer(32k to 44.1k)。But i didn't know why the voice seems changed(too many noise)。Here is the main code:

struct AudioFrame {
    int samples;  //number of samples in this frame.  e.g. 320
    int bytesPerSample;  //number of bytes per sample: 2 for PCM16.
    int channels;  //number of channels (data are interleaved if stereo)
    int samplesPerSec;  //sampling rate
    void* buffer;  //data buffer
};

-(void)convertAudioFrame:(AudioFrame *)buffer outPutData:(unsigned char **)outPutData outPutDataSize:(UInt32 *)outPutDataSize{
if (buffer->bytesPerSample != self.unitDescription.mBitsPerChannel ||
    buffer->channels != self.unitDescription.mChannelsPerFrame ||
    buffer->samplesPerSec != self.unitDescription.mSampleRate){
    // describe the input format's description
    AudioStreamBasicDescription inputDescription = {0};
    inputDescription.mFormatID = kAudioFormatLinearPCM;
    inputDescription.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger;
    inputDescription.mChannelsPerFrame = buffer->channels;
    inputDescription.mSampleRate = buffer->samplesPerSec;
    inputDescription.mBitsPerChannel = 16;
    inputDescription.mBytesPerFrame = (inputDescription.mBitsPerChannel/8) * inputDescription.mChannelsPerFrame;
    inputDescription.mFramesPerPacket = 1;
    inputDescription.mBytesPerPacket = inputDescription.mBytesPerFrame;

    AudioStreamBasicDescription outputDescription = {0};
    outputDescription.mSampleRate = 44100;
    outputDescription.mFormatID = kAudioFormatLinearPCM;
    outputDescription.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
    outputDescription.mChannelsPerFrame = 1;
    outputDescription.mFramesPerPacket = 1;
    outputDescription.mBitsPerChannel = 16;
    outputDescription.mBytesPerFrame = (outputDescription.mBitsPerChannel/8) * outputDescription.mChannelsPerFrame;
    outputDescription.mBytesPerPacket = outputDescription.mBytesPerFrame;

    // create an audio converter
    AudioConverterRef audioConverter;
    OSStatus status = AudioConverterNew(&inputDescription, &outputDescription, &audioConverter);
    [self checkError:status errorMsg:@"AudioConverterNew error"];
    if(!audioConverter)
    {
        *outPutDataSize = 0;
        return;
    }

    UInt32 outputBytes = outputDescription.mBytesPerPacket * (buffer->samples*buffer->bytesPerSample / inputDescription.mBytesPerPacket);
    unsigned char *outputBuffer = (unsigned char*)malloc(outputBytes);
    memset(outputBuffer, 0, outputBytes);

    AudioBuffer inputBuffer;
    inputBuffer.mNumberChannels = inputDescription.mChannelsPerFrame;
    inputBuffer.mDataByteSize = buffer->samples*buffer->bytesPerSample;
    inputBuffer.mData = buffer->buffer;

    AudioBufferList outputBufferList;
    outputBufferList.mNumberBuffers = 1;
    outputBufferList.mBuffers[0].mNumberChannels = outputDescription.mChannelsPerFrame;
    outputBufferList.mBuffers[0].mDataByteSize = outputBytes;
    outputBufferList.mBuffers[0].mData = outputBuffer;

    UInt32 outputDataPacketSize = outputBytes / outputDescription.mBytesPerPacket;

    self.currentBuffer = &inputBuffer;
    self.currentInputDescription = inputDescription;

    // convert
    OSStatus result = AudioConverterFillComplexBuffer(audioConverter,
        converterComplexInputDataProc,
        (__bridge void*)self,
        &outputDataPacketSize,
        &outputBufferList,
        NULL);
    [self checkError:result errorMsg:@"AudioConverterConvertBuffer error"];

    *outPutData = outputBuffer;
    *outPutDataSize = outputBytes;

    AudioConverterDispose(audioConverter);
    }
}

//convert callback

OSStatus converterComplexInputDataProc(AudioConverterRef inAudioConverter,
                                                            UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** ioDataPacketDescription, void* inUserData){
XMMicAudioManager *self = (__bridge XMMicAudioManager *)inUserData;

ioData->mNumberBuffers = 1;
ioData->mBuffers[0] = *(self.currentBuffer);

*ioNumberDataPackets = ioData->mBuffers[0].mDataByteSize / self.currentInputDescription.mBytesPerPacket;

return 0;
}
0

There are 0 answers