最近工作中涉及采集手機(jī)麥克風(fēng)的聲音并且播放出來(lái)搞糕,我先后試了兩種獲取麥克風(fēng)聲音的方案:
1.此方案是通過(guò)AVCaptureSession獲取的原始音頻流窍仰,這個(gè)回調(diào)返回的音頻數(shù)據(jù)
-(void)audioWithSampleBuffer:(CMSampleBufferRef)sampleBuffer {?
}
格式為CMSampleBufferRef,現(xiàn)在要從中提取pcm數(shù)據(jù)才能播放驹吮,方法如下:
-(NSData *)convertAudioSamepleBufferToPcmData:(CMSampleBufferRef)sampleBuffer {
? ? //獲取pcm數(shù)據(jù)大小
? ? size_t size = CMSampleBufferGetTotalSampleSize(sampleBuffer);
? ? //分配空間
? ? int8_t *audio_data = (int8_t *)malloc(size); memset(audio_data, 0, size);
? ? //獲取CMBlockBuffer, 這里面保存了PCM數(shù)據(jù)
? ? CMBlockBufferRef blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer);
? ? //將數(shù)據(jù)copy到我們分配的空間中
? ? CMBlockBufferCopyDataBytes(blockBuffer, 0, size, audio_data);
? ? NSData *data = [NSData dataWithBytes:audio_data length:size];
? ? free(audio_data);
? ? return data;
}
拿到這個(gè)data碟狞,就能直接播放了,此處參考了文章:https://blog.csdn.net/baidu_32469997/article/details/70017321
2.這個(gè)方案是通過(guò)AudioUnit獲取的原始音頻流族沃,AudioUnit不詳細(xì)介紹了近忙,以下介紹從AudioUnit獲取的原始數(shù)據(jù)中提取pcm:
首先AudioUnit有個(gè)錄音的回調(diào):
static OSStatus recordingCallback(void *inRefCon,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AudioUnitRenderActionFlags *ioActionFlags,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const AudioTimeStamp *inTimeStamp,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? UInt32 inBusNumber,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? UInt32 inNumberFrames,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AudioBufferList *ioData) {
// Because of the way our audio format (setup below) is chosen:
// we only need 1 buffer, since it is mono
// Samples are 16 bits = 2 bytes.
// 1 frame includes only 1 sample
AudioBuffer buffer;
buffer.mNumberChannels = 1;
buffer.mDataByteSize = inNumberFrames * 2;
buffer.mData = malloc( inNumberFrames * 2 );
// Put buffer in a AudioBufferList
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0] = buffer;
? ? // Then:
? ? // Obtain recorded samples
? ? OSStatus status;
? ? status = AudioUnitRender([ystAudio audioUnit], ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList);
checkStatus(status);
? ? // Now, we have the samples we just read sitting in buffers in bufferList
// Process the new data
? ? [ystAudio processAudio:&bufferList];
// release the malloc'ed data in the buffer we created earlier
free(bufferList.mBuffers[0].mData);
? ? return noErr;
}
拿到這個(gè)bufferList及舍,然后開(kāi)始轉(zhuǎn)換:
- (void) processAudio: (AudioBufferList*) bufferList{
AudioBuffer sourceBuffer = bufferList->mBuffers[0];
// fix tempBuffer size if it's the wrong size
if (tempBuffer.mDataByteSize != sourceBuffer.mDataByteSize) {
free(tempBuffer.mData);
tempBuffer.mDataByteSize = sourceBuffer.mDataByteSize;
tempBuffer.mData = malloc(sourceBuffer.mDataByteSize);
}
// copy incoming audio data to temporary buffer
memcpy(tempBuffer.mData, bufferList->mBuffers[0].mData, bufferList->mBuffers[0].mDataByteSize);
? ? NSData *data = [NSData dataWithBytes:sourceBuffer.mData length:bufferList->mBuffers[0].mDataByteSize];
}
這里的data拿到的就是pcm數(shù)據(jù)了