1、 AIFF Container概念:
1)AIFF是音频交换文件格式(Audio Interchange File Format)的英文缩写,是Apple公司开发的一种声音文件格式,是一种文件格式存储的数字音频(波形)的数据;
2)AIFF应用于个人电脑及其它电子音响设备以存储音乐数据;
3)AIFF支持ACE2、ACE8、MAC3和MAC6压缩,支持16位44.1kHz立体声;
4)AIFF是Apple苹果电脑上面的标准音频格式,属于QuickTime技术的一部分。
2、AIFF Container规范:
1)数据类型:
char、unsigned char;
short、unsigned short;
long、unsigned long;
extends:80位IEEE标准754浮点数(标准Apple数字环境[SANE]数据类型扩展)。
pstring:Pascal样式的字符串,一个字节计数后跟文本字节。 此数据类型中的总字节数应为偶数。可以在文本末尾添加填充字节以完成此操作。该填充字节不会反映在计数中。
ID:32位,在''(SP,0x20)到'~'(0x7E)范围内的四个可打印ASCII字符的串联。空格(0x20)不能在打印字符之前; 允许尾随空格。禁止控制字符。
OSType:32位。内部定义的由四个字符组成的串接。
文件字节顺序:大端模式,一些格式包含little-endian声音数据。
2)文件结构:
Audio IFF符合“EA IFF 85”标准。“EA IFF 85”文件由许多数据块组成。
块是“EA IFF 85”文件的组件,块由一些header information(ckID、ckSize)和data组成。
用C结构体表示为:
typedef struct {
ID ckID; /* chunk ID */
long ckSize; /* chunk Size */
char ckData[]; /* data */
} Chunk;
ckID描述数据块的数据部分的格式。程序可以通过检查ckID来确定如何解释块数据。
ckSize是块的数据部分的大小,以字节为单位。它不包括ckID和ckSize使用的8个字节。
ckData包含存储在块中的数据。此数据的格式由ckID决定。如果数据长度为奇数字节,则必须在末尾添加零填充字节。ckSize中不包含填充字节。
Audio IFF文件中的块在容器块中组合在一起。 “EA IFF 85”定义了许多容器块,但Audio IFF使用的容器块称为FORM。 FORM具有以下格式:
typedef struct {
ID ckID;
long ckSize;
ID formType;
char chunks[];
} Chunk;
ckID始终是'FORM'。这表明这是一个FORM chunk。
ckSize包含'FORM'块的数据部分的大小。请注意,数据部分已分为两部分,formType和chunks []。
formType描述'FORM'块中的内容。对于Audio IFF文件,formType始终为“AIFF”。
这表示FORM中的块与采样声音有关。FORMType为“AIFF”的FORM块称为FORM AIFF。块是FORM中包含的块。这些块称为本地块。FORM AIFF及其本地块构成Audio IFF文件。
3)Local Chunk Types(本地块类型):
有两种类型的块,一种是必需的,另一种是可选的。公共块是必需的。如果采样的声音长度大于零,则需要声音数据块。所有其他块都是可选的。所有使用表单AIFF的应用程序都必须能够读取所需的块,并且可以选择选择性地忽略可选块。复制FORM AIFF的程序应该复制FOEM AIFF中的所有块。
4)Common Chunk(公共块):
公共块描述采样声音的基本参数,定义如下:
#define CommonID 'COMM' /* ckID for Common Chunk */
typedef struct {
ID ckID;
long ckSize;
short numChannels;
unsigned long numSampleFrames;
short sampleSize;
extended sampleRate;
} CommonChunk;
ckID总是“COMM”。ckSize是块的数据部分的大小,以字节为单位。
它不包括ckID和ckSize使用的8个字节。对于普通块,ckSize总是18。
numChannels包含声音的音频通道的数量。值1表示单声道声音,值2表示立体声,值4表示四声道声音,等等。可以表示任何数量的音频通道。
实际的声音样本存储在另一个块中,即声音数据块。对于多通道声音,每个通道的单采样点是交错的。 一组交错的样本点称为样本帧。
对于单声道声音,一个采样帧是一个单采样点。
numSampleFrames包含Sound Data Chunk中的样本帧数。numSampleFrames是样本帧的数量,而不是Sound Data Chunk中的字节数和采样点数。文件中的采样点总数为numSampleFrames的numChannels倍。
sampleSize是每个采样点中的位数。它可以是1到32之间的任何数字。
sampleRate是声音被回放的采样率,以每秒采样帧数为单位。
每个FORM AIFF都只需要一个公共块。
5)Sound Data Chunk(声音数据块):
声音数据块包含实际的样本帧。
#define SoundDataID 'SSND' /* ckID for Sound Data Chunk */
typedef struct {
ID ckID;
long ckSize;
unsigned long offset;
unsigned long blockSize;
unsigned char soundData[];
} SoundDataChunk;
ckID总是'SSND'。
ckSize是块的数据部分的大小,以字节为单位。它不包括ckID和ckSize使用的8个字节。
offset确定soundData中第一个样本帧的开始位置。offset以字节为单位。大多数应用程序不会使用偏移量,应将其设置为零。
blockSize与偏移量一起用于块对齐声音数据。它包含声音数据对齐到的块的字节大小。与偏移量一样,大多数应用程序不会使用块大小,应该将其设置为零。
soundData包含组成声音的示例帧。soundData中的样本帧数由Common Chunk中的numSampleFrames参数确定。
6)Marker Chunk(标记块)
标记块包含指向声音数据中位置的标记。标记可用于应用程序所需的任何目的。
标记具有一下格式:
typedef short MarkerId;
typedef struct {
MarkerId id;
unsigned long position;
pstring markerName;
} Marker;
id是唯一标识FORM AIFF中标记的数字。id可以是任何正的非零整数,只要同一FORM AIFF中的其他标记没有相同的id。
标记在声音数据中的位置由position确定。标记在概念上落在两个样本帧之间。位置的单位为帧而不是字节。
/*前面的8是什么*/markerName是一个帕斯卡风格的文本字符串,包含标记的名称。
标记块内数据的格式如下所示。
#define MarkerID 'MARK' /* ckID for Marker Chunk */
typedef struct {
ID ckID;
long ckSize;
unsigned short numMarkers;
Marker Markers[];
} MarkerChunk;
ckID总是“MARK”。
ckSize是块的数据部分的大小,以字节为单位。它不包括ckID和ckSize使用的8个字节。
nummarker是标记块中的标记数量。
7)Instrument Chunk(仪器块):
Instrument Chunk定义了仪器(如采样器)可用于回放声音数据的基本参数。
声音数据可以循环,允许重复声音的一部分以延长声音。下面的结构描述了一个循环:
typedef struct {
short playMode;
MarkerId beginLoop;
MarkerId endLoop;
} Loop;
playMode指定要执行哪种类型的循环。
#define NoLooping 0
#define ForwardLooping 1
#define ForwardBackwardLooping 2
如果指定了NoLooping,那么在回放期间将忽略循环点。
beginLoop是一个Markerid,用于标记循环段的开始位置。
endLoop标记一个循环的结束位置。起始位置必须小于结束位置。
Instrument Chunk Format(工具块格式):
工具数据块中的数据格式如下所述:
#define InstrumentID 'INST' /* ckID for Instrument Chunk */
typedef struct {
ID ckID;
long ckSize;
char baseNote;
char detune;
char lowNote;
char highNote;
char lowVelocity;
char highVelocity;
short gain;
Loop sustainLoop;
Loop releaseLoop;
} InstrumentChunk;
ckID始终是'INST'。ckSize是块的数据部分的大小,以字节为单位。对于仪器块,ckSize始终为20。
baseNote是工具在没有音调修改的情况下播放声音数据的注释。单位是MIDI(MIDI是乐器数字接口的首字母缩写)音符编号,范围是0到127.中间C是60。
detune决定工具在播放时应改变声音音高的程度。单位为美分(半音的1/100),范围从-50到+50。负数表示声音的音高应该降低,而正数表示应该提高声音的音高。
lowNote和highNote指定键盘上的建议范围以播放声音数据。如果要求乐器在低音符和高音符之间播放音符,则应播放声音数据。基调不必在此范围内。lowNote和highNote的单位是MIDI音符值。
lowVelocity和highVelocity指定播放声音数据的建议速度范围。如果音符开启速度介于低速和高速之间,则应播放声音数据。单位是MIDI速度值,1(最低速度)到127(最高速度)。
gain(增益)是在播放时改变声音增益的量。单位是分贝。例如,0 db表示没有变化,6 db表示每个采样点的值加倍,而-6 db表示每个采样点的值减半。
sustainLoop指定一个循环,当工具维持声音时要播放该循环。
releaseLoop指定当乐器处于播放声音的释放阶段时要播放的循环。释放阶段通常在乐器上的键释放后发生。
Instrument Chunk是可选的。FORM AIFF中只能出现一个Instrument Chunk。
8)MIDI Data Chunk(MIDI数据块):
MIDI数据块可用于存储MIDI数据。结构定义如下:
#define MIDIDataID 'MIDI' /* ckID for MIDI Data Chunk */
typedef struct {
ID ckID;
long ckSize;
unsigned char MIDIdata[];
} MIDIDataChunk;
ckID总是'MIDI'。ckSize是块的数据部分的大小,以字节为单位。它不包括ckID和ckSize使用的8个字节。
MIDIData包含MIDI数据流。
MIDI数据块是可选的。FORM AIFF中可能存在任意数量的MIDI数据块。如果要将多个乐器的MIDI系统专用信息存储在FORM AIFF中,最好每个乐器使用一个MIDI数据块,而不是所有乐器使用一个大的MIDI数据块。
9)Audio Recording Chunk(录音块)
录音块包含与录音设备有关的信息。结构定义如下:
#define AudioRecordingID 'AESD' /* ckID for Audio Recording Chunk. */
typedef struct {
ID ckID;
long ckSize;
unsigned char AESChannelStatusData[24];
} AudioRecordingChunk;
ckID始终是'AESD'。ckSize是块的数据部分的大小,以字节为单位。对于录音块,ckSize始终为24。
AESChannelStatusData的24个字节在AES推荐的数字音频工程实践 - 线性表示的数字音频数据的串行传输格式,第7.1节,通道状态数据中规定。该文件描述了用于音频设备之间的数字音频的实时数字传输的格式。为方便起见,此信息在音频记录块中重复。一般感兴趣的是字节0的位2,3和4,它们描述了记录强调。
音频录制块是可选的。FORM AIFF中不得出现多个音频录制块。
10)Application Specific Chunk(应用程序特殊块)
Application Specific Chunk可以用于应用程序制造商的任何目的。结构如下:
#define ApplicationSpecificID 'APPL' /* ckID for Application Specific Chunk. */
typedef struct {
ID ckID;
long ckSize;
OSType applicationSignature;
char data[];
} ApplicationSpecificChunk;
ckID总是'APPL'。ckSize是块的数据部分的大小,以字节为单位。它不包括ckID和ckSize使用的8个字节。
applicationSignature标识特定的应用程序。
data是Application Specific Chunk的数据。
Application Specific Chunk是可选的。单个FORM AIFF中可能存在任意数量的Application Specific Chunk。
11)Comments Chunk(注释块)
Comments Chunk用于在FORM AIFF中存储注释。“EA IFF 85”有一个可用于注释的注释块,但是注释块有两个在“EA IFF 85”块中找不到的功能。它们是:1)评论的时间戳;2)指向标记的链接。
Comments由时间戳,标记ID和文本计数跟文本组成。结构如下:
typedef struct {
unsigned long timeStamp;
MarkerID marker;
unsigned short count;
char text;
} Comment;
timeStamp表示Comments的创建时间。单位是自1904年1月1日以来的秒数。
Comments可以链接到标记。这允许应用程序将标记的长描述存储为Comments。如果Comments指的是标记,则marker是该标记的ID。否则,标记为零,表示此Comments未链接到标记。
count是组成Comments的文本的长度。这是一个16位的数量,允许比pstring更长的Comments。
text包含Comments本身。必须在末尾用一个字节填充此文本,以确保它的长度为偶数个字节。该填充字节(如果存在)不包括在计数中。
Comments Chunk Format:
#define CommentID 'COMT' /* ckID for Comments Chunk. */
typedef struct {
ID ckID;
long ckSize;
unsigned short numComments;
Comment comments[];
} CommentsChunk;
ckID总是'COMT'。ckSize是块的数据部分的大小,以字节为单位。它不包括ckID和ckSize使用的8个字节。
numComments包含Comments Chunk中的Comments数。接下来是Comments本身。Comments长度总是为偶数个字节,因此Comments Chunk中的Comments之间没有填充。
Comments Chunk是可选的。一个FORM AIFF中只能出现一个Comments Chunk。
12)Text Chunks - Name, Author, Copyright, Annotation(文本块 - 名称,作者,版权,注释)
这四个块包含在每个“EA IFF 85”文件的定义中。全是文本块;他们的数据部分仅由文本组成。这些块中的每一个都是可选的。
#define NameID 'NAME' /* ckID for Name Chunk. */
#define AuthorID 'AUTH' /* ckID for Author Chunk. */
#define CopyrightID '(c) ' /* ckID for Copyright Chunk. */
#define AnnotationID 'ANNO' /* ckID for Annotation Chunk. */
typedef struct {
ID ckID;
long ckSize;
char text[];
} TextChunk;
ckID是“NAME”,“AUTH”,“(c)”或“ANNO”,具体取决于块是否分别为Name Chunk,Author Chunk,Copyright Chunk或Annotation Chunk。对于版权块,'c'是小写的,并且在右括号后面有一个空格(0x20)。
ckSize是块的数据部分的大小,在本例中是文本。
text包含纯ASCII字符。它不是pstring也不是C字符串。text中的字符数由ckSize确定。text内容取决于块,如下所述:
Name Chunk:
text包含采样声音的名称。名称块是可选的。FORM AIFF中可能只存在一个名称块。
Author Chunk:
text包含一个或多个作者姓名。在这种情况下,作者是采样声音的创建者。作者块是可选的。FORM AIFF中可能只存在一个作者块。
Copyright Chunk:
版权块包含声音的版权声明。文本包含版权所有者遵循的日期。
版权块是可选的。FORM AIFF中可能只存在一个版权块。
Annotation Chunk:
text包含评论。在FORM AIFF中不鼓励使用此块。应该使用功能更强大的Comments Chunk。Annotation Chunk是可选的。FORM AIFF中可能存在许多Annotation Chunk。
13)Chunk Precedence(块优先级)
FORM AIFF的几个本地块可能包含重复信息。例如,乐器块定义了循环点,MIDI数据块中的MIDI系统专用数据也可以定义循环点。如果这些循环点不同会发生什么?应用程序应该如何循环声音?
通过定义块的优先级来解决此类冲突:
Common Chunk(Highest Precedence)->
Sound Data Chunk ->
Marker Chunk ->
Instrument Chunk ->
Comment Chunk ->
Name Chunk ->
Author Chunk ->
Copyright Chunk ->
Annotation Chunk ->
Audio Recording Chunk ->
MIDI Data Chunk ->
Application Specific Chunk(Lowest Precedence)
Common Chunk具有最高优先级,而Application Specific Chunk具有最低优先级。
Common Chunk中的信息始终优先于任何其他块中的冲突信息。Application Specific Chunk总是在与其他块冲突时丢失。
例如,通过查看块层次结构,可以看到Instrument Chunk中的循环点优先于MIDI数据块中发现的冲突循环点。
应用程序负责将数据写入较低优先级的块,以确保更高优先级的块相应地更新。
参考:http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/AIFF.html