mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-29 11:06:00 -05:00
158 lines
4.1 KiB
Haxe
158 lines
4.1 KiB
Haxe
package funkin.audio.visualize;
|
|
|
|
import flixel.math.FlxMath;
|
|
import flixel.math.FlxPoint;
|
|
import flixel.sound.FlxSound;
|
|
import flixel.util.FlxColor;
|
|
import funkin.audio.visualize.VisShit;
|
|
import funkin.graphics.rendering.MeshRender;
|
|
import lime.utils.Int16Array;
|
|
|
|
class PolygonSpectogram extends MeshRender
|
|
{
|
|
var sampleRate:Int;
|
|
|
|
public var vis:VisShit;
|
|
public var visType:VISTYPE = UPDATED;
|
|
public var daHeight:Float = FlxG.height;
|
|
public var realtimeVisLenght:Float = 0.2;
|
|
public var realtimeStartOffset:Float = 0;
|
|
|
|
var numSamples:Int = 0;
|
|
var setBuffer:Bool = false;
|
|
|
|
public var audioData:Int16Array;
|
|
public var detail:Float = 1;
|
|
|
|
public var thickness:Float = 2;
|
|
public var waveAmplitude:Int = 100;
|
|
|
|
public function new(?daSound:FlxSound, ?col:FlxColor = FlxColor.WHITE, ?height:Float = 720, ?detail:Float = 1)
|
|
{
|
|
super(0, 0, col);
|
|
|
|
if (daSound != null) setSound(daSound);
|
|
|
|
if (height != null) this.daHeight = height;
|
|
|
|
this.detail = detail;
|
|
|
|
// col not in yet
|
|
}
|
|
|
|
public function setSound(daSound:FlxSound)
|
|
{
|
|
vis = new VisShit(daSound);
|
|
}
|
|
|
|
override function update(elapsed:Float)
|
|
{
|
|
super.update(elapsed);
|
|
|
|
switch (visType)
|
|
{
|
|
case UPDATED:
|
|
realtimeVis();
|
|
default:
|
|
}
|
|
}
|
|
|
|
var prevAudioData:Int16Array;
|
|
|
|
/**
|
|
* Generates and draws a section of the audio data to a visual waveform
|
|
* @param start start of the song in milliseconds
|
|
* @param seconds how long to generate (also in milliseconds)
|
|
*/
|
|
public function generateSection(start:Float = 0, seconds:Float = 1):Void
|
|
{
|
|
checkAndSetBuffer();
|
|
|
|
if (setBuffer)
|
|
{
|
|
clear();
|
|
|
|
start = Math.max(start, 0);
|
|
|
|
// gets how many samples to generate
|
|
var samplesToGen:Int = Std.int(sampleRate * seconds);
|
|
|
|
if (samplesToGen == 0) return;
|
|
// gets which sample to start at
|
|
var startSample:Int = Std.int(FlxMath.remapToRange(start, 0, vis.snd.length, 0, numSamples));
|
|
|
|
// Check if startSample and samplesToGen are within the bounds of the audioData array
|
|
if (startSample < 0 || startSample >= numSamples) return;
|
|
if (samplesToGen <= 0 || startSample + samplesToGen > numSamples) samplesToGen = numSamples - startSample;
|
|
|
|
var prevPoint:FlxPoint = new FlxPoint();
|
|
|
|
var funnyPixels:Int = Std.int(daHeight * detail); // sorta redundant but just need it for different var...
|
|
|
|
if (prevAudioData == audioData.subarray(startSample, startSample + samplesToGen)) return; // optimize / finish funciton here, no need to re-render
|
|
|
|
prevAudioData = audioData.subarray(startSample, samplesToGen);
|
|
|
|
for (i in 0...funnyPixels)
|
|
{
|
|
var sampleApprox:Int = Std.int(FlxMath.remapToRange(i, 0, funnyPixels, startSample, startSample + samplesToGen));
|
|
var curAud:CurAudioInfo = VisShit.getCurAud(audioData, sampleApprox);
|
|
|
|
var coolPoint:FlxPoint = new FlxPoint();
|
|
coolPoint.x = (curAud.balanced * waveAmplitude);
|
|
coolPoint.y = (i / funnyPixels * daHeight);
|
|
|
|
build_quad(prevPoint.x, prevPoint.y, prevPoint.x
|
|
+ thickness, prevPoint.y, coolPoint.x, coolPoint.y, coolPoint.x
|
|
+ thickness, coolPoint.y
|
|
+ thickness);
|
|
|
|
prevPoint.x = coolPoint.x;
|
|
prevPoint.y = coolPoint.y;
|
|
}
|
|
}
|
|
}
|
|
|
|
var curTime:Float = 0;
|
|
|
|
function realtimeVis():Void
|
|
{
|
|
if (vis.snd != null)
|
|
{
|
|
if (curTime != vis.snd.time)
|
|
{
|
|
// trace("DOIN SHIT" + FlxG.random.int(0, 200));
|
|
|
|
if (vis.snd.playing) curTime = vis.snd.time;
|
|
else
|
|
{
|
|
if (Math.abs(curTime - vis.snd.time) > 10) curTime = FlxMath.lerp(curTime, vis.snd.time, 0.5);
|
|
}
|
|
|
|
curTime = vis.snd.time;
|
|
|
|
if (vis.snd.time < vis.snd.length - realtimeVisLenght) generateSection(vis.snd.time + realtimeStartOffset, realtimeVisLenght);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function checkAndSetBuffer()
|
|
{
|
|
vis.checkAndSetBuffer();
|
|
|
|
if (vis.setBuffer)
|
|
{
|
|
audioData = vis.audioData;
|
|
sampleRate = vis.sampleRate;
|
|
setBuffer = vis.setBuffer;
|
|
numSamples = Std.int(audioData.length / 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
enum VISTYPE
|
|
{
|
|
STATIC;
|
|
UPDATED;
|
|
FREQUENCIES;
|
|
}
|