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

发布于 2024-09-19 12:38:51 字数 834 浏览 10 评论 0原文

我正在尝试从文件中获取原始音频数据(我习惯于看到 -1 和 1 之间的浮点值)。

我试图实时从缓冲区中提取这些数据,以便我可以为应用程序提供某种类型的计量。

我基本上是使用 AudioFileReadPackets 将整个文件读入内存。我创建了一个 RemoteIO 音频单元来进行播放,并且在playbackCallback 内部,我将 mData 提供给 AudioBuffer,以便可以将其发送到硬件。

我遇到的大问题是从我的数据数组(来自 AudioFileReadPackets)发送到缓冲区的数据是 UInt32 ...我真的很困惑。看起来它是 32 位的,我已将数据包/帧设置为每个 4 字节。我到底如何从中获取原始音频数据(从-1到1)?

这是我的格式描述

// Describe format
audioFormat.mSampleRate         = 44100.00;
audioFormat.mFormatID           = kAudioFormatLinearPCM;
audioFormat.mFormatFlags        = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormat.mFramesPerPacket    = 1;
audioFormat.mChannelsPerFrame   = 2;
audioFormat.mBitsPerChannel     = 16;
audioFormat.mBytesPerPacket     = 4;
audioFormat.mBytesPerFrame      = 4;

我当前正在读取波形文件。

谢谢!

I'm trying to get raw audio data from a file (i'm used to seeing floating point values between -1 and 1).

I'm trying to pull this data out of the buffers in real time so that I can provide some type of metering for the app.

I'm basically reading the whole file into memory using AudioFileReadPackets. I've create a RemoteIO audio unit to do playback and inside of the playbackCallback, i'm supplying the mData to the AudioBuffer so that it can be sent to hardware.

The big problem I'm having is that the data being sent to the buffers from my array of data (from AudioFileReadPackets) is UInt32... I'm really confused. It looks like it's 32-bits and I've set the packets/frames to be 4bytes each. How the heck to I get my raw audio data (from -1 to 1) out of this?

This is my Format description

// Describe format
audioFormat.mSampleRate         = 44100.00;
audioFormat.mFormatID           = kAudioFormatLinearPCM;
audioFormat.mFormatFlags        = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormat.mFramesPerPacket    = 1;
audioFormat.mChannelsPerFrame   = 2;
audioFormat.mBitsPerChannel     = 16;
audioFormat.mBytesPerPacket     = 4;
audioFormat.mBytesPerFrame      = 4;

I am reading a wave file currently.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(2

我乃一代侩神 2024-09-26 12:38:51

我不确定为什么您从这个回调中获取 UInt32 数据,但我怀疑它实际上是两个交错的 UInt16 数据包,每个通道一个。无论如何,如果您想要文件中的浮点数据,则需要对其进行转换,并且我不相信@John Ballinger 推荐的方式是正确的方式。我的建议是:

// Get buffer in render/read callback
SInt16 *frames = inBuffer->mAudioData;
for(int i = 0; i < inNumPackets; i++) {
  Float32 currentFrame = frames[i] / 32768.0f;
  // Do stuff with currentFrame (add it to your buffer, etc.)
}

您不能简单地将帧转换为您想要的格式。如果需要浮点数据,则需要除以 32768,这是 16 位样本的最大可能值。这将产生 {-1.0 .. 1.0} 范围内的正确浮点数据。

I'm not sure exactly why you are getting UInt32 data back from this callback, though I suspect that it is actually two interlaced UInt16 packets, one per each channel. Anyways, if you want floating point data from the file, it needs to be converted, and I'm not convinced that the way @John Ballinger recommends is the correct way. My suggestion would be:

// Get buffer in render/read callback
SInt16 *frames = inBuffer->mAudioData;
for(int i = 0; i < inNumPackets; i++) {
  Float32 currentFrame = frames[i] / 32768.0f;
  // Do stuff with currentFrame (add it to your buffer, etc.)
}

You can't simply cast the frames to the format you want. If you need floating point data, you will need to divide by 32768, which is the maximum possible value for 16-bit samples. This will yield correct floating point data in the {-1.0 .. 1.0} range.

路弥 2024-09-26 12:38:51

看看这个功能...
数据为 SInt16。

static void recordingCallback (
    void                                *inUserData,
    AudioQueueRef                       inAudioQueue,
    AudioQueueBufferRef                 inBuffer,
    const AudioTimeStamp                *inStartTime,
    UInt32                              inNumPackets,
    const AudioStreamPacketDescription  *inPacketDesc
) {


    // This callback, being outside the implementation block, needs a reference to the AudioRecorder object
    AudioRecorder *recorder = (AudioRecorder *) inUserData;

    // if there is audio data, write it to the file
    if (inNumPackets > 0) {

        SInt16 *frameBuffer = inBuffer->mAudioData;
        //NSLog(@"byte size %i, number of packets %i, starging packetnumber %i", inBuffer->mAudioDataByteSize, inNumPackets,recorder.startingPacketNumber);

        //int totalSlices = 1;
        //int framesPerSlice = inNumPackets/totalSlices;
        float total = 0;
        for (UInt32 frame=0; frame<inNumPackets; frame+=20) {
            total += (float)abs((SInt16)frameBuffer[frame]) ; 
        }

Have a look at this function...
The data is SInt16.

static void recordingCallback (
    void                                *inUserData,
    AudioQueueRef                       inAudioQueue,
    AudioQueueBufferRef                 inBuffer,
    const AudioTimeStamp                *inStartTime,
    UInt32                              inNumPackets,
    const AudioStreamPacketDescription  *inPacketDesc
) {


    // This callback, being outside the implementation block, needs a reference to the AudioRecorder object
    AudioRecorder *recorder = (AudioRecorder *) inUserData;

    // if there is audio data, write it to the file
    if (inNumPackets > 0) {

        SInt16 *frameBuffer = inBuffer->mAudioData;
        //NSLog(@"byte size %i, number of packets %i, starging packetnumber %i", inBuffer->mAudioDataByteSize, inNumPackets,recorder.startingPacketNumber);

        //int totalSlices = 1;
        //int framesPerSlice = inNumPackets/totalSlices;
        float total = 0;
        for (UInt32 frame=0; frame<inNumPackets; frame+=20) {
            total += (float)abs((SInt16)frameBuffer[frame]) ; 
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文