MGSC

MGSDRV向けの mml->mgsコンパイラがgithubに公開されていたので、メモ。

>MGSC@github
https://github.com/digital-sound-antiques/mgsc

>MSXplay.js
>※こちらはmgs形式など、MSX向けサウンドドライバ向けプレーヤ(及び、コンパイラ)
http://digital-sound-antiques.github.io/msxplay-js/index.html

実機で聴くVGMカセット

めも。

>(FC/FC互換機用) 8BIT MUSIC POWER (8ビットミュージックパワー)
http://www.amazon.co.jp/dp/B018I0R4OS/

その後

 第二弾も出たし、CDが発売になっている…(´・ω・)
 CDは正直本末転倒な気もするけど、実機の音をいつでも聴けるのはメリットなのか。あと聴くだけと考えればCDの方が安いね…実機へのこだわりがすべてとも言える作品なんだけども…(´・ω・
)

>(FC/FC互換機用) 8BIT MUSIC POWER (8ビットミュージックパワー)Final
https://www.amazon.co.jp/dp/B01MQU3LW5

>8BIT MUSIC POWER (8ビットミュージックパワー)
https://www.amazon.co.jp/gp/aw/d/B01LW4AAA6/

chiptune 関連のサイト

なんとなくググって出てきた奴ら。
>vgm midi 投稿サイト
http://www.vgmusic.com/

>chiptuneコミュニティサイト
http://chipmusic.org/

>シンセ関連のニュースサイトのログ
http://www.synthtopia.com/content/tag/chiptune/

>ブラウザベースのSIDエミュレータ
http://www.igorski.nl/experiment/websid

>アーケードのコンパネ形態のMIDIコントローラ
http://www.pianocade.com/

>MIDI音源(NES,C64の音源エミュレータ)@kickstarter

>Famicompo PICO
http://bitpuritans.eu/compo/

[VGMPlayer] 標本化と量子化

PCMサンプリングのことを調べると、標本化(sampling)・量子化(quantization)という言葉が出てくる。

標本化:(波形を)時間方向に区切ってデータを集めること。
量子化:(波形を)振幅方向に区切ってデータを集めること。

前回の話がそのへんのことになるけど、正直全然わかっていない。

で、こういった処理をまとめて離散化(Discretization)と呼んでいる。
数学的には、離散数学と呼ばれる分野になるらしい。

PCMサンプリングの場合でいうと、(数学的に定義される”波形”は)本来連続的に変化していて、時間方向や振幅方向にいくら細かく区切っても基本的に連続する性質を持っている。しかし、これを一定の時間経過・一定の振幅量の単位で区切ってPCMデータに変換する。
そしてこの時、データは切り捨て誤差(Truncation error)と呼ばれるデータの欠落を起こす。
こういったデータを扱う学問が、離散数学ということになる。

言葉で書いても分かりづらいので、映像を見てもらうと下のような感じ。

英語なので説明は分かりづらいと思うけども、元々時間も振幅も “continuous(連続的)” だった波形の情報は、標本化及び量子化によって、 “discrete(離散的)” に変化するよ。ということを説明している。

また、実際の標本化・量子化はこんな感じ。というのが次の映像。

[VGMPlayer] WAVデータの生成

(実処理の内容を書けるほど理解できるか不明だが、チップのWAV生成処理周りが判ったら書く。)

 ストリームバッファの充填にも書いた通り “対応チップオブジェクト->StreamUpdate関数” がWAVデータ生成処理。
 実際はChips_GeneralActions関数(Mode=0x1)の処理時に CAA->StreamUpdate に設定される関数内で行われる。(例:sn764xx_stream_update関数)

音、波形、PCMデータとは。
また、基礎的なPCMデータ生成の方法。

 音と波形…基礎の基礎。
音と波形

 波形の量子化(イメージ)。
量子化イメージ

量子化イメージ_2

PCMデータはデジタル化した波形を、以下のような情報として記録する。
・音程について、一定時間毎の周期的な変化量で音の高さを保持。
・音量について、一定単位毎の音の大きさを保持。

量子化波形を、数値で表す
・中央の横線を基準に、上下に±幾つ という形で音の大きさを計る。

 上の図では、時間軸(水平)方向に13本の縦線が引かれている。
 13本の縦線は、それぞれある時点の音の大きさを表している。そして13本の縦線で1周期分の波を形作っている。
 仮に1周期が 1/1000秒だった場合は1秒間に1000周期なので、1kHz(=1000Hz)の音になる。
 波の振幅が大きいほど大きな音量になる。

 それから、記録時の周波数(サンプリング・レート)が仮に48kHzの場合、再生可能な最高周波数は半分の24kHzとなる。これは音が波であり、波には高い部分と低い部分が必ず必要になる(平坦だと波のない状態)。差があってこそ波が発生する。それには最低2つのデータがなくては、音が鳴らない。
 48kHzの場合、データ2個をサンプリングするのに掛かる時間は半分の24kHz分の期間が必要になるので、理論上の最高出力周波数も24kHzということになる。

シンプルな波形(ja.wikipedia.org/wiki/波形より)

Waveforms

PCM関連の情報や解説ページ

>PCMの基礎知識
http://www.hikari-ongaku.com/study/pcm.html

>波形を見る
http://aidiary.hatenablog.com/entry/20110519/1305808715

>JavaScriptで波をつくろう。リアルタイム波形生成&再生
http://d.hatena.ne.jp/yanagia/20100323/1269334226
https://github.com/yanagia/jsaudio

WindowsがPCM再生をどう行っているのか。

 WAVデータ&出音の原理の方を先に把握しないと、処理の意味が読み取れない..

>Waveフォーマット・PCM・サンプリング周波数・ビット数・チャンネル数とは
http://soundengine.jp/wordpress/tips/glossary/113/
>WAVとは
http://soundengine.jp/wordpress/tips/glossary/1944/

>WindowsPCが音を出す仕組み
http://www.spatiality.jp/pcaudio-research/pc-transport/software/windows-audio

>WAVEデータの作成と再生
http://www13.plala.or.jp/kymats/study/MULTIMEDIA/waveOut_create.html

>PCM の基本
http://wisdom.sakura.ne.jp/system/winapi/media/mm5.html

[VGMPlayer] ストリームバッファの充填を行う処理

 VGMPlayerはそもそも、以下のような動作イメージになる。

処理のイメージ

 で、VGMPlayerのキモの部分は、図のWAV生成の部分。
 ストリームバッファの充填は、以下の処理でWAV生成を行うことで実現される。

  • VGMデータを解釈しチップにデータを設定:InterpretVGM
  • チップ出力のストリーム情報を取得:ResampleChipStream
InterpretVGM関数

 VGMデータを先頭から順に解釈して対応するチップにデータをセットしていく。(VGMデータ仕様はここを参照)

 基本的に、並んでいるデータを順番にチップへ設定していくものなので、早送・巻戻などを無視すれば特に複雑な部分はないと思われる。
 ただVGMの対応チップ数が結構多いので、関数内の処理の把握をしようとした場合はそれなりに手間。

ResampleChipStream関数

 前段のInterpretVGM関数で設定されたデータによるチップの出音結果(32bit Stereo WAVデータ)を受け取る関数。
 処理的には “対応チップオブジェクト->StreamUpdate関数” を呼び出して、得たストリームデータの音量計算と出力バッファへの転送を行う。
 また、出力バッファへの転送については単なるコピー処理以外に幾つかのモード(OLD-resample, Up-sample, Down-sample)によるリサンプリング機能持つ。

[VGMPlayer] 処理の大雑把なところ

コードを準備する

 ソースコードをDLして適当な場所に展開後、VGMPlay.dswを開けばソリューションを開くことができる。

 Visual Studio Express 2013 for Windows Desktopでも可能だった。

 おためしで実行したければ、「ビルド > ソリューションのビルド」でDebugフォルダ下に VGMPlayer.exe が作成される。

コードの中身

 コードはC++で書かれているので、main関数から追っていけば大雑把なことは判る。

UIを使わないで…って考えた場合は、
最後の関数は PlayVGM(); でもよさげ。
ReadOptions関数も、初期設定でよければ不要。
バッファへのデータ充填は後述。

 PlayVGM_UI 関数は名前通りユーザー入力を受けて再生操作(一時停止, 早送, 巻戻..)できる作りになっているので、対応するストリーム生成処理にも初見だと若干判りにくい部分を感じる。
 ただ、やっていることはそんなに多くないので、順を追えば把握できると思う。

  • キー受付
    • キー受付に付随する各種操作
  • サンプル時間の計算
  • ストリームバッファの充填
ストリームバッファの充填

 出音については「サンプル時間の計算~ストリームバッファの充填」が判らないとどうにもならないので、UI処理は基本忘れてストリームバッファの充填をいかにして行っているかの理解に努めたい。
 ストリームバッファの充填に必要なパラメータとしてUI処理を理解しなければならない場合は、追々解析を行えば良いかと思う。

 そしてストリームバッファの充填は、その名の通り FillBuffer 関数が行っている。
 当該関数の内部動作を中心に理解を進めれば、大雑把に動作を把握できるのではないかと思われる。(当該関数が引数に取るものは、16bit Stereo Buffer 及び Buffer Size)
 ただしコードはオブジェクト指向なスタイルではなく、ちょくちょくグローバル定義の変数にアクセスするので、よく使われる変数の正体を逐次類推しながらの作業になる。
 関数・変数・定数各々の機能については、把握できている事柄を順次コメントに追記しながら進めていった方が良いが、extern定義の場合には参照元の定義にコメントを集約しておきたい。

VGMPlayer

音源エミュレータ&プレイヤー実装は、これが一番手っ取り早そう。
※たいがいの音源をカバーしている。2013/11くらいで更新されなくなって、ひとまず完成している感じ。

VGMPlayer紹介ペ-ジ(@SMS Power)


>VGMPlayer関連情報 wiki
http://vgmrips.net/wiki/VGM_Players

>Droidsound-E(for Android-App)
※SNES関連の音源再生も可能
※既存のモジュールの押し込み方の参考にもなるかも..
https://github.com/droidmjt/Droidsound