+++ /dev/null
-using System;\r
-using System.Collections.Generic;\r
-using System.Text;\r
-using System.Diagnostics;\r
-using System.Threading;\r
-using Un4seen.Bass;\r
-//using Un4seen.BassAsio;\r
-//using Un4seen.BassWasapi;\r
-//using Un4seen.Bass.AddOn.Mix;\r
-using Un4seen.Bass.AddOn.Fx;\r
-\r
-namespace FDK\r
-{\r
- public class CBeatDetect : IDisposable\r
- {\r
- public struct stBeatPos\r
- {\r
- public float fBeatTime;\r
- public int n小節番号;\r
- public int nGrid;\r
- public int n小節内Grid;\r
- public bool b無効; // \r
- public bool bレーン表示する; // 未使用\r
-\r
- public stBeatPos( float _fBeatTime, int _n小節番号, int _nGrid, int _n小節内Grid, bool _b無効, bool _bレーン表示する )\r
- {\r
- fBeatTime = _fBeatTime;\r
- n小節番号 = _n小節番号;\r
- nGrid = _nGrid;\r
- n小節内Grid = _n小節内Grid;\r
- b無効 = _b無効;\r
- bレーン表示する= _bレーン表示する;\r
- }\r
- }\r
-\r
- #region [ コンストラクタ ]\r
- public CBeatDetect()\r
- {\r
- Initialize();\r
- }\r
- public CBeatDetect( string _filename )\r
- {\r
- this.filename = _filename;\r
- Initialize();\r
- }\r
- #endregion\r
- #region [ 初期化(コンストラクタから呼び出される) ]\r
- private void Initialize()\r
- {\r
- if ( this.listBeatPositions == null )\r
- {\r
- this.listBeatPositions = new List<stBeatPos>();\r
- }\r
-\r
- #region [ BASS registration ]\r
- // BASS.NET ユーザ登録(BASSスプラッシュが非表示になる)。\r
-\r
- BassNet.Registration( "dtx2013@gmail.com", "2X9181017152222" );\r
- #endregion\r
- #region [ BASS Version Check ]\r
- // BASS のバージョンチェック。\r
- int nBASSVersion = Utils.HighWord( Bass.BASS_GetVersion() );\r
- if ( nBASSVersion != Bass.BASSVERSION )\r
- throw new DllNotFoundException( string.Format( "bass.dll のバージョンが異なります({0})。このプログラムはバージョン{1}で動作します。", nBASSVersion, Bass.BASSVERSION ) );\r
-\r
- int nBASSFXVersion = Utils.HighWord( BassFx.BASS_FX_GetVersion() );\r
- if ( nBASSFXVersion != BassFx.BASSFXVERSION )\r
- throw new DllNotFoundException( string.Format( "bass_fx.dll のバージョンが異なります({0})。このプログラムはバージョン{1}で動作します。", nBASSFXVersion, BassFx.BASSFXVERSION ) );\r
- #endregion\r
-\r
- #region [ BASS の設定。]\r
- //this.bIsBASSFree = true;\r
- //Debug.Assert( Bass.BASS_SetConfig( BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0 ), // 0:BASSストリームの自動更新を行わない。(サウンド出力しないため)\r
- // string.Format( "BASS_SetConfig() に失敗しました。[{0}", Bass.BASS_ErrorGetCode() ) );\r
- #endregion\r
- #region [ BASS の初期化。]\r
- int nデバイス = 0; // 0:"no sound" … BASS からはデバイスへアクセスさせない。\r
- //int nデバイス = -1; // 0:"no sound" … BASS からはデバイスへアクセスさせない。\r
- int n周波数 = 44100; // 仮決め。lデバイス(≠ドライバ)がネイティブに対応している周波数であれば何でもいい?ようだ。いずれにしろBASSMXで自動的にリサンプリングされる。\r
- if ( !Bass.BASS_Init( nデバイス, n周波数, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero ) )\r
- throw new Exception( string.Format( "BASS の初期化に失敗しました。(BASS_Init)[{0}]", Bass.BASS_ErrorGetCode().ToString() ) );\r
- #endregion\r
-\r
- #region [ 指定されたサウンドファイルをBASSでオープンし、必要最小限の情報を取得する。]\r
- //this.hBassStream = Bass.BASS_StreamCreateFile( this.filename, 0, 0, BASSFlag.BASS_STREAM_PRESCAN | BASSFlag.BASS_STREAM_DECODE );\r
- this.hBassStream = Bass.BASS_StreamCreateFile( this.filename, 0, 0, BASSFlag.BASS_STREAM_DECODE );\r
- //this.hBassStream = Bass.BASS_StreamCreateFile( this.filename, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN );\r
- if ( this.hBassStream == 0 )\r
- throw new Exception( string.Format( "{0}: サウンドストリームの生成に失敗しました。(BASS_StreamCreateFile)[{1}]", filename, Bass.BASS_ErrorGetCode().ToString() ) );\r
-\r
- this.nTotalBytes = Bass.BASS_ChannelGetLength( this.hBassStream );\r
-\r
- this.nTotalSeconds = Bass.BASS_ChannelBytes2Seconds( this.hBassStream, nTotalBytes );\r
- if ( !Bass.BASS_ChannelGetAttribute( this.hBassStream, BASSAttribute.BASS_ATTRIB_FREQ, ref fFreq ) )\r
- {\r
- string errmes = string.Format( "サウンドストリームの周波数取得に失敗しました。(BASS_ChannelGetAttribute)[{0}]", Bass.BASS_ErrorGetCode().ToString() );\r
- Bass.BASS_Free();\r
- throw new Exception( errmes );\r
- }\r
-\r
-\r
-\r
- int bs = Bass.BASS_ChannelSetFX( this.hBassStream, BASSFXType.BASS_FX_BFX_BQF, 1 );\r
-\r
- BASS_BFX_BQF param = new BASS_BFX_BQF(\r
- BASSBFXBQF.BASS_BFX_BQF_LOWPASS, // filter\r
- 800.0f, // center default=200\r
- 15, // gain deafult=0\r
- 0, // bandwidth\r
- 1, //0.67f, // Q\r
- 0, // s\r
- BASSFXChan.BASS_BFX_CHANALL //chans\r
- );\r
-\r
- bool b = Bass.BASS_FXSetParameters( bs, param );\r
- if ( b == false )\r
- {\r
- Debug.WriteLine( "effect set failed: " + Bass.BASS_ErrorGetCode().ToString() );\r
- }\r
- //bool b2 = Bass.BASS_ChannelPlay( this.hBassStream, false );\r
- //if ( b2 == false )\r
- //{\r
- // Debug.WriteLine( "plyback failed: " + Bass.BASS_ErrorGetCode().ToString() );\r
- //}\r
- #endregion\r
- }\r
- #endregion\r
-\r
- /// <summary>\r
- /// 曲全体のテンポを取得する\r
- /// </summary>\r
- /// <returns>テンポ値</returns>\r
- /// <remarks>テンポ値の範囲は70-300</remarks>\r
- public float GetTempo()\r
- {\r
- fTempo = BassFx.BASS_FX_BPM_DecodeGet(\r
- this.hBassStream,\r
- 0,\r
- nTotalSeconds,\r
- ( 300 << 16 ) + 70, // MAX BPM=320, MIN BPM=70\r
- //0,\r
- BASSFXBpm.BASS_FX_BPM_DEFAULT, //BASSFXBpm.BASS_FX_BPM_MULT2,\r
- null,\r
- IntPtr.Zero );\r
- return fTempo;\r
- }\r
- /// <summary>\r
- /// 曲の一部分のテンポを取得する\r
- /// </summary>\r
- /// <param name="startSec">開始位置</param>\r
- /// <param name="endSec">終了位置</param>\r
- /// <returns>テンポ値</returns>\r
- /// <remarks>テンポ値の範囲は70-300</remarks>\r
- public float GetTempo( double startSec, double endSec )\r
- {\r
- fTempo = BassFx.BASS_FX_BPM_DecodeGet(\r
- this.hBassStream,\r
- startSec,\r
- endSec,\r
- ( 300 << 16 ) + 70, // MAX BPM=320, MIN BPM=70\r
- //0,\r
- BASSFXBpm.BASS_FX_BPM_DEFAULT, //BASSFXBpm.BASS_FX_BPM_MULT2,\r
- null,\r
- IntPtr.Zero );\r
- return fTempo;\r
- }\r
-\r
-\r
- /// <summary>\r
- /// Beatの検出位置をListで返す\r
- /// </summary>\r
- /// <returns>Beat検出位置群</returns>\r
- public List<stBeatPos> GetBeatPositions()\r
- {\r
- #region [ BeatPosition格納リストの初期化 ]\r
- if ( this.listBeatPositions != null )\r
- {\r
- this.listBeatPositions.Clear();\r
- }\r
- else\r
- {\r
- this.listBeatPositions = new List<stBeatPos>();\r
- }\r
- #endregion\r
-\r
- BPMBEATPROC _beatProc = new BPMBEATPROC( GetBeat_ProgressCallback );\r
-\r
- //\r
- //\r
- // LPFを通してから、BeatDecodeGetしてみること。\r
- //\r
- //\r
-\r
- bool ret = BassFx.BASS_FX_BPM_BeatDecodeGet(\r
- this.hBassStream,\r
- 0,\r
- nTotalSeconds,\r
- //0,\r
- BASSFXBpm.BASS_FX_BPM_DEFAULT, //BASSFXBpm.BASS_FX_BPM_MULT2,\r
- _beatProc,\r
- IntPtr.Zero );\r
-\r
- return this.listBeatPositions;\r
- }\r
-\r
- private void GetBeat_ProgressCallback( int channel, double beatpos, IntPtr user )\r
- {\r
- stBeatPos sbp = new stBeatPos(\r
- (float) beatpos,\r
- 0,\r
- 0,\r
- 0,\r
- false,\r
- true\r
- ); \r
- \r
-\r
- listBeatPositions.Add( sbp );\r
-// Debug.WriteLine( "Beat at: " + beatpos.ToString() );\r
- }\r
-\r
-\r
- \r
- \r
- public void Dispose() // 使い終わったら必ずDispose()すること。BASSのリソースを握りっぱなしにすると、他の再生に不都合が生じるため。\r
- {\r
- BassFx.BASS_FX_BPM_Free( this.hBassStream );\r
- Bass.BASS_StreamFree( this.hBassStream );\r
- this.hBassStream = -1;\r
- Bass.BASS_Free();\r
- }\r
- \r
- // =============\r
- private string filename = "";\r
- private int hBassStream = -1;\r
- private long nTotalBytes = 0;\r
- private double nTotalSeconds = 0.0f;\r
- private float fFreq = 0.0f;\r
- private float fTempo;\r
- private List<stBeatPos> listBeatPositions = null;\r
- }\r
-}\r