はじめに
複数回にわたってSoundFontファイル(.sf2ファイル)を読み込んでシンセサイザーなどに使えるようにパラメーターを組み立てる方法を説明しています。
ここではSoundFontファイル(.sf2)の音色の構成と音色情報(Hydra)チャンクの関係を説明いたします。
各説明のリンクはこちらにまとめております → SoundFontの読み込みと組み立て
サンプルコードなども上記のリンクにあります。
SoundFontの音色の構成について
初めにSounfFontの音色構成についておさらいいたします。
SoundFontでは音色はプリセットとして扱われ、プリセット(音色)には1つ以上のインストルメント(楽器)をキー(ノートNo)とベロシティにマッピングして構成されています。
また、インストルメント(楽器)もプリセットと同様に1つ以上のサンプル(音声波形)をキー(ノートNo)とベロシティにマッピングして構成されます。
SoundFontの音色と内部構成
SounfFontのプリセット(音色)はインストルメント(楽器)やサンプル(音声波形)をマッピングするために、ヘッダ・バッグ・ジェネレータを組み合わせた下記のような内部構成になっています。
プリセット(音色)は下記の4つの情報で構成されており、プリセットバッグ・プリセットジェネレータ・プリセットモジュレータを合わせてプリセットゾーンといいます。
プリセットヘッダ配下にプリセットバッグ(=インストルメントA・B等)があり、プリセットバッグの中にジェネレータ(パラメータ+インストルメント割り当て)とモジュレータ(コントローラ情報)がある形となっています。
ジェネレータにはインストルメントヘッダ(後述)へのリンクがあり、インストルメント(楽器)でも同様の構成をとっています。
項目 | 概要 |
---|---|
プリセットヘッダ | プリセット名、プリセットバッグ(=インストルメントA・B等)などの情報が入ったヘッダ情報 SoundFontファイルのphdrチャンクの内容 |
プリセットバッグ | 割り当てるインストルメント(楽器)に関係するジェネレータ・モジュレータをひとまとめにするためのバッグ情報 SoundFontファイルのpbagチャンクの内容 |
プリセットジェネレータ | マッピング情報(キーとベロシティ)、パラメーター(音量、フィルタ等)、割り当てインストルメント等のパラメータ情報 SoundFontファイルのpgenチャンクの内容 |
プリセットモジュレータ | ベロシティやMIDI CC、ピッチベンド等に対してジェネレータをどのように変化させるか等の設定情報 SoundFontファイルのpmodチャンクの内容 |
インストルメント(楽器)もプリセットとほぼ同様で下記4つの情報で構成されており、インストルメントバッグ・インストルメントジェネレータ・インストルメントモジュレータを合わせてインストルメントゾーンといいます。
ジェネレータにはサンプルヘッダ(後述)へのリンクがあります。
項目 | 概要 |
---|---|
インストルメントヘッダ | インストルメント名、インストルメントバッグ(=サンプルA・B等)などの情報が入ったヘッダ情報 SoundFontファイルのinstチャンクの内容 |
インストルメントバッグ | 割り当てるサンプル(音声波形)に関係するジェネレータ・モジュレータをひとまとめにするためのバッグ情報 SoundFontファイルのibagチャンクの内容 |
インストルメントジェネレータ | マッピング情報(キーとベロシティ)、パラメーター(音量、フィルタ等)、割り当てサンプル等のパラメータ情報 SoundFontファイルのigenチャンクの内容 |
インストルメントモジュレータ | ベロシティやMIDI CC、ピッチベンド等に対してジェネレータをどのように変化させるか等の設定情報された構造体 SoundFontファイルのimodチャンクの内容 |
サンプル(音声波形)は下記の情報で構成されています。
項目 | 概要 |
---|---|
サンプルヘッダ | サンプル名、音声波形の開始・終了位置・ループポイントなどの情報が入ったヘッダ SoundFontファイルのshdrチャンクの内容 |
SoundFontの音色情報(Hydra)チャンクとの関連性
前々回の「SoundFontのフォーマット – 音色情報チャンク」にある通り、プリセットやインストルメントのヘッダやバッグ、ジェネレータ等はすべてSoundFontファイルの音色情報(Hydra)チャンクに保存されています。
そして、音色情報(Hydra)チャンクは「SoundFontの音色と内部構成」の通り、それぞれのチャンクが関連して音色情報を構成しています。
プリセットヘッダ(phdrチャンク、SFPresetHeader構造体)のbagIndexはプリセットバッグ(pbagチャンク)の番号になっています。
上記の図の例では、
phdr[0].bagIndex=0
phdr[1].bagIndex=3
となっており、プリセットヘッダ phdr[0]にはpbag[0]~pbag[2](phdr[1].bagIndexの直前まで)が含まれるプリセットバッグになります。
さらに、プリセットバッグ(pbagチャンク)ではSFBag構造体のgenIndexがプリセットジェネレータ(pgenチャンク)の番号になっています。
上記の図の例のphdr[0]に含まれるpbag[0]~pbag[2]では、
pbag[0].genIndex=0…pgen[0]~pgen[1]がpbag[0]に含まれる(グローバルゾーン。後述)
pbag[1].genIndex=2…pgen[2]~pgen[4]がpbag[1]に含まれる
pbag[2].genIndex=5…pgen[5]~pgen[7]がpbag[2]に含まれる
pbag[3].genIndex=8(次のプリセットヘッダに含まれるプリセットバッグ)
となっています。
プリセットジェネレータ(pgenチャンク)にはマッピング情報、パラメーターとともに割り当てインストルメントが入っています。
割り当てインストルメントはSFGen構造体のgenOper=41の時のgenAmountがインストルメントヘッダの番号になっています。
ただし、図の例のpbag[0]配下のプリセットジェネレータpgen[0]~pgen[1]は割り当てインストルメントを含まないため、グローバルゾーンとなっています。(グローバルゾーンについては後述。)
インストルメントにおいてもほぼ同様のチャンク間の関連があります。
インストルメントヘッダ(instチャンク、SFInstHeader構造体)のbagIndexはインストルメントバッグ(ibagチャンク)の番号になっています。
上記の図の例では、
inst[0].bagIndex=0
inst[1].bagIndex=2
となっており、インストルメントヘッダ inst[0]にはibag[0]~pbag[1](inst[1].bagIndexの直前まで)、inst[1]にはibag[2](inst[2].bagIndexの直前まで)が含まれるインストルメントバッグになります。
さらに、インストルメンバッグ(ibagチャンク)ではSFBag構造体のgenIndexがプリセットジェネレータ(igenチャンク)の番号になっています。
上記の図の例のinst[0]に含まれるibag[0]~ibag[1]とinst[1]に含まれるibag[2]では、
ibag[0].genIndex=0…igen[0]~igen[1]がibag[0]に含まれる(グローバルゾーン。後述)
ibag[1].genIndex=2…igen[2]~igen[3]がibag[1]に含まれる
ibag[2].genIndex=4…igen[4]~igen[6]がibag[2]に含まれる
ibag[3].genIndex=7(次のインストルメントヘッダに含まれるインストルメントバッグ)
となっています。
インストルメントジェネレータ(igenチャンク)にはマッピング情報、パラメーターとともに割り当てサンプルが入っています。
割り当てサンプルはSFGen構造体のgenOper=53の時のgenAmountがサンプルヘッダの番号になっています。
ただし、図の例のibag[0]配下のインストルメントジェネレータigen[0]~igen[1]は割り当てサンプルを含まないため、グローバルゾーンとなっています。(グローバルゾーンについては後述。)
上記のように音色情報(Hydra)チャンクはphdrチャンクから順番にインデックスをたどることで音色を構成することができます。
グローバルゾーンとローカルゾーン
グローバルゾーンとは、ジェネレータ内に割り当てるインストルメントやサンプルの情報(genOper=41やgenOper=53)を持たないものになります。
このグローバルゾーンは、同じレベル内のすべてのゾーン(バッグやジェネレータ)に影響を与えるゾーンとなります。
グローバルゾーンは「全体的に音量を下げたい」や「全体的にエフェクトを効かせたい」等に使用します。
「SoundFontの音色情報(Hydra)チャンクとの関連性」の図の例では、プリセットバッグ pbag[0]とインストルメントバッグ ibag[0]がそれぞれのレベルでのグローバルゾーンとなります。
プリセットバッグ pbag[0]のジェネレータ情報はpbag[1]、pbag[2]の両方に影響し、インストルメントバッグ ibag[0]のジェネレータ情報はibag[1]、ibag[2]の両方に影響します。
また、ジェネレータ内に割り当てるインストルメントやサンプルの情報(genOper=41やgenOper=53)を持つものはローカルゾーンと呼ばれます。
ローカルゾーンでは割り当ててるインストルメントやサンプルにのみ、音量やフィルタのパラメータを調整することができます。
なお、同じ情報がグローバルゾーンとローカルゾーンであった場合、ローカルゾーンが優先されます。
SoundFontの音色情報の組み立て
SoundFontファイルのHydraチャンクの内容を組み立てて、プリセットとしてソフトウェア音源等で実際に利用するに当たっては、
キーやベロシティに応じて発音すべきインストルメント(楽器)・サンプルや(音声波形)パラメータ等の情報を使いやすいようにまとめていく必要があります。
「SoundFontの音色情報(Hydra)チャンクとの関連性」の内容から、プリセット(音色)が決まると配下にあるインストルメント(楽器)が決まり、最終的にサンプル(音声波形)が決まりることがわかります。
プリセット(音色)が決まると最終的にサンプル(音声波形)に行きつくことから、プリセット(音色)に関連するサンプル(音声波形)ごとに下記の情報をまとめると利用しやすくなります。
- キー、ベロシティ範囲
- 発音すべきサンプル
- 音量やフィルタ等のパラメータ
上記の情報は前回の「SoundFontの音色と音色とジェネレータについて – ジェネレータとは」の内容からジェネレータにすべてあることがわかります。
- キー、ベロシティ範囲…keyRange、velRange
- 発音すべきサンプル…instrument、SampleID
- 音量やフィルタ等のパラメータ…startAddrsOffset、initialFilterFc、attackModEnv等
つまりサンプル(音声波形)にプリセットジェネレータ、インストルメントジェネレータの内容を反映させればまとめることができます。
なお、ジェネレータに関するチャンク(pgenチャンク、igenチャンク)には変更のあるジェネレータのみが保存されているため、下記のようにデフォルト値のジェネレータは別途用意する必要があります。(デフォルト値は「SoundFontの音色と音色とジェネレータについて – ジェネレータのとる範囲(最大値・最小値・デフォルト値)」参照)
【ジェネレーターのデフォルト値】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
// ------------------------------------------------------------------------------------ // ジェネレーターのデフォルト値 // ------------------------------------------------------------------------------------ #define SFNA -1 // アサインされていない値用 const short genDefault[endOper + 1] = { 0, // startAddrsOffset 0, // endAddrsOffset 0, // startloopAddrsOffset 0, // endloopAddrsOffset 0, // startAddrsCoarseOffset 0, // modLfoToPitch 0, // vibLfoToPitch 0, // modEnvToPitch 13500, // initialFilterFc 0, // initialFilterQ 0, // modLfoToFilterFc 0, // modEnvToFilterFc 0, // endAddrsCoarseOffset 0, // modLfoToVolume 0, // unused1 0, // chorusEffectsSend 0, // reverbEffectsSend 0, // pan 0, // unused2 0, // unused3 0, // unused4 -12000, // delayModLFO 0, // freqModLFO -12000, // delayVibLFO 0, // freqVibLFO -12000, // delayModEnv -12000, // attackModEnv -12000, // holdModEnv -12000, // decayModEnv 0, // sustainModEnv -12000, // releaseModEnv 0, // keynumToModEnvHold 0, // keynumToModEnvDecay -12000, // delayVolEnv -12000, // attackVolEnv -12000, // holdVolEnv -12000, // decayVolEnv 0, // sustainVolEnv -12000, // releaseVolEnv 0, // keynumToVolEnvHold 0, // keynumToVolEnvDecay SFNA, // instrument 0, // reserved1 32512, // keyRange (範囲は0~127、上位8bit…上限、下位8bit…下限) 32512, // velRange (範囲は0~127、上位8bit…上限、下位8bit…下限) 0, // startloopAddrsCoarseOffset SFNA, // keynum SFNA, // velocity 0, // initialAttenuation 0, // reserved2 0, // endloopAddrsCoarseOffset 0, // coarseTune 0, // fineTune SFNA, // sampleID 0, // sampleModes 0, // reserved3 100, // scaleTuning 0, // exclusiveClass SFNA, // overridingRootKey 0, // unused5 0 // endOper }; |
上記のデフォルト値に対して、インストルメントジェネレータは置き換えるように処理し、プリセットジェネレータはインストルメントジェネレータで置き換えた値やデフォルト値に対して加算するよう処理します。グローバルよりもローカルのジェネレータが優先されることに注意してください。
【オペレータに対しての処理の順番】
- 該当のオペレータがグローバルインストルメントジェネレータにあれば、グローバルインストルメントジェネレータ値で置き換える
- 該当のオペレータがローカルインストルメントジェネレータにあれば、ローカルインストルメントジェネレータ値で置き換える(ローカルが優先される)
- 該当のオペレータがローカルプリセットジェネレータにあれば、ローカルプリセットジェネレータ値を加算し、次のグローバルプリセットジェネレータは無視する
- 該当のオペレータがグローバルプリセットジェネレータにあれば、グローバルプリセットジェネレータ値を加算する
上記の処理を加えて、サンプル(音声処理)用の情報をまとめた後は、「SoundFontの音色とジェネレータについて – ジェネレータのとる範囲(最大値・最小値・デフォルト値)」の「変換式」にしたがって値を変換すれば、ソフトウェア音源等で実際に利用するためのパラメータ値となります。
最後に
SoundFontの音色と音色情報(Hydra)チャンクの関係性については以上になります。
次回はSoundFont規格で想定されているウェーブテーブル音源の概要についての説明をいたします。
- SoundFont規格のウェーブテーブル音源
各説明のリンクはこちらにまとめております → SoundFontの読み込みと組み立て
質問はコメント欄や掲示板、Twitterでいただけばとおもいます。
また、「この部分を詳しく」などの要望も掲示板やTwitterでいただければと思います。
■掲示板
■Twitterアカウント:@vstcpp URL:https://twitter.com/vstcpp