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