rj-action-library/Runtime/Audio/AudioGraph/Generators/WaveTable.cs

79 lines
1.9 KiB
C#

using Godot;
using System.Reflection;
using System.Collections.Generic;
using System.Text;
namespace Rokojori
{
public class WaveTable:iPhaseGenerator
{
float[] _samples;
public float[] samples => _samples;
public void SetPitchRange( float minPitch, float maxPitch )
{
}
public float Get( float phase )
{
var samplePosition = phase * _samples.Length;
samplePosition = MathX.Repeat( samplePosition, _samples.Length );
var l = (int) samplePosition;
var h = MathX.Repeat( l + 1, _samples.Length );
var lerp = samplePosition - l;
return Mathf.Lerp( _samples[ l ], _samples[ h ], lerp );
}
public static WaveTable FromSamples( float[] samples )
{
var wt = new WaveTable();
wt._samples = samples;
return wt;
}
public void Normalize()
{
var max = 0f;
for ( int i = 0; i < _samples.Length; i++ )
{
max = Mathf.Max( Mathf.Abs( _samples[ i ] ), max );
}
for ( int i = 0; i < _samples.Length; i++ )
{
_samples[ i ] = _samples[ i ] / max;
}
}
public static WaveTable FromSines( Vector2[] magnitudesAndPhases, float filterStart = -1, float filterEnd = -1, int size = 4096 )
{
var fftReal = new float[ size ];
var fftImaginary = new float[ size ];
var hasNoFilter = ( filterStart == -1 && filterEnd == -1 );
for ( int i = 0; i < magnitudesAndPhases.Length; i++ )
{
var filter = hasNoFilter ? 1 : ( 1f - MathX.NormalizeClamped( i, filterStart, filterEnd ) );
fftReal[ i ] = Mathf.Cos( magnitudesAndPhases[ i ].Y ) * magnitudesAndPhases[ i ].X * filter;
fftImaginary[ i ] = Mathf.Sin( magnitudesAndPhases[ i ].Y ) * magnitudesAndPhases[ i ].X * filter;
}
FFT.Inverse( size, fftReal, fftImaginary );
return FromSamples( fftReal );
}
}
}