- [WAV File In] Add more format checker.

This commit is contained in:
Tanasart 2024-04-23 09:59:59 +07:00
parent 1279f7ae3c
commit 712bdfa613
10 changed files with 565 additions and 49 deletions

View file

@ -1,4 +1,4 @@
// 2024-04-23 08:59:29
// 2024-04-23 09:05:31
#event properties (no comments/etc. here are saved)
parent_index = _p_dialog;
uses_physics = false;

View file

@ -1,4 +1,4 @@
// 2024-04-23 08:58:27
// 2024-04-23 08:59:29
#event properties (no comments/etc. here are saved)
parent_index = _p_dialog;
uses_physics = false;

View file

@ -1,4 +1,4 @@
// 2024-04-22 19:15:18
// 2024-04-23 09:27:33
#region ---- global names ----
global.junctionEndName = [ "Hold", "Loop", "Ping pong", "Wrap" ];
@ -874,7 +874,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
}
} setDropKey(); #endregion
static resetDisplay = function() { #region //////////////////// RESET DISPLAY ////////////////////
static resetDisplay = function() { #region //////////////////// RESET DISPLAY ////////////////////
editWidget = noone;
switch(display_type) {
case VALUE_DISPLAY.button : #region

View file

@ -1,4 +1,4 @@
// 2024-04-22 18:42:00
// 2024-04-23 09:26:39
#region ---- global names ----
global.junctionEndName = [ "Hold", "Loop", "Ping pong", "Wrap" ];
@ -874,7 +874,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
}
} setDropKey(); #endregion
static resetDisplay = function() { #region //////////////////// RESET DISPLAY ////////////////////
static resetDisplay = function() { #region //////////////////// RESET DISPLAY ////////////////////
editWidget = noone;
switch(display_type) {
case VALUE_DISPLAY.button : #region

View file

@ -0,0 +1,276 @@
// 2024-04-23 09:39:26
function Node_create_WAV_File_Read(_x, _y, _group = noone) { #region
var path = "";
if(!LOADING && !APPENDING && !CLONING) {
path = get_open_filename("audio|*.wav", "");
key_release();
if(path == "") return noone;
}
var node = new Node_WAV_File_Read(_x, _y, _group);
node.inputs[| 0].setValue(path);
node.doUpdate();
return node;
} #endregion
function Node_create_WAV_File_Read_path(_x, _y, path) { #region
if(!file_exists_empty(path)) return noone;
var node = new Node_WAV_File_Read(_x, _y, PANEL_GRAPH.getCurrentContext());
node.inputs[| 0].setValue(path);
node.doUpdate();
return node;
} #endregion
function Node_WAV_File_Read(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "WAV File In";
color = COLORS.node_blend_input;
inputs[| 0] = nodeValue("Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.path, "")
.setDisplay(VALUE_DISPLAY.path_load, { filter: "audio|*.wav" })
.rejectArray();
inputs[| 1] = nodeValue("Sync length", self, JUNCTION_CONNECT.input, VALUE_TYPE.trigger, false )
.setDisplay(VALUE_DISPLAY.button, { name: "Sync", UI : true, onClick: function() {
if(content == noone) return;
TOTAL_FRAMES = max(1, ceil(content.duration * PROJECT.animator.framerate));
} });
inputs[| 2] = nodeValue("Mono", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false);
outputs[| 0] = nodeValue("Data", self, JUNCTION_CONNECT.output, VALUE_TYPE.audioBit, noone)
.setArrayDepth(1);
outputs[| 1] = nodeValue("Path", self, JUNCTION_CONNECT.output, VALUE_TYPE.path, "");
outputs[| 2] = nodeValue("Sample rate", self, JUNCTION_CONNECT.output, VALUE_TYPE.integer, 44100)
.setVisible(false);
outputs[| 3] = nodeValue("Channels", self, JUNCTION_CONNECT.output, VALUE_TYPE.integer, 2)
.setVisible(false);
outputs[| 4] = nodeValue("Duration (s)", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, 0)
.setVisible(false);
content = noone;
path_current = "";
edit_time = 0;
attributes.file_checker = true;
array_push(attributeEditors, [ "File Watcher", function() { return attributes.file_checker; },
new checkBox(function() { attributes.file_checker = !attributes.file_checker; }) ]);
first_update = false;
input_display_list = [ 0, 1, 2 ];
output_display_list = [ 0, 1, 2, 3, 4 ];
preview_audio = -1;
preview_id = noone;
wav_file_reading = false;
wav_file_prg = 0;
wav_file_lim = 1;
#region attribute
attributes.preview_shift = 0;
attributes.preview_gain = 0.5;
array_push(attributeEditors, "Audio Preview");
array_push(attributeEditors, ["Gain", function() { return attributes.preview_gain; },
new textBox(TEXTBOX_INPUT.number, function(val) {
attributes.preview_gain = val;
})]);
array_push(attributeEditors, ["Shift", function() { return attributes.preview_shift; },
new textBox(TEXTBOX_INPUT.number, function(val) {
attributes.preview_shift = val;
})]);
#endregion
on_drop_file = function(path) { #region
if(updatePaths(path)) {
doUpdate();
return true;
}
return false;
} #endregion
function updatePaths(path) { #region
if(path == -1) return false;
if(path_current == "")
first_update = true;
path_current = path;
edit_time = max(edit_time, file_get_modify_s(path_current));
var ext = string_lower(filename_ext(path));
var _name = string_replace(filename_name(path), filename_ext(path), "");
if(ext != ".wav") return false;
outputs[| 1].setValue(path);
printIf(global.FLAG.wav_import, "-- Reading file...");
content = file_read_wav(path);
return true;
} #endregion
function readSoundComplete() { #region
outputs[| 0].setValue(content);
outputs[| 2].setValue(content.sample);
outputs[| 3].setValue(content.channels);
outputs[| 4].setValue(content.duration);
printIf(global.FLAG.wav_import, "-- Creating preview buffer...");
var frm = ceil(content.duration * PROJECT.animator.framerate);
inputs[| 1].editWidget.text = $"Sync ({frm} frames)";
var bufferId = buffer_create(content.packet * 2, buffer_fixed, 1);
buffer_seek(bufferId, buffer_seek_start, 0);
var val_to_write = 1;
for (var i = 0; i < content.packet; i++)
buffer_write(bufferId, buffer_s16, round(content.sound[0][i] / 4 * 65535));
preview_audio = audio_create_buffer_sound(bufferId, buffer_s16, content.sample, 0, content.packet * 2, audio_mono);
var surf = content.checkPreview(320, 128, true);
} #endregion
#region ++++ inspector ++++
insp1UpdateTooltip = __txt("Refresh");
insp1UpdateIcon = [ THEME.refresh_icon, 1, COLORS._main_value_positive ];
insp2UpdateTooltip = __txtx("play_with_timeline", "Play with timeline");
insp2UpdateIcon = [ THEME.play_sound, 1, COLORS._main_icon_light ];
attributes.play = true;
static onInspector1Update = function() {
var path = getInputData(0);
if(path == "") return;
updatePaths(path);
update();
}
static onInspector2Update = function() {
attributes.play = !attributes.play;
}
#endregion
static step = function() { #region
if(file_read_wav_step()) {
print("Load audio complete");
readSoundComplete();
if(content != noone) {
var frm = max(1, ceil(content.duration * PROJECT.animator.framerate));
inputs[| 1].editWidget.text = $"Sync ({frm} frames)";
}
RENDER_ALL_REORDER
}
insp2UpdateIcon[1] = attributes.play;
insp2UpdateIcon[2] = attributes.play? COLORS._main_icon_light : COLORS._main_icon;
if(preview_audio == -1) return;
if(audio_is_playing(preview_audio) && !PROJECT.animator.is_playing)
audio_stop_sound(preview_audio);
if(!attributes.play) return;
if(IS_FIRST_FRAME) { audio_stop_sound(preview_audio); }
if(PROJECT.animator.is_playing) {
var dur = CURRENT_FRAME / PROJECT.animator.framerate - attributes.preview_shift;
if(!audio_is_playing(preview_audio))
preview_id = audio_play_sound(preview_audio, 1, false, attributes.preview_gain, dur);
}
if(attributes.file_checker && path_current != "") {
if(file_get_modify_s(path_current) > edit_time) {
updatePaths();
triggerRender();
}
}
} #endregion
static update = function(frame = CURRENT_FRAME) { #region
var path = path_get(getInputData(0));
var mono = getInputData(2);
if(path_current != path) updatePaths(path);
if(!is_instanceof(content, audioObject)) return;
content.mono = mono;
} #endregion
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region
if(content == noone) return;
var bbox = drawGetBbox(xx, yy, _s);
var surf = content.checkPreview(320, 128);
if(wav_file_reading) {
var cx = xx + w * _s / 2;
var cy = yy + h * _s / 2;
var rr = min(w - 64, h - 64) * _s / 2;
draw_set_color(COLORS._main_icon);
draw_arc(cx, cy, rr, 90, 90 - 360 * wav_file_prg / content.packet, 4 * _s, 180);
return;
} else if(is_surface(surf)) {
var sw = surface_get_width_safe(surf);
var sh = surface_get_height_safe(surf);
var ss = min(bbox.w / sw, bbox.h / sh);
var dx = bbox.xc - sw * ss / 2;
var dy = bbox.yc - sh * ss / 2;
draw_surface_ext_safe(surf, dx, dy, ss, ss,,, 0.50);
var wd = clamp((CURRENT_FRAME / PROJECT.animator.framerate) / content.duration, 0, 1) * sw;
draw_surface_part_ext_safe(surf, 0, 0, min(wd, sw), sh, dx, dy, ss, ss,, attributes.play? COLORS._main_accent : c_white);
draw_set_color(attributes.play? COLORS._main_accent : c_white);
draw_line(dx + wd * ss, bbox.yc - 16 * _s, dx + wd * ss, bbox.yc + 16 * _s);
}
var str = filename_name(path_current);
draw_set_text(f_sdf, fa_center, fa_bottom, COLORS._main_text);
var ss = string_scale(str, bbox.w, bbox.h);
draw_text_transformed(bbox.xc, bbox.y1, str, ss, ss, 0);
} #endregion
static drawAnimationTimeline = function(_shf, _w, _h, _s) { #region
if(content == noone) return;
draw_set_color(COLORS._main_icon_dark);
draw_set_alpha(1);
var _st = round(content.sample / PROJECT.animator.framerate); //sample per frame
var _am = content.packet / _st;
var ox, oy, nx, ny;
if(!struct_has(content, "sound")) return;
if(array_length(content.sound) < 1) return;
for( var i = 0; i <= _am; i++ ) {
var _dat = content.sound[0][min(i * _st, content.packet - 1)];
nx = _shf + i * _s;
ny = _h / 2 + _dat * _h;
if(i) draw_line_width(ox, oy, nx, ny, 2);
ox = nx;
oy = ny;
}
draw_set_alpha(1);
} #endregion
}

View file

@ -0,0 +1,130 @@
// 2024-04-23 09:59:09
function file_read_ASCII(file, amo = 1) {
var b = "";
repeat(amo) b += chr(buffer_read(file, buffer_u8));
return b;
}
function file_read_wav(path) {
wav_file_reader = buffer_load(path);
wav_file_reading = true;
wav_file_prg = 0;
if(wav_file_reader == -1) {
noti_warning("File read error.");
return noone;
}
wav_file_load_time = current_time;
var _buffer_size = buffer_get_size(wav_file_reader);
//RIFF
var debug_str = $">> READING WAV [{path}] <<\n";
debug_str += $"Buffer size: {_buffer_size}\n\n";
debug_str += "-- RIFF --\n";
var b = file_read_ASCII(wav_file_reader, 4); debug_str += $"{b}\n";
var l = buffer_read(wav_file_reader, buffer_u32); debug_str += $"Packages: {l}\n";
var w = file_read_ASCII(wav_file_reader, 4); debug_str += $"{w}\n";
if(b != "RIFF" || w != "WAVE") {
printIf(global.FLAG.wav_import, debug_str);
noti_warning("Not a valid .wav file.");
return noone;
}
if(buffer_get_size(wav_file_reader) != l + 8)
noti_warning(".wav file has different size than the package header. This may cause reading error.");
//FORMAT
debug_str += "-- FORMAT --\n";
var b = file_read_ASCII(wav_file_reader, 4); debug_str += $"{b}\n";
var l = buffer_read(wav_file_reader, buffer_u32); debug_str += $"Length: {l}\n";
var f = buffer_read(wav_file_reader, buffer_u16); debug_str += $"Linear quantize: {f}\n";
if(l != 16 || f != 1) {
printIf(global.FLAG.wav_import, debug_str);
noti_warning("File format not supported, the audio file need to be 8, 16, 32 bit uncompressed PCM wav with no extension.");
return noone;
}
var ch = buffer_read(wav_file_reader, buffer_u16); debug_str += $"Channels: {ch}\n";
var sm = buffer_read(wav_file_reader, buffer_u32); debug_str += $"Sample: {sm}\n";
var l = buffer_read(wav_file_reader, buffer_u32); debug_str += $"BPS: {l}\n";
var br = buffer_read(wav_file_reader, buffer_u16); debug_str += $"Byterate: {br}\n";
var l = buffer_read(wav_file_reader, buffer_u16); debug_str += $"Bit/Sam: {l}\n";
//DATA
debug_str += "-- DATA --\n";
var b = file_read_ASCII(wav_file_reader, 4); debug_str += $"{b}\n";
var l = buffer_read(wav_file_reader, buffer_u32); debug_str += $"Length: {l}\n";
var bpc = br / ch;
var bits = l / br;
var data = array_create(ch);
var dataF = [ array_create(bits) ];
debug_str += "-- READ --\n";
debug_str += $"Channels: {ch}\n";
debug_str += $"BPC: {bpc * 8}\n";
debug_str += $"bits: {bits}\n";
debug_str += $"samples: {sm}\n";
debug_str += $"duration: {real(bits) / real(sm)}s\n";
for( var j = 0; j < ch; j++ )
data[j] = array_create(bits);
wav_file_range = [0, 0];
var _buffer_left = _buffer_size - buffer_tell(wav_file_reader);
if(_buffer_left < l) {
noti_warning($"The file is smaller than the definded length. ({_buffer_left} < {l})");
bits = floor(_buffer_left / br);
}
content = new audioObject(sm, ch);
content.sound = data;
content.soundF = dataF;
content.bit_depth = bpc * 8;
content.duration = real(bits) / real(sm);
content.packet = bits;
printIf(global.FLAG.wav_import, debug_str);
return content;
}
function file_read_wav_step() {
if(!wav_file_reading) return false;
if(!content) return false;
var t = current_time;
var bf_type, lim;
if(content.bit_depth == 8) { bf_type = buffer_u8; lim = 255; }
else if(content.bit_depth == 16) { bf_type = buffer_s16; lim = 32_768; }
else if(content.bit_depth == 32) { bf_type = buffer_s32; lim = 2_147_483_648; }
for(; wav_file_prg < content.packet; wav_file_prg++ ) {
var ch = 0;
var cha = content.channels;
var j = 0;
repeat( cha ) {
var b = buffer_read(wav_file_reader, bf_type) / lim;
ch += b;
content.sound[j][wav_file_prg] = b;
j++;
}
content.soundF[0][wav_file_prg] = ch / content.channels;
if(current_time - t > 1000 / 30) return false;
}
//printIf(global.FLAG.wav_import, $"Wav range: {wav_file_range}");
printIf(global.FLAG.wav_import, $"Load file complete in: {(current_time - wav_file_load_time) / 1000} s.");
wav_file_reading = false;
buffer_delete(wav_file_reader);
return true;
}

View file

@ -0,0 +1,130 @@
// 2024-04-23 09:59:04
function file_read_ASCII(file, amo = 1) {
var b = "";
repeat(amo) b += chr(buffer_read(file, buffer_u8));
return b;
}
function file_read_wav(path) {
wav_file_reader = buffer_load(path);
wav_file_reading = true;
wav_file_prg = 0;
if(wav_file_reader == -1) {
noti_warning("File read error.");
return noone;
}
wav_file_load_time = current_time;
var _buffer_size = buffer_get_size(wav_file_reader);
//RIFF
var debug_str = $">> READING WAV [{path}] <<\n";
debug_str += $"Buffer size: {_buffer_size}\n\n";
debug_str += "-- RIFF --\n";
var b = file_read_ASCII(wav_file_reader, 4); debug_str += $"{b}\n";
var l = buffer_read(wav_file_reader, buffer_u32); debug_str += $"Packages: {l}\n";
var w = file_read_ASCII(wav_file_reader, 4); debug_str += $"{w}\n";
if(b != "RIFF" || w != "WAVE") {
printIf(global.FLAG.wav_import, debug_str);
noti_warning("Not a valid .wav file.");
return noone;
}
if(buffer_get_size(wav_file_reader) != l + 8)
noti_warning(".wav file has different size than the package header. This may cause reading error.");
//FORMAT
debug_str += "-- FORMAT --\n";
var b = file_read_ASCII(wav_file_reader, 4); debug_str += $"{b}\n";
var l = buffer_read(wav_file_reader, buffer_u32); debug_str += $"Length: {l}\n";
var f = buffer_read(wav_file_reader, buffer_u16); debug_str += $"Linear quantize: {f}\n";
if(l != 16 || f != 1) {
printIf(global.FLAG.wav_import, debug_str);
noti_warning("File format not supported, the audio file need to be 8, 16, 32 bit uncompressed PCM wav with no extension.");
return noone;
}
var ch = buffer_read(wav_file_reader, buffer_u16); debug_str += $"Channels: {ch}\n";
var sm = buffer_read(wav_file_reader, buffer_u32); debug_str += $"Sample: {sm}\n";
var l = buffer_read(wav_file_reader, buffer_u32); debug_str += $"BPS: {l}\n";
var br = buffer_read(wav_file_reader, buffer_u16); debug_str += $"Byterate: {br}\n";
var l = buffer_read(wav_file_reader, buffer_u16); debug_str += $"Bit/Sam: {l}\n";
//DATA
debug_str += "-- DATA --\n";
var b = file_read_ASCII(wav_file_reader, 4); debug_str += $"{b}\n";
var l = buffer_read(wav_file_reader, buffer_u32); debug_str += $"Length: {l}\n";
var bpc = br / ch;
var bits = l / br;
var data = array_create(ch);
var dataF = [ array_create(bits) ];
debug_str += "-- READ --\n";
debug_str += $"Channels: {ch}\n";
debug_str += $"BPC: {bpc * 8}\n";
debug_str += $"bits: {bits}\n";
debug_str += $"samples: {sm}\n";
debug_str += $"duration: {real(bits) / real(sm)}s\n";
for( var j = 0; j < ch; j++ )
data[j] = array_create(bits);
wav_file_range = [0, 0];
var _buffer_left = _buffer_size - buffer_tell(wav_file_reader);
if(_buffer_left < l) {
noti_warning($"The file is smaller than the definded length. ({_buffer_left} < {l})");
bits = floor(_buffer_left / br);
}
content = new audioObject(sm, ch);
content.sound = data;
content.soundF = dataF;
content.bit_depth = bpc * 8;
content.duration = real(bits) / real(sm);
content.packet = bits;
printIf(global.FLAG.wav_import, debug_str);
return content;
}
function file_read_wav_step() {
if(!wav_file_reading) return false;
if(!content) return false;
var t = current_time;
var bf_type, lim;
if(content.bit_depth == 8) { bf_type = buffer_u8; lim = 255; }
else if(content.bit_depth == 16) { bf_type = buffer_s16; lim = 32_768; }
else if(content.bit_depth == 32) { bf_type = buffer_s32; lim = 2_147_483_648; }
for(; wav_file_prg < content.packet; wav_file_prg++ ) {
var ch = 0;
var cha = content.channels;
var j = 0;
repeat( cha ) {
var b = buffer_read(wav_file_reader, bf_type) / lim;
ch += b;
content.sound[j][wav_file_prg] = b;
j++;
}
content.soundF[0][wav_file_prg] = ch / content.channels;
if(current_time - t > 1000 / 30) return false;
}
//printIf(global.FLAG.wav_import, $"Wav range: {wav_file_range}");
printIf(global.FLAG.wav_import, $"Load file complete in: {(current_time - wav_file_load_time) / 1000} s.");
wav_file_reading = false;
buffer_delete(wav_file_reader);
return true;
}

View file

@ -873,7 +873,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
}
} setDropKey(); #endregion
static resetDisplay = function() { #region //////////////////// RESET DISPLAY ////////////////////
static resetDisplay = function() { #region //////////////////// RESET DISPLAY ////////////////////
editWidget = noone;
switch(display_type) {
case VALUE_DISPLAY.button : #region

View file

@ -143,23 +143,23 @@ function Node_WAV_File_Read(_x, _y, _group = noone) : Node(_x, _y, _group) const
} #endregion
#region ++++ inspector ++++
insp1UpdateTooltip = __txt("Refresh");
insp1UpdateIcon = [ THEME.refresh_icon, 1, COLORS._main_value_positive ];
insp2UpdateTooltip = __txtx("play_with_timeline", "Play with timeline");
insp2UpdateIcon = [ THEME.play_sound, 1, COLORS._main_icon_light ];
attributes.play = true;
static onInspector1Update = function() {
var path = getInputData(0);
if(path == "") return;
updatePaths(path);
update();
}
static onInspector2Update = function() {
attributes.play = !attributes.play;
}
insp1UpdateTooltip = __txt("Refresh");
insp1UpdateIcon = [ THEME.refresh_icon, 1, COLORS._main_value_positive ];
insp2UpdateTooltip = __txtx("play_with_timeline", "Play with timeline");
insp2UpdateIcon = [ THEME.play_sound, 1, COLORS._main_icon_light ];
attributes.play = true;
static onInspector1Update = function() {
var path = getInputData(0);
if(path == "") return;
updatePaths(path);
update();
}
static onInspector2Update = function() {
attributes.play = !attributes.play;
}
#endregion
static step = function() { #region

View file

@ -1,26 +1,6 @@
function file_read_ASCII(file, amo = 1) {
var b = "";
repeat(amo)
b += chr(buffer_read(file, buffer_u8));
//b += chr(file_bin_read_byte(file));
return b;
}
function file_read_bytes(file, amo = 1, signed = false, little_endian = true) {
var b = 0;
var m = little_endian? 1 : 1 << ((amo - 1) * 8);
repeat(amo) {
//b += file_bin_read_byte(file) * m;
b += buffer_read(file, buffer_u8) * m;
m = little_endian? m * 256 : m / 256;
}
if(signed) {
var mv = 1 << (amo * 8 - 1) - 1;
if(b > mv)
b -= (1 << (amo * 8));
}
repeat(amo) b += chr(buffer_read(file, buffer_u8));
return b;
}
@ -59,17 +39,17 @@ function file_read_wav(path) {
debug_str += "-- FORMAT --\n";
var b = file_read_ASCII(wav_file_reader, 4); debug_str += $"{b}\n";
var l = buffer_read(wav_file_reader, buffer_u32); debug_str += $"Length: {l}\n";
var f = buffer_read(wav_file_reader, buffer_u16); debug_str += $"Linear quantize: {f}\n";
if(l != 16) {
if(l != 16 || f != 1) {
printIf(global.FLAG.wav_import, debug_str);
noti_warning("File format not supported, the audio file need to be 8, 16 bit uncompressed PCM wav with no extension.");
noti_warning("File format not supported, the audio file need to be 8, 16, 32 bit uncompressed PCM wav with no extension.");
return noone;
}
var l = buffer_read(wav_file_reader, buffer_u16); debug_str += $"Linear quantize: {l}\n";
var ch = buffer_read(wav_file_reader, buffer_u16); debug_str += $"Channels: {ch}\n";
var sm = buffer_read(wav_file_reader, buffer_u32); debug_str += $"Sample: {sm}\n";
var l = buffer_read(wav_file_reader, buffer_u32); debug_str += $"BPS: {l}\n";
var l = buffer_read(wav_file_reader, buffer_u32); debug_str += $"BPS: {l}\n";
var br = buffer_read(wav_file_reader, buffer_u16); debug_str += $"Byterate: {br}\n";
var l = buffer_read(wav_file_reader, buffer_u16); debug_str += $"Bit/Sam: {l}\n";