Skip to content

Instantly share code, notes, and snippets.

@myu314
Last active January 24, 2020 04:07
Show Gist options
  • Save myu314/395f643bf5d63f154e1cd7f1d1236135 to your computer and use it in GitHub Desktop.
Save myu314/395f643bf5d63f154e1cd7f1d1236135 to your computer and use it in GitHub Desktop.
プチコン3号の音周りの仕様について調べたメモ

プチコン3号音周り関係メモ

プチコン3号の音周りの仕様について調べたメモです。

実機の動作を見ながら大体こんな感じかなーで書きなぐったものなので、正しさはその程度です。 動作の確認は、今のところ v3.5.2 で行っています。

間違い・質問などございましたら、twitter もしくは下の方のコメント欄にお願いします。

twitter: @myu314_petitcom

今後の予定

  • 推敲、書き忘れ追加などなど
  • 一定の再生スピードを超える発生する不具合について調査

音長計算

内部シーケンサの TPQN は 48。

音長の計算で小数点以下は切り捨て。 付点の計算は、切り捨てた値に対して行われる。

R9  = [R192]21  'FLOOR(192/9)
R9. = [R192]31  'FLOOR(FLOOR(192/9) * 1.5)
R9..= [R192]36  'FLOOR(FLOOR(192/9) * 1.75)

MMLの初期値

T120 V127 @0 O4 L4 Q8

音量 (Vコマンド)

Vo = POW(V/128, 2)

パン (Pコマンド)

Pan Law は square root、P=64 の時 -3dB。

Vo(L) = SQR(1-P/128)
Vo(R) = SQR(P/128)

デチューン (@Dコマンド)

Pitch(cent) += 100 * (@D / 64)

マニュアルには @D127 は1音(200cent)高くなると書かれているが、 実際は 198.4375cent で、1.5cent ほど低い。

音色変更 (@コマンド)

音色変更コマンドは 次のキーオンのタイミングで音色を変更する。

C& @5C C    = C&C @5C
[C& @5]2 C  = C @5C& C

ループ ([]コマンド)

  • 音符/休符の無いループはエラーになる

    [ V100 ] 'Illegal MML

  • ループで戻った場合に復元される情報

      V100 [C V50 C]2 C   = V100 C V50 C V100 C V50 C C
      @0 [C @5 C]2 C      = @C C @5 CCC
    

    QコマンドとVコマンドは、おそらくノート情報に埋め込まれるため、ループしても1度目と同じように演奏される。 それ以外の命令はループで戻っても情報は復元されない。

ゲートタイム (Qコマンド)

音の長さを全体の Q/8 だけ鳴らし、残りを休む。スタッカートなどの表現に使う。Q=0 の時は 192分音符の長さで演奏される。 Qコマンドは2つの音を1つの音として扱う&コマンドを除いて、タイやポルタメントには影響しない。

Q4C2        = Q4C4&C4   = Q8C4R4
Q4C4& C4    = Q8C2 Q4
Q4C_G       = Q8C_G Q4

タイ (&コマンド)

&コマンドは 実際には2種類ある。

  • 2つの音を1つの音として扱う

    C2&C4 のように同じ音程の音を スペースや他のコマンドを挟まずに &でつなぐと、 2つの音を1つの音として扱う。この場合 C2. と見なす。

  • MML上の次の音を、キーオン無しで演奏するノートと見なす

上記を踏まえると次のような動作となる。

C4&C4_G     'C2_G と同じ。2拍でCからGまで滑らかに鳴らす
C4& C4_G    '1拍Cを伸ばし、1拍でCからGまで滑らかに鳴らす。上との違いは&の後のスペースだけ
[C&]3G      'CCC&G と同じ。C& の MML上の次の音はループ後のG
C&@5DE      'C&D@5E と同じ。C& の後のDは キーオン無しのノートなので、音色変更はEから反映される
[C&@5]2D    'C@5C&D と同じ。ループ2回目のCは通常のノートなので、音色変更が反映される

特に C& C4_G のように スペースの有無で挙動が変わる点に注意。

&コマンドが繋がる条件

  1. MMLの見かけ上の前の音に&がついている

  2. 演奏中直前のノートに&がついている

    C&[C&]  'Cの音が鳴りっぱなしになる
    C&[C]   'C&C [C] と同じ。ループ2回目のCは条件2を満たしていない
    [C&]2C  'CC&C と同じ。ループ2回目のC&は条件1を満たしてない
    

おそらくシーケンスデータのノートデータには次のフラグが用意されてるのではないかな…。

  • 自分自身に&が付いている
  • MMLの見かけ上の前の音に&が付いている

ポルタメント

音程1[音長1]_音程2[音長2]

音程1から音程2まで、音長1の長さで滑らかに鳴らしたあと、音程2を音長2の長さ維持する。 音長2は指定されていない場合0(=長さ無し)として扱う。

  • ポルタメントコマンドの間にループは挟めない

    [C_]G   'Illegal MML
    
  • ポルタメントの後の音程に音長をつけた場合、 滑らかに繋いだあと後の音程を音長分伸ばす

    L4 C_G  = 1拍でCからGまで滑らかに鳴らす
    L4 C_G  = 1拍でCからGまで滑らかに鳴らしたあと、Gのまま1拍伸ばす
    
  • ポルタメントの前後の音程の間に入れた V,P,@,@MP,@MA,@ML,@D などのコマンドは、ポルタメント開始地点から反映される

    L4 C_ @1G       = @1 C_G
    L4 C&C_@D-128G  = @D-128C2_G    = >B-2_<F
    L4 C& C_@D-128G = C& @D-128C_G  = C&>B-_<F
    

モジュレーション

パラメータ

  • Depth

  • Range

    モジュレーションのかかり具合

    Range * Depth / 128
    
  • Speed

    LFOの周波数

    LFO freq(Hz) = Speed / 2.5
    
  • Delay

    変調し始めるまでの時間

    Delay time(sec) = 2.5 * Delay / 128
    

ターゲット毎の計算式

W   ... Range * Depth / 128
F   ... Speed / 2.5
t   ... 時間
PI2 ... PI() * 2
TRI ... SINの三角波版みたいな関数
  • @MP: Pitch modulation

    W=1 の時、±100centの幅でビブラートがかかる。

    Pitch(cent) += 100 * W * SIN(F * t * PI2)
    
  • @MA: Amp modulation

    振れ幅が [W*0.5 .. W*2.0] になるような波形。 2を超えた場合、クリッピング。

    Vo *= MIN(2, POW(2, W * SIN(F * t * PI2)))
    
  • @ML: Panpot modulation

    W=1, P=64 の時、丁度P0-P127を滑らかに変化する……(64-0 != 127-64 なのでちょっとだけずれるけど)

    Pan += 64 * W * TRI(F * t * PI2)
    

いろいろ

  • テンポに依存しない
  • キーオンごとにリセットされる (…のでオートパンとしては使い辛い)
  • リリース音にもモジュレーションはかかる

エンベロープ

P = 160 / 32728

Attack

  • 音量

    Vo = POW(4*t, 4) / (1 + POW(4*t, 4))
    
  • 時間

    0<= i <= 108

    A=2570*P
    B=-1/32
    T[i] = A / (i + 1) + B
    

    108 < i <= 127

    T[i] = T[108] * (127 - i) / (127 - 108)
    

Decay, Release

  • 音量

    A = 1/128
    Vo *= (POW(A,t) - A) / (1 - A)
    
  • 時間

    0<= i <= 50 の時

    A=64050*P
    T[i] = A / (2 * i + 1)
    

    50 < i < 126 の時

    T[i] = T[50] * (126 - i) / (126 - 50)
    

    126<= i

    T[126] = 4 * P
    T[127] = P
    

Decay Level

V コマンドと同じ。

Vo *= POW(DL / 128, 2)

Decay の音量が Vo に到達した時点で減衰は打ち切られる。

Decay / Releaseの処理

Decay Time は減衰しきる(音量が0になる)までにかかる時間を表す。 減衰中に音量が Decay Level に到達したらそこからキーオフまで現在の音量を維持する。 この時の t を p とする。 つまり実際の減衰時間は Decay Level に依存する。

Releaseの音量計算に使う t は Decay のものを引き継ぐので、0 ではなく p から始まる。 Release Time は t が p から 1 まで変化する時間を表す。 Decay Level によって減衰するカーブは変化するが、0になるまでの時間は変化しない。

内部シーケンサのあれこれ

  • TPQN=48

  • 160サンプル毎にシーケンスデータは処理される。

    次のMMLのように同一のタイミングでキーオン/オフが発生した場合、音は鳴らない。

    'T256 で 192分音符は 159.80...サンプルとなり 160サンプルより僅かに短い
    @E127,127,127,127 T256 C192
    

    またこの仕様上、波形は必ず160サンプル単位で出力される。

ハードウェア関係

  • sampling rate = 32728 Hz

  • samples per audio frame = 160

    音情報が更新される間隔

ユーザー波形定義

WAVSET

  • WAVSET は 基準音程 33 の時、GMセットと同じ高さになる

WAVSETA

  • 配列サイズが 2^n (n=4..14) ではない時、リサンプリングされる

  • 配列サイズが 8193〜16383 の時、ループ範囲が正しく設定されない(BUG?)

  • 配列のサイズによって音程が変わる

    nが1大きくなると1オクターブ下がり、小さくなると上がる。 n=8(256)の時 WAVSET と同じになる。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment