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

发布于 2024-09-30 05:22:26 字数 1894 浏览 0 评论 0原文

我正在尝试使用核心音频从 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

━╋う一瞬間旳綻放 2024-10-07 05:22:26

您正在分配一个无符号 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)

清秋悲枫 2024-10-07 05:22:26

你可以简化很多事情。我确信您可以让 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]);
}

You could simplify a lot of things. I'm sure you can let the API allocate the buffer for you.

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

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,

SInt16 *buffer = (SInt16 *)bufferList.mBuffers[0].mData;
for (UInt32 i=0; i< frameCount; i++) {
    NSLog (@"%d", buffer[i]);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文