using System; using System.Collections.Generic; using Sandbox; namespace SFXR; public static partial class SFXR { public const short MaxAmplitude = 32767; // Maximum amplitude for a 16-bit audio /// /// Gets the sample of a waveform at a given time and frequency /// /// The waveform /// Time in seconds /// Frequency in Hz /// Sample of the waveform at the given time and frequency public static short GetWaveformSample( Waveform waveform, float t, float frequency ) { switch ( waveform ) { case Waveform.Square: return GetSquareWaveSample( t, frequency ); case Waveform.Sawtooth: return GetSawtoothWaveSample( t, frequency ); case Waveform.Sine: return GetSineWaveSample( t, frequency ); case Waveform.Noise: return GetNoiseWaveSample( t, frequency ); default: throw new ArgumentException( "Invalid waveform" ); } } public static short GetCurveSample( Curve curve, float t, float frequency ) { float period = 1.0f / frequency; return (short)(curve.Evaluate( t / period ) * MaxAmplitude); } /// /// Gets the sample of a square waveform at a given time and frequency /// /// Time in seconds /// Frequency in Hz /// Sample of the square waveform at the given time and frequency public static short GetSquareWaveSample( float t, float frequency ) { float period = 1.0f / frequency; float halfPeriod = period / 2; // Determine the current position in the waveform cycle float cyclePosition = t % period; // Output the maximum amplitude for the first half of the period, // and the minimum amplitude for the second half. return (short)(cyclePosition < halfPeriod ? MaxAmplitude : -MaxAmplitude); } /// /// Gets the sample of a sawtooth waveform at a given time and frequency /// /// Time in seconds /// Frequency in Hz /// Sample of the sawtooth waveform at the given time and frequency public static short GetSawtoothWaveSample( float t, float frequency ) { float period = 1.0f / frequency; return (short)(MaxAmplitude * 2 * (t % period) / period - MaxAmplitude); } /// /// Gets the sample of a sine waveform at a given time and frequency /// /// Time in seconds /// Frequency in Hz /// Sample of the sine waveform at the given time and frequency public static short GetSineWaveSample( float t, float frequency ) { float period = 1.0f / frequency; return (short)(MaxAmplitude * MathF.Sin( t * MathF.PI * 2 / period )); } /// /// Gets the sample of a noise waveform at a given time and frequency /// /// Time in seconds /// Frequency in Hz /// Sample of the noise waveform at the given time and frequency public static short GetNoiseWaveSample( float t, float frequency ) { if ( MathF.Abs( t - lastNoiseT ) >= 1.0f / frequency ) { noisebuffer.Clear(); for ( int i = 0; i < 32; i++ ) { noisebuffer.Add( (short)Random.Shared.Int( short.MinValue, short.MaxValue ) ); } lastNoiseT = t; } // LUA EXAMPLE: sample = noisebuffer[trunc(phase * 32 / period) % 32 + 1] float period = 1.0f / frequency; int index = (int)(t * 32 / period) % 32; return noisebuffer[index]; } static List noisebuffer = new(); static float lastNoiseT = -999f; }