Core Audio AudioFIleReadPackets... 寻找原始音频
Posted
技术标签:
【中文标题】Core Audio AudioFIleReadPackets... 寻找原始音频【英文标题】:Core Audio AudioFIleReadPackets... looking for raw audio 【发布时间】:2011-04-14 00:29:13 【问题描述】:我正在尝试从文件中获取原始音频数据(我习惯于查看介于 -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;
我目前正在读取一个波形文件。
谢谢!
【问题讨论】:
【参考方案1】:我不确定你为什么要从这个回调中获取 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 范围内产生正确的浮点数据。
【讨论】:
所以我拿了 UInt32 并将低位拉到 1 个 SInt16 中,另一个拉到另一个 SInt16 中,看起来每个都很好地代表了 2 个独立的通道。我正在使用 Aran 的示例代码,该代码从 Michael Bolton 关于如何在 iphone 上使用 RemoteIO 音频单元的示例代码中编辑,看起来 Aran 只是将两个交错通道作为 UInt32 传递给 remoteIO 单元,因为他没有进行任何类型的计量/波形图。将 UInt32 分解为双 SInt16 后,看起来一切都应该是这样。 另外,数据不是必须是浮点数。我创建了一个波形绘图类,它期望数据处于浮动状态,它实际上是单独打开音频文件并使用 AudioFileRead() 函数将数据拉出(它是浮点数)。所以我的应用程序正在执行以下操作:完成录制后,通过打开录制的文件来绘制波形,读取每个 xth 样本并将其添加到数组中,循环遍历生成的数组并使用核心图形绘制波形。然后当用户按下播放时,它会初始化 AU。【参考方案2】:看看这个函数... 数据为 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]) ;
【讨论】:
以上是关于Core Audio AudioFIleReadPackets... 寻找原始音频的主要内容,如果未能解决你的问题,请参考以下文章
如何在 iPhone 的 Core Audio (Audio Unit/ Remote IO) 中将录制的声音更改为男人的声音