我写了一个使用" novocaine"用于录制和播放声音的库。我将采样率设置为8kHz。此采样率在音频单元的AudioStreamBasicDescription中以novocaine设置,并作为音频会话属性kAudioSessionProperty_PreferredHardwareSampleRate设置。我知道设置首选硬件采样率并不能保证实际硬件采样率会有所改变,但它适用于除iPhone6和iPhone6s +以外的所有设备(当路由更改为扬声器时)。使用iPhone6s(+)和扬声器路由,我可以从麦克风接收48kHz的声音。所以我需要以某种方式将这48 kHz声音转换为8kHz。在文档中,我发现AudioConverterRef可以在这种情况下使用,但我在使用它时遇到了麻烦。
我使用AudioConverterFillComplexBuffer进行采样率转换,但它总是返回-50 OSStatus(传递给函数的一个或多个参数无效)。这就是我使用音频转换器的方式:
// Setup AudioStreamBasicDescription for input
inputFormat.mSampleRate = 48000.0;
inputFormat.mFormatID = kAudioFormatLinearPCM;
inputFormat.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
inputFormat.mChannelsPerFrame = 1;
inputFormat.mBitsPerChannel = 8 * sizeof(float);
inputFormat.mFramesPerPacket = 1;
inputFormat.mBytesPerFrame = sizeof(float) * inputFormat.mChannelsPerFrame;
inputFormat.mBytesPerPacket = inputFormat.mBytesPerFrame * inputFormat.mFramesPerPacket;
// Setup AudioStreamBasicDescription for output
outputFormat.mSampleRate = 8000.0;
outputFormat.mFormatID = kAudioFormatLinearPCM;
outputFormat.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
outputFormat.mChannelsPerFrame = 1;
outputFormat.mBitsPerChannel = 8 * sizeof(float);
outputFormat.mFramesPerPacket = 1;
outputFormat.mBytesPerFrame = sizeof(float) * outputFormat.mChannelsPerFrame;
outputFormat.mBytesPerPacket = outputFormat.mBytesPerFrame * outputFormat.mFramesPerPacket;
// Create new instance of audio converter
AudioConverterNew(&inputFormat, &outputFormat, &converter);
// Set conversion quality
UInt32 tmp = kAudioConverterQuality_Medium;
AudioConverterSetProperty( converter, kAudioConverterCodecQuality,
sizeof( tmp ), &tmp );
AudioConverterSetProperty( converter, kAudioConverterSampleRateConverterQuality, sizeof( tmp ), &tmp );
// Get the size of the IO buffer(s)
UInt32 bufferSizeFrames = 0;
size = sizeof(UInt32);
AudioUnitGetProperty(self.inputUnit,
kAudioDevicePropertyBufferFrameSize,
kAudioUnitScope_Global,
0,
&bufferSizeFrames,
&size);
UInt32 bufferSizeBytes = bufferSizeFrames * sizeof(Float32);
// Allocate an AudioBufferList plus enough space for array of AudioBuffers
UInt32 propsize = offsetof(AudioBufferList, mBuffers[0]) + (sizeof(AudioBuffer) * outputFormat.mChannelsPerFrame);
// Malloc buffer lists
convertedInputBuffer = (AudioBufferList *)malloc(propsize);
convertedInputBuffer->mNumberBuffers = 1;
// Pre-malloc buffers for AudioBufferLists
convertedInputBuffer->mBuffers[0].mNumberChannels = outputFormat.mChannelsPerFrame;
convertedInputBuffer->mBuffers[0].mDataByteSize = bufferSizeBytes;
convertedInputBuffer->mBuffers[0].mData = malloc(bufferSizeBytes);
memset(convertedInputBuffer->mBuffers[0].mData, 0, bufferSizeBytes);
// Setup callback for converter
static OSStatus inputProcPtr(AudioConverterRef inAudioConverter,
UInt32* ioNumberDataPackets,
AudioBufferList* ioData,
AudioStreamPacketDescription* __nullable* __nullable outDataPacketDescription,
void* __nullable inUserData)
{
// Read data from buffer
}
// Perform actual sample rate conversion
AudioConverterFillComplexBuffer(converter, inputProcPtr, NULL, &numberOfFrames, convertedInputBuffer, NULL)
从不调用inputProcPtr回调。我尝试设置不同数量的帧但仍然接收OSStatus -50。
1)使用AudioConverterRef是正确的方式进行采样率转换还是可以用不同的方式完成?
2)我的转换实施有什么问题?
提前谢谢大家
答案 0 :(得分:0)
一个问题是:
AudioUnitGetProperty(self.inputUnit,
kAudioDevicePropertyBufferFrameSize,
kAudioUnitScope_Global,
0,
&bufferSizeFrames,
&size);
kAudioDevicePropertyBufferFrameSize
是OSX属性,在iOS上不存在。这段代码甚至是如何编译的?
如果你以某种方式编译它,请检查此函数的返回码!我感觉它失败了,bufferSizeFrames
为零。这会使AudioConverterFillComplexBuffer
返回-50(kAudio_ParamError
)。
因此,在iOS上,您可以自己选择bufferSizeFrames
,也可以AVAudioSession
IOBufferDuration
UInt32 tmp = kAudioConverterQuality_Medium;
AudioConverterSetProperty( converter, kAudioConverterCodecQuality,
sizeof( tmp ), &tmp );
为基础。
另一个问题:检查您的退货代码。所有这些!
e.g。
kAudioConverterQuality_Medium
我很确定在LPCM-> LPCM转换中没有编解码器,并且kAudioConverterCodecQuality
在任何情况下都不适合与{{1}}一起使用。我不知道这个电话会怎样成功。