2015年5月30日土曜日
2015年5月27日水曜日
Windows:マイクロ秒精度のタイマー
Dxlibに頼らないFM音源ドライバーになりそうだったので、Dxlibに頼ってた関数を
Windowsの標準APIに置き換え。ほとんどがファイル関連だった。最後に残った
マイクロ秒精度のタイマーは音楽関連では必須なので、これを自分用に変換。
ググったらあんまりいいのがなかったので自分で解決。
これでマイクロ秒精度のタイマーが取得できる。
周波数はアプリの最初に一度だけ取ってきたら良いらしい。その時に0が返って
来たら、そのシステムがこの関数に対応してないそうなので、ミリ秒系のを使う
しかないらしい。timeGetTime()とかを1000倍してあげればいいのかしら。
Windowsの標準APIに置き換え。ほとんどがファイル関連だった。最後に残った
マイクロ秒精度のタイマーは音楽関連では必須なので、これを自分用に変換。
ググったらあんまりいいのがなかったので自分で解決。
LONGLONG MyGetNowHiPerformanceCount(void){
LARGE_INTEGER liFreq;
LARGE_INTEGER liNowTime;
QueryPerformanceFrequency(&liFreq);
QueryPerformanceCounter(&liNowTime);
return ((liNowTime.QuadPart * 1000 * 1000) / liFreq.QuadPart) ;
}
これでマイクロ秒精度のタイマーが取得できる。
周波数はアプリの最初に一度だけ取ってきたら良いらしい。その時に0が返って
来たら、そのシステムがこの関数に対応してないそうなので、ミリ秒系のを使う
しかないらしい。timeGetTime()とかを1000倍してあげればいいのかしら。
Windows:ウィンドウアプリでもadpcmダメ
うまいこといったのでポポポンとZPDを読み込んでバラして一個づつ鳴らすのを
コピペ、ビルドを通して実行。
結果、DxLibの時と同じ鳴り方でした。最初の方だけチラっと鳴るだけ。
残念・・。
コンソールとウィンドウアプリではマルチメディアタイマの扱いが違うのか、
何か根本的に違うのか、今の僕では全然わからない!!
というわけで、一旦X68sound.dllでFMと一緒にadpcmを鳴らすのは保留とします!!
今後の新曲はWAVやOGGを鳴らす方を使えば実害は無いのでOKとします。
でも・・、adpcmを独自解析して鳴らすという方向性もまだ残されている・・。
どうしようかしら・・。
コピペ、ビルドを通して実行。
結果、DxLibの時と同じ鳴り方でした。最初の方だけチラっと鳴るだけ。
残念・・。
コンソールとウィンドウアプリではマルチメディアタイマの扱いが違うのか、
何か根本的に違うのか、今の僕では全然わからない!!
というわけで、一旦X68sound.dllでFMと一緒にadpcmを鳴らすのは保留とします!!
今後の新曲はWAVやOGGを鳴らす方を使えば実害は無いのでOKとします。
でも・・、adpcmを独自解析して鳴らすという方向性もまだ残されている・・。
どうしようかしら・・。
Windows:プリコンパイルヘッダの恐怖
adpcmがちゃんと鳴らない原因を探るため、DxLibを使わないWindowsアプリを
作成中。
コンソールアプリでは、ZPDを分解してadpcmが一つづつ鳴る事を確認!
やった!
次は、ウィンドウアプリだ、ということで、ウィザードに任せて空のアプリを作り、
そこにいつものx68sound.h sound_iocs.h x68sound_load.cpp sound_iocs.cpp
を加えてビルド。エラー出まくり。
プリコンパイルヘッダがなんだと色々文句(warning)が出てきてるし、エラーも
出てビルドできず。
色々やるもダメで、帰宅。
ウチにいる間に頭が冷却されたのか、今朝、もう一回やってみたら、うまくいった。
原因はプリコンパイルヘッダだった!
stdafx.h stdafx.cpp
これらは、コンパイルのスピードをアップするもので、何か規約的なものがあって
それに沿って作られていれば非常にありがたいものらしい。コンパイルの時間が
3倍になるとか!
http://www.geocities.co.jp/Hollywood/2358/mfc_7.html
でも、現代ではCPUのスピードもあがってビルドで待たされる事はほぼ無いよね。
なので、
<< C/C++→プリコンパイル済みヘッダー→プリコンパイル済みヘッダーファイルを使用 >>
これをオフにしてみた。そしたら動いた!
あ、あと一箇所、UNICODEをマルチバイトにする必要もある。
<<全般→文字セット→マルチバイト文字セットを使用する>>
これでDLLが読み込まれてた。
でもまだadpcmを鳴らすトコまでは行ってない。どうなるのか!?
作成中。
コンソールアプリでは、ZPDを分解してadpcmが一つづつ鳴る事を確認!
やった!
次は、ウィンドウアプリだ、ということで、ウィザードに任せて空のアプリを作り、
そこにいつものx68sound.h sound_iocs.h x68sound_load.cpp sound_iocs.cpp
を加えてビルド。エラー出まくり。
プリコンパイルヘッダがなんだと色々文句(warning)が出てきてるし、エラーも
出てビルドできず。
色々やるもダメで、帰宅。
ウチにいる間に頭が冷却されたのか、今朝、もう一回やってみたら、うまくいった。
原因はプリコンパイルヘッダだった!
stdafx.h stdafx.cpp
これらは、コンパイルのスピードをアップするもので、何か規約的なものがあって
それに沿って作られていれば非常にありがたいものらしい。コンパイルの時間が
3倍になるとか!
http://www.geocities.co.jp/Hollywood/2358/mfc_7.html
でも、現代ではCPUのスピードもあがってビルドで待たされる事はほぼ無いよね。
なので、
<< C/C++→プリコンパイル済みヘッダー→プリコンパイル済みヘッダーファイルを使用 >>
これをオフにしてみた。そしたら動いた!
あ、あと一箇所、UNICODEをマルチバイトにする必要もある。
<<全般→文字セット→マルチバイト文字セットを使用する>>
これでDLLが読み込まれてた。
でもまだadpcmを鳴らすトコまでは行ってない。どうなるのか!?
2015年5月26日火曜日
Windows:FM音源はほぼ終了
怪しい所はあるにはあるが、FM音源周りに関しては以前のデータが同じ感じで
鳴るようになってきた。長かった・・。
■繰り返しの恐怖
|: |:cdefg:| gfedc:|
なんていう繰り返しのネストが可能だったのをだいぶ後に気づき、
ネスト対応にする為にえらく苦労した・・。ハマった。
・相対的に指定する
・ループエンドを見つけたら前にたぐってループスタートを見つける
この2点を思いついたら意外と少ないコードで実現できた。よかった。
■オクターブの恐怖
よくわかんないが、繰り返しの中でオクターブの上下をしても、
繰り返しから出たら元通りになるという仕様を発見。なんだこれ。
これも悩みに悩んだけど、繰り返し展開のスタート時にオクターブ
をセットするということを思いついて、なんとかなった。
■ポルタメントとLFO
ピッチ問題は後にひきまくって、数日かけてめちゃくちゃになって
しまった。ハマった。
そこで、
・オクターブと音階とKF
はOPMに寄り添わず、独自の方式で運用し、最後の最後に
独自方式からOPM対応方式に変換するという方法を思いつき、
作ってみたら意外とサックリいけた。
この方式を採用後、ピッチ関連のポルタメントとLFOが実現可能に。
ポルタメントは数日かけて悩みまくったがなんとか鳴るように。
LFOは耳コピ的に同じ数字を入れたらいい感じっぽくなるように。
sin()を使う所で結構ハマった。
sin((DX_PI / 120) * 経過時間 * 波の幅)
これでうにゅうにゅとLFOがかかるようになった。
とにかくピッチ関連はハマった。
■adpcm沼
半日くらいかけて検証してみたが、どうにもadpcmが鳴らない。
ZPDデータをバラして、一つ一つのPCMにしてファイルセーブ、
PCMをWAVに変換、WAVをOGGに変換、OGGをリストにして
読み込み、ノートデータから鳴らすということはできたので、
とりあえずめんどくさいが曲を鳴らす事は可能になった。
しかし、adpcmをそのまま鳴らしたい!という欲求が出て、
ひたすら検証をしてみた。
・普通に鳴らすと、ちょっとだけ鳴ってすぐに音が切れる。
・同じコードをコマンドラインでビルドして試した所、普通に鳴った。
そこで、DxLibが何かしてるのかと思いDxLibの息のかからない
所で鳴らしてみた。やっぱりダメ。
今の所、ウィンドウズアプリとしては僕の実力では鳴らせない。
コマンドラインのアプリだったらいけるのに。なんでだー!!
鳴るようになってきた。長かった・・。
■繰り返しの恐怖
|: |:cdefg:| gfedc:|
なんていう繰り返しのネストが可能だったのをだいぶ後に気づき、
ネスト対応にする為にえらく苦労した・・。ハマった。
・相対的に指定する
・ループエンドを見つけたら前にたぐってループスタートを見つける
この2点を思いついたら意外と少ないコードで実現できた。よかった。
■オクターブの恐怖
よくわかんないが、繰り返しの中でオクターブの上下をしても、
繰り返しから出たら元通りになるという仕様を発見。なんだこれ。
これも悩みに悩んだけど、繰り返し展開のスタート時にオクターブ
をセットするということを思いついて、なんとかなった。
■ポルタメントとLFO
ピッチ問題は後にひきまくって、数日かけてめちゃくちゃになって
しまった。ハマった。
そこで、
・オクターブと音階とKF
はOPMに寄り添わず、独自の方式で運用し、最後の最後に
独自方式からOPM対応方式に変換するという方法を思いつき、
作ってみたら意外とサックリいけた。
この方式を採用後、ピッチ関連のポルタメントとLFOが実現可能に。
ポルタメントは数日かけて悩みまくったがなんとか鳴るように。
LFOは耳コピ的に同じ数字を入れたらいい感じっぽくなるように。
sin()を使う所で結構ハマった。
sin((DX_PI / 120) * 経過時間 * 波の幅)
これでうにゅうにゅとLFOがかかるようになった。
とにかくピッチ関連はハマった。
■adpcm沼
半日くらいかけて検証してみたが、どうにもadpcmが鳴らない。
ZPDデータをバラして、一つ一つのPCMにしてファイルセーブ、
PCMをWAVに変換、WAVをOGGに変換、OGGをリストにして
読み込み、ノートデータから鳴らすということはできたので、
とりあえずめんどくさいが曲を鳴らす事は可能になった。
しかし、adpcmをそのまま鳴らしたい!という欲求が出て、
ひたすら検証をしてみた。
・普通に鳴らすと、ちょっとだけ鳴ってすぐに音が切れる。
・同じコードをコマンドラインでビルドして試した所、普通に鳴った。
そこで、DxLibが何かしてるのかと思いDxLibの息のかからない
所で鳴らしてみた。やっぱりダメ。
今の所、ウィンドウズアプリとしては僕の実力では鳴らせない。
コマンドラインのアプリだったらいけるのに。なんでだー!!
2015年5月18日月曜日
2015年5月16日土曜日
2015年5月15日金曜日
Windows:FM音源鳴ってきた
ZMSのパーサーをじっくりと作りつつ、ようやくFM音源が鳴りだしてキタ!
今覚えているウチに「えーそうなの!?」みたいのを覚書しておこう!
■音色設定方法
音色の設定方式は、通常形式と、AL/FB分離形式というのがあるらしい。
FM音源使ってた時は、分離形式しか使ってなかったので、通常形式は
記憶の彼方に飛んでいっていた。しかし、OPMに書き込む為にはここは
避けては通れない。
AF(フィードバック/アルゴリズム) = (FL(フィードバックレベル)*8) + CON(FM operator connection)
という形でAFを作ったり、直接3bitづつFLとCONを書き込んだり。
まあ、分かれてる方が音が作りやすいわね。なんで一つになってたんだろ?
■音程がわかりにくい
X68kFM音源の神、GORRYさんがTWITTERで言っていた。
4MHzのYM2151にデータシート通りの音階を設定すると「3半音-8セント」ほど高い音が出る(Cを出したつもりがほぼD#の音階で鳴る)ので、そこはドライバ側で吸収する必要がある
ここをきっちり「3半音-8セント」で計算しないで「3半音」で計算して、8セントはデチューン命令でゲタをはかせて与えるという実装もそこそこある。うちのドライバが「^20(=8セント)が標準」だったのはそういう実装
ちなみにこの「3半音ずらす」ときに「単純にKCレジスタ設定値から3引く」と正しくない。KCレジスタに与える音階値は0-2,4-6,8-10,12-14だけが有効で、3,7,11,15は無効値なので
どうも、YM2151への供給クロックが、業務用3.579MHz / X68000用 4.00MHz
今覚えているウチに「えーそうなの!?」みたいのを覚書しておこう!
■音色設定方法
音色の設定方式は、通常形式と、AL/FB分離形式というのがあるらしい。
FM音源使ってた時は、分離形式しか使ってなかったので、通常形式は
記憶の彼方に飛んでいっていた。しかし、OPMに書き込む為にはここは
避けては通れない。
AF(フィードバック/アルゴリズム) = (FL(フィードバックレベル)*8) + CON(FM operator connection)
という形でAFを作ったり、直接3bitづつFLとCONを書き込んだり。
まあ、分かれてる方が音が作りやすいわね。なんで一つになってたんだろ?
■音程がわかりにくい
X68kFM音源の神、GORRYさんがTWITTERで言っていた。
4MHzのYM2151にデータシート通りの音階を設定すると「3半音-8セント」ほど高い音が出る(Cを出したつもりがほぼD#の音階で鳴る)ので、そこはドライバ側で吸収する必要がある
ここをきっちり「3半音-8セント」で計算しないで「3半音」で計算して、8セントはデチューン命令でゲタをはかせて与えるという実装もそこそこある。うちのドライバが「^20(=8セント)が標準」だったのはそういう実装
ちなみにこの「3半音ずらす」ときに「単純にKCレジスタ設定値から3引く」と正しくない。KCレジスタに与える音階値は0-2,4-6,8-10,12-14だけが有効で、3,7,11,15は無効値なので
どうも、YM2151への供給クロックが、業務用3.579MHz / X68000用 4.00MHz
というような歴史があるらしく、その辺もしっかりとイミュレートしているx68sound.dll
なので、その通り音階を入れてあげないといけない。ここは面倒くさくてハマった。
なので、CとDは音程が狭い。なんだこれ。
■マルチメディアタイマーの発見
かなり正確に指定msecごとにCALLBACKしてくれるのがWindowsにあるらしい。
早速使ってみたら、いい感じ!!invokeの時は60分の1秒でしか色々できなかった
ので、結構ズレまくってた。
それでも16msecごとなんだけどね。描画があったりで時々ガッっとズレてた。絵は
少々ズレてもカ・ワ・イ・イでなんとかなったけど、音は流石にズレるとしんどい。
最近捨てたT3exのシーケンサーを思い出す。小節ごとにグっと待ちが発生する
ナイスなシーケンサー。
■繰り返し
これがハマった!!繰り返しの実装は本当に大変だった・・。ZMSでは簡単に
|:16 cdefg :|
なんて書けちゃうけど、これを実現するのは本当にめんどくさい!!ズレるのが
嫌だったから、イベントは絶対時間で持っておいたので、絶対時間の足し込みが
すげーめんどくさかった。でもなんとかなった・・かな?
2015年5月12日火曜日
Windows:ハマったところ
現在自作のアプリでFM音源を鳴らしたくて、X68sound.dllを組み込めるか実験中。
10年以上前のソースコードとの格闘中に色々とハマったのでメモ。
■CからC++へ
元々のソースコードはCで記述してあるので、関数の宣言時にヘッダに初期値を
入れる事ができていた。ヘッダへ初期値を入れる場合はC++の場合はクラス化
してコンストラクタに入れるのが正しいのかな?とにかくコンパイラがエラーを
出すので、初期値をはずす。
関数呼び出し時も初期値を省くことができるCと違って、C++はちゃんと入れて
あげる必要がある。ここもハマった。
■fopenとfopen_s
昔おなじみのファイルを扱うfopenも、現在ではセキュリティの低いAPIとして
使うなと怒られる。fopenをそのままfopen_sにしてもダメで、引数と戻り値が
違うのでハマった。
if((fp = fopen(filename,"rb")) == NULL)
こんな感じのは良くみる。このifでエラー処理を入れるのが普通。
それを
if(fopen(&fp,filename,"rb") == NULL)
だけではダメで、
if(fopen(&fp,filename,"rb") != 0)
10年以上前のソースコードとの格闘中に色々とハマったのでメモ。
■CからC++へ
元々のソースコードはCで記述してあるので、関数の宣言時にヘッダに初期値を
入れる事ができていた。ヘッダへ初期値を入れる場合はC++の場合はクラス化
してコンストラクタに入れるのが正しいのかな?とにかくコンパイラがエラーを
出すので、初期値をはずす。
関数呼び出し時も初期値を省くことができるCと違って、C++はちゃんと入れて
あげる必要がある。ここもハマった。
■fopenとfopen_s
昔おなじみのファイルを扱うfopenも、現在ではセキュリティの低いAPIとして
使うなと怒られる。fopenをそのままfopen_sにしてもダメで、引数と戻り値が
違うのでハマった。
if((fp = fopen(filename,"rb")) == NULL)
こんな感じのは良くみる。このifでエラー処理を入れるのが普通。
それを
if(fopen(&fp,filename,"rb") == NULL)
だけではダメで、
if(fopen(&fp,filename,"rb") != 0)
とする。ハマった。
■文字コード
昔のはマルチバイトに対応してないプロジェクトもそのままあるので、ファイルを
扱う場合はマルチバイトにする必要あり。
プロジェクト→プロパティ→構成プロパティ→全般
にある、「文字セット」を変える必要アリ。ハマった。
2015年5月4日月曜日
2015年5月3日日曜日
2015年5月2日土曜日
登録:
投稿 (Atom)