使用 Core Audio 从 PCM 原始数据获取电平值
我正在尝试使用核心音频从 PCM 音频文件中提取电平数据。我已经(我相信)将原始数据放入字节数组(UInt8)中,但它是 16 位 PCM 数据,我在读取数据时遇到问题。输入来自iPhone麦克风,我设置为:
[recordSetting setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt:1] forKey:AVNumberOfChannelsKey];
[recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
显然是16位。然后,我尝试打印出一些值,看看它们对于下面的调试目的是否合理,并且它们看起来不合理(许多 0)。
ExtAudioFileRef 输入文件 = NULL; ExtAudioFileOpenURL(track.location, &inputFile);
AudioStreamBasicDescription inputFileFormat;
UInt32 dataSize = (UInt32)sizeof(inputFileFormat);
ExtAudioFileGetProperty(inputFile, kExtAudioFileProperty_FileDataFormat, &dataSize, &inputFileFormat);
UInt8 *buffer = malloc(BUFFER_SIZE);
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mNumberChannels = 1;
bufferList.mBuffers[0].mData = buffer; //pointer to buffer of audio data
bufferList.mBuffers[0].mDataByteSize = BUFFER_SIZE; //number of bytes in the buffer
while(true) {
UInt32 frameCount = (bufferList.mBuffers[0].mDataByteSize / inputFileFormat.mBytesPerFrame);
// Read a chunk of input
OSStatus status = ExtAudioFileRead(inputFile, &frameCount, &bufferList);
// If no frames were returned, conversion is finished
if(0 == frameCount)
break;
NSLog(@"---");
int16_t *bufferl = &buffer;
for(int i=0;i<100;i++){
//const int16_t *bufferl = bufferl[i];
NSLog(@"%d",bufferl[i]);
}
}
不确定我做错了什么,我认为这与读取字节数组有关。抱歉,代码很长......
I am trying to extract level data from a PCM audio file using core audio. I have gotten as far as (I believe) getting the raw data into a byte array (UInt8) but it is 16 bit PCM data and I am having trouble reading the data out. The input is from the iPhone microphone, which I have set as:
[recordSetting setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
[recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
[recordSetting setValue:[NSNumber numberWithInt:1] forKey:AVNumberOfChannelsKey];
[recordSetting setValue:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
[recordSetting setValue:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];
which is obviously 16 bits. I am then trying to just print out a few values to see if they look reasonable for debug purposes below, and they do not look reasonable (many 0's).
ExtAudioFileRef inputFile = NULL;
ExtAudioFileOpenURL(track.location, &inputFile);
AudioStreamBasicDescription inputFileFormat;
UInt32 dataSize = (UInt32)sizeof(inputFileFormat);
ExtAudioFileGetProperty(inputFile, kExtAudioFileProperty_FileDataFormat, &dataSize, &inputFileFormat);
UInt8 *buffer = malloc(BUFFER_SIZE);
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
bufferList.mBuffers[0].mNumberChannels = 1;
bufferList.mBuffers[0].mData = buffer; //pointer to buffer of audio data
bufferList.mBuffers[0].mDataByteSize = BUFFER_SIZE; //number of bytes in the buffer
while(true) {
UInt32 frameCount = (bufferList.mBuffers[0].mDataByteSize / inputFileFormat.mBytesPerFrame);
// Read a chunk of input
OSStatus status = ExtAudioFileRead(inputFile, &frameCount, &bufferList);
// If no frames were returned, conversion is finished
if(0 == frameCount)
break;
NSLog(@"---");
int16_t *bufferl = &buffer;
for(int i=0;i<100;i++){
//const int16_t *bufferl = bufferl[i];
NSLog(@"%d",bufferl[i]);
}
}
Not sure what I am doing wrong, I think it has to do with reading the byte array. Sorry for the long code post...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您正在分配一个无符号 8 位整数的缓冲区,然后将其地址转换为无符号 16 位整数。咔嚓。
您想要在 for 循环中执行的操作是将 bufferList.mBuffers[0].mData 转换为 SInt16 *,然后迭代它以打印出您的值。
你根本不需要你的缓冲区变量。 (为了这)
youre allocating a buffer of unsigned 8 bit ints and then casting the address of that to an unsigned 16 bit int. ka-boom.
what you want to do in your for loop is cast bufferList.mBuffers[0].mData to a SInt16 *, and then iterate thru that to print out your values.
you dont need your buffer var at all. (for this)
你可以简化很多事情。我确信您可以让 API 为您分配缓冲区。
另外,您应该在读取调用后使用 bufferList 中的值,而不是假设它们与您传入的值相同。因此,在读取之后,
You could simplify a lot of things. I'm sure you can let the API allocate the buffer for you.
Also you should use the values in the bufferList after the read call instead of assuming they're the same ones you passed in. So after you read,