52604
お世話になります。

C#で周波数を指定して三角波（TriangleWave）

<https://ja.wikipedia.org/wiki/%E4%B8%89%E8%A7%92%E6%B3%A2_(%E6%B3%A2%E5%BD%A2)>

を再生したいのですが、何か方法はないでしょうか。  
ざっと検索しては見ましたが、うまく見つけられませんでした。
CC BY-SA 4.0
2019-02-06T13:28:18.773
52601
2019-02-06T15:49:08.310
29034
question
c#
C#で特定の周波数の三角波を再生したい
「再生したい」というのが、どういうことなのか、が良く分からないのですが、  
サウンドならばこの辺の記事が参考になるのでは？  
記事には三角波そのものは出てきませんが。  
[C＃でダイナミックに作成されたシンプルなサウンドを外部ライブラリなしで再生する](https://stackoverrun.com/ja/q/3144018)  
[Intro to Audio Programming, Part 3: Synthesizing Simple Wave Audio using
C#](https://blogs.msdn.microsoft.com/dawate/2009/06/24/intro-to-audio-
programming-part-3-synthesizing-simple-wave-audio-using-c/)  
[Generating Sound Waves with C# Wave
Oscillators](https://channel9.msdn.com/coding4fun/articles/Generating-Sound-
Waves-with-C-Wave-Oscillators)

C/C++言語での参考記事  
[Is there a one-line function that generates a triangle
wave?](https://stackoverflow.com/q/1073606/9014308)  
[Is There a Triangle Wave
Function?](https://stackoverflow.com/q/28588292/9014308)

データとしての作成方法だと、ここでC#のクラス化されているので、使えるのでは？  
[Simple Signal Generator - Tefik Becirovic, 29 Oct
2008](https://www.codeproject.com/Articles/30180/Simple-Signal-Generator)

以下を基に作られているようです。  
[Waveform - Wikipedia](https://en.wikipedia.org/wiki/Waveform) / [波形 -
Wikipedia](https://ja.wikipedia.org/wiki/%E6%B3%A2%E5%BD%A2)

以下に前書きの翻訳と例示されているソースコードをコピーしておきます。  
全体のソースやサンプルは、サイトにメンバー登録して、元記事からダウンロードしてください。

> 前書き  
>  Simple Signal
> Generatorは、正弦波、方形波、三角波、のこぎり波を含む4つの単純な周期波形を生成するように設計されたC＃クラスです。このクラスは、計測アプリケーションの開発中にソフトウェアおよびハードウェアコンポーネントをテストするために提供されています。生成された信号は時間領域によって異なり、デフォルトでは振幅と周期で正規化されています。任意の振幅、周波数、DCオフセット、位相シフトを設定し、信号を反転することができます。A
> € [-1,1]T € [0,1]
```

    public class SignalGenerator
    {
        #region [ Properties ... ]
    
        private SignalType signalType = SignalType.Sine;
        /// <summary>
        /// Signal Type.
        /// </summary>
        public SignalType SignalType
        {
            get { return signalType; }
            set { signalType = value; }
        }
    
        private float frequency = 1f;
        /// <summary>
        /// Signal Frequency.
        /// </summary>
        public float Frequency
        {
            get { return frequency; }
            set { frequency = value; }
        }
    
        private float phase = 0f;
        /// <summary>
        /// Signal Phase.
        /// </summary>
        public float Phase
        {
            get { return phase; }
            set { phase = value; }
        }
    
        private float amplitude = 1f;
        /// <summary>
        /// Signal Amplitude.
        /// </summary>
        public float Amplitude
        {
            get { return amplitude; }
            set { amplitude = value; }
    
        }
    
        private float offset = 0f;
        /// <summary>
        /// Signal Offset.
        /// </summary>
        public float Offset
        {
            get { return offset; }
            set { offset = value; }
        }
    
        private float invert = 1; // Yes=-1, No=1
        /// <summary>
        /// Signal Inverted?
        /// </summary>
        public bool Invert
        {
            get { return invert==-1; }
            set { invert = value ? -1 : 1; }
        }
    
        #endregion  [ Properties ]
    
        #region [ Private ... ]
    
        /// <summary>
        /// Time the signal generator was started
        /// </summary>
        private long startTime = Stopwatch.GetTimestamp();
    
        /// <summary>
        /// Ticks per second on this CPU
        /// </summary>
        private long ticksPerSecond = Stopwatch.Frequency;
    
        #endregion  [ Private ]
    
        #region [ Public ... ]
    
        public SignalGenerator(SignalType initialSignalType)
        {
            signalType = initialSignalType;
        }
    
        public SignalGenerator() { }
    
        #if DEBUG
        public float GetValue(float time)
        #else
        private float GetValue(float time)
        #endif
        {
            float value = 0f;
            float t = frequency * time + phase;
            switch (signalType)
            { // http://en.wikipedia.org/wiki/Waveform
                case SignalType.Sine: // sin( 2 * pi * t )
                    value = (float)Math.Sin(2f*Math.PI*t);
                    break;
                case SignalType.Square: // sign( sin( 2 * pi * t ) )
                    value = Math.Sign(Math.Sin(2f*Math.PI*t));
                    break;
                case SignalType.Triangle:
                // 2 * abs( t - 2 * floor( t / 2 ) - 1 ) - 1
                    value = 1f-4f*(float)Math.Abs
                        ( Math.Round(t-0.25f)-(t-0.25f) );
                    break;
                case SignalType.Sawtooth:
                // 2 * ( t/a - floor( t/a + 1/2 ) )
                    value = 2f*(t-(float)Math.Floor(t+0.5f));
                    break;
            }
    
            return(invert*amplitude*value+offset);
        }
    
        public float GetValue()
        {
            float time = (float)(Stopwatch.GetTimestamp() - startTime)
                            / ticksPerSecond;
            return GetValue(time);
        }
    
        public void Reset()
        {
            startTime = Stopwatch.GetTimestamp();
        }
    
        #endregion [ Public ]
    }
    
    #region [ Enums ... ]
    
    public enum SignalType
    {
        Sine,
        Square,
        Triangle,
        Sawtooth
    }
    
    #endregion [ Enums ]
    
```
CC BY-SA 4.0
2019-02-06T15:49:08.310
52604
2019-02-06T15:49:08.310
26370
52601
answer