"bass_fx.dll is not loaded. bass_fx.dll or bass.dll must not exist." + newLine + "Please download DTXMania again."
))
bDLLnotfound = true;
+ //if (!tDLLの存在チェック("dll\\BASSThreadedMixer.dll",
+ // "BASSThreadedMixer.dll を読み込めません。BASSThreadedMixer.dll が存在しません。" + newLine + "DTXManiaをダウンロードしなおしてください。",
+ // "BASSThreadedMixer.dll is not loaded. BASSThreadedMixer.dll must not exist." + newLine + "Please download DTXMania again."
+ // ))
+ // bDLLnotfound = true;
if (!tDLLの存在チェック("dll\\DirectShowLib.dll",
"DirectShowLib.dll が存在しません。" + newLine + "DTXManiaをダウンロードしなおしてください。",
"DirectShowLib.dll is not found." + newLine + "Please download DTXMania again."
</DocumentationFile>
<UseVSHostingProcess>false</UseVSHostingProcess>
<NoWarn>0219</NoWarn>
- <DefineConstants>TRACE;DEBUG;TEST_CancelEnterCodeInAltEnter2 TEST_Direct3D9Ex_</DefineConstants>
+ <DefineConstants>TRACE;DEBUG;TEST_CancelEnterCodeInAltEnter2 TEST_Direct3D9Ex_ TEST_MulthThreadedMixer_</DefineConstants>
<Optimize>false</Optimize>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<Compile Include="コード\02.入力\IInputDevice.cs" />
<Compile Include="コード\02.入力\SlimDX.DirectInput.Key.cs" />
<Compile Include="コード\02.入力\STInputEvent.cs" />
+ <Compile Include="コード\03.サウンド\BASSThreadedMixerWrapper.cs" />
<Compile Include="コード\03.サウンド\Cmp3.cs" />
<Compile Include="コード\03.サウンド\Cogg.cs" />
<Compile Include="コード\03.サウンド\CSound.cs" />
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace FDK
+{
+ public unsafe class BASSThreadedMixerLibraryWrapper
+ {
+
+ //* Parameters
+ public static readonly int BASSTM_PARAMETER_NO_THREAD_FOR_1_SOURCE = 1; //* Default = True
+ public static readonly int BASSTM_PARAMETER_THREADS_PRIORITY = 2; //* Affects only sources added after setting this parameter
+ public static readonly int BASSTM_THREADS_PRIORITY_Idle = 0;
+ public static readonly int BASSTM_THREADS_PRIORITY_Lowest = 1;
+ public static readonly int BASSTM_THREADS_PRIORITY_Lower = 2;
+ public static readonly int BASSTM_THREADS_PRIORITY_Normal = 3;
+ public static readonly int BASSTM_THREADS_PRIORITY_Higher = 4; //* Default
+ public static readonly int BASSTM_THREADS_PRIORITY_Highest = 5;
+ public static readonly int BASSTM_THREADS_PRIORITY_TimeCritical = 6;
+
+ //* .dll file name
+ public static readonly string FILENAME_DLL_BASS_THREADED_MIXER_LIBRARY = @"dll\BASSThreadedMixer.dll";
+ //public static readonly int BASSARLIBCALL __stdcall
+ //public static readonly int GETBASSTMLIBFUNCTION(f) *((void**)&f) = GetProcAddress(BASSThreadedMixerLibraryDLLHandle, #f)
+
+
+ #region [DllImport]
+ [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
+ internal static extern void FreeLibrary(IntPtr hModule);
+
+ [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
+ internal static extern IntPtr LoadLibrary(string lpFileName);
+ #endregion
+
+ #region [ BASSThreadedMixer.dll インポート ]
+ //-----------------
+ [return: MarshalAs(UnmanagedType.U4)]
+ [DllImport("BASSThreadedMixer.dll", EntryPoint = "BASS_ThreadedMixer_Create", CallingConvention = CallingConvention.StdCall)]
+ public static extern Int32 BASS_ThreadedMixer_Create(Int32 Freq, Int32 Chans, Int32 Flags, out IntPtr ThreadedMixerHandle);
+
+ [return: MarshalAs(UnmanagedType.Bool)]
+ [DllImport("BASSThreadedMixer.dll", EntryPoint = "BASS_ThreadedMixer_AddSource", CallingConvention = CallingConvention.StdCall)]
+ public static extern bool BASS_ThreadedMixer_AddSource(IntPtr ThreadedMixerHandle, Int32 SourceChannel, IntPtr Matrix);
+ [return: MarshalAs(UnmanagedType.Bool)]
+ [DllImport("BASSThreadedMixer.dll", EntryPoint = "BASS_ThreadedMixer_RemoveSource", CallingConvention = CallingConvention.StdCall)]
+ public static extern bool BASS_ThreadedMixer_RemoveSource(IntPtr ThreadedMixerHandle, Int32 SourceChannel);
+ [return: MarshalAs(UnmanagedType.Bool)]
+ [DllImport("BASSThreadedMixer.dll", EntryPoint = "BASS_ThreadedMixer_SetMatrix", CallingConvention = CallingConvention.StdCall)]
+ public static extern bool BASS_ThreadedMixer_SetMatrix(IntPtr ThreadedMixerHandle, Int32 SourceChannel, IntPtr Matrix, Single FadeTime);
+ [return: MarshalAs(UnmanagedType.Bool)]
+ [DllImport("BASSThreadedMixer.dll", EntryPoint = "BASS_ThreadedMixer_SetParameter", CallingConvention = CallingConvention.StdCall)]
+ public static extern bool BASS_ThreadedMixer_SetParameter(IntPtr ThreadedMixerHandle, Int32 Parameter, Int32 Value);
+
+ //typedef DWORD(BASSARLIBCALL* t_BASS_ThreadedMixer_Create)(DWORD Freq, DWORD Chans, DWORD Flags, HBASSTM* ThreadedMixerHandle);
+ //typedef BOOL(BASSARLIBCALL* t_BASS_ThreadedMixer_AddSource)(HBASSTM ThreadedMixerHandle, DWORD SourceChannel, void* Matrix);
+ //typedef BOOL(BASSARLIBCALL* t_BASS_ThreadedMixer_RemoveSource)(HBASSTM ThreadedMixerHandle, DWORD SourceChannel);
+ //typedef BOOL(BASSARLIBCALL* t_BASS_ThreadedMixer_SetMatrix)(HBASSTM ThreadedMixerHandle, DWORD SourceChannel, void* Matrix, float FadeTime);
+ //typedef BOOL(BASSARLIBCALL* t_BASS_ThreadedMixer_SetParameter)(HBASSTM ThreadedMixerHandle, DWORD Parameter, int Value);
+
+ //-----------------
+ #endregion
+
+
+ private static IntPtr BASSThreadedMixerLibraryDLLHandle;
+
+ public static bool InitBASSThreadedMixerLibrary()
+ {
+ //#if _WIN32
+ BASSThreadedMixerLibraryDLLHandle = LoadLibrary(FILENAME_DLL_BASS_THREADED_MIXER_LIBRARY);
+ //#else //* OSX
+ //BASSThreadedMixerLibraryDLLHandle = dlopen(FILENAME_DLL_BASS_THREADED_MIXER_LIBRARY, RTLD_NOW);
+ //#endif
+
+ if (null != BASSThreadedMixerLibraryDLLHandle)
+ {
+ throw new Exception("BASSThreadedMixer.dllの組み込みに失敗しました。");
+
+ //GETBASSTMLIBFUNCTION(BASS_ThreadedMixer_Create);
+ //GETBASSTMLIBFUNCTION(BASS_ThreadedMixer_AddSource);
+ //GETBASSTMLIBFUNCTION(BASS_ThreadedMixer_RemoveSource);
+ //GETBASSTMLIBFUNCTION(BASS_ThreadedMixer_SetMatrix);
+ //GETBASSTMLIBFUNCTION(BASS_ThreadedMixer_SetParameter);
+
+ //if ((NULL == BASS_ThreadedMixer_Create)
+ // || (NULL == BASS_ThreadedMixer_AddSource)
+ // || (NULL == BASS_ThreadedMixer_RemoveSource)
+ // || (NULL == BASS_ThreadedMixer_SetMatrix)
+ // || (NULL == BASS_ThreadedMixer_SetParameter)
+ // )
+ //{
+ // BASSThreadedMixerLibraryDLLLoaded = FALSE;
+ //}
+ //else
+ //{
+ // BASSThreadedMixerLibraryDLLLoaded = TRUE;
+ //}
+ }
+
+ return true;
+ }
+
+ public static bool FreeBASSThreadedMixerLibrary()
+ {
+ if (null != BASSThreadedMixerLibraryDLLHandle)
+ {
+//# ifdef _WIN32
+ FreeLibrary(BASSThreadedMixerLibraryDLLHandle);
+//#else //* OSX
+// BASSThreadedMixerLibraryDLLLoaded = dlclose(BASSThreadedMixerLibraryDLLHandle);
+//#endif
+ }
+ return true;
+ }
+ }
+}
// ... と思ったが、1サウンド辺り1つのテンポ変更ストリームが存在することになり、
// ミキシング負荷が非常に高くなるため、結局TimeStretch=ONの時のみ店舗変更ストリームを提供することにした。
{
- this._hTempoStream = BassFx.BASS_FX_TempoCreate( this._hBassStream, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_FX_FREESOURCE );
- if ( this._hTempoStream == 0 )
+ this._hTempoStream = BassFx.BASS_FX_TempoCreate(this._hBassStream, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_FX_FREESOURCE);
+ if (this._hTempoStream == 0)
{
hGC.Free();
- throw new Exception( string.Format( "サウンドストリームの生成に失敗しました。(BASS_FX_TempoCreate)[{0}]", Bass.BASS_ErrorGetCode().ToString() ) );
+ throw new Exception(string.Format("サウンドストリームの生成に失敗しました。(BASS_FX_TempoCreate)[{0}]", Bass.BASS_ErrorGetCode().ToString()));
}
else
{
- Bass.BASS_ChannelSetAttribute( this._hTempoStream, BASSAttribute.BASS_ATTRIB_TEMPO_OPTION_USE_QUICKALGO, 1f ); // 高速化(音の品質は少し落ちる)
+ Bass.BASS_ChannelSetAttribute(this._hTempoStream, BASSAttribute.BASS_ATTRIB_TEMPO_OPTION_USE_QUICKALGO, 1f); // 高速化(音の品質は少し落ちる)
}
}
- if ( _hTempoStream != 0 && !this.bIs1倍速再生 ) // 再生速度がx1.000のときは、TempoStreamを用いないようにして高速化する
+ if (_hTempoStream != 0 && !this.bIs1倍速再生) // 再生速度がx1.000のときは、TempoStreamを用いないようにして高速化する
{
this.hBassStream = _hTempoStream;
}
{
this.hBassStream = _hBassStream;
}
-
// #32248 再生終了時に発火するcallbackを登録する (演奏終了後に再生終了するチップを非同期的にミキサーから削除するため。)
_cbEndofStream = new SYNCPROC( CallbackEndofStream );
Bass.BASS_ChannelSetSync( hBassStream, BASSSync.BASS_SYNC_END | BASSSync.BASS_SYNC_MIXTIME, 0, _cbEndofStream, IntPtr.Zero );
}
public bool tBASSサウンドをミキサーから削除する( int channel )
{
- bool b = BassMix.BASS_Mixer_ChannelRemove( channel );
+//bool b = BASSThreadedMixerLibraryWrapper.BASS_ThreadedMixer_RemoveSource((IntPtr)this.hMixer, channel );
+//mixingChannel.Remove((IntPtr)this.hMixer);
+ bool b = BassMix.BASS_Mixer_ChannelRemove(channel);
if ( b )
{
Interlocked.Decrement( ref CSound管理.nMixing );
}
-// mixer への追加
-
+ // mixer への追加
+
+//private List<IntPtr> mixingChannel = new List<IntPtr>();
+
public bool tBASSサウンドをミキサーに追加する()
{
+//if (!mixingChannel.Contains((IntPtr)this.hMixer))
if ( BassMix.BASS_Mixer_ChannelGetMixer( hBassStream ) == 0 )
{
BASSFlag bf = BASSFlag.BASS_SPEAKER_FRONT | BASSFlag.BASS_MIXER_NORAMPIN | BASSFlag.BASS_MIXER_PAUSE;
// preloadされることを期待して、敢えてflagからはBASS_MIXER_PAUSEを外してAddChannelした上で、すぐにPAUSEする
// -> ChannelUpdateでprebufferできることが分かったため、BASS_MIXER_PAUSEを使用することにした
- bool b1 = BassMix.BASS_Mixer_StreamAddChannel( this.hMixer, this.hBassStream, bf );
+//bool b1 = BASSThreadedMixerLibraryWrapper.BASS_ThreadedMixer_AddSource( (IntPtr)this.hMixer, this.hBassStream, IntPtr.Zero );
+//mixingChannel.Add((IntPtr)this.hMixer);
+ bool b1 = BassMix.BASS_Mixer_StreamAddChannel(this.hMixer, this.hBassStream, bf);
//bool b2 = BassMix.BASS_Mixer_ChannelPause( this.hBassStream );
t再生位置を先頭に戻す(); // StreamAddChannelの後で再生位置を戻さないとダメ。逆だと再生位置が変わらない。
//Trace.TraceInformation( "Add Mixer: " + Path.GetFileName( this.strファイル名 ) + " (" + hBassStream + ")" + " MixedStreams=" + CSound管理.nMixing );
#endregion
}
+//LoadLibraryに失敗する・・・
+//BASSThreadedMixerLibraryWrapper.InitBASSThreadedMixerLibrary();
// string.Format( "BASS_SetConfig(CONFIG_MIXER_BUFFER) に失敗しました。[{0}", Bass.BASS_ErrorGetCode() ) );
var info = BassWasapi.BASS_WASAPI_GetInfo();
+//this.hMixer = BASSThreadedMixerLibraryWrapper.BASS_ThreadedMixer_Create(
+// info.freq,
+// info.chans,
+// (int)(BASSFlag.BASS_MIXER_NONSTOP | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_MIXER_POSEX),
+// out hMixerThreaded
+// );
+
this.hMixer = BassMix.BASS_Mixer_StreamCreate(
info.freq,
info.chans,
- BASSFlag.BASS_MIXER_NONSTOP | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_MIXER_POSEX ); // デコードのみ=発声しない。WASAPIに出力されるだけ。
+ BASSFlag.BASS_MIXER_NONSTOP | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_MIXER_POSEX); // デコードのみ=発声しない。WASAPIに出力されるだけ。
if ( this.hMixer == 0 )
{
BASSError errcode = Bass.BASS_ErrorGetCode();
for (int i = 0; i <= (int)CSound.EInstType.Unknown; i++)
{
+//this.hMixer_Chips[i] = BASSThreadedMixerLibraryWrapper.BASS_ThreadedMixer_Create(
+// info.freq,
+// info.chans,
+// (int)(BASSFlag.BASS_MIXER_NONSTOP | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_MIXER_POSEX),
+// out this.hMixerThreaded_Chips[i]
+//); // デコードのみ=発声しない。WASAPIに出力されるだけ。
this.hMixer_Chips[ i ] = BassMix.BASS_Mixer_StreamCreate(
info.freq,
info.chans,
}
// Mixerのボリューム設定
- Bass.BASS_ChannelSetAttribute(this.hMixer_Chips[ i ], BASSAttribute.BASS_ATTRIB_VOL, CSound管理.nMixerVolume[ i ] / 100.0f );
-//Trace.TraceInformation("Vol{0}: {1}", i, CSound管理.nMixerVolume[i]);
+ Bass.BASS_ChannelSetAttribute(this.hMixer_Chips[i], BASSAttribute.BASS_ATTRIB_VOL, CSound管理.nMixerVolume[i] / 100.0f);
+ //Trace.TraceInformation("Vol{0}: {1}", i, CSound管理.nMixerVolume[i]);
+//bool b1 = BASSThreadedMixerLibraryWrapper.BASS_ThreadedMixer_AddSource(this.hMixerThreaded, this.hMixer_Chips[i], IntPtr.Zero);
bool b1 = BassMix.BASS_Mixer_StreamAddChannel(this.hMixer, this.hMixer_Chips[i], BASSFlag.BASS_DEFAULT);
if (!b1)
{
public CSound tサウンドを作成する( string strファイル名, CSound.EInstType eInstType )
{
var sound = new CSound();
- int hmixer = hMixer_Chips[ (int)eInstType ];
+//int hmixer = (int)hMixerThreaded_Chips[ (int)eInstType ];
+ int hmixer = hMixer_Chips[(int)eInstType];
sound.tWASAPIサウンドを作成する( strファイル名, hmixer, this.e出力デバイス, eInstType );
return sound;
}
public CSound tサウンドを作成する( byte[] byArrWAVファイルイメージ, CSound.EInstType eInstType )
{
var sound = new CSound();
+//int hmixer = (int)hMixerThreaded_Chips[(int)eInstType];
int hmixer = hMixer_Chips[(int)eInstType];
sound.tWASAPIサウンドを作成する( byArrWAVファイルイメージ, hmixer, this.e出力デバイス, eInstType );
return sound;
}
public void tサウンドを作成する( string strファイル名, ref CSound sound, CSound.EInstType eInstType )
{
+//int hmixer = (int)hMixerThreaded_Chips[(int)eInstType];
int hmixer = hMixer_Chips[(int)eInstType];
sound.tWASAPIサウンドを作成する( strファイル名, hmixer, this.e出力デバイス, eInstType );
}
public void tサウンドを作成する( byte[] byArrWAVファイルイメージ, ref CSound sound, CSound.EInstType eInstType)
{
+//int hmixer = (int)hMixerThreaded_Chips[(int)eInstType];
int hmixer = hMixer_Chips[(int)eInstType];
sound.tWASAPIサウンドを作成する( byArrWAVファイルイメージ, hmixer, this.e出力デバイス, eInstType );
}
}
}
}
+//BASSThreadedMixerLibraryWrapper.FreeBASSThreadedMixerLibrary();
if ( !this.bIsBASSFree )
{
protected int hMixer_Record = 0;
protected int[] hMixer_Chips = new int[(int)CSound.EInstType.Unknown + 1]; //DTX2WAV対応 BGM, SE, Drums...を別々のmixerに入れて、個別に音量変更できるようにする
+//protected IntPtr hMixerThreaded = IntPtr.Zero;
+//protected IntPtr[] hMixerThreaded_Chips = new IntPtr[(int)CSound.EInstType.Unknown + 1];
+
protected BaseEncoder encoder;
protected int stream;
protected WASAPIPROC tWasapiProc = null;
{
// BASSミキサからの出力データをそのまま WASAPI buffer へ丸投げ。
- int num = Bass.BASS_ChannelGetData( this.hMixer_DeviceOut, buffer, length ); // num = 実際に転送した長さ
+ int num = Bass.BASS_ChannelGetData( this.hMixer_DeviceOut, buffer, length ); // num = 実際に転送した長さ
+ //int num = BassMix.BASS_Mixer_ChannelGetData(this.hMixer_DeviceOut, buffer, length); // これだと動作がめちゃくちゃ重くなる
if ( num == -1 ) num = 0;