// 初期化。 public static void 状態をリセットする() { スコア = null; データ種別 = データ種別.DTX; Random = new Random((int)(Stopwatch.GetTimestamp() % int.MaxValue)); 行番号 = 0; コマンド = ""; コマンドzzなし = ""; zz16進数 = -1; zz36進数 = -1; パラメータ = ""; コメント = ""; 小節番号 = 0; チャンネル番号 = 0; チップ種別 = チップ種別.Unknown; 小節解像度 = 384; // DTX の小節解像度は 384 固定 オブジェクト総数 = 0; オブジェクト番号 = 0; PAN定義マップ = new Dictionary <int, int>(); VOLUME定義マップ = new Dictionary <int, int>(); BGMWAVリスト = new List <int>(); BASEBPM = 0.0; BPM定義マップ = new Dictionary <int, double>(); BPM参照マップ = new Dictionary <チップ, int>(); 小節長倍率マップ = new SortedDictionary <int, double>(); }
public void 登録する(チップ種別 chipType, int subChipId, VariablePath サウンドファイルパス) { if (File.Exists(サウンドファイルパス.数なしパス)) { lock (this._Sound利用権) { // すでに辞書に存在してるなら、解放して削除する。 if (this._チップtoコンテキスト.ContainsKey((chipType, subChipId))) { this._チップtoコンテキスト[(chipType, subChipId)]?.Dispose(); this._チップtoコンテキスト.Remove((chipType, subChipId)); } // コンテキストを作成する。 var context = new Cコンテキスト(this._多重度); // サウンドファイルを読み込んでデコードする。 context.SampleSource = SampleSourceFactory.Create(App.サウンドデバイス, サウンドファイルパス); // 多重度分のサウンドを生成する。 for (int i = 0; i < context.Sounds.Length; i++) { context.Sounds[i] = new Sound(App.サウンドデバイス, context.SampleSource); } // コンテキストを辞書に追加する。 this._チップtoコンテキスト.Add((chipType, subChipId), context); Log.Info($"ドラムサウンドを生成しました。[({chipType.ToString()},{subChipId}) = {サウンドファイルパス.変数付きパス}]"); } }
/// <summary> /// 指定した番号のWAVを、指定したチップ種別として発声する。 /// </summary> /// <param name="音量">0:無音~1:原音</param> public void 発声する(int WAV番号, チップ種別 chipType, float 音量 = 1f) { if (!(this._WavContexts.ContainsKey(WAV番号))) { return; } // 現在発声中のサウンドを全部止めるチップ種別の場合は止める。 if (0 != chipType.排他発声グループID()) // グループID = 0 は対象外。 { // 消音対象のコンテキストの Sounds[] を select する。 var 停止するサウンドs = from kvp in this._WavContexts where (chipType.直前のチップを消音する(kvp.Value.最後に発声したときのチップ種別)) select kvp.Value.Sounds; // 集めた Sounds[] をすべて停止する。 foreach (var sounds in 停止するサウンドs) { foreach (var sound in sounds) { sound.Stop(); } } } // 発声する。 this._WavContexts[WAV番号].発声する(chipType, 音量); }
public bool 選択されている(チップ種別 chipType) { // First() で要素が見つからなかったらバグなので、そのまま System.InvalidOperationException を放出させる。 var key = this.dic行とチップ種別対応表.First((kvp) => (kvp.Value == chipType)).Key; return(this.checkedListBoxチップ選択リスト.GetItemCheckState(key) == CheckState.Checked); }
/// <summary> /// 指定した番号のWAVを、指定したチップ種別として発声する。 /// </summary> /// <param name="音量">0:無音~1:原音</param> public void 発声する(int WAV番号, チップ種別 chipType, bool 発声前に消音する, 消音グループ種別 muteGroupType, bool BGM以外も再生する, float 音量 = 1f, double 再生開始時刻sec = 0.0) { if (!(this._WAV情報リスト.ContainsKey(WAV番号)) || (!(BGM以外も再生する) && !(this._WAV情報リスト[WAV番号].BGMである))) { return; } // 消音する(必要あれば)。 if (発声前に消音する && muteGroupType != 消音グループ種別.Unknown) { // 発生時に指定された消音グループ種別に属するWAVサウンドをすべて停止する。 var 停止するWavContexts = this._WAV情報リスト.Where((kvp) => (kvp.Value.最後に発声したときの消音グループ種別 == muteGroupType)); foreach (var kvp in 停止するWavContexts) { kvp.Value.発声を停止する(); } } // 発声する。 this._WAV情報リスト[WAV番号].発声する(muteGroupType, 音量, 再生開始時刻sec); }
public static bool 直前のチップを消音する(this チップ種別 今回のチップの種別, チップ種別 直前のチップの種別) { int 今回のチップのGID = 今回のチップの種別.排他発声グループID(); int 直前のチップのGID = 直前のチップの種別.排他発声グループID(); if (直前のチップのGID != 今回のチップのGID) { return(false); } // 以下は、消音する。 if ((今回のチップの種別 == チップ種別.SE1) || (今回のチップの種別 == チップ種別.SE2) || (今回のチップの種別 == チップ種別.SE3) || (今回のチップの種別 == チップ種別.SE4) || (今回のチップの種別 == チップ種別.SE5) || //( 今回のチップの種別 == チップ種別.BGM ) || BGM は消音しない。(DTX仕様) (今回のチップの種別 == チップ種別.GuitarAuto) || (今回のチップの種別 == チップ種別.BassAuto)) { return(true); } // グループIDがシンバルである場合は、Mute が来た場合を除き、消音しない。 if (直前のチップのGID == GID_LEFT_CYMBAL) { return(今回のチップの種別 == チップ種別.LeftCymbal_Mute); } if (直前のチップのGID == GID_RIGHT_CYMBAL) { return(今回のチップの種別 == チップ種別.RightCymbal_Mute); } return(true); }
/// <summary> /// チップの排他発声グループID を表す。 /// ただし、グループID 0 は排他発声にはしないことを意味する。 /// </summary> /// <remarks> /// このグループIDを 0 以外に設定すると、チップの発声時に、そのチップ種別に対応する排他発声グループIDを参照して /// それと同じ値を持つチップ種別のサウンドがすべて再生停止する必要があるかを確認し、必要あれば停止してから発声されるようなる。 /// なお、同一かどうかだけを見るので、グループIDに設定する数値は(0を除いて)どんな値でもいい。 /// </remarks> /// <param name="チップ種別">調べるチップ種別。</param> /// <returns>チップ種別に対応する排他発声グループID。</returns> public static int 排他発声グループID(this チップ種別 チップ種別) { switch (チップ種別) { case チップ種別.HiHat_Close: case チップ種別.HiHat_Foot: case チップ種別.HiHat_HalfOpen: case チップ種別.HiHat_Open: return(GID_HIHAT); case チップ種別.LeftCrash: case チップ種別.LeftCymbal_Mute: return(GID_LEFT_CYMBAL); case チップ種別.RightCrash: case チップ種別.RightCymbal_Mute: return(GID_RIGHT_CYMBAL); case チップ種別.China: // return ( user.オプション設定.表示レーンの左右.Chinaは左 ) ? GID_LEFT_CYMBAL : GID_RIGHT_CYMBAL; return(GID_RIGHT_CYMBAL); // China は右で固定 case チップ種別.Splash: //return ( user.オプション設定.表示レーンの左右.Splashは左 ) ? GID_LEFT_CYMBAL : GID_RIGHT_CYMBAL; return(GID_LEFT_CYMBAL); // Splash は左で固定 case チップ種別.Ride: case チップ種別.Ride_Cup: //return ( user.オプション設定.表示レーンの左右.Rideは左 ) ? GID_LEFT_CYMBAL : GID_RIGHT_CYMBAL; return(GID_RIGHT_CYMBAL); // Ride は右で固定 } return(0); }
protected void チップを描画する_通常(Graphics g, チップ種別 eチップ, int 音量, Rectangle チップ描画領域, string チップ内文字列, Color 描画色) { using (var 背景ブラシ = new SolidBrush(描画色)) using (var 明るいペン = new Pen(Color.FromArgb(チップ明影透明度, 描画色))) using (var 暗いペン = new Pen(Color.FromArgb(チップ暗影透明度, 描画色))) { this.チップ音量に合わせてチップ描画領域を縮小する(音量, ref チップ描画領域); // チップ本体 g.FillRectangle(背景ブラシ, チップ描画領域); g.DrawLine(明るいペン, チップ描画領域.X, チップ描画領域.Y, チップ描画領域.Right, チップ描画領域.Y); g.DrawLine(明るいペン, チップ描画領域.X, チップ描画領域.Y, チップ描画領域.X, チップ描画領域.Bottom); g.DrawLine(暗いペン, チップ描画領域.X, チップ描画領域.Bottom, チップ描画領域.Right, チップ描画領域.Bottom); g.DrawLine(暗いペン, チップ描画領域.Right, チップ描画領域.Bottom, チップ描画領域.Right, チップ描画領域.Y); // チップ内文字列 if (チップ内文字列.Nullでも空でもない()) { var layout = new RectangleF() { X = チップ描画領域.X, Y = チップ描画領域.Y, Width = チップ描画領域.Width, Height = チップ描画領域.Height, }; g.DrawString(チップ内文字列, this.チップ内文字列フォント, Brushes.Black, layout, this.チップ内文字列フォーマット); layout.X--; layout.Y--; g.DrawString(チップ内文字列, チップ内文字列フォント, Brushes.White, layout, this.チップ内文字列フォーマット); } } }
protected void チップを描画する_幅狭白丸(Graphics g, チップ種別 eチップ, int 音量, Rectangle チップ描画領域, string チップ内文字列) { // 幅狭チップを描画。 this.チップを描画する_幅狭(g, eチップ, 音量, チップ描画領域, チップ内文字列); // その上に丸を描く。 this.チップ音量に合わせてチップ描画領域を縮小する(音量, ref チップ描画領域); g.DrawEllipse(this.白丸白バツペン, チップ描画領域); }
protected void チップを描画する_幅狭(Graphics g, チップ種別 eチップ, int 音量, Rectangle チップ描画領域, string チップ内文字列, Color 描画色) { // チップの幅を半分にする。 int w = チップ描画領域.Width; チップ描画領域.Width = w / 2; チップ描画領域.X += w / 4; this.チップを描画する_通常(g, eチップ, 音量, チップ描画領域, チップ内文字列, 描画色); }
/// <summary> /// 指定したチップ種別扱いでWAVを発声する。 /// </summary> /// <param name="音量">0:無音~1:原音</param> public void 発声する(チップ種別 chipType, float 音量) { this.最後に発声したときのチップ種別 = chipType; // 発声。 音量 = (0f > 音量) ? 0f : (1f < 音量) ? 1f : 音量; this.Sounds[this.次に再生するSound番号].Volume = 音量; this.Sounds[this.次に再生するSound番号].Play(0); // サウンドローテーション。 this.次に再生するSound番号 = (this.次に再生するSound番号 + 1) % this.Sounds.Length; }
protected void チップを描画する_幅狭白狭丸(Graphics g, チップ種別 eチップ, int 音量, Rectangle チップ描画領域, string チップ内文字列) { // 幅狭チップを描画。 this.チップを描画する_幅狭(g, eチップ, 音量, チップ描画領域, チップ内文字列); // その上に狭い丸を描く。 this.チップ音量に合わせてチップ描画領域を縮小する(音量, ref チップ描画領域); int w = チップ描画領域.Width; チップ描画領域.Width = w / 3; チップ描画領域.X += w / 3 - 1; // -1 は見た目のバランス(直感) g.DrawEllipse(this.白丸白バツペン, チップ描画領域); }
public void チップを指定領域へ描画する(Graphics g, チップ種別 eチップ, int 音量, Rectangle チップ描画領域, string チップ内文字列) { // ※SSTFormat.チップ の描画以外の目的でも呼ばれるため、本メソッドの引数には SSTFormat.チップ を入れていない。 switch (eチップ) { case チップ種別.BPM: case チップ種別.LeftCrash: case チップ種別.HiHat_Close: case チップ種別.Snare: case チップ種別.Tom1: case チップ種別.Bass: case チップ種別.Tom2: case チップ種別.Tom3: case チップ種別.RightCrash: case チップ種別.China: case チップ種別.Splash: case チップ種別.背景動画: case チップ種別.BGM: this.チップを描画する_通常(g, eチップ, 音量, チップ描画領域, チップ内文字列); break; case チップ種別.Snare_Ghost: this.チップを描画する_小丸(g, eチップ, 音量, チップ描画領域, チップ内文字列); break; case チップ種別.Ride: this.チップを描画する_幅狭(g, eチップ, 音量, チップ描画領域, チップ内文字列); break; case チップ種別.Snare_OpenRim: case チップ種別.HiHat_Open: this.チップを描画する_幅狭白丸(g, eチップ, 音量, チップ描画領域, チップ内文字列); break; case チップ種別.HiHat_HalfOpen: case チップ種別.Ride_Cup: this.チップを描画する_幅狭白狭丸(g, eチップ, 音量, チップ描画領域, チップ内文字列); break; case チップ種別.HiHat_Foot: case チップ種別.Snare_ClosedRim: case チップ種別.Tom1_Rim: case チップ種別.Tom2_Rim: case チップ種別.Tom3_Rim: case チップ種別.LeftCymbal_Mute: case チップ種別.RightCymbal_Mute: this.チップを描画する_幅狭白バツ(g, eチップ, 音量, チップ描画領域, チップ内文字列); break; } }
protected void チップを描画する_幅狭白バツ(Graphics g, チップ種別 eチップ, int 音量, Rectangle チップ描画領域, string チップ内文字列) { // 幅狭チップを描画。 this.チップを描画する_幅狭(g, eチップ, 音量, チップ描画領域, チップ内文字列); // その上にバツを描く。 this.チップ音量に合わせてチップ描画領域を縮小する(音量, ref チップ描画領域); int w = チップ描画領域.Width; チップ描画領域.Width = w / 3; チップ描画領域.X += w / 3; g.DrawLine(this.白丸白バツペン, new Point(チップ描画領域.Left, チップ描画領域.Top), new Point(チップ描画領域.Right, チップ描画領域.Bottom)); g.DrawLine(this.白丸白バツペン, new Point(チップ描画領域.Left, チップ描画領域.Bottom), new Point(チップ描画領域.Right, チップ描画領域.Top)); }
protected void チップを描画する_小丸(Graphics g, チップ種別 eチップ, int 音量, Rectangle チップ描画領域, string チップ内文字列) { this.チップ音量に合わせてチップ描画領域を縮小する(音量, ref チップ描画領域); Color 描画色 = this.チップto色[eチップ]; int w = チップ描画領域.Width; チップ描画領域.Width = w / 3; チップ描画領域.X += w / 3; using var 背景ブラシ = new SolidBrush(描画色); using var 枠ペン = new Pen(Color.Orange); g.FillEllipse(背景ブラシ, チップ描画領域); g.DrawEllipse(枠ペン, チップ描画領域); }
protected void チップカーソルを描画する(Graphics g, チップ種別 eチップ) { #region " 事前チェック。" //----------------- if ((0 >= this.現在のチップカーソル領域.Width) || (0 >= this.現在のチップカーソル領域.Height) || (this.現在チップカーソルがある編集レーン == 編集レーン種別.Unknown) || (eチップ == チップ種別.Unknown) || (eチップ == チップ種別.小節線) || (eチップ == チップ種別.拍線)) { return; // 描画しない。 } //----------------- #endregion this.Form.譜面.チップを指定領域へ描画する(g, eチップ, this.Form.現在のチップ音量, this.現在のチップカーソル領域, null); this.Form.譜面.チップの太枠を指定領域へ描画する(g, this.現在のチップカーソル領域); }
/// <summary> /// 指定したチップ種別・サブチップIDの組に対応するドラムサウンドを再生する。 /// </summary> /// <remarks> /// <paramref name="発声前に消音する"/> を true にすると、ドラムサウンドは多重再生されなくなる。 /// この場合、現在再生しているサウンドを停止(消音)してから再生することになるが、 /// <paramref name="消音グループ種別"/> で指定されたグループ種別と同じグループ種別に属する /// ドラムサウンドが停止の対象となる。 /// </remarks> public void 発声する(チップ種別 chipType, int subChipId, bool 発声前に消音する = false, 消音グループ種別 消音グループ種別 = 消音グループ種別.Unknown, float 音量0to1 = 1f) { lock (this._Sound利用権) { if (this._チップtoコンテキスト.TryGetValue((chipType, subChipId), out ドラムサウンド情報 context)) { // 必要あれば消音する。 if (発声前に消音する && 消音グループ種別 != 消音グループ種別.Unknown) { // 指定された消音グループ種別に属するドラムサウンドをすべて停止する。 var 停止するSoundContexts = this._チップtoコンテキスト.Where((kvp) => (kvp.Value.最後に発声したときの消音グループ種別 == 消音グループ種別)); foreach (var wavContext in 停止するSoundContexts) { foreach (var sound in wavContext.Value.Sounds) { sound.Stop(); } } } // 発声する。 context.発声する(消音グループ種別, 音量0to1); }
/// <summary> /// SSTFormat.v1.チップ種別 を、SSTFormat.v2.チップ種別 に変換して返す。 /// </summary> public static v2.チップ種別 ToV2(this チップ種別 v1type) { return((v2.チップ種別)((int)v1type)); // 仕様に変更なし。 }
public void チップを配置または置換する(編集レーン種別 e編集レーン, チップ種別 eチップ, int 譜面内絶対位置grid, string チップ文字列, int 音量, double BPM, bool 選択確定中) { try { this.Form.UndoRedo管理.トランザクション記録を開始する(); // 配置位置にチップがあれば削除する。 this.チップを削除する(e編集レーン, 譜面内絶対位置grid); // そこにチップがなければ何もしない。 // 新しいチップを作成し配置する。 var 小節情報 = this.譜面内絶対位置gridに位置する小節の情報を返す(譜面内絶対位置grid); int 小節の長さgrid = this.小節長をグリッドで返す(小節情報.小節番号); var chip = new 描画用チップ() { 選択が確定している = 選択確定中, BPM = BPM, 発声時刻sec = 0, // SSTFEditorでは使わない チップ種別 = eチップ, 音量 = 音量, 小節解像度 = 小節の長さgrid, 小節内位置 = 譜面内絶対位置grid - 小節情報.小節の先頭位置grid, 小節番号 = 小節情報.小節番号, 譜面内絶対位置grid = 譜面内絶対位置grid, チップ内文字列 = チップ文字列, }; // チップを譜面に追加。 var 更前チップ = new 描画用チップ(chip); var cell = new UndoRedo.セル <描画用チップ>( 所有者ID: null, Undoアクション: (更対象, 更前, 更後, 任意1, 任意2) => { this.SSTFormatScore.チップリスト.Remove(更対象); this.Form.未保存である = true; }, Redoアクション: (更対象, 更前, 更後, 任意1, 任意2) => { 更対象.CopyFrom(更前); this.SSTFormatScore.チップリスト.Add(更対象); this.SSTFormatScore.チップリスト.Sort(); this.Form.未保存である = true; }, 更対象: chip, 更前の値: 更前チップ, 更後の値: null); this.Form.UndoRedo管理.セルを追加する(cell); cell.Redoを実行する(); // 配置した小節が現状最後の小節だったら、後ろに小節を4つ追加する。 if (chip.小節番号 == this.SSTFormatScore.最大小節番号を返す()) { this.最後の小節の後ろに小節を4つ追加する(); } } finally { this.Form.UndoRedo管理.トランザクション記録を終了する(); this.Form.UndoRedo用GUIのEnabledを設定する(); this.Form.未保存である = true; } }
/// <summary> /// SSTFormat.v2.チップ種別 を、SSTFormat.v3.チップ種別 に変換して返す。 /// </summary> public static v3.チップ種別 ToV3(this チップ種別 v2type) { return((v3.チップ種別)((int)v2type)); // 仕様に変更なし。 }
protected void チップを描画する_幅狭(Graphics g, チップ種別 eチップ, int 音量, Rectangle チップ描画領域, string チップ内文字列) { this.チップを描画する_幅狭(g, eチップ, 音量, チップ描画領域, チップ内文字列, this.チップto色[eチップ]); }