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


HSPTV!掲示板


未解決 解決 停止 削除要請

2025
0829
usagiXAudio2を使った再生5解決


usagi

リンク

2025/8/29(Fri) 17:44:50|NO.103884

こんにちわ。
XAudio2でwavを再生するモジュールを作ってみました。
mmplayなどに比べ「DLL不要、多重再生、途中ループ、音量、パン、ピッチ、フィルター」が魅力かと思います。
Win10以降で動くと思います。("XAudio2_9.dll"標準で搭載されている環境)
なるべくシンプルにしたので、ちょっと無駄があるかもしれませんが、
もっとこうする方が良い、これは良くないなどご意見頂けると嬉しいです。
改変、組み込みもご自由にどうぞ。

※wavの途中ループはWavosaurなどのsmplチャンクを編集できるツールで保存。

;=============================================================================== ; 簡易XAudioモジュール v1.0 author: usagi file: ezXAudio.hsp ;=============================================================================== #ifndef __EZXAUDIO__ #define global __EZXAUDIO__ #module "ezXAudio" ; DLL #uselib "msvcrt.dll" #cfunc malloc "malloc" int #func free "free" int #uselib "kernel32.dll" #func VirtualProtect "VirtualProtect" var,int,int,var #uselib "XAudio2_9.dll" #func XAudio2Create "XAudio2Create" var,int,int ; COM #define IID_IXAudio2 "{2B02E3CF-2E0B-4ec3-BE45-1B2A3FE7210D}" #usecom IXAudio2 IID_IXAudio2 #comfunc CreateSourceVoice 5 var,var,int,float,int,int,int #comfunc CreateSubmixVoice 6 var,int,int,int,int,int,int #comfunc CreateMasteringVoice 7 var,int,int,int,int,int,int #comfunc StartEngine 8 #comfunc StopEngine 9 ; Dummy Function #uselib "" #cfunc float "" float #func __GetVoiceDetails "" int, var #func __SetFilterParameters "" int, var, int #func __SetVolume "" int, float, int #func __SetOutputMatrix "" int,int,int,int,var,int #func __DestroyVoice "" int #func __Start "" int, int, int #func __Stop "" int, int, int #func __SubmitSourceBuffer "" int, int, int #func __FlushSourceBuffers "" int #func __ExitLoop "" int, int #func __GetState "" int, var, int #func __SetFrequencyRatio "" int, float, int ; Overwrite Function #deffunc local overwriteFunction int _libptr, int _pp, int _index dupptr p, _pp, 4 : dupptr pfuncs, p, (_index+1)*4 : dupptr _sdat, _libptr, 28 : _sdat.6 = pfuncs._index : return #define ctype def(%1,%2,%3=_p) overwriteFunction libptr(%2),%3,%1:%2 %3 ; ------------------ #deffunc local _GetVoiceDetails int _p, var _details def( 0, __GetVoiceDetails), _details : return stat #deffunc local _SetFilterParameters int _p, var _filterParams def( 8, __SetFilterParameters ), _filterParams, 0 : return stat #deffunc local _SetVolume int _p, double _vol def(12, __SetVolume), _vol,0 : return stat #deffunc local _SetOutputMatrix int _p, int _srcCh, int _dstCh, var _lvMtx def(16, __SetOutputMatrix), 0,_srcCh,_dstCh,_lvMtx,0 : return stat #deffunc local _DestroyVoice int _p def(18, __DestroyVoice) : return stat #deffunc local _Start int _p def(19, __Start), 0, 0 : return stat #deffunc local _Stop int _p def(20, __Stop), 0, 0 : return stat #deffunc local _SubmitSourceBuffer int _p, int _pBuffer def(21, __SubmitSourceBuffer), _pBuffer, 0 : return stat #deffunc local _FlushSourceBuffers int _p def(22, __FlushSourceBuffers) : return stat #deffunc local _ExitLoop int _p def(24, __ExitLoop), 0 : return stat #deffunc local _GetState int _p, var _state def(25, __GetState), _state, 0 : return stat #deffunc local _SetFrequencyRatio int _p, double _ratio def(26, __SetFrequencyRatio), _ratio, 0 : return stat ; ------------------ #deffunc local machinecode int _p, array _code VirtualProtect _code, varsize(_code),$40, _ : dupptr _sdat, _p, 28 : _sdat.6 = varptr(_code) : return #defcfunc local getInputChannels int _p res = 0,0,0,0 : _GetVoiceDetails _p, res : return res.2 #defcfunc local getInputSampleRate int _p res = 0,0,0,0 : _GetVoiceDetails _p, res : return res.3 #defcfunc local getStateBuffersQueued int _p res = 0,0,0,0 : _GetState _p, res : return res.1 #defcfunc local getStateSamplesPlayed int _p res = 0,0,0,0 : _GetState _p, res : d = 0.0 : lpoke d,0,res.2 : lpoke d,4,res.3 : return double(strf("%I64u",d)) #defcfunc local checkID var _data, str _identifier, int _offset mref identifier, 65 : identifier = " " : lpoke identifier, 0, lpeek(_data, _offset) : return identifier == _identifier #defcfunc local dupChunkData var _dup, var _data, int _offset size = lpeek(_data, _offset + 4) : dupptr _dup, varptr(data) + offset + 8, size : return offset + 8 + size ; Once #deffunc local call_once __float = $0424448b, $c3909090 : machinecode libptr(float), __float ; mov 0x4(%esp),%eax ; ret xaInit 1024, 2, 0, 0 return ;=============================================================================== ; コマンド ;=============================================================================== ; 初期化 ;----------------------------- #deffunc xaInit int _max, double _freqRatio, int _channels, int _sampleRate if m_pXAudio != 0 { xaDeinit } ; Reset m_voiceMax = _max m_freqRatio = limitf(_freqRatio, 1.0/1024.0, 1024.0) dim m_pSourceVoice, m_voiceMax dim m_pAudioData, m_voiceMax dim m_pAudioDataSize, m_voiceMax dim m_loopBegin, m_voiceMax dim m_loopLength, m_voiceMax dim m_loopCount, m_voiceMax ; XAudio2 Start XAudio2Create m_pXAudio, 0, 1 newcom m_XAudio, IID_IXAudio2, -1, m_pXAudio if stat != 0 : return -1 CreateMasteringVoice m_XAudio, m_pMasteringVoice, _channels, _sampleRate, 0, 0,0,0 if stat != 0 : return -1 return 0 ; 読み込み ;----------------------------- #deffunc xaLoad str _file, int _id, int _count, int _flags flags = 0 if _flags & 1 : flags |= 0x0002 ; *XAUDIO2_VOICE_NOPITCH if _flags & 2 : flags |= 0x0008 ; *XAUDIO2_VOICE_USEFILTER if _id >= m_voiceMax : return -1 xaDel _id xaLoop _id, 0, 0, _count exist _file : sdim data, strsize : bload _file, data if (checkID(data,"RIFF", 0) && checkID(data,"WAVE", 8)) = 0 : return -1 offset = 12 repeat -1 if offset >= varsize(data) : break if checkID(data,"fmt ", offset) { offset = dupChunkData(fmtChunk, data, offset) continue } if checkID(data,"data", offset) { offset = dupChunkData(dataChunk, data, offset) continue } if checkID(data,"smpl", offset) { offset = dupChunkData(smplChunk, data, offset) m_loopBegin._id = smplChunk.11 m_loopLength._id = smplChunk.12 - smplChunk.11 continue } offset = dupChunkData(_, data, offset) loop m_pAudioDataSize._id = varsize(dataChunk) m_pAudioData._id = malloc(m_pAudioDataSize._id) dupptr audioData, m_pAudioData._id, m_pAudioDataSize._id memcpy audioData, dataChunk, m_pAudioDataSize._id CreateSourceVoice m_XAudio, m_pSourceVoice._id, fmtChunk, flags, m_freqRatio,0,0,0 if stat != 0 : return -1 xaPan _id, 0 return 0 ; 削除 ;----------------------------- #deffunc xaDel int _id if m_pAudioData._id != 0 { free m_pAudioData._id m_pAudioDataSize._id = 0 m_pAudioData._id = 0 } if m_pSourceVoice._id != 0 { _DestroyVoice m_pSourceVoice._id m_pSourceVoice._id = 0 } return #deffunc xaDelAll repeat m_voiceMax : xaDel cnt : loop return ; 再生 ;----------------------------- #deffunc xaPlay int _id, int _mode xaStop _id if m_pAudioDataSize._id == 0 : return xaudio2_buffer.0 = 0x40, m_pAudioDataSize._id, m_pAudioData._id, 0, 0 xaudio2_buffer.5 = m_loopBegin._id, m_loopLength._id, m_loopCount._id, 0 _SubmitSourceBuffer m_pSourceVoice._id, varptr(xaudio2_buffer) _Start m_pSourceVoice._id return stat ; 停止 ;----------------------------- #deffunc xaStop int _id if m_pSourceVoice._id == 0 : return _Stop m_pSourceVoice._id : _FlushSourceBuffers m_pSourceVoice._id return stat #deffunc xaStopAll repeat m_voiceMax : xaStop cnt : loop return ; ポーズ ;----------------------------- #deffunc xaPause int _id if m_pSourceVoice._id == 0 : return _Stop m_pSourceVoice._id return stat ; リジューム ;----------------------------- #deffunc xaResume int _id if m_pSourceVoice._id == 0 : return _Start m_pSourceVoice._id return stat ; ループ ;----------------------------- #deffunc xaLoop int _id, int _st, int _ed, int _count m_loopBegin._id = _st : m_loopLength._id = _ed - _st if _count < 0 { m_loopCount._id = 255 } else { m_loopCount._id = limit(_count, 0, 255) } return stat #deffunc xaExitLoop int _id if m_pSourceVoice._id == 0 : return _ExitLoop m_pSourceVoice._id return stat ; 音量 ;----------------------------- #deffunc xaVol int _id, double _vol if m_pSourceVoice._id == 0 : return _SetVolume m_pSourceVoice._id, _vol return stat ; 周波数 ;----------------------------- #deffunc xaFreq int _id, double _ratio if m_pSourceVoice._id == 0 : return _SetFrequencyRatio m_pSourceVoice._id, _ratio return stat ; 定位 ;----------------------------- #deffunc xaPan int _id, double _pan if m_pSourceVoice._id == 0 : return srcCh = getInputChannels(m_pSourceVoice._id) dstCh = getInputChannels(m_pMasteringVoice) ; TODO: 現状ステレオのリニアパンニングにだけ対応 if dstCh = 2 { l = limitf(0.5 - _pan * 0.5, 0, 1) r = 1.0 - l if srcCh = 1 { ; L_IN ;------------------- lvMtx.0 = float(l) ; L_OUT lvMtx.1 = float(r) ; R_OUT _SetOutputMatrix m_pSourceVoice._id, srcCh, dstCh, lvMtx } if srcCh = 2 { ; L_IN : R_IN ;----------------------------- lvMtx.0 = float(l), float(0) ; L_OUT lvMtx.2 = float(0), float(r) ; R_OUT _SetOutputMatrix m_pSourceVoice._id, srcCh, dstCh, lvMtx } } return ; フィルター tyep: enum { LowPass, BandPass, HighPass, Notch } ;----------------------------- #deffunc xaFilter int _id, int _type, double _freq, double _oneOverQ if m_pSourceVoice._id == 0 : return filterParams = _type, float(_freq), float(limitf(_oneOverQ, 0, 1.5)) _SetFilterParameters m_pSourceVoice._id, filterParams return ; 情報 ;----------------------------- #defcfunc xaStat int _id, int _mode if m_pSourceVoice._id == 0 : return ; TODO: 種類を増やす、番号整理(もしくは小分けにする) if _mode = 4 : return getInputChannels(m_pSourceVoice._id) if _mode = 5 : return getInputSampleRate(m_pSourceVoice._id) if _mode = 16 : return getStateBuffersQueued(m_pSourceVoice._id) if _mode = 17 : return getStateSamplesPlayed(m_pSourceVoice._id) return ; 破棄 ;----------------------------- #deffunc xaDeinit onexit if m_pXAudio = 0 : return StopEngine m_XAudio repeat m_voiceMax : xaDel cnt : loop _DestroyVoice m_pMasteringVoice : m_pMasteringVoice = 0 delcom m_XAudio : m_pXAudio = 0 return #global call_once@ezXAudio #endif ;=============================================================================== ; テスト xaLoad dir_tv+"se_block2.wav", 0, -1, 2 : xaPlay 0 xaLoad dir_tv+"se_shot.wav" , 1 xaLoad dir_tv+"se_bom.wav" , 2 *MAIN vol = 1.0 - (double(mousey)/ginfo_sy) freq= vol pan = (double(mousex)/ginfo_sx)*2.0 - 1.0 title strf("pan=%f, freq=%f, stat=%f", pan, freq, xaStat(0, 16)) xaFilter 0, 0, freq, 1 xaPan 0, pan getkey key, 51 : if key { xaVol 0, freq } getkey key, 52 : if key { xaFreq 0, freq } stick pad if pad & 256 : xaPlay 0 if pad & 512 : xaStop 0 getkey key, 49 : if key { xaPlay 1 } getkey key, 50 : if key { xaPlay 2 } cmp = ginfo_wx1<ginfo_mx & ginfo_mx<ginfo_wx2 & ginfo_wy1<ginfo_my & ginfo_my<ginfo_wy2 if cmp : xaResume 0 : else :xaPause await 16 goto *MAIN



この記事に返信する


名無し

リンク

2025/8/29(Fri) 19:31:24|NO.103885

HSPしか分からない自分にはXAudio2とか理解できないので扱えちゃうのが凄いです。
usagiさんの技術力とフリーで公開しちゃう心の広さに脱帽です。



窓月らら

リンク

2025/8/31(Sun) 23:47:53|NO.103901

すごいのだ!! 研究素材として使用させて頂きます。
この手あまり反応ない気がしますが、HSPはこの部分(サウンド周り)あまり強くないんで
もう少し拡充してほしいと思ってたりします。
そう思ってうちも独自開発して追加しようと思ってるんですが、なかなかリリースできないのだ。
HSPOGGの周波数変更については要望だしてありますが、これが追加されるだけで
できることがかなり広がると思われます。



Nick Bender

リンク

2025/9/3(Wed) 16:25:07|NO.103927

DLL不要で、途中のループ再生や音量、パンなどを扱えるのは大きな利点です。通常、こういった機能は実装が最も難しい部分ですからね。シンプルさを保つという設計思想も素晴らしいですし、他の人も採用して発展させやすいでしょう。素晴らしい仕事です!
https://ragdollhitstickman.io



usagi

リンク

2025/9/5(Fri) 11:55:25|NO.103939

みなさんコメントありがとうございます。
>名無しさん
とんでもないです。私も研究目的なので至らない所があり、指摘いただけると嬉しいです。
>窓月ららさん
OGGのデコードも面白そうですね。自作音源開発されてましたね楽しみです。
>Nick Bender
難しい処理は全部XAudioがしてくれるので楽でしたが、インターフェースから関数引っ張ってくるのが厄介でした。。。



usagi

リンク

2025/9/5(Fri) 12:09:29|NO.103940

折角なので、仕様を少しかえエフェクトとサブミックスも試してみました。
ゲーム的な使用に耐えられるかテストしてみたのですが、wav参照の複製かフォーマット固定してボイスプールする仕組みにした方が良かったかもです。
※それを掲示板に書くにはスペースが足りない。。。長くてすみません。
XAudioのラッパーだけ分けて、それを使うモジュールを用意する方が正解だったかもですね(でも複雑かなぁ)
良いアイデアいただけると嬉しいです。

#ifndef __EZXAUDIO__ #define global __EZXAUDIO__ #module "ezXAudio" ; DLL #uselib "msvcrt.dll" #cfunc malloc "malloc" int #func free "free" int #uselib "kernel32.dll" #func VirtualProtect "VirtualProtect" var,int,int,var #uselib "XAudio2_9.dll" #func XAudio2Create "XAudio2Create" var,int,int #func XAudio2CreateReverb "CreateAudioReverb" var,int #func XAudio2CreateVolumeMeter "CreateAudioVolumeMeter" var,int #func XAudio2CreateFX "CreateFX" var,var,nullptr,nullptr ; COM #define IID_IUnknown "{00000000-0000-0000-C000-000000000046}" #define IID_IXAudio2 "{2B02E3CF-2E0B-4ec3-BE45-1B2A3FE7210D}" #usecom IXAudio2 IID_IXAudio2 #comfunc CreateSourceVoice 5 var,var,int,float,int,int,int #comfunc CreateSubmixVoice 6 var,int,int,int,int,int,int #comfunc CreateMasteringVoice 7 var,int,int,int,int,int,int #comfunc StartEngine 8 #comfunc StopEngine 9 ; Dummy Function #uselib "" #cfunc float "" float #func f2ds "" var,var,int; float[],double[],int #func __GetVoiceDetails "" int,var #func __SetOutputVoices "" int,var #func __SetEffectChain "" int,var #func __EnableEffect "" int,int,int #func __DisableEffect "" int,int,int #func __SetEffectParameters "" int,int,var,int,int #func __GetEffectParameters "" int,int,var,var #func __SetFilterParameters "" int,var,int #func __SetVolume "" int,float,int #func __SetOutputMatrix "" int,int,int,int,var,int #func __DestroyVoice "" int #func __Start "" int,int,int #func __Stop "" int,int,int #func __SubmitSourceBuffer "" int,int,int #func __FlushSourceBuffers "" int #func __ExitLoop "" int,int #func __GetState "" int,var,int #func __SetFrequencyRatio "" int,float,int #func __GetChannelMask "" int,var ; Overwrite Function #deffunc local overwriteFunction int _libptr, int _pp, int _index dupptr p, _pp, 4 : dupptr pfuncs, p, (_index+1)*4 : dupptr _sdat, _libptr, 28 : _sdat.6 = pfuncs._index : return #define ctype def(%1,%2,%3=_p) overwriteFunction libptr(%2),%3,%1:%2 %3 ; IXAudio2Voice #deffunc local _GetVoiceDetails int _p, var _details def( 0, __GetVoiceDetails), _details : return stat #deffunc local _SetOutputVoices int _p, var _sendList def( 1, __SetOutputVoices), _sendList : return stat #deffunc local _SetEffectChain int _p, var _effectChain def( 2, __SetEffectChain), _effectChain : return stat #deffunc local _EnableEffect int _p, int _index def( 3, __EnableEffect), _index, 0 : return stat #deffunc local _DisableEffect int _p, int _index def( 4, __DisableEffect), _index, 0 : return stat #deffunc local _SetEffectParameters int _p, int _index, var _param, int _size def( 6, __SetEffectParameters), _index, _param, _size, 0 : return stat #deffunc local _GetEffectParameters int _p, int _index, var _param, var _size def( 7, __GetEffectParameters), _index, _param, _size : return stat #deffunc local _SetFilterParameters int _p, var _filterParams def( 8, __SetFilterParameters ), _filterParams, 0 : return stat #deffunc local _SetVolume int _p, double _vol def(12, __SetVolume), _vol,0 : return stat #deffunc local _SetOutputMatrix int _p, int _srcCh, int _dstCh, var _lvMtx def(16, __SetOutputMatrix), 0,_srcCh,_dstCh,_lvMtx,0 : return stat #deffunc local _DestroyVoice int _p def(18, __DestroyVoice) : return stat ; IXAudio2SourceVoice #deffunc local _Start int _p def(19, __Start), 0, 0 : return stat #deffunc local _Stop int _p def(20, __Stop), 0, 0 : return stat #deffunc local _SubmitSourceBuffer int _p, int _pBuffer def(21, __SubmitSourceBuffer), _pBuffer, 0 : return stat #deffunc local _FlushSourceBuffers int _p def(22, __FlushSourceBuffers) : return stat #deffunc local _ExitLoop int _p def(24, __ExitLoop), 0 : return stat #deffunc local _GetState int _p, var _state, var _flags def(25, __GetState), _state, _flags : return stat #deffunc local _SetFrequencyRatio int _p, double _ratio def(26, __SetFrequencyRatio), _ratio, 0 : return stat ; IXAudio2MasteringVoice #deffunc local _GetChannelMask int _p, var _channelmask def(19, __GetChannelMask), _channelmask : return stat ; ------------------ #deffunc local machinecode int _p, array _code VirtualProtect _code, varsize(_code),$40, _ : dupptr _sdat, _p, 28 : _sdat.6 = varptr(_code) : return #defcfunc local getInputChannels int _p res = 0,0,0,0 : _GetVoiceDetails _p, res : return res.2 #defcfunc local getInputSampleRate int _p res = 0,0,0,0 : _GetVoiceDetails _p, res : return res.3 #defcfunc local getStateBuffersQueued int _p res = 0,0,0,0 : _GetState _p, res, $100 : return res.1 #defcfunc local getStateSamplesPlayed int _p res = 0,0,0,0 : _GetState _p, res, 0 : d = 0.0 : lpoke d,0,res.2 : lpoke d,4,res.3 : return double(strf("%I64u",d)) #defcfunc local checkID var _data, str _identifier, int _offset mref identifier, 65 : identifier = " " : lpoke identifier, 0, lpeek(_data, _offset) : return identifier == _identifier #defcfunc local dupChunkData var _dup, var _data, int _offset size = lpeek(_data, _offset + 4) : dupptr _dup, varptr(data) + offset + 8, size : return offset + 8 + size+(size\2);BUGFIX:奇数バイト対策 ; Once #deffunc local call_once __float = $0424448b,$c3909090 : machinecode libptr(float), __float __f2ds = $0c244c8b,$1f7ec985,$0424448b,$0824548b,$8d880c8d,$90002674,$c08300d9,$08c28304,$39f85add,$31f175c8,$9090c3c0 : machinecode libptr(f2ds), __f2ds _CLSID_FXMASTERINGLIMITER = $c4137916,$46fd2be1,$15449985,$5698f436; "{C4137916-2BE1-46FD-8599-441536F49856}" _CLSID_FXEQ = $f5e01117,$485ad6c4,$5169f5a3,$fadbf396; "{F5E01117-D6C4-485A-A3F5-695196F3DBFA}" _CLSID_FXECHO = $5039d740,$449af736,$62a5d384,$877b5502; "{5039D740-F736-449A-84D3-A56202557B87}" _CLSID_FXREVERB = $7d9aca56,$4807cb68,$37b132b6,$96852e35; "{7D9ACA56-CB68-4807-B632-B137352E8596}" ;Name |WDM |Room |RoomHF |* |DecayT |DecayHFR|Reflect |ReflectD|Reverb |ReverbD |Diffus |Density |HFRef | ;------------------------------------------------------------------------------------------------------------------------------ _REVERB_PRESETS = {" DEFAULT , 100, -10000, 0, 0, 1.00, 0.50, -10000., 0.020, -10000, 0.040, 100, 100, 5000 GENERIC , 100, -1000, -100, 0, 1.49, 0.83, -2602., 0.007, 200, 0.011, 100, 100, 5000 PADDEDCELL , 100, -1000, -6000, 0, 0.17, 0.10, -1204., 0.001, 207, 0.002, 100, 100, 5000 ROOM , 100, -1000, -454, 0, 0.40, 0.83, -1646., 0.002, 53, 0.003, 100, 100, 5000 BATHROOM , 100, -1000, -1200, 0, 1.49, 0.54, -370., 0.007, 1030, 0.011, 100, 60, 5000 LIVINGROOM , 100, -1000, -6000, 0, 0.50, 0.10, -1376., 0.003, -1104, 0.004, 100, 100, 5000 STONEROOM , 100, -1000, -300, 0, 2.31, 0.64, -711., 0.012, 83, 0.017, 100, 100, 5000 AUDITORIUM , 100, -1000, -476, 0, 4.32, 0.59, -789., 0.020, -289, 0.030, 100, 100, 5000 CONCERTHALL , 100, -1000, -500, 0, 3.92, 0.70, -1230., 0.020, -2, 0.029, 100, 100, 5000 CAVE , 100, -1000, 0, 0, 2.91, 1.30, -602., 0.015, -302, 0.022, 100, 100, 5000 ARENA , 100, -1000, -698, 0, 7.24, 0.33, -1166., 0.020, 16, 0.030, 100, 100, 5000 HANGAR , 100, -1000, -1000, 0, 10.05, 0.23, -602., 0.020, 198, 0.030, 100, 100, 5000 CARPETEDHALLWAY, 100, -1000, -4000, 0, 0.30, 0.10, -1831., 0.002, -1630, 0.030, 100, 100, 5000 HALLWAY , 100, -1000, -300, 0, 1.49, 0.59, -1219., 0.007, 441, 0.011, 100, 100, 5000 STONECORRIDOR , 100, -1000, -237, 0, 2.70, 0.79, -1214., 0.013, 395, 0.020, 100, 100, 5000 ALLEY , 100, -1000, -270, 0, 1.49, 0.86, -1204., 0.007, -4, 0.011, 100, 100, 5000 FOREST , 100, -1000, -3300, 0, 1.49, 0.54, -2560., 0.162, -613, 0.088, 79, 100, 5000 CITY , 100, -1000, -800, 0, 1.49, 0.67, -2273., 0.007, -2217, 0.011, 50, 100, 5000 MOUNTAINS , 100, -1000, -2500, 0, 1.49, 0.21, -2780., 0.300, -2014, 0.100, 27, 100, 5000 QUARRY , 100, -1000, -1000, 0, 1.49, 0.83, -10000., 0.061, 500, 0.025, 100, 100, 5000 PLAIN , 100, -1000, -2000, 0, 1.49, 0.50, -2466., 0.179, -2514, 0.100, 21, 100, 5000 PARKINGLOT , 100, -1000, 0, 0, 1.65, 1.50, -1363., 0.008, -1153, 0.012, 100, 100, 5000 SEWERPIPE , 100, -1000, -1000, 0, 2.81, 0.14, 429., 0.014, 648, 0.021, 80, 60, 5000 UNDERWATER , 100, -1000, -4000, 0, 1.49, 0.10, -449., 0.007, 1700, 0.011, 100, 100, 5000 SMALLROOM , 100, -1000, -600, 0, 1.10, 0.83, -400., 0.005, 500, 0.010, 100, 100, 5000 MEDIUMROOM , 100, -1000, -600, 0, 1.30, 0.83, -1000., 0.010, -200, 0.020, 100, 100, 5000 LARGEROOM , 100, -1000, -600, 0, 1.50, 0.83, -1600., 0.020, -1000, 0.040, 100, 100, 5000 MEDIUMHALL , 100, -1000, -600, 0, 1.80, 0.70, -1300., 0.015, -800, 0.030, 100, 100, 5000 LARGEHALL , 100, -1000, -600, 0, 1.80, 0.70, -2000., 0.030, -1400, 0.060, 100, 100, 5000 PLATE , 100, -1000, -200, 0, 1.30, 0.90, 0., 0.002, 0, 0.010, 100, 75, 5000 "} xaInit 1024, 2, 2, 48000 return ; 定数 #enum global XA_FXLIMITER = 0 #enum global XA_FXEQ #enum global XA_FXECHO #enum global XA_FXREVERB ;=============================================================================== ; コマンド ;=============================================================================== ; 初期化 ;----------------------------- #deffunc xaInit int _max, double _freqRatio, int _channels, int _sampleRate if m_pXAudio != 0 { xaDeinit } ; Reset m_sampleRate = _sampleRate : m_channels = _channels : m_channelMask = 3 m_deviceId = 0; TODO: 変更可能にする ; Audio m_voiceMax = _max m_freqRatio = limitf(_freqRatio, 1.0/1024.0, 1024.0) dim m_pSourceVoice, m_voiceMax dim m_pAudioData, m_voiceMax dim m_pAudioDataSize, m_voiceMax dim m_loopBegin, m_voiceMax dim m_loopLength, m_voiceMax dim m_loopCount, m_voiceMax ; Group m_submixMax = 16 dim m_pSubmixVoice, m_submixMax; 0=MasteringVoice dim m_pGroupFx, m_submixMax dim m_pVolumeMeter, m_submixMax dimtype m_groupFx,6, m_submixMax dimtype m_volumeMeter,6, m_submixMax dim m_groupFxType, m_submixMax dim m_peakLevels, m_channels dim m_rmsLevels, m_channels m_volumeMeterLevels = varptr(m_peakLevels), varptr(m_rmsLevels), m_channels ; XAudio2 Start XAudio2Create m_pXAudio, 0, 1 : newcom m_XAudio, IID_IXAudio2, -1, m_pXAudio if stat != 0 : return -1 CreateMasteringVoice m_XAudio, m_pSubmixVoice.0, m_channels, m_sampleRate, 0, m_deviceId, 0, 0 if stat != 0 : return -2 _GetChannelMask m_pSubmixVoice.0, m_channelMask ; FX CreateGroupFx 0, 0 if stat != 0 : return -3 return ; 破棄 ;----------------------------- #deffunc xaDeinit onexit if m_pXAudio = 0 : return StopEngine m_XAudio xaDelAll xaDelGroupAll delcom m_XAudio : m_pXAudio = 0 return ; エフェクト作成 ;----------------------------- #deffunc local CreateGroupFx int _id, int _type if m_pGroupFx._id != 0 { _DisableEffect m_pSubmixVoice._id, 0 _DisableEffect m_pSubmixVoice._id, 1 delcom m_groupFx._id : m_pGroupFx._id = 0 delcom m_volumeMeter._id : m_pVolumeMeter._id = 0 } m_groupFxType._id = _type switch m_groupFxType._id case XA_FXLIMITER : XAudio2CreateFX _CLSID_FXMASTERINGLIMITER, m_pGroupFx._id : swbreak case XA_FXEQ : XAudio2CreateFX _CLSID_FXEQ, m_pGroupFx._id : swbreak case XA_FXECHO : XAudio2CreateFX _CLSID_FXECHO, m_pGroupFx._id : swbreak case XA_FXREVERB : XAudio2CreateReverb m_pGroupFx._id, 0 : swbreak swend newcom m_groupFx._id, IID_IUnknown, -1, m_pGroupFx._id XAudio2CreateVolumeMeter m_pVolumeMeter._id, 0 newcom m_volumeMeter._id, IID_IUnknown, -1, m_pVolumeMeter._id effects = /*0*/ m_pGroupFx._id, 0, m_channels, /*1*/ m_pVolumeMeter._id, 0, m_channels effectChain = 2, varptr(effects) _SetEffectChain m_pSubmixVoice._id, effectChain return ; リミッター release(1-6-20), loudness(1-1000-18000) ;----------------------------- #deffunc xaFxLimiter int _id, int _release, int _loudness if m_groupFxType._id != XA_FXLIMITER : CreateGroupFx _id, XA_FXLIMITER _EnableEffect m_pSubmixVoice._id, 0 prarams = limit(_release, 1, 20), limit(_loudness, 1, 1800) _SetEffectParameters m_pSubmixVoice._id, 0, prarams, 8 return ; イコライザ― def f0:100, f1:800, f2:2000, f3:10000 ;----------------------------- #deffunc xaFxEq int _id, double _f0, double _g0, double _b0, double _f1, double _g1, double _b1, double _f2, double _g2, double _b2, double _f3, double _g3, double _b3 if m_groupFxType._id != XA_FXEQ : CreateGroupFx _id, XA_FXEQ _EnableEffect m_pSubmixVoice._id, 0 prarams.0 = float(limitf(_f0, 20, 20000)), float(limitf(_g0, 0.126, 7.94)), float(limitf(_b0, 0.1, 2.0)) prarams.3 = float(limitf(_f1, 20, 20000)), float(limitf(_g1, 0.126, 7.94)), float(limitf(_b1, 0.1, 2.0)) prarams.6 = float(limitf(_f2, 20, 20000)), float(limitf(_g2, 0.126, 7.94)), float(limitf(_b2, 0.1, 2.0)) prarams.9 = float(limitf(_f3, 20, 20000)), float(limitf(_g3, 0.126, 7.94)), float(limitf(_b3, 0.1, 2.0)) _SetEffectParameters m_pSubmixVoice._id, 0, prarams, 48 return ; エコー mix(0-0.5-1) feedback(0-0.5-1) delay(1-500-2000) ;----------------------------- #deffunc xaFxEcho int _id, double _mix, double _feedback, double _delay if m_groupFxType._id != XA_FXECHO : CreateGroupFx _id, XA_FXECHO _EnableEffect m_pSubmixVoice._id, 0 prarams = float(limitf(_mix, 0, 1)), float(limitf(_feedback, 0, 1)), float(limitf(_delay, 1, 2000)) _SetEffectParameters m_pSubmixVoice._id, 0, prarams, 12 return ; リバーブ name(DEFAULT) ;----------------------------- #deffunc xaFxReverb int _id, str _name notesel _REVERB_PRESETS noteget noteline, limit(notefind(_name,1), 1) split noteline, ",", sPreset repeat 13 : paramI3DL2.cnt = double(sPreset(cnt+1)) : loop noteunsel ReverbConvertI3DL2ToNative paramI3DL2, paramNative if m_groupFxType._id != XA_FXREVERB : CreateGroupFx _id, XA_FXREVERB _EnableEffect m_pSubmixVoice._id, 0 _SetEffectParameters m_pSubmixVoice._id, 0, paramNative, 54 return #deffunc local ReverbConvertI3DL2ToNative array _s, array _d sdim _d, 54 if _s.5 >= 1.0 { t = limit(-4.0 * (logf(_s.5)/logf(10)) + 8,0,12), 8, float(_s.4 * _s.5) } else { t = 8, limit(4.0 * (logf(_s.5)/logf(10)) + 8,0,8), float(_s.4) } lpoke _d, 0, float(_s.0) ;WetDryMix lpoke _d, 4, limit(_s.7 * 1000.0,1,299) ;ReflectionsDelay poke _d, 8, limit(_s.9 * 1000.0,0,84) ;ReverbDelay poke _d, 9, 5 ;RearDelay poke _d, 10, 5 ;SideDelay poke _d, 11, 6 ;PositionLeft poke _d, 12, 6 ;PositionRight poke _d, 13, 27 ;PositionMatrixLeft poke _d, 14, 27 ;PositionMatrixRight poke _d, 15, int(15.0 * _s.10 / 100.0) ;EarlyDiffusion poke _d, 16, int(15.0 * _s.10 / 100.0) ;LateDiffusion poke _d, 17, t.0 ;LowEQGain poke _d, 19, t.1 ;LowEQCutoff poke _d, 18, 4 ;HighEQGain poke _d, 20, 6 ;HighEQCutoff lpoke _d, 21, float(_s.12) ;RoomFilterFreq lpoke _d, 25, float(_s.1 / 100.0) ;RoomFilterMain lpoke _d, 29, float(_s.2 / 100.0) ;RoomFilterHF lpoke _d, 33, float(_s.6 / 100.0) ;ReflectionsGain lpoke _d, 37, float(_s.8 / 100.0) ;ReverbGain lpoke _d, 41, t.2 ;DecayTime lpoke _d, 45, float(_s.11) ;Density lpoke _d, 49, float(100) ;RoomSize poke _d, 53, 0 ;DisableLateField return ; ピークメーター ;----------------------------- #deffunc xaPeakMeter int _id, array _out if m_pSubmixVoice._id = 0 : return _EnableEffect m_pSubmixVoice._id, 1 _GetEffectParameters m_pSubmixVoice._id, 1, m_volumeMeterLevels, size if vartype(_out)!=3 || length(_out) < m_channels { ddim _out, m_channels } f2ds m_peakLevels, _out, m_channels return ; グループ作成 ;----------------------------- #deffunc xaGroup int _id, int _stage, int _fxType if _id >= m_submixMax : return -1 xaDelGroup _id flags = 0x0008 ; *XAUDIO2_VOICE_USEFILTER CreateSubmixVoice m_XAudio, m_pSubmixVoice._id, m_channels, m_sampleRate, flags, _stage, 0,0 if stat != 0 : return -1 CreateGroupFx _id, _fxType if stat != 0 : return -2 return 0 ; グループ出力先設定 ;----------------------------- #define global xaGroupSend(%1,%2=-1,%3=-1,%4=-1,%5=-1) _xaGroupSend %1,%2,%3,%4,%5 #deffunc _xaGroupSend int _id, int _s1, int _s2, int _s3, int _s4 if m_pSubmixVoice._id = 0 : return sends = 0, 0 : count = 0 : i = 0 if _s1>-1 { send.i = 0 : i++ : send.i = m_pSubmixVoice._s1 : i++ : count++ } if _s2>-1 { send.i = 0 : i++ : send.i = m_pSubmixVoice._s2 : i++ : count++ } if _s3>-1 { send.i = 0 : i++ : send.i = m_pSubmixVoice._s3 : i++ : count++ } if _s4>-1 { send.i = 0 : i++ : send.i = m_pSubmixVoice._s4 : i++ : count++ } if count > 0 { sends = count, varptr(send)} _SetOutputVoices m_pSubmixVoice._id, sends if stat != 0 : return -1 return 0 ; グループ削除 ;----------------------------- #deffunc xaDelGroup int _id if m_pSubmixVoice._id != 0 { _DestroyVoice m_pSubmixVoice._id m_pSubmixVoice._id = 0 } if m_pVolumeMeter._id != 0 { delcom m_volumeMeter._id m_pVolumeMeter._id = 0 } if m_pGroupFx._id != 0 { delcom m_groupFx._id m_pGroupFx._id = 0 m_groupFxType._id = 0 } return #deffunc xaDelGroupAll repeat m_submixMax : xaDelGroup cnt : loop return ; グループ音量 ;----------------------------- #deffunc xaGroupVol int _id, double _vol if m_pSubmixVoice._id == 0 : return _SetVolume m_pSubmixVoice._id, _vol return stat ; グループフィルター ;----------------------------- #deffunc xaGroupFilter int _id, int _type, double _freq, double _q/*1/q*/ if m_pSubmixVoice._id == 0 : return filterParams = _type, float(_freq), float(limitf(_q, 0, 1.5)) _SetFilterParameters m_pSubmixVoice._id, filterParams return stat ; 読み込み ;----------------------------- #deffunc xaLoad str _file, int _id, int _gid, int _flags if (_id < 0) || (_id >= m_voiceMax) : return -1 if (_gid < 0) || (_gid >= m_submixMax) : return -2 if m_pSubmixVoice._gid = 0 : return -3 xaDel _id xaLoop _id, 0, 0, 0 flags = 0 if _flags & 1 : flags |= 0x0008 ; *XAUDIO2_VOICE_USEFILTER if _flags & 2 : flags |= 0x0002 ; *XAUDIO2_VOICE_NOPITCH exist _file : sdim data, strsize : bload _file, data if (checkID(data,"RIFF", 0) && checkID(data,"WAVE", 8)) = 0 : return -1 offset = 12 repeat -1 if offset >= varsize(data) : break if checkID(data,"fmt ", offset) { offset = dupChunkData(fmtChunk, data, offset) continue } if checkID(data,"data", offset) { offset = dupChunkData(dataChunk, data, offset) continue } if checkID(data,"smpl", offset) { offset = dupChunkData(smplChunk, data, offset) xaLoop _id, smplChunk.11, smplChunk.12, -1 continue } offset = dupChunkData(_, data, offset) loop m_pAudioDataSize._id = varsize(dataChunk) m_pAudioData._id = malloc(m_pAudioDataSize._id) dupptr audioData, m_pAudioData._id, m_pAudioDataSize._id memcpy audioData, dataChunk, m_pAudioDataSize._id send = 0, m_pSubmixVoice._gid : sends = 1, varptr(send) : pSends= varptr(sends) CreateSourceVoice m_XAudio, m_pSourceVoice._id, fmtChunk, flags, m_freqRatio,0,pSends,0 if stat != 0 : return -1 xaPan _id, 0 return 0 ; 削除 ;----------------------------- #deffunc xaDel int _id if m_pAudioData._id != 0 { free m_pAudioData._id m_pAudioDataSize._id = 0 m_pAudioData._id = 0 } if m_pSourceVoice._id != 0 { _DestroyVoice m_pSourceVoice._id m_pSourceVoice._id = 0 } return #deffunc xaDelAll repeat m_voiceMax : xaDel cnt : loop return ; 再生 ;----------------------------- #deffunc xaPlay int _id, int _mode xaStop _id if m_pAudioDataSize._id == 0 : return xaudio2_buffer.0 = 0x40, m_pAudioDataSize._id, m_pAudioData._id, 0, 0 xaudio2_buffer.5 = m_loopBegin._id, m_loopLength._id, m_loopCount._id, 0 _SubmitSourceBuffer m_pSourceVoice._id, varptr(xaudio2_buffer) _Start m_pSourceVoice._id return stat ; 停止 ;----------------------------- #deffunc xaStop int _id if m_pSourceVoice._id == 0 : return _Stop m_pSourceVoice._id : _FlushSourceBuffers m_pSourceVoice._id return stat #deffunc xaStopAll repeat m_voiceMax : xaStop cnt : loop return ; ポーズ ;----------------------------- #deffunc xaPause int _id if m_pSourceVoice._id == 0 : return _Stop m_pSourceVoice._id return stat ; リジューム ;----------------------------- #deffunc xaResume int _id if m_pSourceVoice._id == 0 : return _Start m_pSourceVoice._id return stat ; ループ ;----------------------------- #deffunc xaLoop int _id, int _count, int _st, int _ed m_loopBegin._id = _st : m_loopLength._id = _ed - _st if _count < 0 { m_loopCount._id = 255 } else { m_loopCount._id = limit(_count, 0, 255) } return stat #deffunc xaExitLoop int _id if m_pSourceVoice._id == 0 : return _ExitLoop m_pSourceVoice._id return stat ; 音量 ;----------------------------- #deffunc xaVol int _id, double _vol if m_pSourceVoice._id == 0 : return _SetVolume m_pSourceVoice._id, _vol return stat ; 周波数 ;----------------------------- #deffunc xaFreq int _id, double _ratio if m_pSourceVoice._id == 0 : return _SetFrequencyRatio m_pSourceVoice._id, _ratio return stat ; フィルター tyep: enum { LowPass, BandPass, HighPass, Notch } ;----------------------------- #deffunc xaFilter int _id, int _type, double _freq, double _q/*1/q*/ if m_pSourceVoice._id == 0 : return filterParams = _type, float(_freq), float(limitf(_q, 0, 1.5)) _SetFilterParameters m_pSourceVoice._id, filterParams return stat ; 定位 ;----------------------------- #deffunc xaPan int _id, double _pan if m_pSourceVoice._id == 0 : return srcCh = getInputChannels(m_pSourceVoice._id) dstCh = m_channels if dstCh = 2 { ; ステレオのみ対応 l = limitf(0.5 - _pan * 0.5, 0, 1) : r = 1.0 - l ; リニア l = sin(0.5*M_PI*l) : r = sin(0.5*M_PI*r) ; 等パワー if srcCh = 1 { ; L_IN ;------------------- lvMtx.0 = float(l) ; L_OUT lvMtx.1 = float(r) ; R_OUT _SetOutputMatrix m_pSourceVoice._id, srcCh, dstCh, lvMtx } if srcCh = 2 { ; L_IN : R_IN ;----------------------------- lvMtx.0 = float(l), float(0) ; L_OUT lvMtx.2 = float(0), float(r) ; R_OUT _SetOutputMatrix m_pSourceVoice._id, srcCh, dstCh, lvMtx } } return ; 情報 TODO: 種類を増やす、番号整理(もしくは小分けにする) ;----------------------------- #defcfunc xaStat int _id, int _mode if m_pSourceVoice._id == 0 : return if _mode = 4 : return getInputChannels(m_pSourceVoice._id) if _mode = 5 : return getInputSampleRate(m_pSourceVoice._id) if _mode = 16 : return getStateBuffersQueued(m_pSourceVoice._id) if _mode = 17 : return getStateSamplesPlayed(m_pSourceVoice._id) return #global call_once@ezXAudio #endif ;=============================================================================== ; サンプル ※エフェクトグループとゲーム的な使用に耐えられるかのテスト #include "hsp3dish.as" #enum SND_GROUP_MASTER = 0 ; マスター※固定自動生成 #enum SND_GROUP_BGM ; 音楽 #enum SND_GROUP_SFX ; 効果音 #enum SND_GROUP_REV ; 残響エフェクト #enum SND_GROUP_ECH ; エコー TBL_GROUP_TEXT = "MASTER","BGM","SFX","REVERB","ECHO" TBL_GROUP_ID = SND_GROUP_MASTER,SND_GROUP_BGM,SND_GROUP_SFX,SND_GROUP_REV,SND_GROUP_ECH ; グループを追加 xaGroup SND_GROUP_BGM, 0 ; 第二引数で処理の階層を設定 xaGroup SND_GROUP_SFX, 0 ; ※同値以下にはSend出来ません。 xaGroup SND_GROUP_REV, 1 xaGroup SND_GROUP_ECH, 1 ; グループの出力先を設定 xaGroupSend SND_GROUP_BGM, SND_GROUP_MASTER xaGroupSend SND_GROUP_SFX, SND_GROUP_MASTER, SND_GROUP_REV, SND_GROUP_ECH xaGroupSend SND_GROUP_REV, SND_GROUP_MASTER ; エフェクト ※グループに対して1つ設定できます。 xaFxLimiter SND_GROUP_MASTER, 6, 1800 xaFxLimiter SND_GROUP_SFX, 6, 1800 xaFxReverb SND_GROUP_REV, "CITY" xaFxEcho SND_GROUP_ECH, 1, 0.1, 200 : xaGroupVol SND_GROUP_ECH, 0.1 ; 読み込み xaLoad dir_tv+"se_block2.wav", 0, SND_GROUP_BGM : xaLoop 0, -1 xaLoad dir_tv+"se_shot.wav" , 1, SND_GROUP_SFX xaLoad dir_tv+"se_bom.wav" , 2, SND_GROUP_SFX xaLoad dir_tv+"se_foot.wav" , 3, SND_GROUP_SFX xaLoad dir_tv+"se_jump.wav" , 4, SND_GROUP_SFX xaLoad dir_tv+"se15.wav" , 5; 指定なしはマスター xaLoad dir_tv+"se14.wav" , 6; 指定なしはマスター screen 0,640,480 : title "早打ちゲーム" : randomize sx_max = ginfo_sx : sx_mid = sx_max/2 : sy_max = ginfo_sy : sy_mid = sy_max/2 ranking = 20000,15000,12500,10000,7500,5000,2500,1000,500 : ranking_cur = 8 game_state = 0 : gosub *RESET : xaPlay 0 *MAIN on game_state gosub *UPDATE_TITLE, *UPDATE_INGAME, *UPDATE_RESULT redraw 0 : gmode 0 : font "", 32 on game_state gosub *DRAW_TITLE, *DRAW_INGAME, *DRAW_RESULT if mousex>120 { gosub *DRAW_METER } redraw 1 : await 16 goto *MAIN *RESET bullets = 6 : score = 0 : score_pt = 100 : time_limit = 60*10 : pt=0,0,0,0 gosub *RESET_TERGET return *RESET_TERGET target_px = limit(rnd(sx_max),64,sx_max-64) : target_py = limit(rnd(ginfo_sy),64,sy_max-64) : target_r = rnd(4)*8+16 return *SHOT_GUN pan = (double(mousex)/sx_max)*2.0 - 1.0 xaPlay 1 : xaPan 1, pan : xaFreq 1, 1.+0.01*rnd(50) : shot_time = 5 : bullets = limit(bullets-1,0) return *UPDATE_TITLE stick pad if pad == 256 { gosub *SHOT_GUN } : shot_time=limit(shot_time-1,0,255) if pad == 512 { xaPlay 5 : xaStop 0 : game_state = 1 : gosub *RESET} return *UPDATE_INGAME stick pad if pad == 256 { if bullets>0 { gosub *SHOT_GUN dist = sqrt(powf(mousex-target_px,2)+powf(mousey-target_py,2)) if dist<=target_r { xaPlay 2 : xaPan 2, pan : xaFreq 2, 1.+0.01*rnd(50) pt = score_pt*limit(40-dist,1),target_px,target_py,30 score += pt : score_pt = 100 gosub *RESET_TERGET } } else { xaPlay 3 : xaFreq 3, 1.+0.01*rnd(50) } } if pad & 512 { xaPlay 4 : bullets = 6 } shot_time=limit(shot_time-1,0,255) : pt.3-- score_pt=limit(score_pt-1,0) : hightscore=limit(score,hightscore) time_limit-- if time_limit == 180 || time_limit == 120 || time_limit == 60 { xaPlay 6 } if time_limit <= 0 { gosub *UPDATE_RANKING : xaPlay 5 : game_state = 2} return *UPDATE_RANKING ranking.8 = score : sortval ranking, 1 : repeat 9 : sortget i, cnt : if i=8 { ranking_cur=cnt : break } : loop return *UPDATE_RESULT stick pad if pad == 256 { gosub *SHOT_GUN } : shot_time=limit(shot_time-1,0,255) if pad == 512 { xaPlay 4 : xaPlay 0 : game_state = 0 } return *DRAW_TITLE gosub *DRAW_BG : gosub *DRAW_TITLELOGO : gosub *DRAW_RANKING : gosub *DRAW_GUN return *DRAW_INGAME gosub *DRAW_BG : gosub *DRAW_TARGET : gosub *DRAW_GUN : gosub *DRAW_UI return *DRAW_TITLELOGO font "", 64 : pos sx_mid-320, 16 : rgbcolor $ffff00 : mes " - Quick Shooting -", 4 font "", 32 : pos sx_mid-160, sy_max-64 : rgbcolor $ff00ff : mes "Right click to start", 4 return *DRAW_RESULT gosub *DRAW_BG : gosub *DRAW_RANKING : gosub *DRAW_GUN : gosub *DRAW_UI return *DRAW_RANKING pos sx_mid-96,88 : rgbcolor $ff0000 : mes " RNAKING", 4 repeat 8 :rgbcolor (cnt!=ranking_cur)*$ff<<16|$00ffff : mes strf("%2d: %8d", cnt+1, ranking.cnt), 4 : loop return *DRAW_BG gradf 0,0,sx_max,0.75*sy_max,1,$83aeff,$c6f4fb : gradf 0,0.75*sy_max,sx_max,0.25*sy_max,1,$ffeecd,$82e487 return *DRAW_GUN rgbcolor : line mousex-32,mousey,mousex+32,mousey : line mousex,mousey-32,mousex,mousey+32 circle mousex-8,mousey-8,mousex+8,mousey+8,0 gmode 5,,,shot_time*64: rgbcolor $ffffff : grect sx_mid, sy_mid, 0,sx_max, sy_max return *DRAW_TARGET repeat target_r/4:r=target_r-cnt*4:rgbcolor (cnt\2)*$ffffff : circle target_px-r,target_py-r,target_px+r,target_py+r:loop if pt.3>0 {rgbcolor $ffffff:pos sx_max,sx_may:mes pt:pos pt.1-ginfo_mesx/2,pt.2+pt.3-ginfo_mesy*2:mes pt,4} return *DRAW_UI pos 0,0 : rgbcolor $ffff00 : mes strf("HIGHT%8d",hightscore),5 pos sx_max-208,0: rgbcolor $00ffff : mes strf("SCORE%8d",score),5 pos sx_mid-32 : rgbcolor $ffffff : mes strf("Time\n %02d",time_limit/60),5 pos sx_mid-bullets*16,ginfo_sy-40 : rgbcolor $ac813f : repeat bullets : mes "■",5 : loop rgbcolor $ff5d22 : boxf sx_mid-score_pt, sy_max-60, sx_mid+score_pt, sy_max-50 return *DRAW_METER pos 0,64 : font "", 16 foreach TBL_GROUP_ID xaPeakMeter TBL_GROUP_ID.cnt, peak rgbcolor $ffffff: mes "◆"+TBL_GROUP_TEXT.cnt, 4 foreach peak dB = limitf(20.0*(logf(peak.cnt)/logf(10)), -96) : amp = peak.cnt*96 rgbcolor $333333: boxf ginfo_cx, ginfo_cy, ginfo_cx+ 96, ginfo_cy+15 rgbcolor $663333: boxf ginfo_cx+96, ginfo_cy, ginfo_cx+120, ginfo_cy+15 rgbcolor $00ee00: boxf ginfo_cx, ginfo_cy, ginfo_cx+amp, ginfo_cy+14 rgbcolor $ffffff: if dB<=-96 : mes "-∞",4 : else : mes strf("%+4.2f",dB), 4 loop loop return



記事削除

記事NO.パスワード
(質問が解決したスレッドは他の利用者に活用してもらうため、削除しないようお願いします)

NO.103884への返信

マスコット

好きなマスコットを選んでください。

名前

e-mail
HOME
  1. 初めて利用する方は、HSP3掲示板の使い方をお読みください。
  2. 不要部分の多い長いスクリプトの投稿は ご遠慮ください。
  3. 書き込みは自動改行されません。適度に改行を入れてください。
  4. スクリプトは小文字の<pre>〜</pre>で囲むと見やすく表示できます。

削除用パスワード

エラー発生時、再送信すると二重送信になることがあります。
回答が得られたら、お礼書き込み時に[解決]チェックしてください。
SPAM防止のためURLから始まる文章は投稿できません。
SPAM防止のため英文字のみの本文を投稿することはできません。

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