/// <summary> /// 0番のアルゴリズムを定義します。 /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public static double ZeroSerial(IList <FMOperator> op, ref object tag, FMSynthesisState state) { if (op.Count < 4) { throw new InvalidOperationException("OPN系アルゴリズムではオペレータは4つ必要です"); } return(_serial(op, ref tag, state)); }
/// <summary> /// 最初のチャンネルをキャリア、次のチャンネルをモジュレータとして変調します。 /// それ以降のオペレータは無視されます。 /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public static double PairModulationAlgorithm(IList<FMOperator> op, ref object tag, FMSynthesisState state) { var s = state; if (op.Count < 2) throw new ArgumentException("オペレータは最低2つ必要です"); var mod = op[1].GetState(s); s.State = mod; return op[0].GetState(s) / op[0].ModulationIndex; }
/// <summary> /// ホールドし始めた時刻を0として、 /// 指定した時刻のオペレータ出力を取得します。 /// </summary> /// <param name="state">合成状態の情報</param> /// <returns>オペレータ出力</returns> public double GetState(FMSynthesisState state) { var env = GetEnvelopeState(state.Time, state.IsHolding); var myfr = state.Frequency * Detune; var ctime = 1.0 / myfr; var pos = ((state.Time) % ctime) / ctime; return(ModulationIndex * Oscillator(pos, state.State) * env); }
/// <summary> /// 全てのチャンネルを独立して計算し、 /// 全て同じ比率でミックスします。 /// <para>厳密にはこれはFM音源にはなりません。</para> /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public static double ParallelMixAlgorithm(IList<FMOperator> op, ref object tag, FMSynthesisState state) { var mix = 0.0; var max = op.Sum(p => p.ModulationIndex); foreach (var i in op) { mix += i.GetState(state); } return mix / max; }
/// <summary> /// 先頭をキャリア、それ以降をモジュレータとして、 /// 全て直列に接続して変調します。 /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public static double SerialModulationAlgorithm(IList<FMOperator> op, ref object tag, FMSynthesisState state) { var s = state; var mix = 0.0; for (int i = op.Count - 1; i >= 0; i--) { mix = op[i].GetState(s); s.State = mix; } return mix / op[0].ModulationIndex; }
/// <summary> /// 現在の状態でのアルゴリズムを定義します。 /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public double Algorithm(IList <FMOperator> op, ref object tag, FMSynthesisState state) { var s = state; var mix = 0.0; for (int i = op.Count - 1; i >= 0; i--) { if (i == FeedbackChannel) { var fbs = state; fbs.Time -= FeedbackReferenceBackingtime; s.State += op[i].GetState(fbs); } mix = op[i].GetState(s); s.State = mix; } return(mix / op[0].ModulationIndex); }
/// <summary> /// 現在の状態でのアルゴリズムを定義します。 /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public double Algorithm(IList <FMOperator> op, ref object tag, FMSynthesisState state) { var s = state; var mix = 0.0; for (int i = op.Count - 1; i >= 0; i--) { if (i == FeedbackChannel) { s.State += PreviousFeedbackState; } mix = op[i].GetState(s); if (i == FeedbackChannel) { PreviousFeedbackState = mix; } s.State = mix; } return(mix / op[0].ModulationIndex); }
/// <summary> /// 先頭をキャリア、それ以降をモジュレータとして、 /// 全て直列に接続して変調します。 /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public static double SerialModulationAlgorithm(IList <FMOperator> op, ref object tag, FMSynthesisState state) { var s = state; var mix = 0.0; for (int i = op.Count - 1; i >= 0; i--) { mix = op[i].GetState(s); s.State = mix; } return(mix / op[0].ModulationIndex); }
/// <summary> /// 全てのチャンネルを独立して計算し、 /// 全て同じ比率でミックスします。 /// <para>厳密にはこれはFM音源にはなりません。</para> /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public static double ParallelMixAlgorithm(IList <FMOperator> op, ref object tag, FMSynthesisState state) { var mix = 0.0; var max = op.Sum(p => p.ModulationIndex); foreach (var i in op) { mix += i.GetState(state); } return(mix / max); }
/// <summary> /// 3番のアルゴリズムを定義します。 /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public static double ThreeSingleAndSerial(IList <FMOperator> op, ref object tag, FMSynthesisState state) { if (op.Count < 4) { throw new InvalidOperationException("OPN系アルゴリズムではオペレータは4つ必要です"); } var fbs = state; fbs.Time -= 0.001; var ch3 = op[1].GetState(state); var ch1 = op[3].GetState(fbs); state.State = ch1; var ch2 = op[2].GetState(state); state.State = ch2 + ch3; state.State = (ch2 + ch3); return(op[0].GetState(state)); }
/// <summary> /// 最初のチャンネルをキャリア、次のチャンネルをモジュレータとして変調します。 /// それ以降のオペレータは無視されます。 /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public static double PairModulationAlgorithm(IList <FMOperator> op, ref object tag, FMSynthesisState state) { var s = state; if (op.Count < 2) { throw new ArgumentException("オペレータは最低2つ必要です"); } var mod = op[1].GetState(s); s.State = mod; return(op[0].GetState(s) / op[0].ModulationIndex); }
/// <summary> /// ホールドし始めた時刻を0として、 /// 指定した時刻のオペレータ出力を取得します。 /// </summary> /// <param name="state">合成状態の情報</param> /// <returns>オペレータ出力</returns> public double GetState(FMSynthesisState state) { var env = GetEnvelopeState(state.Time, state.IsHolding); var myfr = state.Frequency * Detune; var ctime = 1.0 / myfr; var pos = ((state.Time) % ctime) / ctime; return ModulationIndex * Oscillator(pos, state.State) * env; }
/// <summary> /// 0番のアルゴリズムを定義します。 /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public static double ZeroSerial(IList<FMOperator> op, ref object tag, FMSynthesisState state) { if (op.Count < 4) throw new InvalidOperationException("OPN系アルゴリズムではオペレータは4つ必要です"); return _serial(op, ref tag, state); }
/// <summary> /// 2番のアルゴリズムを定義します。 /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public static double TwoFeedbackAndSerial(IList<FMOperator> op, ref object tag, FMSynthesisState state) { if (op.Count < 4) throw new InvalidOperationException("OPN系アルゴリズムではオペレータは4つ必要です"); var fbs = state; fbs.Time -= 0.001; var ch2 = op[2].GetState(state); state.State = ch2; var ch3 = op[1].GetState(state); var ch1 = op[3].GetState(fbs); state.State = (ch1 + ch3); return op[0].GetState(state); }
/// <summary> /// 現在の状態でのアルゴリズムを定義します。 /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public double Algorithm(IList<FMOperator> op, ref object tag, FMSynthesisState state) { var s = state; var mix = 0.0; for (int i = op.Count - 1; i >= 0; i--) { if (i == FeedbackChannel) { s.State += PreviousFeedbackState; } mix = op[i].GetState(s); if (i == FeedbackChannel) { PreviousFeedbackState = mix; } s.State = mix; } return mix / op[0].ModulationIndex; }
/// <summary> /// 現在の状態でのアルゴリズムを定義します。 /// </summary> /// <param name="op">オペレーターのリスト</param> /// <param name="tag">フィードバックの保持など自由に使えるタグオブジェクト</param> /// <param name="state">合成状態の情報</param> /// <returns>状態</returns> public double Algorithm(IList<FMOperator> op, ref object tag, FMSynthesisState state) { var s = state; var mix = 0.0; for (int i = op.Count - 1; i >= 0; i--) { if (i == FeedbackChannel) { var fbs = state; fbs.Time -= FeedbackReferenceBackingtime; s.State += op[i].GetState(fbs); } mix = op[i].GetState(s); s.State = mix; } return mix / op[0].ModulationIndex; }