rj-action-library/Runtime/Audio/AudioGraph/Test/SineWaveTest.cs

140 lines
2.8 KiB
C#

using Godot;
using System.Reflection;
using System.Collections.Generic;
using System.Text;
namespace Rokojori
{
[GlobalClass]
public partial class SineWaveTest: Node
{
[Export]
public float frequency = 100;
[Export]
public AudioStreamPlayer player;
AudioStreamGeneratorPlayback _playback;
public override void _Ready()
{
CreateGraph();
if ( player.Stream is AudioStreamGenerator generator )
{
ag.sampleRate = generator.MixRate;
player.Play();
_playback = (AudioStreamGeneratorPlayback) ( player.GetStreamPlayback() );
Fill();
}
}
WaveTableGenerator generator;
AudioGraph ag;
Constant constant;
public override void _Process( double delta )
{
Fill();
}
void Fill()
{
if ( _playback == null )
{
return;
}
constant.SetConstant( frequency );
int framesAvailable = _playback.GetFramesAvailable();
if ( framesAvailable == 0 )
{
return;
}
int blocks = 0;
while ( framesAvailable > frameBuffer.Count )
{
ProcessAudio();
blocks ++;
}
var frameBufferData = frameBuffer.ToArray();
var bufferSlice = new Vector2[ framesAvailable ];
System.Array.Copy( frameBufferData, 0, bufferSlice, 0, framesAvailable );
_playback.PushBuffer( bufferSlice );
var rest = new Vector2[ frameBuffer.Count - framesAvailable ];
System.Array.Copy( frameBufferData, framesAvailable, rest, 0, rest.Length );
frameBuffer = new List<Vector2>( rest );
}
List<Vector2> frameBuffer = new List<Vector2>();
void ProcessAudio()
{
ag.Process();
var outputBuffer = generator.output.GetOutputStreamBuffer();
var data = new Vector2[ ag.bufferSize ];
for ( int i = 0; i < ag.bufferSize ; i++ )
{
data[ i ] = outputBuffer[ i ] * Vector2.One;
}
frameBuffer.AddRange( data );
}
public void CreateGraph()
{
ag = new AudioGraph();
var sine = new float[ 2048 ];
var square = new float[ 2048 ];
for ( int i = 0; i < sine.Length; i++ )
{
var p = i / 2048f;
var v = Mathf.Sin( p * Mathf.Pi * 2.0f );
sine[ i ] = v;
square[ i ] = i < sine.Length / 2 ? 1 : -1;
}
var sines = new Vector2[ 10 ];
sines[ 0 ] = Vector2.Zero;
for ( int i = 1; i < sines.Length; i++ )
{
sines[ i ] = new Vector2( Mathf.Pow( 0.5f, i - 1 ), 0 );
}
var waveTable = WaveTable.FromSines( sines );
waveTable.Normalize();
generator = new WaveTableGenerator( ag, waveTable );
constant = new Constant( ag, frequency );
constant.output.ConnectTo( generator.frequency );
ag.output = generator;
}
}
}