2 Replies
      Latest reply on Oct 31, 2019 12:57 AM by workhardupc1
      michael.wang Level 1 Level 1 (0 points)

        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:@"AudioConverterFillComplexBuffer error"];
        
        
            *outPutData = outputBuffer;
        
            *outPutDataSize = outputBytes;
        
        
            AudioConverterDispose(audioConverter);
        
            }
        
        }
        
        
        
        OSStatus converterComplexInputDataProc(AudioConverterRef inAudioConverter,
        
                                                                        UInt32* ioNumberDataPackets,
        
                                                                        AudioBufferList* ioData,
        
                                                                        AudioStreamPacketDescription** ioDataPacketDescription,
        
                                                                        void* inUserData)
        
        {
        
        
            XMMicAudioManager *self = (XMMicAudioManager *)inUserData;
        
            ioData->mNumberBuffers = 1;
        
            ioData->mBuffers[0] = *(self.currentBuffer);
        
            *ioNumberDataPackets = ioData->mBuffers[0].mDataByteSize / self.currentInputDescription.mBytesPerPacket;
        
            return 0;
        
        }