iOS 将音频采样率从 16 kHz 转换为 8 kHz
Posted
技术标签:
【中文标题】iOS 将音频采样率从 16 kHz 转换为 8 kHz【英文标题】:iOS convert audio sample rate from 16 kHz to 8 kHz 【发布时间】:2017-03-23 09:41:44 【问题描述】:我尝试将 PCM 音频从 16kHz 转换为 8kHz,只是采样率,没有格式更改,流程看起来很简单,但我一直通过调用 AudioConverterFillComplexBuffer
得到 kAudioConverterErr_InvalidInputSize
("insz")。我的输入音频样本大小是 320 字节,结果应该是 160 字节,但我的输出缓冲区中只有 144 字节。在过去的几个小时里一直在拉我的头发。是不是设置错了?
static AudioConverterRef PCM8kTo16kConverterRef;
- (instancetype)init
self = [super init];
if (self)
[self initConverter];
return self;
-(void)initConverter
AudiostreamBasicDescription PCM8kDescription = 0;
PCM8kDescription.mSampleRate = 8000.0;
PCM8kDescription.mFormatID = kAudioFormatLinearPCM;
PCM8kDescription.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked | kAudioFormatFlagsNativeEndian;
PCM8kDescription.mBitsPerChannel = 8 * sizeof(SInt16);
PCM8kDescription.mChannelsPerFrame = 1;
PCM8kDescription.mBytesPerFrame = sizeof(SInt16) * PCM8kDescription.mChannelsPerFrame;
PCM8kDescription.mFramesPerPacket = 1;
PCM8kDescription.mBytesPerPacket = PCM8kDescription.mBytesPerFrame * PCM8kDescription.mFramesPerPacket;
AudioStreamBasicDescription PCM16kDescription = 0;
PCM16kDescription.mSampleRate = 16000.0;
PCM16kDescription.mFormatID = kAudioFormatLinearPCM;
PCM16kDescription.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked | kAudioFormatFlagsNativeEndian;
PCM16kDescription.mBitsPerChannel = 8 * sizeof(SInt16);
PCM16kDescription.mChannelsPerFrame = 1;
PCM16kDescription.mBytesPerFrame = sizeof(SInt16) * PCM16kDescription.mChannelsPerFrame;
PCM16kDescription.mFramesPerPacket = 1;
PCM16kDescription.mBytesPerPacket = PCM16kDescription.mBytesPerFrame * PCM16kDescription.mFramesPerPacket;
OSStatus status = AudioConverterNew(&PCM16kDescription, &PCM8kDescription, &converterRef);
OSStatus inInputDataProc(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void *inUserData)
AudioBufferList audioBufferList = *(AudioBufferList *)inUserData;
ioData->mBuffers[0].mData = audioBufferList.mBuffers[0].mData;
ioData->mBuffers[0].mDataByteSize = audioBufferList.mBuffers[0].mDataByteSize;
return noErr;
- (NSData *)testSample:(NSData *)inAudio
NSMutableData *ddd = [inAudio mutableCopy];
AudioBufferList inAudioBufferList = 0;
inAudioBufferList.mNumberBuffers = 1;
inAudioBufferList.mBuffers[0].mNumberChannels = 1;
inAudioBufferList.mBuffers[0].mDataByteSize = (UInt32)[ddd length];
inAudioBufferList.mBuffers[0].mData = [ddd mutableBytes];
uint32_t bufferSize = (UInt32)[inAudio length] / 2;
uint8_t *buffer = (uint8_t *)malloc(bufferSize);
memset(buffer, 0, bufferSize);
AudioBufferList outAudioBufferList;
outAudioBufferList.mNumberBuffers = 1;
outAudioBufferList.mBuffers[0].mNumberChannels = 1;
outAudioBufferList.mBuffers[0].mDataByteSize = bufferSize;
outAudioBufferList.mBuffers[0].mData = buffer;
UInt32 ioOutputDataPacketSize = bufferSize;
OSStatus ret = AudioConverterFillComplexBuffer(converterRef, inInputDataProc, &inAudioBufferList, &ioOutputDataPacketSize, &outAudioBufferList, NULL) ;
NSData *data = [NSData dataWithBytes:outAudioBufferList.mBuffers[0].mData length:outAudioBufferList.mBuffers[0].mDataByteSize];
free(buffer);
return data;
【问题讨论】:
【参考方案1】:有两个问题:
你的AudioConverterComplexInputDataProc
没有设置ioNumberDataPackets
:
*ioNumberDataPackets = audioBufferList.mBuffers[0].mDataByteSize/2;
ioOutputDataPacketSize
应该是 packets/frames 中的输出缓冲区容量,而不是字节,所以你不应该除以 2 吗?
【讨论】:
非常感谢!就是这样。没搞懂这些变量的正确含义,现在明白了XD再次感谢! 如何快速做到这一点?以上是关于iOS 将音频采样率从 16 kHz 转换为 8 kHz的主要内容,如果未能解决你的问题,请参考以下文章
如何将 8 kHz 音频采样率提高到 16 kHz STM32