SoundFont2技术协议 之 pdta-list Chunk

1.Hydra九头数据结构

SoundFont 2兼容文件中的发音数据包含在九个子块中。这个数据以神话中的九头兽命名为“hydra(九头蛇)”。该结构是为交换而设计的;它没有针对运行时合成或动态编辑进行优化。SoundFont兼容的客户端程序在读取和写入SoundFont兼容文件时,可以合理地转换为九头蛇结构。pdta列表块结构:

<pdta-ck> -> LIST (‘pdta’   
                     {    
                     <phdr-ck> ; The Preset Headers    
                     <pbag-ck> ; The Preset Index list    
                     <pmod-ck> ; The Preset Modulator list    
                     <pgen-ck> ; The Preset Generator list    
                     <inst-ck> ; The Instrument Names and Indices    
                     <ibag-ck> ; The Instrument Index list    
                     <imod-ck> ; The Instrument Modulator list    
                     <igen-ck> ; The Instrument Generator list    
                     <shdr-ck> ; The Sample Headers   
                     }   
                )

2. PHDR Sub-chunk【预设标题子块】

phdr子块是必需的子块,列出了SoundFont兼容文件中的所有预设。它始终是38字节长度的倍数,并且至少包含两个记录,每个预设一个记录,根据结构,一个终端记录一个记录:

struct sfPresetHeader 
{  
	CHAR achPresetName[20];  
	WORD wPreset;  
	WORD wBank;  
	WORD wPresetBagNdx;  
	DWORD dwLibrary;  
	DWORD dwGenre;  
	DWORD dwMorphology; 
}; 

ASCII字符字段achPresetName包含以ASCII表示的预设名称,其中未使用的终端字符用零值字节填充。预设名称区分大小写。应始终为SoundFont兼容库中的每个预设指定一个唯一的名称,以启用标识。但是,若读取的库包含具有相同预设名称的错误状态时,不应丢弃这些预设。它们应该保留为已读,或者最好是指定唯一的重命名。

WORD wPreset包含MIDI预设编号,WORD wBank包含适用于此预设的MIDI库编号。请注意,预设不是在SoundFont兼容库中订购的。预设应该有一组独特的wPreset和wBank编号。但是,如果两个预设具有相同的wPreset和wBank值,则PHDR块中第一个出现的预设是活动预设,但应保留具有相同wBank和wPreset值的任何其他预设,以便在以后重新编号和使用。通常wBank的值为128时通用MIDI打击乐库需要进行特殊处理。若任一字段中的值不是0到127的有效MIDI值,或者wBank值为128,则预设应一直保持不播放。

WORD wPresetBagNdx是PBAG sub-chunk子块中预设区域列表的索引。由于预设区域列表与预设标题列表的顺序相同,预设包指数将随着预设标题的增加而依次增加。PBAG子块的大小(以字节为单位)将等于终端预设的(wPresetBagNdx + 4)的四倍[此处不太确定翻译的准确性 The size of the PBAG sub-chunk in bytes will be equal to four times the terminal preset’s wPresetBagNdx plus four.]。如果预设包指数是非依次的,或者终端预设的wPresetBagNdx与PBAG subchunk子块大小不匹配,则认为该文件在结构上有缺陷,应在加载时拒绝。除终端预设外,所有预设必须至少有一个区域;任何没有区域的预设都应被忽略。

DWORDs dwLibrarydwGenredwMorphology在预设的库管理功能中为将来的实现而保留,并应保留为可读,默认值为零。

终端sfPresetHeader记录不应被访问,它的存在只是为了提供一个终端wPresetBagNdx,用于确定上一个预设中的区域数。除AchPresetName之外,所有其他值通常为零,可以选择“EOP”来表示预设结束。

如果PHDR sub-chunk子块丢失,或者包含的记录少于两个,或者它的大小不是38字节的倍数,那么应该拒绝该文件,因为它的结构不健全。

3. PBAG sub-chunk 【预设索引列表 子块】

PBAG sub-chunk子块是列出SoundFont兼容文件中所有预设区域的必需子块。它始终是四个字节长度的倍数,并且根据结构包含每个预设区域的每条记录加上终端区域的一条记录[and contains one record for each preset zone plus one record for a terminal zone according to the structure]:

struct sfPresetBag 
{  
	WORD wGenNdx;  
	WORD wModNdx; 
}; 

给定预设中的第一个区域位于该预设的wPresetBagNdx。预设中的区域数由下一个预设的wPresetBagNdx和当前wPresetBagNdx之间的差异决定。

WORD wGenNdx是PGEN sub-chunk子块中预设发生器区域列表的索引,wModNdx是PMOD sub-chunk子块中其调制器列表的索引。由于发生器和调制器列表与预设标题和区域列表的顺序相同,因此这些索引将随着预设区域的增加而依次增加。以字节为单位的PMOD sub-chunk子块的大小将等于终端预设的wModNdx的10倍加上10[ equal to ten times the terminal preset’s wModNdx plus ten],以字节为单位的PGEN sub-chunk子块的大小将等于终端预设的wGenNdx的4倍加上4倍[four times the terminal preset’s wGenNdx plus four.]。如果生成器或调制器索引是非依次的,或者与各自的PGEN或PMOD sub-chunks子块的大小不匹配,则该文件在结构上有缺陷,应在加载时被拒绝。

如果预设有多个区域,则第一个区域可能是全局区域。全局区域由列表中的最后一个生成器不是乐器生成器这一事实决定。所有生成器列表必须至少包含一个生成器,但有一个例外-如果存在一个全局区域,而该区域没有生成器,但只有调制器。调制器列表可以包含零个或多个调制器。

如果第一个区域以外的区域缺少作为最后一个生成器的乐器生成器,则应忽略该区域。一个没有调制器和发生器的全局区域也应该被忽略。

如果缺少PBAG sub-chunk子块,或者它的大小不是四个字节的倍数,那么应该拒绝该文件,因为它的结构不健全。

4.  PMOD Sub-chunk【预设调制器列表 子块】

PMOD子块是列出SoundFont兼容文件中所有预设区域调制器的必需子块。它总是长度为十个字节的倍数,并且根据结构包含零个或多个调制器加上一个终端记录:

struct sfModList 
{  
	SFModulator sfModSrcOper;  
	SFGenerator sfModDestOper;  
	SHORT modAmount;  
	SFModulator sfModAmtSrcOper;  
	SFTransform sfModTransOper; 
}; 

预设区域的wModNdx指向该预设区域的第一个调制器,而当前预设区域的调制器数量由下一个较高预设区域的wModNdx和当前预设的wModNdx之间的差异决定。差为零表示此预设区域中没有调制器。

sfModSrcOper是SFModulator枚举类型值之一的值。忽略未知或未定义的值。将sfModAmtSrcOper设置为“link”且没有其他调制器链接的调制器将被忽略。该值表示调制器的数据源。请注意,此枚举的长度为两个字节。

sfModDestOper指示调制器的终点。终点要么是一个SFGenerator枚举类型值的值,要么是到另一个调制器块的sfModSrcOper的链接。后者由设置的sfModDestOper字段的最高位表示,其他15位表示调制器的索引值,其源应该是当前调制器的输出相对于乐器区中的第一个调制器。忽略未知或未定义的值。调制器的链接指向调制器索引超过给定区域的调制器总数将被忽略。作为循环链接一部分的链接调制器也将被忽略。 请注意,此枚举的长度为两个字节。

SHORT modAmount 是一个有符号的值,表示源对目标进行调制的程度。零值表示没有固定数值。

sfModAmtSrcOper是SFModulator枚举类型值之一的值。忽略未知或未定义的值。将sfModAmtSrcOper设置为“link”的调制器将被忽略。该值表示源对目标调制的程度,由指定的调制源控制。请注意,此枚举的长度为两个字节。

sfModTransOper是SFTransform枚举类型值之一的值。忽略未知或未定义的值。此值表示在应用到调制器之前,将对调制源应用指定类型的转换。请注意,此枚举的长度为两个字节。

终端记录通常在所有字段中都包含零,并且总是被忽略。

调制器由它的sfModSrcOper、sfModDestOper和sfModSrcAmtOper定义。一个区域中的所有调制器必须具有这三个枚举器的唯一集合。如果第二个调制器与前一个具有相同区域的调制器使用相同的三个枚举器,则第一个调制器将被忽略。

与IMOD子块中的调制器相比,PMOD子块中的调制器充当额外的相对调制器。换句话说,PMOD调制器可以增加或减少IMOD调制器的数量。

在SoundFont 2.00中,还没有定义任何调制器,PMOD子块将始终由10个零值字节组成。

如果PMOD子块缺失,或者其大小不是十个字节的倍数,则应该拒绝该文件在结构上的不合理。

5. PGEN Sub-chunk 【预设生成器列表】

PGEN块是一个必需的块,包含音源兼容文件中每个预设区域的预设区域生成器列表。它始终是四个字节长度的倍数,并且每个预设区域包含一个或多个生成器(除了仅包含调制器的全局区域)以及根据结构的终端记录:

struct sfGenList 
{  
	SFGenerator sfGenOper;  
	genAmountType genAmount; 
};

类型被定义为:

typedef struct 
 {  
	 BYTE byLo;  
	 BYTE byHi; 
 } rangesType; 
 
 typedef union 
 {  
	 rangesType ranges;  
	 SHORT shAmount;  
	 WORD wAmount; 
 } genAmountType; 

sfGenOper是SFGenerator枚举类型值之一的值。忽略未知或未定义的值。该值表示所指示的生成器类型。请注意,此枚举的长度为两个字节。

genAmount是要分配给指定生成器的值。请注意,它有三种格式。某些生成器指定MIDI速度的MIDI键数范围,及最小值和最大值。其他生成器指定无符号字值。但是,大多数生成器指定一个有符号的16位SHORT值。

预设区域的wGenNdx指向该预设区域的第一个生成器。除非区域是全局区域,否则列表中的最后一个生成器是“乐器”生成器,其值是指向与该区域关联的乐器的指针。如果预设区域存在“关键范围”生成器,则它始终是该预设区域列表中的第一个生成器。如果预设区域存在“速度范围”生成器,则其前面只能有一个关键范围生成器。如果任何生成器跟随乐器生成器则它们将被忽略掉。

生成器由其sfGenOper定义。区域中的所有生成器都必须具有唯一的sfGenOper枚举器。如果第二个生成器与具有相同区域的前一个生成器具有相同的sfGenOper枚举器,则将忽略第一个生成器。

PGEN sub-chunk子块中的生成器相对于IGEN sub-chunk子块中的生成器以相加的方式应用。换句话说,PGEN生成器增加或减少IGEN生成器的值。

如果PGEN sub-chunk子块缺少,或者它的大小不是四个字节的倍数,那么应该拒绝该文件,因为它的结构不健全。如果一个键范围生成器不是第一个生成器,则应忽略它。如果存在速度范围生成器,并且前面是除关键范围生成器之外的生成器,则应忽略该生成器。如果非全局列表不以乐器生成器结尾,则应忽略区域。如果仪器生成器值等于或大于终端乐器,则文件应被视为结构不健全而拒绝。

6.INST Sub-chunk【乐器 子块】

inst sub-chunk子块是必需的子块,列出了音源兼容文件中的所有乐器。它始终是22字节长度的倍数,并且至少包含两个记录,每个仪器一个记录,根据结构,终端记录一个记录:
 

struct sfInst 
{  
	CHAR achInstName[20];  
	WORD wInstBagNdx; 
};

ASCII字符字段achInstName包含用ASCII表示的乐器名称,未使用的终端字符用零值字节填充。乐器名称区分大小写。应始终为音源兼容库中的每个乐器指定一个唯一的名称,以便进行识别。但是,如果一库被读取时包含同名乐器的错误状态,则不应丢弃这些乐器。它们应该保留为已读,或最好是重命名唯一名称。

WORD wInstBagNdx是IBAG sub-chunk子块中乐器区域列表的索引。由于乐器区域列表与乐器列表的顺序相同,乐器包指数将随着仪表数量的增加而依次增加。以字节为单位的IBAG sub-chunk子块的大小将是终端(EOI)乐器的wInstBagNdx的四倍以上。如果仪器包索引不依次,或者终端仪器的wInstBagNdx与IBAG sub-chunk子块大小不匹配,则该文件在结构上有缺陷,应在加载时拒绝。除终端乐器外的所有乐器必须至少有一个区域;任何没有区域的预设都应忽略。

终端的sfInst记录不应被访问,它的存在只是为了提供一个终端wInstBagNdx,用于确定最后一个乐器中的区域数。除achInstName外,所有其他值通常为零,它应为“EOI”,表示仪器结束。

如果INST sub-chunk子块丢失、包含的记录少于两个或其大小不是22字节的倍数,则应拒绝该文件,因为它的结构不健全。inst sub-chunk子块中存在的所有乐器通常由预设区域引用。但是,不需要拒绝包含任何“孤立”乐器的文件。与音源兼容的应用程序可以根据用户偏好选择忽略或过滤这些孤立的乐器。

7. IBAG Sub-chunk 【乐器索引列表 子块】

IBAG子块是列出音源兼容文件中所有乐器区域的必需子块。它始终是四个字节长度的倍数,并且根据结构包含每个仪器区域的一个记录加上终端区域的一个记录:

struct sfInstBag 
{  
	WORD wInstGenNdx;  
	WORD wInstModNdx; 
}; 

给定乐器中的第一个区域位于该乐器的wInstBagNdx。仪器中的区域数由下一个仪器的wInstBagNdx和当前wInstBagNdx之间的差异决定。

WORD wInstGenNdx是IGEN sub-chunk子块中乐器区域发生器列表的索引,wInstModNdx是IMOD sub-chunk子块中调制器列表的索引。由于发生器和调制器列表与乐器和区域列表的顺序相同,这些指数将随着区域的增加而依次增加。以字节为单位的IMOD sub-chunk子块的大小将等于终端设备的wModNdx的10倍加上10倍,以字节为单位的IGEN sub-chunk子块的大小将等于终端设备的wGenNdx的4倍加上4倍。如果生成器或调制器索引是非依次的,或者与各自的IGEN或IMOD子块的大小不匹配,则该文件在结构上有缺陷,应在加载时拒绝。

如果仪器有多个区域,则第一个区域可能是全局区域。全局区域由列表中的最后一个生成器不是sampleid生成器这一事实决定。所有生成器列表必须至少包含一个生成器,但有一个例外-如果存在一个全局区域,而该区域没有生成器,但只有调制器。调制器列表可以包含零个或多个调制器。

如果第一个区域以外的区域缺少作为最后一个生成器的sampleID生成器,则应忽略该区域。一个没有调制器和发生器的全局区域也应该被忽略。

如果IBAG sub-chunk子块缺失,或者其大小不是四个字节的倍数,则应拒绝该文件,因为其结构不健全。

8. IMOD Sub-chunk 【乐器调制器列表 子块】

IMOD sub-chunk子块是必需的子块,列出了音源兼容文件中的所有乐器区调制器。它的长度总是10个字节的倍数,包含零个或多个调制器,并根据结构添加一个终端记录:

struct sfModList 
{  
	SFModulator sfModSrcOper;  
	SFGenerator sfModDestOper;  
	SHORT modAmount;  
	SFModulator sfModAmtSrcOper;  
	SFTransform sfModTransOper; 
};

该区域的wInstModNdx指向该区域的第一个调制器,并且该区域存在的调制器数量由下一个较高区域的wInstModNdx和当前区域的wModNdx之间的差异决定。零差表示该区没有调制器。

sfModSrcOper是SFModulator枚举类型的值。忽略未知或未定义的值。将sfModAmtSrcOper设置为“link”且没有其他调制器链接的调制器将被忽略。该值表示调制器的数据源。请注意,此枚举的长度为两个字节。

sfModDestOper指示调制器的目的地。目的地要么是一个SFGenerator枚举类型的值,要么是到另一个调制器块的sfModSrcOper的链接。后者由正在设置的sfModDestOper字段的首位指示,其他15位表示调制器的索引值,其值应该是当前调制器相对乐器区中第一个调制器的输出。忽略未知或未定义的值。具有指向超过给定区域的调制器总数的调制器索引的链路的调制器将被忽略。忽略部分循环链路的链接调制器。请注意,此枚举的长度为两个字节。

SHORT modAmount是一个有符号的值,指示源对目标进行调制的程度。零值表示没有固定值。

sfModAmtSrcOper是SFModulator枚举类型的值。忽略未知或未定义的值。将sfModAmtSrcOper设置为“link”的调制器将被忽略。该值表示源对目标调制器的调制程度,由指定的调制源控制。请注意,此枚举的长度为两个字节。

sfModTransOper是SFTransform枚举类型的值。忽略未知或未定义的值。此值表示在应用到调制器之前,将对调制源应用指定类型的转换。请注意,此枚举的长度为两个字节。

终端记录通常在所有字段中都包含零,并且总是被忽略。

调制器由它的sfModSrcOper、sfModDestOper和sfModSrcAmtOper来定义。一个区域中的所有调制器必须具有这三个枚举器的唯一区域。如果在同一区域内第二个调制器遇到与前一个调制器相同的三个枚举器,则第一个调制器将被忽略。

IMOD sub-chunk子块中的调制器是绝对的。这意味着IMOD调制器是替换而不是增加默认的调制器。然而,调节器对生成器的影响是附加的,即调节器的输出加上生成器的值。

在SoundFont2.00中,调制器还没有被定义,IMOD sub-chunk子块将始终由10个零值字节组成。

如果IMOD sub-chunk子块缺失,或者它的大小不是10字节的倍数,那么应该拒绝该文件,因为它的结构不健全。

9.IGEN Sub-chunk【乐器生成器列表 子块】

IGEN块是必需的块,包含SoundFont兼容文件中每个乐器区域生成器的列表。它始终是四个字节长度的倍数,并且包含每个区域的一个或多个生成器(仅包含调制器的全局区域除外),以及根据结构的终端记录:

struct sfInstGenList 
{  
	SFGenerator sfGenOper;  
	genAmountType genAmount; 
};

在上面的PGEN区域中定义了类型。

genAmount是要分配给指定生成器的值。请注意,它有三种格式。某些生成器指定了一个MIDI键数范围的MIDI速度,具有最小值和最大值。其他生成器指定无符号字值。但是,大多数生成器指定一个有符号的16位短值。

该区域的wInstGenNdx指向该区域的第一个生成器。除非是全局区域,否则列表中的最后一个生成器是“sampleID”生成器,其值是指向与该区域关联的采样的指针。如果区域存在“键范围”生成器,则它始终是该区域列表中的第一个生成器。如果该区域存在“速度范围”生成器,则其前面只能有一个关键范围生成器。如果任何一个生成器跟随一个采样生成器,它们将被忽略。

生成器由其sfGenOper定义。区域中的所有生成器都必须具有唯一的sfGenOper枚举器。如果在同一区域中第二个生成器遇到与前一个生成器具有相同sfGenOper枚举器的,则将忽略第一个生成器。

IGEN sub-chunk子块中的生成器本质上是绝对的。这意味着IGEN生成器将替换(而不是添加)生成器的默认值。

如果IGEN子块缺失,或者其大小不是四个字节的倍数,则应拒绝该文件,因为它的结构不健全。如果存在一个键范围生成器而不是第一个生成器,则应忽略它。如果存在速度范围生成器,并且前面是除关键范围生成器之外的生成器,则应忽略该生成器。如果非全局列表不以sampleID生成器结尾,则应忽略该区域。如果sampleID生成器值等于或大于终端sampleID,则应将该文件视为结构不健全而拒绝。

10.  SHDR Sub-chunk【采样标题 子块】

SHDR块是一个必需的子块,列出了smpl sub-chunk子块中的所有采样和所有引用的ROM采样。它始终是46字节长度的倍数,并且根据如下结构为每个采样包含一条加上一个终端记录的记录:

struct sfSample 
{  
	CHAR achSampleName[20];  
	DWORD dwStart;  
	DWORD dwEnd;  
	DWORD dwStartloop;  
	DWORD dwEndloop;  
	DWORD dwSampleRate;  
	BYTE byOriginalPitch;  
	CHAR chPitchCorrection;  
	WORD wSampleLink;  
	SFSampleLink sfSampleType; 
};

ASCII字符字段achSampleName包含用ASCII表示的采样名称,其中未使用的终端字符用零值字节填充。采样名称区分大小写。应始终为SoundFont兼容库中的每个采样分配一个唯一的名称,以启用标识。但是,如果读取的库包含具有相同名称的采样错误状态,则不应丢弃这些样本。它们应该保留为已读,或者最好是唯一重命名。

DWORD dwStart含有索引值,即从采样数据字段开始到该采样的第一个数据点的索引(在采样数据点中)。

DWORD dwEnd包含采样数据点中的索引,从采样数据字段的开头到该采样后面46个零值数据点集的第一个。

The DWORD dwStartloop包含采样数据点中从采样数据字段开始到该采样循环中第一个数据点的索引。

DWORD dwEndloop包含从采样数据字段开始到该采样循环之后的第一个数据点的索引(在采样数据点中)。请注意,这是“相当于”第一个循环数据点的数据点,并且为了生成可移植的自由循环,环绕Startloop和Endloop点的八个近端数据点应该是相同的。

dwStart、dwEnd、dwStartloop和dwEndloop的值必须都在SoundFont兼容库中包含的或在音频ROM中引用的采样数据字段范围内。此外,为了使各种硬件平台能够复制数据,采样的最小长度为48个数据点,最小循环大小为32个数据点。在dwStartloop之前和dwEndloop之后至少有8个有效点。因此dwStart必须小于dwStartloop-7,dwStartloop必须小于dwEndloop-31,dwEndloop必须小于dwEnd-7。如果在不满足这些限制条件,且硬件不支持对给定参数进行无缝循环时则可以选择不播放声音。

DWORD dwSampleRate包含获取此样本或将其转换为最近一次的采样率(以赫兹为单位)。某些硬件平台可能无法复制大于50000或小于400的值,应避免。零值是非法的。如果遇到非法或不切实际的值,应使用最接近的实际值。

BYTE byOriginalPitch包含采样录制音高的MIDI键编号。例如,播放中音C (261.62 Hz) 的乐器的录制应接收到60的值。此值用作采样的默认“根键”,因此在采样中,用于音符60的MIDI键打开命令将以其原始音高重现声音。对于未调音[unpitched]的声音,应使用255的常规值。128和254之间的值是非法的。每当遇到非法值或255值时,应使用值60。

CHAR chPitchCorrection包含一个以分贝为单位的音高校正,应该在回放时应用于采样。此字段的目的是补偿采样记录过程中的任何螺距误差。修正值是要应用的修正值。例如,如果声音尖锐度为4分贝,则需要进行修正,使其平缓4分贝;因此,值应为-4。

sfSampleType中的值是一个具有八个定义值的枚举:monoSample=1、rightSample=2、leftSample=4、linkedSample=8、RomMonoSample=32769、RomRightSample=32770、RomLeftSample=32772和RomLinkedSample=32776。可以看出,这是编码的,因此如果采样在ROM中,则设置16位值中的第15位,如果采样包含在SoundFont兼容库中,则重置。然后,The four LS bits of the word 被专门设置为表示单声道、左声道、右声道或链接。

如果声音被标记为ROM采样,并且没有包含有效的“irom”子块,那么文件在结构上有缺陷,应该在加载时被拒绝。

如果sfSampleType表示为单声道采样,那么wSampleLink是未定义的,其值通常应为零,但无论值是多少,都将被忽略。如果sfSampleType表示左声道或右声道采样,则wSampleLink分别是相关右声道或左声道立体声采样的头索引。两个采样都应该完全同步播放,其音高由正确的采样发生器控制。所有非螺距发生器应正常使用;特别是应该通过盘式发生器完成向左和向右平移各个采样。左右对应始终位于同一仪器内。还请注意,任何乐器都不应设计为可以激活特定立体声对的多个实例。链接的采样类型当前在SoundFont 2规范中没有定义,但最终将支持使用wSampleLink的循环链接采样列表。请注意,此枚举的长度为两个字节。

终端采样记录从不被引用,并且通常完全为零,除achSampleName之外(它应该是“EOS”),表示采样结束。smpl sub-chunk子块中存在的所有采样通常由一个工具引用,但是包含任何“孤立”采样的文件不需要被拒绝。与SoundFont兼容的应用程序可以根据用户偏好选择忽略或筛选出这些孤立的采样。

如果SHDR sub-chunk子块缺失,或者它的大小不是46字节的倍数,那么应该拒绝该文件,因为它的结构不健全。


 

发布了26 篇原创文章 · 获赞 49 · 访问量 137万+

猜你喜欢

转载自blog.csdn.net/ldghd/article/details/89380623