// 音量関係

#pragma once

#include <Windows.h>
#include "Constants.h"
#include "Interface.h"

namespace GuruGuruSmf { namespace Core {

	/// <summary>
	/// 音量コントローラ
	/// </summary>
	class Volume
	{
	private:
		IDevice* device;
		VOLUMESTATE state;
		enum{MAX_PORT = GuruGuruSmf::Core::Constant::MaxPort};
		//int* volumes;
		int volumes[MAX_PORT][16];//複数ポート対応 by Kobarin
		int masterVolume, normalizedGain;
		bool updated;
		int /*fadingCount, fadingTime,*/ fadingGain, oldFadingGain;// del by Kobarin(fadingCount/fadingTime)
		DWORD fadeInStartTime; //フェードイン開始時刻
		DWORD fadeInEndTime;   //フェードイン終了時刻
		DWORD fadeOutStartTime;//フェードアウト開始時刻
		DWORD fadeOutEndTime;  //フェードアウト終了時刻
		DWORD fadePauseTime;   //フェード中の一時停止でフェードが進まないように時間調整
		CRITICAL_SECTION lockObject;

	public:
		Volume(IDevice* dev);	// コンストラクタ
		~Volume();	// デストラクタ

		// 状態
		int GetState(){ return state; }
		
		// trueだと音量を強制的に0にする、falseだと解除(同期)
		void Mute(bool isMute);
		
		// チャンネルごとのボリューム設定(同期)
		//void SetVolume(int channel, int vol);
		void SetVolume(int port, int channel, int vol);//by Kobarin ポートごとにも設定

		// マスターボリュームを設定(非同期)
		void SetMasterVolume(int vol);
		
		// フェードインを設定(非同期) InitializeModuleの前に呼ぶ
		void SetFadeIn(int time);
		
		// フェードアウトを設定(非同期)
		void SetFadeOut(int time);

		// フェード音量を計算
		void CalcFadingGain();
		
		// 非同期処理用のエントリーポイント tureの場合フェードアウト終了
		bool Worker();
		
		// 初期化
		void InitializeModule(bool normalize, int maxVolume);

		//by Kobarin
		//フェードイン/フェードアウト中なら true を返す
		bool IsFading(){return state != VOLUMESTATE::Normal;}

		//フェードイン/フェードアウト中の一時停止
		void FadePause(); 
		void EndFadePause(){fadePauseTime = 0;}

		//最初のノートオンの直前で呼び出す
		void Update(){updated = true;}
		//ここまで
	};


}}


