2 using System.Collections.Generic;
4 using System.Diagnostics;
5 using System.Threading;
7 //using Un4seen.BassAsio;
8 //using Un4seen.BassWasapi;
9 //using Un4seen.Bass.AddOn.Mix;
10 using Un4seen.Bass.AddOn.Fx;
14 public class CBeatDetect : IDisposable
16 public struct stBeatPos
18 public float fBeatTime;
23 public bool bレーン表示する; // 未使用
25 public stBeatPos( float _fBeatTime, int _n小節番号, int _nGrid, int _n小節内Grid, bool _b無効, bool _bレーン表示する )
27 fBeatTime = _fBeatTime;
41 public CBeatDetect( string _filename )
43 this.filename = _filename;
47 #region [ 初期化(コンストラクタから呼び出される) ]
48 private void Initialize()
50 if ( this.listBeatPositions == null )
52 this.listBeatPositions = new List<stBeatPos>();
55 #region [ BASS registration ]
56 // BASS.NET ユーザ登録(BASSスプラッシュが非表示になる)。
58 BassNet.Registration( "dtx2013@gmail.com", "2X9181017152222" );
60 #region [ BASS Version Check ]
62 int nBASSVersion = Utils.HighWord( Bass.BASS_GetVersion() );
63 if ( nBASSVersion != Bass.BASSVERSION )
64 throw new DllNotFoundException( string.Format( "bass.dll のバージョンが異なります({0})。このプログラムはバージョン{1}で動作します。", nBASSVersion, Bass.BASSVERSION ) );
66 int nBASSFXVersion = Utils.HighWord( BassFx.BASS_FX_GetVersion() );
67 if ( nBASSFXVersion != BassFx.BASSFXVERSION )
68 throw new DllNotFoundException( string.Format( "bass_fx.dll のバージョンが異なります({0})。このプログラムはバージョン{1}で動作します。", nBASSFXVersion, BassFx.BASSFXVERSION ) );
72 //this.bIsBASSFree = true;
73 //Debug.Assert( Bass.BASS_SetConfig( BASSConfig.BASS_CONFIG_UPDATEPERIOD, 0 ), // 0:BASSストリームの自動更新を行わない。(サウンド出力しないため)
74 // string.Format( "BASS_SetConfig() に失敗しました。[{0}", Bass.BASS_ErrorGetCode() ) );
77 int nデバイス = 0; // 0:"no sound" … BASS からはデバイスへアクセスさせない。
78 //int nデバイス = -1; // 0:"no sound" … BASS からはデバイスへアクセスさせない。
79 int n周波数 = 44100; // 仮決め。lデバイス(≠ドライバ)がネイティブに対応している周波数であれば何でもいい?ようだ。いずれにしろBASSMXで自動的にリサンプリングされる。
80 if ( !Bass.BASS_Init( nデバイス, n周波数, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero ) )
81 throw new Exception( string.Format( "BASS の初期化に失敗しました。(BASS_Init)[{0}]", Bass.BASS_ErrorGetCode().ToString() ) );
84 #region [ 指定されたサウンドファイルをBASSでオープンし、必要最小限の情報を取得する。]
85 //this.hBassStream = Bass.BASS_StreamCreateFile( this.filename, 0, 0, BASSFlag.BASS_STREAM_PRESCAN | BASSFlag.BASS_STREAM_DECODE );
86 this.hBassStream = Bass.BASS_StreamCreateFile( this.filename, 0, 0, BASSFlag.BASS_STREAM_DECODE );
87 //this.hBassStream = Bass.BASS_StreamCreateFile( this.filename, 0, 0, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN );
88 if ( this.hBassStream == 0 )
89 throw new Exception( string.Format( "{0}: サウンドストリームの生成に失敗しました。(BASS_StreamCreateFile)[{1}]", filename, Bass.BASS_ErrorGetCode().ToString() ) );
91 this.nTotalBytes = Bass.BASS_ChannelGetLength( this.hBassStream );
93 this.nTotalSeconds = Bass.BASS_ChannelBytes2Seconds( this.hBassStream, nTotalBytes );
94 if ( !Bass.BASS_ChannelGetAttribute( this.hBassStream, BASSAttribute.BASS_ATTRIB_FREQ, ref fFreq ) )
96 string errmes = string.Format( "サウンドストリームの周波数取得に失敗しました。(BASS_ChannelGetAttribute)[{0}]", Bass.BASS_ErrorGetCode().ToString() );
98 throw new Exception( errmes );
103 int bs = Bass.BASS_ChannelSetFX( this.hBassStream, BASSFXType.BASS_FX_BFX_BQF, 1 );
105 BASS_BFX_BQF param = new BASS_BFX_BQF(
106 BASSBFXBQF.BASS_BFX_BQF_LOWPASS, // filter
107 800.0f, // center default=200
108 15, // gain deafult=0
112 BASSFXChan.BASS_BFX_CHANALL //chans
115 bool b = Bass.BASS_FXSetParameters( bs, param );
118 Debug.WriteLine( "effect set failed: " + Bass.BASS_ErrorGetCode().ToString() );
120 //bool b2 = Bass.BASS_ChannelPlay( this.hBassStream, false );
123 // Debug.WriteLine( "plyback failed: " + Bass.BASS_ErrorGetCode().ToString() );
132 /// <returns>テンポ値</returns>
133 /// <remarks>テンポ値の範囲は70-300</remarks>
134 public float GetTempo()
136 fTempo = BassFx.BASS_FX_BPM_DecodeGet(
140 ( 300 << 16 ) + 70, // MAX BPM=320, MIN BPM=70
142 BASSFXBpm.BASS_FX_BPM_DEFAULT, //BASSFXBpm.BASS_FX_BPM_MULT2,
150 /// <param name="startSec">開始位置</param>
151 /// <param name="endSec">終了位置</param>
152 /// <returns>テンポ値</returns>
153 /// <remarks>テンポ値の範囲は70-300</remarks>
154 public float GetTempo( double startSec, double endSec )
156 fTempo = BassFx.BASS_FX_BPM_DecodeGet(
160 ( 300 << 16 ) + 70, // MAX BPM=320, MIN BPM=70
162 BASSFXBpm.BASS_FX_BPM_DEFAULT, //BASSFXBpm.BASS_FX_BPM_MULT2,
170 /// Beatの検出位置をListで返す
172 /// <returns>Beat検出位置群</returns>
173 public List<stBeatPos> GetBeatPositions()
175 #region [ BeatPosition格納リストの初期化 ]
176 if ( this.listBeatPositions != null )
178 this.listBeatPositions.Clear();
182 this.listBeatPositions = new List<stBeatPos>();
186 BPMBEATPROC _beatProc = new BPMBEATPROC( GetBeat_ProgressCallback );
190 // LPFを通してから、BeatDecodeGetしてみること。
194 bool ret = BassFx.BASS_FX_BPM_BeatDecodeGet(
199 BASSFXBpm.BASS_FX_BPM_DEFAULT, //BASSFXBpm.BASS_FX_BPM_MULT2,
203 return this.listBeatPositions;
206 private void GetBeat_ProgressCallback( int channel, double beatpos, IntPtr user )
208 stBeatPos sbp = new stBeatPos(
218 listBeatPositions.Add( sbp );
219 // Debug.WriteLine( "Beat at: " + beatpos.ToString() );
225 public void Dispose() // 使い終わったら必ずDispose()すること。BASSのリソースを握りっぱなしにすると、他の再生に不都合が生じるため。
227 BassFx.BASS_FX_BPM_Free( this.hBassStream );
228 Bass.BASS_StreamFree( this.hBassStream );
229 this.hBassStream = -1;
234 private string filename = "";
235 private int hBassStream = -1;
236 private long nTotalBytes = 0;
237 private double nTotalSeconds = 0.0f;
238 private float fFreq = 0.0f;
239 private float fTempo;
240 private List<stBeatPos> listBeatPositions = null;