ch3*_*0ke 10 python avaudiorecorder wave ios
我正在开发iPhone上的一个项目,我正在使用AVAudioRecorder从设备麦克风录制音频,然后将操作录制.
为了确保我正确地读取文件中的样本,我使用python的波形模块来查看它是否返回相同的样本.
但是,当尝试打开由AVAudioRecorder保存的wav文件时,python的wave模块返回"fmt chunk和/或data chunk missing".
这些是我用来记录文件的设置:
[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];
Run Code Online (Sandbox Code Playgroud)
之后,我只是打电话给recordForDuration来实际录音.
录音成功 - 我可以播放文件等,我可以使用AudioFile服务读取示例,但我无法验证它,因为我无法使用Python的波形模块打开文件.
这是文件的前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
Run Code Online (Sandbox Code Playgroud)
知道我需要做些什么才能确保AVAudioRecorder写出正确的WAV标头?
Mik*_*ark 34
Apple软件经常"FLLR"
在"fmt "
子块之后和子块之前创建具有非标准(但"规范"符合)子块的WAVE文件"data"
.我假设"FLLR"代表"填充",我假设子块的目的是启用某种数据对齐优化.子块通常长约4000字节,但其实际长度可根据其前面的数据长度而变化.
将任意子块添加到WAVE文件通常被认为是符合规范的,因为WAVE是RIFF的子集,并且RIFF文件处理中的常见做法是忽略具有无法识别的标识符的块和子块.标识符"FLLR"
是"非标准的",因此任何遇到它的软件都应该忽略它.
有相当数量的软件可以比它应该更严格地处理WAVE格式,我怀疑你使用的库可能是那些软件之一.例如,我见过软件假定音频字节总是从偏移44开始 - 这是一个不正确的假设.
实际上,在WAVE文件中查找音频字节必须通过查找"data"
RIFF中子块的位置和大小来完成; 这是在WAVE文件中定位音频字节的正确方法.
正确读取WAVE文件必须真正开始作为定位和识别RIFF子块的练习.RIFF子块有一个8字节的头:4个字节用于标识符/名称字段,传统上填充有人类可读的ASCII字符(例如"fmt "
),以及4字节的小端无符号整数,用于指定子块数据中的字节数payload - 子块的数据有效负载紧跟在其8字节头之后.
WAVE文件格式保留某些子块标识符(或"名称")对WAVE格式有意义.每个WAVE文件中必须始终显示至少两个子块:
"fmt "
- 具有此标识符的子块具有有效负载,该有效负载描述有关音频格式的基本信息:采样率,位深度等. "data"
- 具有此标识符的子块在其有效负载中具有实际的音频字节"fact"
是下一个最常见的子块标识符.它通常在使用压缩编解码器的WAVE文件中找到,例如μ-law.有关当前在野外使用的各种子块标识符的更多信息,以及有关其有效负载结构的信息,请参阅此发烧友网页.
从纯粹的RIFF角度来看,子块不需要以任何特定顺序出现在文件中,也不需要出现在任何特定的固定偏移处.然而,在实践中,几乎所有软件都希望"fmt "
子块是第一个子块.这是对实用性的让步:在数据流中尽早了解WAVE包含的音频格式是很方便的 - 例如,这使得从网络流播放波形文件变得更加容易.如果WAVE文件使用压缩格式,例如μ-law,则通常假设"fact"
子块将直接出现在"fmt "
.
在格式指定块不在之后,应该放弃关于子块的位置,排序和命名的假设.此时,软件应仅按名称定位预期的子块(例如"data"
).如果遇到具有无法识别名称的"FLLR"
子块(例如),则应简单地跳过并忽略这些子块.跳过子块需要读取其长度,以便您可以跳过正确的字节数.
苹果公司在这个"FLLR"
子组件上所做的事情有点不同寻常,我对一些软件被它绊倒并不感到惊讶.我怀疑你使用的库只是没有准备好处理"FLLR"
子块的存在.我认为这是库中的缺陷.图书馆作者犯的错误可能是这样的:
他们可能期望"data"
子块出现在文件开头的前N个字节内,其中N小于~4kB.他们可能会放弃查看是否必须扫描到文件太远.Apple "FLLR"
子块将"data"
子块推送到文件中大约4kB的位置.
他们可能期望"data"
子块在RIFF内具有特定的序数子块位置或字节偏移.也许他们希望"data"
紧接着出现"fmt "
.但是,这是处理RIFF文件的错误方法."data"
不应假设子块的顺序位置和/或偏移位置.
只要我们谈论正确的WAVE文件处理,我不妨提醒大家音频字节(data
子块的有效负载)可能无法正好运行到文件的末尾.允许在有效负载之后插入子块data
.有些程序使用它来在文件末尾存储文本"注释"字段.如果你从data
有效载荷的开头盲目读取直到EOF,你可以将一些元数据子块作为音频引入,这听起来像是在回放结束时的"点击".您需要遵守data
子块的长度字段,并在消耗完整个数据有效负载后停止读取音频 - 而不是在您按下EOF时停止.
归档时间: |
|
查看次数: |
6805 次 |
最近记录: |