HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2009
0620
p、USAGIエンジン音の作り方15解決


p、USAGI

リンク

2009/6/20(Sat) 03:50:49|NO.25857

レースゲームのエンジン音の作り方を教えて下さい。
エンジン音っぽく(なるべくなめらかに)聞えればいいので。

とりあえず試してみたこと↓
1.midiapi.as(ちょくとのページより)を使って、エンジンの回転数によって音階を変え毎回停止&再生。
結果→エンジンの回転数によって音が鳴る。
しかし、いろんな音色で試してみたがエンジン音っぽく聞こえない。

2.まずWAVEファイル(低音〜高音)をひとつ作る。
hmm.dllを使って、エンジンの回転数によって毎回再生する位置を変える。
結果→回転数によって再生されるが音がぶつ切りに…

3.まずWAVEファイル(低音〜高音)を複数ファイル作る。(例:00.wavは低音、19.wavは高音)
hmm.dllを使って、エンジンの回転数によって毎回再生するファイルを変える。
結果→回転数によって再生されるようだが、処理落ちが激しすぎてよくわからん…



「レースゲーム エンジン音 作り方」でググってみた。(あまり関係のないものもあるけど…

ISD12-2.html
http://homepage3.nifty.com/isd-hp/TEXT/ISD12-2.html
エンジンの回転数と音程の正しい対応について - CRI Middleware Co., Ltd.
http://www.cri-mw.co.jp/product/column/2nt4hm0000001juy.html
効果音の作りかた
http://www.nintendo.co.jp/nom/0106/koukaon/make/index.html
GAMERS EDEN ゲーム音楽のしくみ
http://gamerseden.kir.jp/gm_sikumi/gmsikumi.html



この記事に返信する


GENKI

リンク

2009/6/20(Sat) 11:42:23|NO.25860

1.適当なエンジン音を拾ってきてWaveSpectraとかでFFTのデータを作る。

2.FFTのデータから1周期分(数秒程度?)の音を作る。
  waveファイルにするかリアルタイム生成かはお好きなほうで。
  →そのまま流せば一定の回転数のエンジン音になります。
   音の切れ目もたぶんないはずです。

3.回転数によって音の高低を調整しつつ音を作る。
  FFTから作るか、E3DSetSoundFrequencyを使う。


参考資料:
http://hsp.tv/play/pforum.php?mode=pastwch&num=21985



とりあえず「音」の仕組みと波形の作り方から調べたほうが速いかもしれませんね。
midiでエンジン音ってだいぶ無茶な気がします…。



Sucret

リンク

2009/6/20(Sat) 23:00:09|NO.25878

hmm.dllを使って、エンジン音を無限ループで違和感無く聞こえるように再生位置を設定して、
その上でエンジン音の再生速度を変えたらならないでしょうか?
再生速度を速めれば高音になるり、遅くすれば低音になるので走行速度が速い時は再生速度も早く、
走行速度が遅い時は再生速度も遅くすればできそうな気がするんですが、

試していないので分かりませんが参考の一つ位になれれば幸いです。



p、USAGI

リンク

2009/6/22(Mon) 08:06:08|NO.25969

>GENKIさん
>Sucretさん
返信ありがとうございます。

>とりあえず「音」の仕組みと波形の作り方から調べたほうが速いかもしれませんね。
すこし調べましたが、自分にはむずかしいのでじっくりと理解していきたいと思います。

>FFTのデータを作る。
(「FFT」ググる前に思ったのは某SRPG。
つまり、「123123123..」という音があるとした場合、「123」の部分だけを抜き取る(又は作成する)ということですね?



RAY

リンク

2009/6/22(Mon) 11:38:56|NO.25970

操作に少々MIDIに関する知識が必要なうえ、まだまだ改良の余地がありますが、
最低限の機能としてこんな感じでどうでしょう?
WindowsXP以上なら動作するはずです。
停止時にエンジン音のピッチを下げても面白いかも知れませんね。

#include "midiapi.as"; ちょくと様の"midiapi.as"を追加して下さい title "Sample" screen 0,640,480,0,(ginfo(20)-640>>1),(ginfo(21)-480>>1); // ウィンドウ初期化 onexit *_end; // 終了処理 MidiOpen -1; "Microsoft GS Wavetable SW Synth"を指定すること sdim lmes,11,1 lpoke lmes,0,0x421041F0 lpoke lmes,4,0x7F004012 wpoke lmes,8,0x4100 poke lmes,10,0xF7 SendMidiLongMsg lmes,11 SendMidiMsg2 0x0100B0 SendMidiMsg2 0x007DC0 SendMidiMsg2 0x0064B0 SendMidiMsg2 0x0065B0 SendMidiMsg2 0x1506B0 SendMidiMsg2 0x4000E0 pb=$4000 *_main stick key,256 if key==128 : goto *_end if key==256 : if keyFlg=0 : keyFlg=1 : SendMidiMsg2 0x7F3090 if key==000 : if keyFlg=1 : keyFlg=0 : SendMidiMsg2 0x003080 if keyFlg==1 : SendMidiMsg2 0x0000E0+(pb<<8) : pb+=80 : if pb>$7F00 : pb=$7F00 if keyFlg==0 : SendMidiMsg2 0x4000E0 : pb=$4000 await 20 : goto *_main *_end MidiClose end



RAY

リンク

2009/6/22(Mon) 11:43:26|NO.25971

連投すいません…。
マウスクリックで発音。
pb+=80 の値を変えれば変化速度が変わります。
SendMidiMsg2 0x1506B0 の 15 の部分の値を変えればどこまで高くなるかが変わります。
以上です。



GENKI

リンク

2009/6/23(Tue) 00:30:30|NO.25980

> 「FFT」ググる前に思ったのは某SRPG。

もちろん舌をかみそうな名前の某ゲームのことではありません。
ググって知ってるかもしれませんが一応簡単な解説。

FFT(フーリエ変換)とはこの場合、音の波形を分析して、どの周波数がどのくらいの音量かを調べる方法のこと。
横軸時間、縦軸音量の音の波形をFFTすると、横軸周波数、縦軸音量のグラフになります。
これを元に、全部の周波数分、各音量にあわせたSIN波を作って、それらを全部重ねると元の音の波形に戻すことが出来ます。

FFTは難しいのでWaveSpectraとかのツールを使わないと自力は無理。プログラム内でやる必要もないですし。

ちなみに横軸周波数のグラフの段階でグラフ全体を左右に移動すれば全体の音が高くなったり低くなったりします。

ちと難しいっぽい話になったので適当に聞き流してください。(^ ^;


> 「123123123..」という音があるとした場合

むう。この前提よくわからないです…。



p、USAGI

リンク

2009/6/23(Tue) 10:26:47|NO.25981

>Sucretさん
>hmm.dllを使って、エンジン音を無限ループで違和感無く聞こえるように再生位置を設定して、
>その上でエンジン音の再生速度を変えたらならないでしょうか?
やってみましたが、Win ME : CPU 120MHz の私のPCでははげしく処理落ちします。
DirectShow再生サンプルにも、
>//倍速再生はパワーをかなり使います。
>//セレロン500MHzぐらいだとつらいかも
とありました。


>RAYさん
サンプル有難うございます。すごいです。
どんな意味のMIDIメッセージを送信しているのかさっぱりですが。


>GENKIさん
グラフ(WaveSpectraの下画面)はある程度 理解できました。
ただいま「WAVEデータの作成」を勉強中です。

>むう。この前提よくわからないです…。
失礼しました。忘れてください。(汗



RAY

リンク

2009/6/23(Tue) 19:06:39|NO.25983

>どんな意味のMIDIメッセージを送信しているのか…

MIDIメッセージについてはスペース的にここでは全ては説明しきれませんので、
もし興味があれば詳しくは専門の書籍やサイト等をご覧になって各自学んで下さい。

簡単に内容を説明しますと、
"Microsoft GS Wavetable SW Synth"(XP以降では標準搭載、それ以前はDirectXに付属)
…の本体である "gm.dls" をMIDIメッセージで操作しています。
サンプルでは省略していますが本当ならデバイス名を取得して確認し、
このデバイスを確実に開けるようにするべきです。
GM音源と言いつつデバイス名にある通り、実はGS音源です。
但しそれらを扱う為には専用の初期化が必要です。
それをやっているのが "SendMidiLongMsg lmes,11" のところで、
その上にある poke で内容を定義しています。
これでGSモードになりましたので次の2行のSendMidiMsg2でエンジン音の音色を呼び出しています。
次の4行のSendMidiMsg2はピッチに関する設定とピッチの初期化をしています。
SendMidiMsg2 0x1506B0 の 15 の所がピッチレンジ(範囲)。
すなわち 0x15 = 21(十進)半音分のレンジを表します。適当に調節して下さい。
メインルーチンでマウスをクリックした時にフラグが立っていなければ発音、離したら停止。
フラグが立っている時に次々と値を加算してピッチを上げているのが pb+=80 の所。
正確にはこの変数の1byte目にも0x80(128[十進])以上の値が入ってはいけないのですが、
MSGSでは特にエラーにならないのでそのまま代入しています…。
なので本来は0x80以上で第2byte目に繰り上がるように適当に作り変えて下さい。

SendMidiMsg2系のメッセージは全て第1byte目の下位4bitがチャンネルを表しますので、
サンプルで言うところの 0 の部分を変えてそれぞれ($0〜$F)に設定すれば、
16チャンネル分の音を個別にピッチを変えて再生出来ます。
カーレースなら16台まで同時に走行出来る事になります。

ちなみに余談ですが、GS音色には他にも車の衝突音やブレーキ音など、
カーレースで使えそうな効果音も沢山入っています。
これらも設定する事で音量や定位、ピッチ等を変えながら、
ノートオンメッセージひとつで再生することが出来ます。

…まあ、簡単ではありますが上記スクリプトの説明はこんな感じです。
長文失礼しました。



p、USAGI

リンク

2009/6/25(Thu) 05:49:33|NO.26012

>RAYさん
わかりやすい解説ありがとうございます。
かなり参考になりました。

今回のゲームはWaveで行こうかと思います。
本当はMIDIのほうが軽い(処理)のですがゲーム本編がまったく制作してないので、
MIDIを勉強している時間がありません。

今後のために聞きます。↓
MIDIを勉強できるようなサイトなどありませんか?
それとも書籍で学んだ方がよいのでしょうか?



あり

リンク

2009/6/25(Thu) 11:21:42|NO.26014




SYAM

リンク

2009/6/25(Thu) 11:59:15|NO.26015

MIDIは電子楽器を制御するインターフェースであって、極端にいえばそれ自体は「音を出すものではない」ですから、効果音には不向きです。
ユーザーの環境によっては、何らかの電子楽器を接続してそれを使う設定になっていた場合には意図しない動作になります。

たとえば、アクセルを踏むとパソコンの横に置いてある電子ピアノがぽーーん(↑)と変な音を出すなんてことになります。



p、USAGI

リンク

2009/6/25(Thu) 23:18:36|NO.26020

>ありさん
>SYAMさん
返信ありがとうございます。
参考にしたいと思います。



p、USAGI

リンク

2009/6/26(Fri) 06:53:45|NO.26027

とりあえず自分的にはうまくいったと思っていますが、よろしければアドバイスして下さい。


下のスクリプト(モジュール)は、試行錯誤しながらテスト用に作ったので無駄が多いと思います。
(そこは無視して下さい)
音声データも改良予定(まぁほとんど改良しますが…)
自分用なのでコメントもほとんどありません。

※起動後1〜2分ほどお待ち下さい。

インクルード用ファイル↓ "waveOutEngine01.hsp"で保存してください。

#uselib "winmm.dll" #func global waveOutOpen "waveOutOpen" sptr, sptr, sptr, sptr, sptr, sptr #func global waveOutPrepareHeader "waveOutPrepareHeader" sptr, sptr, sptr #func global waveOutWrite "waveOutWrite" sptr, sptr, sptr #func global waveOutReset "waveOutReset" sptr #func global waveOutUnprepareHeader "waveOutUnprepareHeader" sptr, sptr, sptr #func global waveOutClose "waveOutClose" sptr ;#define SAMPRATE 11025 //サンプリングレート(変更可) ;#define BITSPERSAMP 8 //量子化ビット数(変更不可) ;#define NCHANNELS 1 //チャンネル数(変更不可) ;#define BUFCNT 2 //多重バッファ数 oncmd gosub *OnWomDone, $000003BD/*MM_WOM_DONE*/ #module #deffunc Waveloop int kaiten repeat BUFCNT bcnt = cnt repeat bufsize/4 lpoke bWave(bcnt), cnt*4, lpeek(kWave(bcnt,kaiten),cnt*4) loop loop return #deffunc StartProc duration = 80 SAMPRATE= 11025 //サンプリングレート(変更可) BITSPERSAMP= 8 //量子化ビット数(変更不可) NCHANNELS= 1 //チャンネル数(変更不可) BUFCNT = 2 //多重バッファ数 //WAVEFORMATEX構造体を用意 dim wfe, 5 wfe(0) = $00000001/*WAVE_FORMAT_PCM*/ + (NCHANNELS<<16) //wFormatTag + (nChannels<<16) wfe(1) = SAMPRATE //nSamplesPerSec wfe(2) = SAMPRATE*NCHANNELS*BITSPERSAMP/8 //nAvgBytesPerSec wfe(3) = (NCHANNELS*BITSPERSAMP/8) + (BITSPERSAMP<<16) //nBlockAlign + (wBitsPerSample<<16) wfe(4) = 18 //cbSize //WAVEHDR構造体を用意 bufsize = (duration)*int(1.0*SAMPRATE/1000) sdim bWave, bufsize, BUFCNT //音声データ格納用バッファ sdim kWave, bufsize, BUFCNT,401 //音声データ格納用バッファ dim whdr, 8, BUFCNT repeat BUFCNT whdr(0, cnt) = varptr(bWave(cnt)) whdr(1, cnt) = bufsize whdr(4, cnt) = $00000004|$00000008 //WHDR_BEGINLOOP|WHDR_ENDLOOP whdr(5, cnt) = 1 loop //波形データを作成/////////////////////////// PI=3.141592653589793 //円周率 dim otovol,25 dim Hz,25 otovol(0)=127.0*1046.4/20000,127.0*3514.75/20000,127.0*4694.37/20000,127.0*1566.45/20000,127.0*1569.91/20000 //音量 otovol(5)=127.0*607.88/20000,127.0*874.27/20000,127.0*496.59/20000,127.0*512.61/20000,127.0*620.43/20000 //音量 otovol(10)=127.0*1504.62/20000,127.0*1291.39/20000,127.0*541.55/20000,127.0*315.37/20000,127.0*816.32/20000 //音量 otovol(15)=127.0*272.51/20000,127.0*372.11/20000,127.0*210.69/20000,127.0*277.78/20000,127.0*193.45/20000 //音量 otovol(20)=127.0*515.95/20000,127.0*337.9/20000,127.0*316.53/20000,127.0*23.15/20000,127.0*190.67/20000 //音量 Hz(0)=118.4,226.1,344.5,463.0,570.6 Hz(5)=689.1,807.5,915.2,1033.6,1152.0 Hz(10)=1270.5,1378.1,1496.6,1615.0,1722.7 Hz(15)=1841.1,1959.5,2067.2,2185.6,2304.1 Hz(20)=2411.7,2530.2,2648.6,2777.8,2874.7 repeat 401 kaitencnt=cnt repeat BUFCNT bcnt = cnt repeat bufsize val=128 count=cnt repeat 25 len=1.0*SAMPRATE/(Hz(cnt)*(1.0*(kaitencnt+1)/(401/4))) d=PI*2/len*(count) val+=(sin(d)*otovol(cnt)) loop poke kWave(bcnt,kaitencnt), cnt, limit(val,0,255) loop loop pset cnt*100/401,cnt*100/401 //進行状況(テスト用) await 0 loop repeat BUFCNT bcnt = cnt repeat bufsize poke bWave(bcnt), cnt, 128 loop loop //WaveOutの初期化 hWaveOut = 0 waveOutOpen varptr(hWaveOut), $FFFFFFFF/*WAVE_MAPPER*/, varptr(wfe), hwnd, 0, $00010000/*CALLBACK_WINDOW*/ repeat BUFCNT waveOutPrepareHeader hWaveOut, varptr(whdr(0, cnt)), 32 loop repeat BUFCNT waveOutWrite hWaveOut, varptr(whdr(0, cnt)), 32 loop return #deffunc StopProc //WaveOutの後始末 waveOutReset hWaveOut repeat BUFCNT WaveOutUnprepareHeader hWaveOut, varptr(whdr(0, cnt)), 32 loop waveOutClose hWaveOut return #deffunc EngineStop StopProc flgPlay=0 return #deffunc EngineStart StartProc flgPlay=1 return #deffunc ExitProc onexit StopProc return #global goto *@f *OnWomDone //バッファの再生が終了するごとに呼ばれる waveOutWrite wparam, lparam, 32 return *@
インクルード用ファイル↑ "waveOutEngine01.hsp" ここまで
/////////////////////////////////////////////////////////
メインスクリプト↓

screen 0,300,300 : title "[左クリック] = アクセル" centerpos=300/2 //中心点 kaiten=0 //回転数 onexit gosub *ending #include "waveOutEngine01.hsp" EngineStart *main redraw 2 getkey ky,1 //[左クリック] kaiten=limit(kaiten+(ky*50*2)-25*2,800,9999) : kaiten+=((rnd(100)*(kaiten<=800))-(rnd(50)*(kaiten>=9999))) //エンジン音処理↓ Waveloop 1*kaiten/25 //描画処理↓ color : boxf : color 0,100,255 : pos 50,230 : mes "MIN" : color 255 : pos 230,230 : mes "MAX" d=3.141593*2/(360*2)*((270.0/10 *kaiten/1000*2)+(135*2)) cx=centerpos+cos(d)*125 : cy=centerpos+sin(d)*125 color 255,240,150 line cx,cy,centerpos,centerpos : circle centerpos-2,centerpos-2,centerpos+3,centerpos+3 mes ""+kaiten+"rpm" redraw 1 await 16 goto *main *ending end



emg

リンク

2009/6/27(Sat) 14:32:24|NO.26051

もはや本読んでエンジンの構造を理解して、エンジンをプログラムでシミュレートしたほうがはやいんじゃね?
実際に音出すときはdsoundxのプラグイン使って、wavでつなぎ目あわせて、周波数指定してloopさせて・・



p、USAGI

リンク

2009/6/28(Sun) 03:50:58|NO.26054

>emgさん
ありがとうございます。


一応解決しました。
皆さんありがとうございました。



ONION software Copyright 1997-2021(c) All rights reserved.