Sti*_*Sti 5 audio objective-c core-audio avfoundation ios
我正在尝试为我的应用程序制作一个音量计,它将在录制视频时显示。我在 iOS 上发现了很多对此类仪表的支持,但主要是支持AVAudioPlayer,这对我来说是没有选择的。我正在使用AVCaptureSession来记录,然后将得到如下所示的委托方法:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer);
CFRetain(sampleBuffer);
CFRetain(formatDescription);
if(connection == audioConnection)
{
CMBlockBufferRef blockBuffer;
AudioBufferList audioBufferList;
CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer,
NULL, &audioBufferList, sizeof(AudioBufferList), NULL, NULL,
kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
&blockBuffer);
SInt16 *data = audioBufferList.mBuffers[0].mData;
}
//Releases etc..
}
Run Code Online (Sandbox Code Playgroud)
(只显示相关代码)
据我所知,我收到一个“样本缓冲区”,其中包含音频或视频。一旦我确认连接确实是音频,然后我从缓冲区“提取”audioBufferList,然后我坐在这儿留下一个(或多个?)audioBuffers 的列表。据我了解,实际数据表示为SInt16,或“16 位有符号整数”,据我了解,范围从-32,768到32,767。但是,如果我简单地打印出这个接收到的值,我会得到很多反弹的数字。当处于“沉默”状态时,我得到的值在-200和之间快速反弹200,当有噪音时,我得到的值从-4,000到13,000完全乱序。正如我从阅读中了解到的,价值0将代表沉默。但是,我不明白负值和正值之间的区别,也不知道它们是否能够一直向上/向下到达+-32,768.
我相信我需要一定比例的“响亮”,但一直找不到任何东西。
我已经阅读了一些关于此事的教程和参考资料,但对我来说没有任何意义。我按照一个指南执行此操作(附加到上面的代码,在 中if):
float accumulator = 0;
for(int i = 0; i < audioBufferList.mBuffers[0].mDataByteSize; i++)
accumulator += data[i] * data[i];
float power = accumulator / audioBufferList.mBuffers[0].mDataByteSize;
float decibels = log10f(power);
NSLog(@"%f", decibels);
Run Code Online (Sandbox Code Playgroud)
显然,这段代码应该从-1to对齐+1,但这并没有发生。我现在6.194681在沉默和7.773492一些噪音时获得价值。这感觉像是正确的“范围”,但在“错误的地方”。我不能简单地从数字中减去 7 并假设我在-1和之间+1。这应该如何工作背后应该有一些逻辑和科学,但我对数字音频的工作原理知之甚少。
有谁知道这背后的逻辑?0总是沉默而-32,768和32,767有大声喧哗?然后我可以简单地将所有负值乘以-1总是得到正值,然后找出它们的百分比(在 0 和 32767 之间)吗?不知何故,我不相信这会起作用,因为我想负值是有原因的..我不完全确定要尝试什么。
您问题中的代码在多个方面都是错误的。此代码尝试复制下面文章中的代码,但您没有正确处理从文章中基于浮点的代码转换为 16 位整数数学的情况。您还会循环使用错误数量的值(max i),最终会提取垃圾数据。所以这是完全错误的。
https://www.mikeash.com/pyblog/friday-qa-2012-10-12-obtaining-and-interpreting-audio-data.html
文章中的代码是正确的。这就是它的内容,稍微扩展了一下。这仅查看 32 位浮点缓冲区列表中的第一个缓冲区。
float accumulator = 0;
AudioBuffer buffer = bufferList->mBuffers[0];
float * data = (float *)buffer.mData;
UInt32 numSamples = buffer.mDataByteSize / sizeof(float);
for (UInt32 i = 0; i < numSamples; i++) {
accumulator += data[i] * data[i];
}
float power = accumulator / (float)numSamples;
float decibels = 10 * log10f(power);
Run Code Online (Sandbox Code Playgroud)
正如文章所说,这里的结果是使用 0dB 参考的分贝。例如,0.0 是最大值。例如,这与 AVAudioPlayer 的averagePowerForChannel 返回的内容相同。
要在 16 位整数上下文中使用它,您需要 a) 适当地循环每个 16 位样本,b) 将 data[i] 值从 16 位整数转换为 [ 中的浮点值-1.0, 1.0] 平方并添加到累加器之前的范围。
| 归档时间: |
|
| 查看次数: |
1257 次 |
| 最近记录: |