Python AVAudioRecorder不';t写出正确的WAV文件头
我正在iPhone上做一个项目,我正在使用AVAudioRecorder从设备麦克风录制音频,然后将处理录音 为了确保正确读取文件中的样本,我使用python的wave模块查看它是否返回相同的样本 但是,当试图打开AVAudioRecorder保存的wav文件时,python的wave模块返回“fmt块和/或数据块丢失” 以下是我用来录制文件的设置:Python AVAudioRecorder不';t写出正确的WAV文件头,python,ios,avaudiorecorder,wave,Python,Ios,Avaudiorecorder,Wave,我正在iPhone上做一个项目,我正在使用AVAudioRecorder从设备麦克风录制音频,然后将处理录音 为了确保正确读取文件中的样本,我使用python的wave模块查看它是否返回相同的样本 但是,当试图打开AVAudioRecorder保存的wav文件时,python的wave模块返回“fmt块和/或数据块丢失” 以下是我用来录制文件的设置: [audioSettings setObject:[NSNumber numberWithInt:kAudioFormatLinearPCM] f
[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
解决了这个问题。。。我想AVAudioRecorder需要一个扩展来解决问题。苹果软件通常会在“fmt”
子chunk之后和“data”
子chunk之前创建非标准(但“spec”一致)的WAVE文件。我假设“FLLR”代表“filler”,我假设subchunk的目的是实现某种数据对齐优化。子块的长度通常约为4000字节,但其实际长度可能因其前面的数据长度而异
将任意子块添加到WAVE文件通常被认为符合规范,因为WAVE是的子集,RIFF文件处理中的常见做法是忽略具有无法识别标识符的块和子块。标识符“FLLR”是“非标准”的,因此任何遇到它的软件都应该忽略它
有相当多的软件对WAVE格式的处理比它应该的要严格得多,我怀疑您正在使用的库可能就是其中的一个软件。例如,我看到一个软件假设音频字节总是从偏移量44开始——这是一个错误的假设
事实上,查找WAVE文件中的音频字节必须通过查找RIFF中“data”
子块的位置和大小来完成;这是在WAVE文件中定位音频字节的正确方法
正确读取WAVE文件必须真正作为定位和识别RIFF子块的练习开始。RIFF子块有一个8字节的头:标识符/名称字段有4个字节,通常由人类可读的ASCII字符填充(例如,“fmt”
),以及一个4字节的小尾数无符号整数,指定子chunk数据有效负载中的字节数——子chunk的数据有效负载紧跟在其8字节头之后
WAVE文件格式保留对WAVE格式有意义的某些子chunk标识符(或“名称”)。每个WAVE文件中至少必须出现两个子块:
“fmt”
-具有此标识符的子单元有一个有效负载,用于描述音频格式的基本信息:采样率、位深度等“data”
-具有此标识符的子chunk在其有效负载中具有实际音频字节“事实”
是下一个最常见的子chunk标识符。它通常出现在使用压缩编解码器的WAVE文件中,如μ-law。有关当前在野外使用的各种子chunk标识符的更多信息,以及有关其有效负载结构的信息,请参见本文
从纯RIFF的角度来看,子块不需要在文件中以任何特定的顺序出现,也不需要以任何特定的固定偏移量出现。然而,实际上,几乎所有的软件都希望“fmt”
子模块是第一个子模块。这是对实用性的让步:在数据流的早期知道WAVE包含的音频格式很方便——例如,这使得从网络流播放WAVE文件更容易。如果WAVE文件使用压缩格式,如μ-law,则通常假定“事实”
子块将直接出现在“fmt”
之后
在指定块的格式已经过时之后,应该放弃关于子块的位置、顺序和命名的假设。此时,软件应仅按名称定位预期的子块(例如,“数据”
)。如果遇到名称无法识别的子块(例如,“FLLR”
),则应跳过并忽略这些子块。跳过子块需要读取其长度,以便跳过正确的字节数
苹果用“FLLR”
subchunk所做的事情有点不寻常,我对某些软件被它绊倒并不感到惊讶。我怀疑您正在使用的库根本没有准备好处理“FLLR”
子chunk的存在。我认为这是图书馆的一个缺点。图书馆作者所犯的错误可能是:
“data”
子chunk出现在文件开头的前N个字节内,其中N是小于~4kB的值。如果必须扫描文件太远,他们可能会放弃查找。苹果“FLLR”
子chunk将“数据”
子chunk推送到文件中约4kB的位置“data”
子块在RIFF中具有特定的顺序子块位置或字节偏移量。也许他们希望“数据”
在“fmt”之后立即出现