DAW悪戦苦闘記

DAWやMIDIを通じてDTMを楽しむ記録。MIDI検定試験にもチャレンジするなり。

PythonでSMFを操作する (4) デルタタイム修正

前回記事の続き(注: かなりマニアックです)。今回は、前回未解決であった最初のノートオン・メッセージのデルタタイム、すなわち発音タイミングをシフトして修正する。

daw-jones.hatenablog.com

データ挿入に伴うズレ

途中挿入したセットアップ・データのメッセージ総数と送信経過時間を求める。以下のような簡単な関数を定義してみる。なお、各メッセージのデルタタイムは、そのtime属性*1を参照して引っ張り出せる。下記プログラム例では、msg.timeがそれに該当する。

# セットアップ・データのメッセージ総数と経過時間を求める関数
def setup_time(setup_msg):
    n = len(setup_msg)
    delta_time = sum([msg.time for msg in setup_msg])
    return (n, delta_time)

# 実際に計算してみると
nmsg, time_to_shift = setup_time(setup_msg)
print(nmsg, time_to_shift)

実際の計算結果は、15メッセージ (nmsg) かつ600ティック (time_to_shift) 分の長さとなる。したがって、冒頭から18 (= 3*2 + 15) メッセージ目に来る最初のノートオン・メッセージ*3につき、そのデルタタイムを600ティックだけ減らす必要がある。

該当メッセージのデルタタイム修正

該当メッセージのデルタタイム値を書き換えるには、そのメッセージ・オブジェクトのtime属性値を直接修正してしまえばよい。たとえば、以下の1行で事足りる。

# 該当メッセージのデルタタイム修正
track1[3 + nmsg].time -= time_to_shift

修正後のtrack1冒頭は下例の通りとなり、タイミングが修正されたことがわかる。

f:id:daw_jones:20170716173156p:plain

このように、メッセージ・オブジェクトの属性値を修正すれば、元からあるMIDIデータを色々と自由自在に変更修正可能で、MIDIチャネルや移調なども同様のやり方で簡単に編集できる。これらについては次回以降述べる。

*1:タイムと言いつつ値はティック単位である。ティックあたりの時間分解能(μs)は、メタトラックのテンポ設定値で定義される。

*2:元からあったメタメッセージ2件に、前々回に追加挿入したSysExメッセージ1件、計3件。

*3:本例ではたまたまノートオンだが、一般的にはコントロール・チェンジやピッチベンド・チェンジなどの可能性がある。

DominoでSMF保存した場合の注意点

今になって気づいたのだが、Domino上で各トラックの音色を選択設定した後にSMF保存すると、Domino独自の余計なバンクセレクトMSB/LSBメッセージが挿入されてしまう。

MIDI検定実技では、2級と1級を問わず、レギュレーション違反で減点対象になる可能性があるので、残さずに削除しておくべきと思われる。

現象

Dominoで音色設定すると、SMFに余分なバンクセレクトMSB/LSBメッセージ2行が書き足されてしまう。DominoからSMFとして書き出したものを再度Dominoに読み込んでみると確認できる(下図参照)。

f:id:daw_jones:20170717140505p:plain

対策 (1)

この不要メッセージは手動で削除した上で、SMFとして再保存する。多少手間が掛かってしまうが、三度再読み込みして不要メッセージが消去されたかどうか最終確認した方がよいだろう。2級2次試験の楽曲はトラック数が少ないので、このような手動対応でも全然問題ないと思う。

なお、この余計なバンクセレクトMSB/LSBがなくても指定音色(プログラム・チェンジ)によるDominoでの再生は可能である。

対策 (2)

2級にせよ1級にせよ、プログラム・チェンジを含めたシステム・セットアップデータはDominoで再生確認する前に、別途Dominoを使わずに追加する。すなわち、Studio One からベースとなるMIDIデータを書き出したSMFに、Pythonによるバッチ処理でセットアップデータを丸ごと書き込んでしまう。この場合は、Dominoで音色を選択操作する必要が一切ないため、Domino独自のバンクセレクト・メッセージが書き足されずに済む。

トラック数が非常に多い1級楽曲に関しては、このやり方でないと対応が難しいと思う。

確認作業

最終成果物としてのSMFは、再度Dominoに読み込んで、上記のような不要なメッセージが残存していないかどうか検証した方が安心である。念には念を入れるのであれば、さらにPythonのmidoパッケージを使い、SMFの各トラック冒頭部分を目視チェックするとより確実であろう(下記記事参照)*1

daw-jones.hatenablog.com

*1:むろんこれはPythonプログラミングができる人限定。MIDIのイベントリストを閲覧チェックできるDAWであればそれで十分であろう。

PythonでSMFを操作する (3) セットアップデータ挿入

前回の続き(注: かなりマニアックです)。前準備は済んでいるものとする。

daw-jones.hatenablog.com

セットアップデータの生成

セットアップ用のデータは、コントロール・チェンジとプログラム・チェンジを組み合わせた一連のメッセージ・リストとして定義できる。

前回同様に、midoパッケージのMessageメソッドで個々のメッセージ・オブジェクトを生成し、それをリストとして繋げればよい。下例では、リスト化した一連のメッセージを変数setup_msgに格納している*1。中身は、協会テンプレでお馴染みのセットアップ・データそのままであるが*2、説明せずともほとんど自明だと思う。

# セットアップ用データのメッセージ・リスト定義
setup_msg = [Message('control_change', channel=0, control=0, value=121, time=480),
             Message('control_change', channel=0, control=32, value=0, time=10),
             Message('control_change', channel=0, control=0, value=0, time=10),
             Message('control_change', channel=0, control=32, value=4, time=0),
             Message('program_change', channel=0, program=68, time=0),
             Message('control_change', channel=0, control=7, value=102, time=10),
             Message('control_change', channel=0, control=10, value=64, time=10),
             Message('control_change', channel=0, control=11, value=127, time=10),
             Message('control_change', channel=0, control=91, value=58, time=10),
             Message('control_change', channel=0, control=93, value=0, time=10),
             Message('control_change', channel=0, control=101, value=0, time=10),
             Message('control_change', channel=0, control=100, value=0, time=10),
             Message('control_change', channel=0, control=6, value=2, time=10),
             Message('control_change', channel=0, control=101, value=127, time=10),
             Message('control_change', channel=0, control=100, value=127, time=10)]

該当トラックへのセットアップデータの挿入

あとは上で作ったメッセージの塊をトラック・オブジェクト(メッセージのリスト)の所定の位置に挿入するだけである。前回のSysExメッセージ挿入後であれば、メタメッセージ2件とあわせて、先頭から3件飛ばした位置に差し込むことになる。これは単なるリスト操作に過ぎない。

# セットアップ・データを所定位置に挿入する
track1[3:3] = setup_msg

挿入後のトラック冒頭は以下のような結果となる。

f:id:daw_jones:20170716161637p:plain

実はこのセットアップ・データの挿入に伴って一番最初のノートオン・メッセージのデルタタイムを修正する必要がある。なぜなら、セットアップ・データの送信時間だけタイミングがズレてしまうからである。これについては、次回詳述する。

*1:実際にはプログラム・チェンジなどの値は各トラックに応じて変更する。なお、プログラム・チェンジの値はゼロ・ベース(0〜127のレンジ)に変換する必要がある。

*2:本例はメロディ・トラック用のもの。リズム用トラックの場合は、一番先頭のバンクセレクトMSBの値を"120"とし、末尾5行のベンド・レンジ設定部分を省く。また本例では、DominoでSMF保存した際に追加された余計なバンクセレクトMSB/LSB(頭から3行目および4行目)を付けたままだが、本来は不要である。これについては後日補足する。

PythonでSMFを操作する (2) SysEx挿入

前回記事の続き(注: かなりマニアックです)。今回はトラック1の1小節目冒頭に所定のSysExメッセージを挿入してみる。

daw-jones.hatenablog.com

下準備

midoパッケージのインポートと、Studio One から書き出したサンプルのSMFファイルをmid変数に読み込むところまでやっておく。

from mido import MidiFile, Message

# 各トラック毎の全メッセージを表示する
def dump_track(track_obj):
    for msg in track_obj:
        print(msg)

# 全トラックの全メッセージをトラック毎に表示する
def dump_smf(midi_obj):
    for i, track in enumerate(midi_obj.tracks):
        print(f"Track {i}: {track.name}")
        dump_track(track)

# Studio One から書き出したSMFを mid に読み込む
mid = MidiFile('smf_studio1.mid')

対象トラックの抽出

SysExメッセージはトラック1に挿入したいと思うので、SMFオブジェクト(上例ではmid変数に格納)を構成するトラック・リストより、トラック1を抜き出して操作することにする*1

mid.tracksの中身を見れば、構成トラックは以下の通りに7件あるが、このうち最初の要素はメタイベント用のトラックなので、トラック1は2番目の要素("Oboe"というトラック名が付いている)ということになる。

f:id:daw_jones:20170716133626p:plain

したがって、トラック1を以下のように抜き出して変数代入する(リストのインデックスはゼロベースなので、2ではなくて1)。

# トラック1を抜き出して、変数"track1"に代入する
track1 = mid.tracks[1]

このトラックの中身は以下のようになっている(11行目以降は省略)。このメッセージ・リストの2番目の要素の直後(メタメッセージの直後)にSysExメッセージを挿入する。

f:id:daw_jones:20170716134356p:plain

メッセージ・オブジェクトの生成

メッセージ・データの作成は非常に簡単で、たとえばGM2音源使用オンのためのSysExメッセージは、以下の1行で済む*2。データ値は10進数のタプルで与える。ここは協会テンプレSMFを上記と同じくmidoパッケージを使って覗いてみた結果をそのままコピーすればよい。他セットアップ用のデータも同様である(次回以降詳述)。

# SysExメッセージの作成
msg = Message('sysex', data=(126, 127, 9, 3))

本メッセージをprintすれば、以下のように中身を表示確認できる。

f:id:daw_jones:20170716140156p:plain

なお、midoパッケージにおける各種MIDIメッセージの仕様については、公式ドキュメントを参照されたい。

メッセージの挿入

トラック・オブジェクトはリストのサブクラスで、要はメッセージのリスト構造になっているので、リスト操作のメソッドが適用可能である。したがって、上記メッセージの挿入は、そのものずばりinsertメソッドで入れてしまえばできあがりである。

# 上記SysExメッセージを2番目の要素の後ろに挿入する
track1.insert(2, msg)

挿入後のトラック1の中身は、以下のようになった(冒頭5行)。

f:id:daw_jones:20170716141707p:plain

*1:元のSMFオブジェクトmidを直接修正してもよいが、ここでは分かりやすくするために該当のトラック・オブジェクトを切り出して編集操作する。[ここからはマニアックな話] Pythonではリストなどのミュータブルなオブジェクトを変数に代入しても、それはオリジナルに対する参照になるため、実は変数track1の中身を操作すると元のmid.tracks[1]にも反映される。「Pythonのリストで参照渡しでないコピーを作成する話」などを参考。

*2:ここではデルタタイムはデフォルトのゼロのままでよい。

小岩井さんのMIDI検定1級合格体験記事

今朝上げた記事の補足。

daw-jones.hatenablog.com

たまたま同タイミングで、小岩井ことりさんのMIDI検定1級合格関連の大変興味深いインタビュー記事が「DTMステーション」に掲載されていたので参考まで。トップ合格であると同時に、2次審査では出題者の外山和彦先生よりS判定を貰っているとはまったく驚嘆するほかない成果である。

www.dtmstation.com

 

記事中でかなり驚いたのは、MIDIデータを2度打ち込んで比較照合することによりミスを炙り出したというくだり。昨年の課題曲は音数少なめだったからこそできた芸当かもしれず。私にはこのアプローチは正直しんどいと思う(無理っす)。

あと楽器音色に応じて複数音源を使い分けておられる点は、案の定というか、私が昨日書いた所感と共通しているところである。個人的に気になったのは、ホルン(ゲシュトップフト奏法含む)はシンセ音色なのだろうか、という点。

ミックスとエフェクト処理は凝りまくってる感じで、ここはもうツールからなにから私は足元にも及ばないな、と僭越ながら感心することしきり。ただ、ステレオ・エンハンサーを使い過ぎでは、と怪訝に思い、小岩井さん自身が制作されたオーディオ(これは結構貴重です)を聴いたら、やっぱり中央がぽっかり抜けてて左右振り過ぎな感は否めなかった。しかし、ハープとかストリングズの音色は結構印象的。またEQやフィルター等駆使して不要な音域を積極的にカットする処理は私も見習いたい。

MIDI検定1級2016年課題曲制作の感想など

掲題の件で、ミックスダウンとマスター編集後のWAVファイル出力まで一通りやってみての感想などを書き記しておき、今後のワークフローの改善などに役立てることとしたい。

曲調などの雑感

2016年課題曲は、はっきり言ってジャズ・ブルーズの名曲 "Summertime" (原曲はジョージ・ガーシュウィンの「ポーギーとベス」)を換骨奪胎した印象を受ける。不協和音を敢えて積極的に盛り込んだ、若干奇異な感じもするクラシック風楽曲で、現代音楽ほどではないがやや難解かもしれない。

リズム・セクションがない楽曲なので、ドラム・パーカッションが入った課題曲を別途練習する必要があることは言うまでもない*1

スコアのボリュームとしては、パート数12および小節数47で、A3用紙6ページという分量である。音数は少ない方なので、ノートの打ち込み自体はさほど難しくはなく、作業量も極端に多いという感じはしなかった。そういう意味では、1級課題曲演習の最初のチャレンジにふさわしいのではないかと思う。また初心者にとっては、クラシックの表現方法やオーケストラ楽器の良き勉強機会を与えてくれる。

本曲はリズム・パートがない分ダイナミックな抑揚表現が大きな勘所で、かつ隠し味の不協和音をあまり目立たせないような各パートの音圧レベル調整も神経を使う。定位(パンポット)については、以下の記事で指摘したとおりである。

daw-jones.hatenablog.com

制作手順について

ノート入力

一番最初は音価100%でノートを次々に打ち込んでいく。ベロシティやコントロール・チェンジ (CC) などは後回しにした。2級実技もそうだが、とにかくノートを入れないことにはまったく前に進まない。

入力順や作業の区切りは、パートごとあるいは譜面ページごと、リハーサル・マークごと、など人によってやりやすい順番で潰していけばよい。私は今回はページ単位に区切って作業を進めた。ただし、そのせいかどうか不確かだが、後の間違い検証で小節丸ごと入力し忘れが2、3箇所あった。どうやらページ変わり目冒頭が特に要注意のようだ。

2級実技演習ではパート毎入力のやり方で慣れているため、そのアプローチも考えられなくはない。しかし、1級のようにパート数が非常に多い場合、このやり方では全体像が把握しづらく、なかなか完成形が見えてこないといった欠点がある。そういう意味では、リハーサル・マーク単位での作業進行がベストかもしれない。

ゲートタイムおよびベロシティやPB/CCの編集入力

これは必ず各パート毎にソロ再生して耳で確認しながら入れる方がよい。同時に譜面と照合してピッチとタイミングの再チェックを兼ねる。

ゲートタイム

協会推奨基準*2を念頭に置きつつ、ある程度適当に手動調整。2級実技ほど厳密に設定する必要はない。

ベロシティ

以前にも書いたように、少なくとも初期入力の段階では協会推奨基準に準拠でよいと思う。あれこれ迷わずに済むからだ。再生確認後に微調整すれば十分だろう。

音量変化と CC#11 Expression

Studio One 編集画面でのCCの変化曲線は、Parabolaを使わずにLineで描いてベンドする(中点をつまんで円弧状に変形させる)方が後からの微修正が楽で効率的であるように思う。

一見区別がつかないため、CCの入力タブ切り替えには注意である。私は今回の演習で、Expression を入れているつもりが After Touch を入力していたり、などというミスがあった(すぐに気づいたものの)。必ず再生チェックして確認すべきところである。

またデフォルト値がゼロのままであるところを気づかずに修正し忘れも要注意である(下図参照)*3。最大値127への戻し忘れももちろんチェックする。当たり前だが必ずソロ再生して問題ないか検証する。

f:id:daw_jones:20170710174115p:plain

ビブラートと CC#1 Modulation

ビブラートは2級実技と違って譜面上は特に指定がないのだが、管楽器系のデュレーション長めのノートにはある程度ビブラートを入れないと平板に聞こえてしまう。少なくともクラリネットオーボエは必要最低限の範囲でビブラートは盛り込むべきだろう。

ただし、サンプリング音色によっては既にある程度のビブラート効果がかかっているものがあり、その場合はくどくなるので重ねてモジュレーションを掛けなくともよいと思う。今回で言えば、Presence XT 音源のピッコロがそれに該当する*4

音源について

率直に言って1級2次審査は音源音色のクオリティでほとんど評価が決まってしまうと思うので、単独の音源にこだわらずに適材適所で使い分けた方がいいだろう(有償無償問わず)。制作時間が限られる本番時点であれやこれやと探索している暇はないだろうから、過去の課題曲演習含めて日頃から各楽器に対応するベストの音源を準備しておく必要がある。

生楽器はほとんどのケースで Presence XT の音色で間に合うと思うが、該当音色がない場合、あるいはその音色に不満がある場合の代用音源としては VSCO2 もいい(過去記事参照)。

bigcatinstruments.blogspot.jp

マスター編集とWAV書き出し

Studio One 3.5 Prime(以下S3)の2ミックスを Tracktion 5(以下T5)にインポートしてマスター編集する。この仕上げ工程は必須だと思う。何度も書いていることだが、構成音のメリハリ強調と、高域と低域(特に低域)の押し上げに必要だからだ。

ただし、S3から各トラック毎ステムを書き出し、T5で再度ミックスダウンからやり直すのは、さすがに時間的に無理だと悟る。いずれにせよS3をProfessional版へアップグレードした暁には、S3とT5の併用に伴う面倒な追加編集は一切無用になってしまう。

SMF作成

今回はオーディオ出力までで、SMFの作成は未着手である。これについては、Dominoで最終確認する前準備の定型プロセスをPythonによる自動バッチ処理に任せたい思惑もあるので、その検証と合わせて追々やっていきたい(すでに記事はシリーズ化)。

もちろん、しょぼいGM音源で再生した場合にどういう感じに聞こえるか、といった点も気になるところではある。

*1:私は一応過去の課題曲(本年分含めて計8曲)は全部やってみるつもりだが、上級者は、クラシック、ジャズおよびロック各1曲ずつ計3曲程度で十分かもしれない。

*2:レガートは音価の100%(レガート終端は90%)、スタッカートは50%、それ以外は概ね80%。あくまで参考基準値であるから楽曲に応じて微調整はする。

*3:全休符を飛ばしてMIDIイベントを分割入力しているとやらかしやすい。

*4:モジュレーション・マトリックスの定義設定については、過去記事を参照。

譜面解釈とMIDI表現 (7) ダブルベース

ダブルベース(コントラバス)の奏法は、弓を使う方法(アルコ)と、弦を指で弾くピチカートの2種類があり、2016年のMIDI検定1級課題曲でも1箇所だけ使い分けが必要である(下記譜例参照)。なお、ダブルベースの楽器自体の解説については下記動画に詳しい。

www.youtube.com

 

2016年課題曲では、下記譜例のとおり、2小節だけピチカートのモードになり、その後アルコに戻る。

f:id:daw_jones:20170711190703p:plain

これはホルンのゲシュトップフト奏法と同じく、MIDI表現の範疇を越えて音源側で対処すべき音色選択の問題である。以下、私が採用した方策の例を述べてみる。

ピチカートについては、 Presence XT の Upright Bass で代用する。Presence XT の他のベース系音色同様にこれはオクターブ下げなくてもよい(記譜通りに発音させる)。なぜなら、既に1オクターブ下げた音色になっているからである*1

一方、弓を使った奏法は Presence XT にふさわしい音色が見当たらなかったため*2、VSCO2音源の Double Bass 音色で差し替えた。この音色は再生時に1オクターブ下げる。

bigcatinstruments.blogspot.jp

いずれにせよ、SMFとして書き出すMIDIデータはDominoでオクターブ下げておく必要がある(はず)。この点は2級実技での対応と同様。

蛇足。上記コントラバスに限らずオーケストラの生楽器については、以下の London Philharmonia Orchestra の楽器解説シリーズが大変勉強になるので参考まで。

www.youtube.com

*1:VSCO2ダブルベース音色とも比較検証したのでたぶん間違っていないはず。

*2:Studio One 3.5 Prime版。上位版ではアルコの音色が含まれている可能性が高い。