4

サウンドの録音と再生に「novocaine」ライブラリを使用する voip アプリを作成します。サンプルレートを 8kHz に設定しました。このサンプル レートは、オーディオ ユニットの AudioStreamBasicDescription の novocaine で、オーディオ セッション プロパティ kAudioSessionProperty_PreferredHardwareSampleRate として設定されます。優先ハードウェア サンプル レートを設定しても、実際のハードウェア サンプル レートが変更される保証はないことは理解していますが、iPhone6s および iPhone6s+ (ルートがスピーカーに変更された場合) を除くすべてのデバイスで機能しました。iPhone6s(+)とスピーカー経路でマイクから48kHzの音を受信。というわけで、この48kHzの音をどうにかして8kHzに変換する必要があります。ドキュメントでは、この場合に AudioConverterRef を使用できることがわかりましたが、使用に問題があります。

サンプル レートの変換に AudioConverterFillComplexBuffer を使用していますが、常に -50 OSStatus を返します (関数に渡された 1 つ以上のパラメーターが無効でした)。これは私がオーディオコンバーターを使用する方法です:

// 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) 変換の実装の何が問題になっていますか?

よろしくお願いします

4

1 に答える 1