【问题标题】:AVAudioRecorder doesn't write out proper WAV File HeaderAVAudioRecorder 没有写出正确的 WAV 文件头
【发布时间】:2011-09-11 04:42:08
【问题描述】:

我正在 iPhone 上进行一个项目,我正在使用 AVAudioRecorder 从设备麦克风录制音频,然后将操纵录音。

为了确保我从文件中正确读取样本,我使用 python 的 wave 模块来查看它是否返回相同的样本。

但是,python 的 wave 模块在尝试打开 AVAudioRecorder 保存的 wav 文件时返回“fmt 块和/或数据块丢失”。

这些是我用来记录文件的设置:

[audioSettings setObject:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
[audioSettings setObject:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[audioSettings setObject:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
[audioSettings setObject:[NSNumber numberWithFloat:4096] forKey:AVSampleRateKey];
[audioSettings setObject:[NSNumber numberWithInt:1] forKey:AVNumberOfChannelsKey];
[audioSettings setObject:[NSNumber numberWithBool:YES] forKey:AVLinearPCMIsNonInterleaved];
[audioSettings setObject:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey]; 

之后,我只是调用 recordForDuration 来实际进行录制。

录制成功——我可以播放文件等,我可以使用 AudioFile 服务读取示例,但我无法验证它,因为我无法使用 Python 的 wave 模块打开文件。

这是文件的前 128 个字节的样子:

1215N:~/Downloads$ od -c --read-bytes 128 testFile.wav
0000000   R   I   F   F   x   H 001  \0   W   A   V   E   f   m   t    
0000020 020  \0  \0  \0 001  \0 001  \0   @ 037  \0  \0 200   >  \0  \0
0000040 002  \0 020  \0   F   L   L   R 314 017  \0  \0  \0  \0  \0  \0
0000060  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0000200

知道我需要做什么来确保 AVAudioRecorder 写出正确的 WAV 标头吗?

【问题讨论】:

  • 我遇到了类似的问题,我的应用程序中录制的 WAV 文件无法在 Windows 中播放。

标签: python ios avaudiorecorder wave


【解决方案1】:

Apple 软件通常会在 "fmt " 子块之后和 "data" 子块之前创建具有非标准(但符合“规范”)"FLLR" 子块的 WAVE 文件。我假设“FLLR”代表“填充”,并且我假设子块的目的是启用某种数据对齐优化。子块的长度通常约为 4000 字节,但其实际长度可能会根据其前面的数据长度而有所不同。

向 WAVE 文件添加任意子块通常被认为符合规范,因为 WAVE 是 RIFF 的子集,而 RIFF 文件处理中的常见做法是忽略具有无法识别标识符的块和子块。标识符"FLLR" 是“非标准的”,因此遇到它的任何软件都应该忽略它。

有相当多的软件对 WAVE 格式的处理比应有的严格得多,我怀疑您正在使用的库可能就是这些软件之一。例如,我见过假设音频字节总是从偏移量 44 开始的软件——这是一个不正确的假设。

事实上,在 WAVE 文件中查找音频字节必须通过查找 RIFF 中 "data" 子块的位置和大小来完成;这是在 WAVE 文件中定位音频字节的正确方法。

正确阅读 WAVE 文件必须真正从定位和识别 RIFF 子块的练习开始。 RIFF 子块有一个 8 字节的标头:4 字节用于标识符/名称字段,传统上用人类可读的 ASCII 字符(例如"fmt ")填充,以及一个 4 字节的小端无符号整数,用于指定其中的字节数子块的数据负载——子块的数据负载紧跟在它的 8 字节标头之后。

WAVE 文件格式保留某些对 WAVE 格式有意义的子块标识符(或“名称”)。每个 WAVE 文件中必须始终出现至少两个子块:

  1. "fmt " - 带有此标识符的子块有一个有效载荷,它描述了有关音频格式的基本信息:采样率、位深度等。
  2. "data" - 具有此标识符的子块在其有效负载中具有实际的音频字节

"fact" 是下一个最常见的子块标识符。它通常出现在使用压缩编解码器(例如 μ-law)的 WAVE 文件中。请参阅此enthusiast webpage,了解有关当今在野外使用的各种子块标识符的更多信息,以及有关其有效负载结构的信息。

从纯粹的 RIFF 角度来看,子块不需要以任何特定的顺序出现在文件中,也不需要以任何特定的固定偏移量出现。然而在实践中,几乎所有软件都期望"fmt " 子块是第一个子块。这是对实用性的让步:在数据流的早期就知道 WAVE 包含什么格式的音频很方便——例如,这使得从网络流中播放波形文件变得更加容易。如果 WAVE 文件使用压缩格式,例如 μ-law,通常假设"fact" 子块会直接出现在"fmt " 之后。

在指定格式的块不碍事后,应该放弃关于子块的位置、顺序和命名的假设。此时,软件应仅按名称定位预期的子块(例如"data")。如果遇到名称无法识别的子块(例如"FLLR"),则应简单地跳过并忽略这些子块。跳过一个子块需要读取它的长度,以便您可以跳过正确的字节数。

Apple 对"FLLR" 子块所做的事情有点不寻常,我对某些软件被它绊倒并不感到惊讶。我怀疑您使用的库根本没有准备好处理"FLLR" 子块的存在。我认为这是图书馆的一个缺陷。图书馆作者所犯的错误可能是这样的:

  1. 他们可能期望 "data" 子块出现在文件开头的前 N ​​个字节内,其中 N 小于 ~4kB。如果他们必须扫描太远的文件,他们可能会放弃查找。 Apple "FLLR" 子块将"data" 子块推送到文件中 >~4kB 的位置。

  2. 他们可能期望 "data" 子块在 RIFF 中具有特定的序号子块位置或字节偏移量。也许他们希望"data" 紧跟在"fmt " 之后。但是,这是处理 RIFF 文件的错误方法。不应假定"data" 子块的序号位置和/或偏移位置。

只要我们谈论正确的 WAVE 文件处理,我不妨提醒大家,音频字节(data 子块的有效负载)可能不会完全运行到文件末尾。允许在data 有效负载之后插入子块。一些程序使用它在文件末尾存储文本“评论”字段。如果您从 data 有效负载的开头一直到 EOF 盲目阅读,您可能会将一些元数据子块作为音频拉入,这在播放结束时听起来像是“点击”。您需要遵守 data 子块的长度字段,并在您消耗完整个数据负载后停止读取音频——当您点击 EOF 时不要停止。

【讨论】:

  • 这是一个很好的答案。也帮助了我,在我的 WAV 文件中找到了一个看似随机的 4044 字节长的 FLLR 块,其中填充了00 字节。谢谢!
  • fact 是一个完全有效的块,即使对于 WAVE_FORMAT_PCM(类型 1)也是如此。尽管该格式不是“必需的”,但大多数 MS 软件无论如何都会将它放在那里(甚至是 W2K soundrec.exe 等)。窒息它与FLLR 块(我想它可以对齐波形(作为文件,而不是裸音频cd PCM-流)相同的错误(没有正确找到块并读取它们的数据大小) cd-alignment 到 2048 年(想想游戏音乐,不是 16bps 41.1khz 音频-cd 格式),这是以前用 JUNK 块完成的)。
  • SoundForge 例如在文件末尾的数据块之后放置一个 72 字节的块。如果您没有正确评估数据块的大小,您会在音频部分的结尾听到咔哒声。
【解决方案2】:

您要录制到磁盘上的文件的名称是什么?我有一个类似的问题,只是通过在我的文件名末尾添加.wav 来解决它......我猜AVAudioRecorder 需要一个扩展来解决问题。

【讨论】:

  • 我正在添加 .wav 文件扩展名。这些文件在 iTunes 中正常播放,但我无法使用 wavread 库读取它们。
  • 另一件没有意义的事情是,在 16 位单通道、4096 采样频率下记录的 5 秒剪辑的文件大小为 84 KB。 IT 应该接近 40KB (4096*5*2)
  • 经过进一步检查——QuickTime 播放器显示文件以 8000hz 录制,而不是我指定的 4096。我猜iPhone模拟器不能在4096hz录制?
  • 刚尝试用IOS 4.3.2在iPhone4上录制,它仍然可以录制@ 8000 hz。
  • 您好抱歉以这种方式解释,我正在创建一个音频数据文件偏移量为 4096 的 wav 文件,有没有什么办法可以使用 avfoundation 将其设为 76 问题如下:stackoverflow.com/questions/51277675/…@ch3rryc0ke 建议请
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多