使用Core Audio从PCM原始数据获取级别值

时间:2010-10-30 04:49:27

标签: iphone c core-audio

我正在尝试使用核心音频从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 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]);
    }

}

不确定我做错了什么,我认为这与读取字节数组有关。对不起,长代码发布......

2 个答案:

答案 0 :(得分:1)

你分配一个无符号8位整数的缓冲区,然后将其地址转换为无符号的16位int。 KA-吊杆。

你想要在for循环中做的是将bufferList.mBuffers [0] .mData转换为SInt16 *,然后通过迭代来打印出你的值。

根本不需要缓冲区var。 (为此)

答案 1 :(得分:0)

你可以简化很多事情。我相信你可以让API为你分配缓冲区。

bufferList.mBuffers[0].mData = nil;
bufferList.mBuffers[0].mDataByteSize = 0;

此外,您应该在读取调用后使用bufferList中的值,而不是假设它们与您传入的值相同。所以在您阅读之后,

SInt16 *buffer = (SInt16 *)bufferList.mBuffers[0].mData;
for (UInt32 i=0; i< frameCount; i++) {
    NSLog (@"%d", buffer[i]);
}