我目前正在构建一个应用程序,该应用程序可以从iPhone的麦克风读取音频,然后进行一些处理和视觉效果。当然,我首先从音频开始,但我有一个小问题。
我将采样率定义为 44100 Hz,并将缓冲区定义为容纳 4096 个样本。这是确实如此。但是,当我打印出这些数据并将其复制到 MATLAB 中以仔细检查准确性时,我必须使用的采样率是我 iPhone 定义速率的一半,即 22050 Hz,才能正确无误。
我认为这与以下代码以及它如何为每个数据包放置 2 个字节有关,当我循环遍历缓冲区时,缓冲区会吐出整个数据包,我的代码假设这是一个数字。所以我想知道的是如何拆分这些数据包并将它们作为单独的数字读取。
- (void)setupAudioFormat {
memset(&dataFormat, 0, sizeof(dataFormat));
dataFormat.mSampleRate = kSampleRate;
dataFormat.mFormatID = kAudioFormatLinearPCM;
dataFormat.mFramesPerPacket = 1;
dataFormat.mChannelsPerFrame = 1;
// dataFormat.mBytesPerFrame = 2;
// dataFormat.mBytesPerPacket = 2;
dataFormat.mBitsPerChannel = 16;
dataFormat.mReserved = 0;
dataFormat.mBytesPerPacket = dataFormat.mBytesPerFrame = (dataFormat.mBitsPerChannel / 8) * dataFormat.mChannelsPerFrame;
dataFormat.mFormatFlags =
kLinearPCMFormatFlagIsSignedInteger |
kLinearPCMFormatFlagIsPacked;
}
如果我描述的内容不清楚,请告诉我。谢谢!
编辑
添加我用于打印数据的代码
float *audioFloat = (float *)malloc(numBytes * sizeof(float));
int *temp = (int*)inBuffer->mAudioData;
int i;
float power = pow(2, 31);
for (i = 0;i<numBytes;i++) {
audioFloat[i] = temp[i]/power;
printf("%f ",audioFloat[i]);
}
我发现我正在做的事情有问题。这是一个 c 指针问题,由于我以前从未真正用 C 编程过,我当然弄错了。
您不能直接将 inBuffer->mAudioData 转换为 int 数组。所以我所做的只是以下内容
SInt16 *buffer = malloc(sizeof(SInt16)*kBufferByteSize);
buffer = inBuffer->mAudioData;
这很好,现在我的数据长度正确,数据正确表示。
我看到了你的答案,还有一个潜在的问题,它给出了错误的示例数据字节,这是因为字节被交换的字节序问题。
-(void)feedSamplesToEngine:(UInt32)audioDataBytesCapacity audioData:(void *)audioData { int sampleCount = audioDataBytesCapacity/sizeof(SAMPLE_TYPE);
SAMPLE_TYPE *samples = (SAMPLE_TYPE*)audioData;
//SAMPLE_TYPE *sample_le = (SAMPLE_TYPE *)malloc(sizeof(SAMPLE_TYPE)*sampleCount );//for swapping endians
std::string shorts;
double power = pow(2,10);
for(int i = 0; i < sampleCount; i++)
{
SAMPLE_TYPE sample_le = (0xff00 & (samples[i] << 8)) | (0x00ff & (samples[i] >> 8)) ; //Endianess issue
char dataInterim[30];
sprintf(dataInterim,"%f ", sample_le/power); // normalize it.
shorts.append(dataInterim);
}