ラベル 独自音源 の投稿を表示しています。 すべての投稿を表示
ラベル 独自音源 の投稿を表示しています。 すべての投稿を表示

2012年3月5日月曜日

分解率(解決)

昨日、独自PSG音源の分解率(分解性能)のことで難産してましたが、解が見えてきました。

VG-Engineの音声システムは、100ミリ秒の周期で発音情報をD/A変換(ディジタルデータを音に変換)する形で音声を鳴らしています。WindowsとAndroidで、この部分の実装に用いる仕組みは違いますが、理屈は同じ。

  • Windows(DirectSound)の場合: 次の動作をする専用スレッドでループ処理
    1. 100ms分の音バッファを作る
    2. D/A変換
    3. 100再生完了のイベント待機
  • Android(OpenSL|ES)の場合:  100ms再生完了する都度、次の処理を実行(コールバック)
    1. 100ms分の音バッファを作る
    2. D/A変換

で、独自PSG音源+ドライバ(音源を発音させたり、消音させたりする処理部分のこと)は、何れも「100ms分の音バッファを作る」処理部分で実装してます。

問題があったのは、独自PSG音源の①発音(キーオン)、②消音(キーオフ)、③無音で処理をスイッチ的に切り分けていたこと。だから、そこでドライバのキーオンやキーオフの指示を処理するのが難しかった訳です。

なので、その部分の処理をスイッチ的に切り分けるのではなく、キーオン、キーオフ、無音などの状態に関係無く、常に(元々の)①発音(キーオン)相当として処理すれば良い訳です。

偉そうに言ってますが、実はコレ(スイッチ的に切り分けること自体が)、単純なバグじゃないか・・・
・・・ということに、この記事を書いていて気付きました。
何故昨日、気付かなかったし。
まぁ、バグとは得てしてそういうものか。
(ロジック的なバグは、処理を言葉で書いて整理すれば、解決し易い)

分解率=分解性能(かなり厄介)

先ほどの記事で、独自PSG音源のドライバ(バイナリのMMLを鳴らす機能)の分解率(分解性能と呼ぶべきか?)を22050回/秒にしようとしましたが、処理実装上、それは不可能・・・ではないけど、もの凄く複雑なことになりそうです。

素直に、音源とドライバは別スレッドで独立させてあげれば楽。
中々面倒です。
しかも、そうなると、分解率は1000回/秒か。
まぁ、1秒間に1000回も音符を鳴らす音楽は想定されないけど。

もの凄い複雑な処理をあくまでもシングルスレッドで実装するか。
又は、簡素にマルチスレッドで実装するか。
私の好みは前者ですが。
スレッドはオーバーヘッドが大きいので、不可避な事情が無い限り、使わない派。

プログラミングを始めた頃(11歳頃)から現在にかけて出会った、難しいロジックのベスト30位以内に入ると思います。公私で膨大な量のプログラムを日々作り続けているから、あまり定かではないですが。

さて、どうしたものか。。。

全然関係ありませんが、、プログラミングを始めた歳を書いて気付きました。
来年でプログラミング歴20年のようです。
時が経つのは、何とはやいことか・・・


2012年3月4日日曜日

分解率

独自PSG音源のMMLを実装していますが、分解率は、秒間22050回にする方向で。
つまり、周波数(22050Hz)と同じ。
分解率というのは、1秒間に音符を鳴らせる回数の上限。
その分、処理負荷が掛かりますが、この分解率如何で表現の幅が変わるから、ここは落とせない。
これを最大限に細かくするために、周波数を22050Hzにしたり、音色を固定プリセットにしたりするなど、処理性能を最大限に高めたといっても過言ではないです。

これが完成すれば、独自PSG音源について、残すTODOはMMLコンバータとMIDIコンバータを作る等の面倒な作業を残すのみ。

MMLコンバータは良いけど、MIDIコンバータは規格を解析するのが少しだけ面倒くさい。
なので、MMLコンバータ単体で作り易くしておき、MIDIコンバータは後付にする方向。
というより、MIDIコンバータは作りらないかも。
昔(PC-9801の頃)は、PMDのMMLで何一つ不自由しなかったし。

中々美しく響きます

独自PSG音源で、高音部が上手く鳴らせなかったのですが、どうもプリセットするバッファサイズが小さいことが原因だった模様。

1秒の周波数 = 88200Hz

という実際に鳴らす音(22050Hz)の×4のバッファサイズをプリセットに準備することで解決。
ようやく機械調整での調律が完了。

以下↓は、この状態で手何も手を入れずに、エンベロープを実装して鳴らしたもの。
http://www.k2.dion.ne.jp/~ysuzuki/seikou2.mp3

良い感じで、美しく鳴ってくれました。

×4バッファなら手動調整は不要そうです。
これで、独自PSG音源の音源部はほぼ完成か。

FM音源は要らないかな。
VG-Engineは、PC-Engine並のソフトウェア音源搭載が目標なので。
個人的には、ゲーム音楽用の音源として、FM音源はゴージャス過ぎる気がするというのもあります。
性能を落としてまで、FM音源を搭載させる価値を見出せません。

調律・・・

独自PSG音源の調律を行うために、オクターブと音色を選択できるように改造。

現状の音程を一通りの音色で一通り鳴らしてみましたが、かなりの調整が必要そうです。
これは、特定の波形データを特定の音程で出すシミュレータを作り、それを用いる形で作業が要りそうです・・・なかなか、そういった目的に適うソフトは無い・・・自分で作るしかなさそうです。

エンベロープとMML


(1)エンベロープ

エンベロープについては当初、アルゴリズムパターンを選択する方式にしようとしていましたが。

  • キーONしてから出力100%になるまでの時間(100ms単位)
  • キーOFFしてから出力100%になるまでの時間(100ms単位)
を任意値で指定できる仕様が一番良さそう。

(2)MML

楽曲データはMML→(独自コンバータ)→バイナリ形式というのが当初想定。
しかし、MIDIシーケンサ(SSWとか)でお手軽に作曲したいので、
MIDI→(独自コンバータ1)→MML→(独自コンバータ2)→バイナリ形式
の方向で。

MIDIからダイレクトにバイナリ形式にしてしまうと、エンベロープや音色等の細かい選択ができなくなってしまうので、ワンクッション(MML)を設けるのが適当。MIDIの特定パラメタ(イベント)を利用してダイレクト変換する方式もアリといえばアリですが、MIDIの解析が面倒なので、MIDIからは純粋にノート(音程+音の長さ+音の強さ)の情報のみ拾う感じにするつもり。

本当はピスコラ(ピストンコラージュ)からノート情報を拾いたいんですが....
(ピスコラのバイナリフォーマットは非公開なので、独自に解析するのが面倒)


純旋律で調整(成功)

純旋律で調整してみたところ、無事成功。

http://www.k2.dion.ne.jp/~ysuzuki/seikou.mp3

最後に「プツッ」と切れてしまうのは、エンベロープのアルゴリズムを実装すれば解消するので問題ではありません。今の所、キーオフすればブッツリ切っているから、それが問題なだけです。(つまり、大した問題ではありません)


厄介なのは、Dの音とかがノイズっぽい感じのところとか。
音程はあっています。
なので、これは周波数ではなく波の形状(波形)の問題。

今のところ、C言語で計算式で求めた波形データを元に、C言語の配列宣言の形式で出力するCGIプログラムを使ってメモリ波形情報を(85音階分)プリセットし、それを使って鳴らしています。
なので、波形データは編集自由。

音程の調律は無事完了しましたが、音色の質を調整する調律も必要です。
この部分(アナログデータ)は、流石に機械計算に任せきりにはできません。
この作業で、独自PSG音源の品質が決まるから、ここは手を抜けません。

この部分(音色の質)をシッカリ作りこめば、音色数の少なさは、大した問題ではない筈。
音色数=三角波、ノコギリ波、短形波の3種類+ノイズ
量の少なさは質でカバーする。

純平均律

どうも、純粋な平均律は、一般的な聴きなれた音階ではないようでした。

http://www.k2.dion.ne.jp/~ysuzuki/shippai2.mp3

上記は、以下の周波数で三角波を鳴らしたもの。


C 275.0000
C# 293.3333
D 311.6667
D# 330.0000
E 348.3333
F 366.6667
F# 385.0000
G 403.3333
G# 421.6667
A 440.0000
A# 476.6667
B 513.3333
C 550.0000


計算で鳴らしているのではなく、予め計算されたプリセット(1周期分の波形を準備したもの)を用いて鳴らしているので、微妙な誤差が生じるのは想定の範囲内ですが、ここまで違うとなると純粋な平均値で求めた音階というのは、一般的な平均律とは違うということ・・・かな?

そろそろ思考が停止してきたので、明日考えるか。

2012年3月3日土曜日

これは酷い

とりあえず、三角波のテスト波形ができたので、VG-Engineに載せて、ついでに以下のような鍵盤プログラムを作成し、ドレミファソラシドを演奏してみました。

結果は、
これは酷い()笑

あまりにも酷すぎるので、記念に録音しておきました。
http://www.k2.dion.ne.jp/~ysuzuki/shippai.mp3

これ、ドレミファソラシドって鳴らしています。(念のため)
一応、音程は変わっているので、基本的な理論は正しくできているようです。
なので、実験は失敗ですが概ね成功。

さて、鬼調整でもするか。

音程周波数のアルゴリズム化

音声プログラミング一般の理論は、前記事の書籍で大丈夫。
ただ、音程周波数のアルゴリズム化はその本では話題にしていないから自分で作る必要がありそう。

まず、音程というのは、波の周期(0→正方向の波→負方向の波→0)を単位時間(1秒)内に何回繰り返すかで決まります。そして、その単位のことを周波数(波の周期の回数)といい、ヘルツ(Hz)という単位で表記します。(音量は波の大きさで決まる)

で、ラ(A)の周波数は、

  • オクターブ5=880Hz
  • オクターブ4=440Hz
  • オクターブ3=220Hz
という具合に決まっています。

オクターブnのAの周波数がmHzであれば、オクターブn+1のAの周波数は2mHz

Aの音は全ての楽器の基準周波数になっているので、人間が一番聞き分け易い音です。
絶対音感が無い人でも、「Aの音だけは分かる」という人は結構居るものです。
ベースなど弦楽器のチューニングはAでやるし、オーケストラや室内楽なんかでも、演奏する前にA音の調整(チューニング)をしてます。ついでに、音楽大学の音の聞き分けテスト(そんなんあるんかい?)なんかでも、聞き分ける音の間にA音を鳴らしているようなことが漫画(のだめ)に描いてあったような気がします。

他の11個の音程(A#, B, C, C#, D, D#, E, F, F#, G, G#)の求め方は諸説色々あります。
一番シンプルなのは平均律。
半音=(55×オクターブ)÷12Hzの増加
という単純計算。
※55は12で割り切れない(4.583333333...になる)から、諸説乱立する訳です

で、コンピュータでアルゴリズム化する場合、55も1秒(1000ミリ秒)で割り切れないから更に厄介。
18.181818....回、波形の周期を繰り返せば、オクターブ1のラになる訳です・・・
18×55=990msなので、ラ音では1%の誤差が生じます。
平均律だと、ラ音以外にも強かに誤差が生じる筈。
この辺りの誤差は、実際に鳴らしてみて微調整するしか無いですねぇ....
まさか、ディジタル楽器を作るのに調律が必要になるとは。

とりあえず、
  • オクターブ1のA~G#の波形パターンをオンメモリでプリセットする
  • 配列サイズ(周期)は小数点以下は切り捨てて考える
という感じで、作ってみます。
性能優先なので、違和感があった場合、DDT又は配列サイズの調整で調律する感じ。
(浮動小数点数は重いので使わない)

とりあえず、三角波の波形パターンを作ってみてテストしてみようと思います。
あ・・・あと、サイン波は音が気に入らなかった(使いどころが少なそうだった)し、面倒くさいので、落とす方向で。(三角波、ノコギリ波、短形波+ノイズで実装する方向)

良書(音関連)

VG-Engineの独自PSG音源を実装するにあたり、先ずは、波形と周波数の関係が分かり易く解説されている理論書を探しに本屋に行ったところ、良書過ぎる良書を発見。


C言語ではじめる音のプログラミング
サウンドエフェクトの信号処理
青木直史・著(オーム社/出版局)
http://www.amazon.co.jp/C%E8%A8%80%E8%AA%9E%E3%81%A7%E3%81%AF%E3%81%98%E3%82%81%E3%82%8B%E9%9F%B3%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E2%80%95%E3%82%B5%E3%82%A6%E3%83%B3%E3%83%89%E3%82%A8%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E4%BF%A1%E5%8F%B7%E5%87%A6%E7%90%86-%E9%9D%92%E6%9C%A8-%E7%9B%B4%E5%8F%B2/dp/4274206505


ウチの近所の本屋では、プログラミング関連の本の所ではなく、ディジタル信号処理関連の本の所に有りました(理論ベースで調べようとして正解)。まだ、全体をパッと斜め読み(速読)しただけですが、独自PSG音源を実装する上で必要な理論は一通り揃っていて、尚且つ、C言語で解説つき。

一般的な理論書から音(波形や周波数)の理論をC言語に落とし込む手間が省けます。
ついでに、(入門書的な位置づけのようなので)書いてある内容も簡素。

独自音源(ソフトシンセ)を実装したい人に、オススメの一冊です。
まあ、普通の人はwav、ogg、mp3でお手軽に鳴らせれば良いんでしょうけど。
普通じゃない人は、理論書ベースで何ら苦労しない簡単な内容だから、そもそも、こういう本が存在することを期待していなかったので、ラッキーでした。

VG-Engine 2.00の強化

とりあえず、INVADER BLOCK2に開発については、一通りの作業が完了したっぽいです。
AndroidMarketの場合、かなり本腰を入れて販促活動(プロモーション)をしないと全然売れないと思うので、公開開始してからがスタートラインの気がしないでもないですが。
ただ、Android/Windowsの独自ソース共通化エンジン(VG-Engine)を強化する作業を優先。

■VG-Engine version 2.00に向けた強化点

  • 効果音の合成:INVADER BLOCK2では不要だったけど、他ゲームでは必要。
  • 音源搭載:独自PSG音源を搭載する。

音関連だけです。

グラフィック方面も強化の為所は有りますが・・・回転、拡大縮小、半透明など。
ただ、それらは無ければ無くても何とかなる。

「音源搭載」も、BGMを全てPCMで鳴らせば何とかなりますが、それだと容量がデカくなり過ぎる。
如何に、スマホのダウンロード性能が早くて、大容量のストレージを積んでいたとしても、その部分に頼るのは、プログラマの信義に反します。

という訳で、独自PSG音源のスペックとしては、

  1. モノラル
  2. 同時発音数:6チャネル
  3. 波形:サイン波、三角波、ノコギリ波、矩形波の4種類(固定)+ノイズ
  4. エンベロープ:固定アルゴリズムパターンから選択
  5. フィルター、モジュレーション、エフェクト等:なし
各チャネルで、任意の波形・エンベロープ・音量・音程で音を鳴らすことができる・・・という仕様。
まぁ、ほぼPC-Engineの内臓音源と同等スペックだと思います。
不要な奢侈機能は実装しない方向で。
独自シンセにすると、性能が悪くなるので。
「独自シンセなのに高性能」を目指したい。
ローパスフィルタ、ハイパスフィルタぐらいなら有っても良いかもしれませんが。(軽いので)

私は、音関連の知識は素人同然なので、まずは、波形と周波数の関係とかの勉強が必要。
面倒くさそうなもの&有益度が低いものについては随時省いて、完成を早めたいところです。
とりあえず、PCMを鳴らす機能はINVADER BLOCK2に載せているVG-Engine version 1.00で完成しているから、後は音の仕組み(理論)さえ理解すれば良いので、完成は結構早いと思います。(音を聞くことができれば、理論の理解は容易な筈)

合理的ではないものを作りたい

ここ最近、実機版の東方VGSの開発が忙しくて、東方VGSの曲追加が滞っています。 東方VGS(実機版)のデザインを作りながら検討中。基本レトロUIベースですがシークバーはモダンに倣おうかな…とか pic.twitter.com/YOYprlDsYD — SUZUKI PLAN (...