使用 Core Audio 从 PCM 原始数据中获取电平值

Posted

技术标签:

【中文标题】使用 Core Audio 从 PCM 原始数据中获取电平值【英文标题】:Getting level values from PCM raw data using Core Audio 【发布时间】:2010-10-30 04:49:27 【问题描述】:

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


不知道我做错了什么,我认为这与读取字节数组有关。抱歉,代码太长了...

【问题讨论】:

我发现了这个:***.com/questions/3833356/… 但我仍然看不出我做错了什么。 我还应该补充一点,track.location 是一个带有 pcm caf 文件的 NSURL,BUFFER_SIZE = ((4096 * 4) * 8) 应该是 32K。 【参考方案1】:

您正在分配一个无符号 8 位整数的缓冲区,然后将其地址转换为一个无符号 16 位整数。轰隆隆。

您想要在 for 循环中执行的操作是将 bufferList.mBuffers[0].mData 转换为 SInt16 *,然后通过它进行迭代以打印出您的值。

您根本不需要缓冲区变量。 (为此)

【讨论】:

【参考方案2】:

你可以简化很多事情。我确定您可以让 API 为您分配缓冲区。

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

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

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

【讨论】:

以上是关于使用 Core Audio 从 PCM 原始数据中获取电平值的主要内容,如果未能解决你的问题,请参考以下文章

Core Audio AudioFIleReadPackets... 寻找原始音频

Core Audio 大(压缩)文件播放和内存占用

Android 音频采集——MediaRecord(编码后录影文件) AudioRecord(PCM原始数据)

Core Audio 指定要解码的音轨

Core Audio:用于提升信号电平的音频单元

使用 Android SDK 从原始 PCM 数据创建 WAV 文件