Wave Generator Library (WGL)
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © peacefulLizard50262

//@version=5

// @description Wave Generator Library
library("WaveGenerator")

n = bar_index
//@function max
//@param source is the input to take the maximum.
//@returns foat
export max(float source)=>
    var float max = na
    src = array.new<float>()
    array.push(src, source)
    max := math.max(nz(max[1]), array.get(src, 0))

//@function min
//@param source is the input to take the minimum.
//@returns foat
export min(float source)=>
    var float min = na
    src = array.new<float>()
    array.push(src, source)
    min := math.min(nz(min[1]), array.get(src, 0))

//@function min_max
//@param src is the input for the min/max
//@returns float
export min_max(float src, float height)=>
    (((src - min(src))/(max(src) - min(src)) - 0.5) * 2) * height

//@function sine_wave
//@param _wave_height Maximum output level
//@param _wave_duration Wave length
//@param _phase_shift Number of harmonics
//@param _phase_shift_2_shift Phase shift
//@returns float
export sine_wave(float _wave_height, int _wave_duration, float _phase_shift, float _phase_shift_2) =>
    _pi = math.pi
    _w = 2 * _pi / _wave_duration
    _sine_wave = _wave_height * math.sin(_w * n + _phase_shift + _phase_shift_2)
    _sine_wave

//@function triangle_wave
//@param _wave_height Maximum output level
//@param _wave_duration Wave length
//@param _num_harmonics Number of harmonics
//@param _phase_shift Phase shift
//@returns float   
export triangle_wave(float _wave_height, int _wave_duration, int _num_harmonics, float _phase_shift) =>
    _pi = math.pi
    sine_waves = array.new<float>()
    for i = 1 to _num_harmonics
        array.push(sine_waves, sine_wave(1 / math.pow(2 * i - 1, 2), _wave_duration / (2 * i - 1), (i - 1) * _pi, int(_phase_shift) * _pi))
    _triangle_wave = array.avg(sine_waves)
    min_max(_triangle_wave, _wave_height) 

//@function saw_wave
//@param _wave_height Maximum output level
//@param _wave_duration Wave length
//@param _num_harmonics Number of harmonics
//@param _phase_shift Phase shift
//@returns float   
export saw_wave(float _wave_height, int _wave_duration, int _num_harmonics, float _phase_shift) =>
    _pi = math.pi
    sine_waves = array.new<float>()
    for i = 1 to _num_harmonics
        array.push(sine_waves, sine_wave(1 / (i), _wave_duration / (i), i * _phase_shift * _pi, 0))
    _saw_wave = array.avg(sine_waves)
    min_max(_saw_wave, _wave_height) 

//@function ramp_saw_wave
//@param _wave_height Maximum output level
//@param _wave_duration Wave length
//@param _num_harmonics Number of harmonics
//@param _phase_shift Phase shift
//@returns float   
export ramp_saw_wave(float _wave_height, int _wave_duration, int _num_harmonics, float _phase_shift) =>
    _pi = math.pi
    sine_waves = array.new<float>()
    for i = 1 to _num_harmonics
        array.push(sine_waves, sine_wave(1 / (i), _wave_duration / (i), i * _phase_shift * _pi, 66))
    _ramp_saw_wave = array.sum(sine_waves)
    min_max(_ramp_saw_wave, _wave_height) 

//@function square_wave 
//@param _wave_height Maximum output level
//@param _wave_duration Wave length
//@param _num_harmonics Number of harmonics
//@param _phase_shift Phase shift
//@returns float   
export square_wave(float _wave_height, int _wave_duration, int _num_harmonics, float _phase_shift) =>
    _pi = math.pi
    sine_waves = array.new<float>()
    for i = 1 to _num_harmonics
        array.push(sine_waves, sine_wave(1 / (2 * i - 1), _wave_duration / (2 * i - 1), (i * 2 - 1) * _phase_shift  * _pi, 0))
    _square_wave = array.avg(sine_waves)
    min_max(_square_wave, _wave_height) 

//@function wave_select
//@peram style Select the style of wave. "Sine", "Triangle", "Saw", "Ramp Saw", "Square"
//@param _wave_height Maximum output level
//@param _wave_duration Wave length
//@param _num_harmonics Number of harmonics
//@param _phase_shift Phase shift
//@returns float
export wave_select(string style, float _wave_height, int _wave_duration, int _num_harmonics, float _phase_shift)=>
    switch style
        "Sine"     => sine_wave(_wave_height, _wave_duration, 0, _phase_shift)
        "Triangle" => triangle_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "Saw"      => saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "Ramp Saw" => ramp_saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "Square"   => square_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "sine"     => sine_wave(_wave_height, _wave_duration, 0, _phase_shift)
        "triangle" => triangle_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "saw"      => saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "ramp saw" => ramp_saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "square"   => square_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "SINE"     => sine_wave(_wave_height, _wave_duration, 0, _phase_shift)
        "TRIANGLE" => triangle_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "SAW"      => saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "RAMP SAW" => ramp_saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "SQUARE"   => square_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "RAMPSAW" => ramp_saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "RampSaw" => ramp_saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "Ramp_Saw" => ramp_saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "ramp_saw" => ramp_saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "Rampsaw" => ramp_saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "rampSaw" => ramp_saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "rampsaw" => ramp_saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "1"     => sine_wave(_wave_height, _wave_duration, 0, _phase_shift)
        "2" => triangle_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "3"      => saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "4" => ramp_saw_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        "5"   => square_wave(_wave_height, _wave_duration, _num_harmonics, _phase_shift)
        
Wave_Select = min_max(wave_select("Saw", 1, 64, 64, 0) * wave_select("Triangle", sine_wave(1, 24, 0, 0), 32, 1, 0), 1)

plot(Wave_Select)