Files
CodenameEngine/source/funkin/editors/charter/CharterWaveformHandler.hx
T
2024-03-23 02:51:28 +01:00

110 lines
3.2 KiB
Haxe

package funkin.editors.charter;
import flixel.util.FlxColor;
import funkin.backend.system.Conductor;
import flixel.sound.FlxSound;
import funkin.backend.shaders.CustomShader;
import openfl.display.BitmapData;
class CharterWaveformHandler extends FlxBasic {
public var ampsNeeded:Float = 0;
public var ampSqrt(get, never):Int;
public function get_ampSqrt():Int {
var sqrt:Float = Math.sqrt(Math.floor(ampsNeeded/3));
var ampRet:Int = Math.floor(sqrt);
if (sqrt % 1 > 0) ampRet += 1;
return ampRet;
}
public var waveDatas:Map<String, BitmapData> = [];
public var waveShaders:Map<String, CustomShader> = [];
public var sounds:Map<String, FlxSound> = [];
public var analyzers:Map<String, AudioAnalyzer> = [];
public var waveformList:Array<String> = [];
public function new() {super(); exists = false;}
public function generateData(name:String, sound:FlxSound):BitmapData {
if (!sounds.exists(name)) sounds.set(name, sound);
if (!analyzers.exists(name))
analyzers.set(name, new AudioAnalyzer(sound));
var analyzer:AudioAnalyzer = analyzers.get(name);
var pixelsNeeded:Int = Math.floor(ampsNeeded/3);
if ((ampsNeeded/3) % 1 > 0) pixelsNeeded += 1;
var waveData:BitmapData = new BitmapData(
ampSqrt, 1+Math.floor(pixelsNeeded/ampSqrt), true, 0xFF000000
);
for (y in 0...waveData.height)
for (x in 0...waveData.width) {
var amplitudes:Array<Float> = [0., 0., 0.];
for (color in 0...3) {
var gridY:Float = (y * (waveData.width * 3)) + (x * 3) + color;
var startTime:Float = Conductor.getTimeForStep(gridY/40);
if (startTime > sound.length) if (color == 0) break; else continue;
var endTime:Float = Conductor.getTimeForStep((gridY+1)/40);
if (endTime > sound.length) if (color == 0) break; else continue;
var amplitude:Float = analyzer.analyze(startTime, endTime);
amplitudes[color] = amplitude;
}
waveData.setPixel(x, y, FlxColor.fromRGBFloat(amplitudes[0], amplitudes[1], amplitudes[2]));
}
waveDatas.set(name, waveData);
return waveData;
}
public function generateShader(name:String, sound:FlxSound):CustomShader {
if (!waveDatas.exists(name)) generateData(name, sound);
var waveData:BitmapData = waveDatas.get(name);
var waveShader:CustomShader = new CustomShader("engine/editorWaveforms");
waveShader.data.waveformSize.value = [waveData.width, waveData.height];
waveShader.data.waveformTexture.input = waveData;
waveShader.data.textureRes.value = [0, 0];
waveShader.data.pixelOffset.value = [0];
waveShader.data.lowDetail.value = [Options.charterLowDetailWaveforms];
waveShaders.set(name, waveShader);
return waveShader;
}
public function clearWaveform(name:String) {
waveDatas.get(name).dispose();
waveDatas.remove(name);
waveShaders.set(name, null);
waveShaders.remove(name);
analyzers.set(name, null);
analyzers.remove(name);
sounds.remove(name);
waveformList.remove(name);
}
public function clearWaveforms() {
for (data in waveDatas) data.dispose();
for (shader in waveShaders) shader = null;
for (analyzer in analyzers) analyzer = null;
waveDatas.clear(); waveShaders.clear();
analyzers.clear(); sounds.clear();
waveformList = [];
}
public override function destroy() {
clearWaveforms();
super.destroy();
}
}