[WIP] Audio shader almost working
This commit is contained in:
parent
e077c4e036
commit
fbd3dd52c7
|
@ -189,7 +189,7 @@ const TEX_WIDTH := 2048
|
||||||
const FILTER_PAD := 3
|
const FILTER_PAD := 3
|
||||||
func samples_to_texture():
|
func samples_to_texture():
|
||||||
var num_samples := INST_NUM + SFX_NUM
|
var num_samples := INST_NUM + SFX_NUM
|
||||||
var header_length := num_samples * 6
|
var header_length := num_samples * 8
|
||||||
|
|
||||||
# Create header and unwrapped payload separately first
|
# Create header and unwrapped payload separately first
|
||||||
var header_buffer := StreamPeerBuffer.new()
|
var header_buffer := StreamPeerBuffer.new()
|
||||||
|
@ -201,15 +201,16 @@ func samples_to_texture():
|
||||||
var nonlooping: bool = loop_begin >= loop_end
|
var nonlooping: bool = loop_begin >= loop_end
|
||||||
if nonlooping:
|
if nonlooping:
|
||||||
loop_begin = loop_end
|
loop_begin = loop_end
|
||||||
loop_end += 1
|
loop_end += 3
|
||||||
header_buffer.put_u16(header_length + (payload_buffer.get_position()/2) + FILTER_PAD) # sample_start
|
header_buffer.put_32(header_length + (payload_buffer.get_position()/2) + FILTER_PAD) # sample_start
|
||||||
header_buffer.put_u16(sample.loop_end + FILTER_PAD) # sample_length
|
header_buffer.put_u16(loop_end + FILTER_PAD) # sample_length
|
||||||
header_buffer.put_u16(sample.loop_begin + FILTER_PAD) # sample_loop_begin
|
header_buffer.put_u16(loop_begin + FILTER_PAD) # sample_loop_begin
|
||||||
header_buffer.put_u16(sample.mix_rate) # sample_mixrate
|
header_buffer.put_u16(sample.mix_rate) # sample_mixrate
|
||||||
header_buffer.put_u8(0) # TODO: attack
|
header_buffer.put_u8(0) # TODO: attack
|
||||||
header_buffer.put_u8(0) # TODO: decay
|
header_buffer.put_u8(0) # TODO: decay
|
||||||
header_buffer.put_u8(0) # TODO: sustain
|
header_buffer.put_u8(0) # TODO: sustain
|
||||||
header_buffer.put_u8(0) # TODO: release
|
header_buffer.put_u8(0) # TODO: release
|
||||||
|
header_buffer.put_u16(0) # TODO: unk
|
||||||
for i in FILTER_PAD: # Prepend 3 frames of silence
|
for i in FILTER_PAD: # Prepend 3 frames of silence
|
||||||
payload_buffer.put_16(0)
|
payload_buffer.put_16(0)
|
||||||
payload_buffer.put_data(sample.data) # Copy entire S16LE audio data
|
payload_buffer.put_data(sample.data) # Copy entire S16LE audio data
|
||||||
|
@ -251,7 +252,7 @@ func samples_to_texture():
|
||||||
var samples_img = Image.new()
|
var samples_img = Image.new()
|
||||||
samples_img.create_from_data(TEX_WIDTH, rows, false, Image.FORMAT_LA8, data)
|
samples_img.create_from_data(TEX_WIDTH, rows, false, Image.FORMAT_LA8, data)
|
||||||
self.samples_tex = ImageTexture.new()
|
self.samples_tex = ImageTexture.new()
|
||||||
self.samples_tex.create_from_image(samples_img, Texture.FLAG_FILTER)
|
self.samples_tex.create_from_image(samples_img, 0) #Texture.FLAG_FILTER)
|
||||||
|
|
||||||
|
|
||||||
var player := AudioStreamPlayer.new() # Make one for each channel, later
|
var player := AudioStreamPlayer.new() # Make one for each channel, later
|
||||||
|
|
|
@ -98,7 +98,7 @@ vec4 test_writeback(sampler2D tex, vec2 uv) {
|
||||||
// With the 258 texel header, which uses 3 texels of margin, 255 would be subtracted from the above payload,
|
// With the 258 texel header, which uses 3 texels of margin, 255 would be subtracted from the above payload,
|
||||||
// leaving 261121 texels for the sample data.
|
// leaving 261121 texels for the sample data.
|
||||||
|
|
||||||
const float HEADER_LENGTH_TEXELS = 6.0;
|
const float HEADER_LENGTH_TEXELS = 8.0;
|
||||||
uniform sampler2D instrument_samples;
|
uniform sampler2D instrument_samples;
|
||||||
uniform vec2 instrument_samples_size = vec2(2048.0, 128.0);
|
uniform vec2 instrument_samples_size = vec2(2048.0, 128.0);
|
||||||
uniform float instrument_row_padding = 3.0; // In case we want to go to cubic filtering
|
uniform float instrument_row_padding = 3.0; // In case we want to go to cubic filtering
|
||||||
|
@ -115,15 +115,21 @@ vec2 get_inst_texel(vec2 xy) {
|
||||||
return texture(instrument_samples, xy/instrument_samples_size).xw;
|
return texture(instrument_samples, xy/instrument_samples_size).xw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float get_inst_texel_int16(float s) {
|
||||||
|
float x = mod(s, instrument_row_payload) + instrument_row_padding;
|
||||||
|
float y = trunc(s / instrument_row_payload);
|
||||||
|
return unpack_int16(texture(instrument_samples, (vec2(x, y) + 0.5)/instrument_samples_size).xw);
|
||||||
|
}
|
||||||
|
|
||||||
float get_instrument_sample(float instrument_index, float pitch_scale, float t, float t_end) {
|
float get_instrument_sample(float instrument_index, float pitch_scale, float t, float t_end) {
|
||||||
// t_end is for ADSR purposes
|
// t_end is for ADSR purposes
|
||||||
float header_offset = instrument_index * HEADER_LENGTH_TEXELS;
|
float header_offset = instrument_index * HEADER_LENGTH_TEXELS;
|
||||||
float sample_start = unpack_uint16(get_inst_texel(vec2(header_offset, 0.0))); // The true start, after the prepended 3 frames of silence
|
float sample_start = float(unpack_int32(vec4(get_inst_texel(vec2(header_offset, 0.0)), get_inst_texel(vec2(header_offset + 1.0, 0.0))))); // The true start, after the prepended 3 frames of silence
|
||||||
float sample_length = unpack_uint16(get_inst_texel(vec2(header_offset + 1.0, 0.0))); // 3 frames after the true end, because of how we loop
|
float sample_length = unpack_uint16(get_inst_texel(vec2(header_offset + 2.0, 0.0))); // 3 frames after the true end, because of how we loop
|
||||||
float sample_loop_begin = unpack_uint16(get_inst_texel(vec2(header_offset + 2.0, 0.0))); // 3 frames after the true loop point
|
float sample_loop_begin = unpack_uint16(get_inst_texel(vec2(header_offset + 3.0, 0.0))); // 3 frames after the true loop point
|
||||||
float sample_mixrate = unpack_uint16(get_inst_texel(vec2(header_offset + 3.0, 0.0)));
|
float sample_mixrate = unpack_uint16(get_inst_texel(vec2(header_offset + 4.0, 0.0)));
|
||||||
vec2 attack_decay = get_inst_texel(vec2(header_offset + 4.0, 0.0));
|
vec2 attack_decay = get_inst_texel(vec2(header_offset + 5.0, 0.0));
|
||||||
vec2 sustain_release = get_inst_texel(vec2(header_offset + 5.0, 0.0));
|
vec2 sustain_release = get_inst_texel(vec2(header_offset + 6.0, 0.0));
|
||||||
// Calculate the point we want to sample in linear space
|
// Calculate the point we want to sample in linear space
|
||||||
float mixrate = sample_mixrate * pitch_scale;
|
float mixrate = sample_mixrate * pitch_scale;
|
||||||
float target_frame = t * mixrate;
|
float target_frame = t * mixrate;
|
||||||
|
@ -134,10 +140,11 @@ float get_instrument_sample(float instrument_index, float pitch_scale, float t,
|
||||||
target_frame -= overshoot_loops*loop_length;
|
target_frame -= overshoot_loops*loop_length;
|
||||||
// Now we need to identify the sampling point since our frames are spread across multiple rows for GPU reasons
|
// Now we need to identify the sampling point since our frames are spread across multiple rows for GPU reasons
|
||||||
// We only sample from texel 4 onwards on a given row - texel 0 is the header, texels 1,2,3 are lead-in for filtering
|
// We only sample from texel 4 onwards on a given row - texel 0 is the header, texels 1,2,3 are lead-in for filtering
|
||||||
// Note that y should be integral, but x should be continuous, as that's what applies the filtering!
|
|
||||||
target_frame += sample_start;
|
target_frame += sample_start;
|
||||||
vec2 sample_xy = vec2(instrument_row_padding + mod(target_frame, instrument_row_payload), trunc(target_frame/instrument_row_payload));
|
float a = get_inst_texel_int16(floor(target_frame));
|
||||||
return rescale_int16(unpack_int16(get_inst_texel(sample_xy)));
|
float b = get_inst_texel_int16(ceil(target_frame));
|
||||||
|
float mix_amount = fract(target_frame);
|
||||||
|
return rescale_int16(mix(a, b, mix_amount));
|
||||||
}
|
}
|
||||||
|
|
||||||
const int NUM_CHANNELS = 8;
|
const int NUM_CHANNELS = 8;
|
||||||
|
@ -196,13 +203,7 @@ vec4 render_song(int smp) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Convert the stereo float audio to S16LE
|
// Convert the stereo float audio to S16LE
|
||||||
// return vec4(pack_float_to_int16(downmixed_stereo.x), pack_float_to_int16(downmixed_stereo.y));
|
return vec4(pack_float_to_int16(downmixed_stereo.x), pack_float_to_int16(downmixed_stereo.y));
|
||||||
// return vec4(pack_float_to_int16(downmixed_stereo.x), pack_float_to_int16(mod(t, 2.0) - 1.0));
|
|
||||||
vec2 isuv = vec2(mod(float(smp), instrument_samples_size.x), trunc(float(smp)/instrument_samples_size.x))/instrument_samples_size;
|
|
||||||
// float ins = rescale_int16(unpack_int16(texture(instrument_samples, isuv).xw));
|
|
||||||
// return vec4(pack_float_to_int16(ins), pack_float_to_int16(mod(t, 2.0) - 1.0));
|
|
||||||
return vec4(texture(instrument_samples, isuv).xw, pack_float_to_int16(mod(t, 2.0) - 1.0));
|
|
||||||
// return vec4(pack_float_to_int16((t/10.0) - 1.0), pack_float_to_int16(mod(t, 2.0) - 1.0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fragment() {
|
void fragment() {
|
||||||
|
|
|
@ -138,9 +138,9 @@ func test_rendering() -> void:
|
||||||
var midi_events_bytes3 := StreamPeerBuffer.new()
|
var midi_events_bytes3 := StreamPeerBuffer.new()
|
||||||
var midi_events_bytes4 := StreamPeerBuffer.new()
|
var midi_events_bytes4 := StreamPeerBuffer.new()
|
||||||
for i in 2048:
|
for i in 2048:
|
||||||
var t = i * 10.0
|
var t = i * 3.0
|
||||||
midi_events_bytes.put_32(t*32000) # t_start
|
midi_events_bytes.put_32(t*32000) # t_start
|
||||||
midi_events_bytes2.put_32((t+3.0)*32000) # t_end
|
midi_events_bytes2.put_32((t+2.75)*32000) # t_end
|
||||||
midi_events_bytes3.put_u8((i%35)) # instrument
|
midi_events_bytes3.put_u8((i%35)) # instrument
|
||||||
midi_events_bytes3.put_u8(71) # pitch_idx
|
midi_events_bytes3.put_u8(71) # pitch_idx
|
||||||
# midi_events_bytes.put_float((35 + (i%40))) # pitch_idx
|
# midi_events_bytes.put_float((35 + (i%40))) # pitch_idx
|
||||||
|
|
|
@ -13,7 +13,6 @@ shader_param/instrument_row_payload = 2042.0
|
||||||
shader_param/reference_note = 71.0
|
shader_param/reference_note = 71.0
|
||||||
shader_param/output_mixrate = 32000.0
|
shader_param/output_mixrate = 32000.0
|
||||||
shader_param/midi_events_size = Vector2( 2048, 16 )
|
shader_param/midi_events_size = Vector2( 2048, 16 )
|
||||||
shader_param/t_scale = 524.0
|
|
||||||
|
|
||||||
[node name="audio_system" type="Node2D"]
|
[node name="audio_system" type="Node2D"]
|
||||||
script = ExtResource( 1 )
|
script = ExtResource( 1 )
|
||||||
|
|
Loading…
Reference in New Issue