79 lines
1.9 KiB
C#
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 );
|
|
}
|
|
}
|
|
} |