diff --git a/scripts/MusicPlayer.gd b/scripts/MusicPlayer.gd index 28f3d3c..c1c3270 100644 --- a/scripts/MusicPlayer.gd +++ b/scripts/MusicPlayer.gd @@ -550,6 +550,7 @@ func render_channels(_t_start: float, _t_end: float, inst_map: Array) -> Array: p_end = note_event.p_start else: channel_loop_p_returns.append(-1) + channel_loop_p_lengths.append(0) if p_end > longest_channel_p_end: longest_channel_p_end = p_end diff --git a/scripts/loaders/SoundLoader.gd b/scripts/loaders/SoundLoader.gd index 596d688..a051882 100644 --- a/scripts/loaders/SoundLoader.gd +++ b/scripts/loaders/SoundLoader.gd @@ -198,7 +198,7 @@ func samples_to_texture(): var loop_begin: int = sample.loop_begin var loop_length: int = sample.loop_end - loop_begin var nonlooping: bool = loop_length <= 0 - print('Processing sample, nonlooping=%s'%nonlooping) + # print('Processing sample, nonlooping=%s'%nonlooping) for i in FILTER_PAD: # Prepend frames of silence payload_buffer.put_16(0) diff --git a/shaders/audio_renderer.gdshader b/shaders/audio_renderer.gdshader index 36d5666..9754508 100644 --- a/shaders/audio_renderer.gdshader +++ b/shaders/audio_renderer.gdshader @@ -153,12 +153,12 @@ float get_instrument_sample(float instrument_index, float note, float t) { const int NUM_CHANNELS = 8; const int MAX_CHANNEL_NOTE_EVENTS = 2048; const int NUM_CHANNEL_NOTE_PROBES = 11; // log2(MAX_CHANNEL_NOTE_EVENTS) -uniform sampler2D midi_events : hint_normal; -uniform vec2 midi_events_size = vec2(2048.0, 16.0); -vec4 get_midi_texel(float x, float y) { - return texture(midi_events, vec2(x, y)/midi_events_size).xyzw; +// uniform sampler2D midi_events : hint_normal; +uniform vec2 midi_events_size = vec2(2048.0, 32.0); +vec4 get_midi_texel(sampler2D tex, float x, float y) { + return texture(tex, vec2(x, y)/midi_events_size).xyzw; } -vec4 render_song(int smp) { +vec4 render_song(sampler2D tex, int smp) { // Each output texel rendered is a stereo S16LE frame representing 1/32000 of a second // 2048 is an established safe texture dimension so may as well go 2048 wide @@ -172,17 +172,17 @@ vec4 render_song(int smp) { int smp_start; for (int i = 0; i < NUM_CHANNEL_NOTE_PROBES; i++) { float step_size = exp2(float(NUM_CHANNEL_NOTE_PROBES - i - 1)); - smp_start = int(unpack_int32(get_midi_texel(event_idx + step_size, row))); + smp_start = int(unpack_int32(get_midi_texel(tex, event_idx + step_size, row))); event_idx += (smp >= smp_start) ? step_size : 0.0; } - smp_start = int(unpack_int32(get_midi_texel(event_idx, row))); - int smp_end = int(unpack_int32(get_midi_texel(event_idx, row+1.0))); - vec4 note_event_supplement = get_midi_texel(event_idx, row+2.0); // left as [0.0, 1.0] + smp_start = int(unpack_int32(get_midi_texel(tex, event_idx, row))); + int smp_end = int(unpack_int32(get_midi_texel(tex, event_idx, row+1.0))); + vec4 note_event_supplement = get_midi_texel(tex, event_idx, row+2.0); // left as [0.0, 1.0] float instrument_idx = trunc(note_event_supplement.x * 255.0); float pitch_idx = note_event_supplement.y * 255.0; float velocity = note_event_supplement.z; float pan = note_event_supplement.w; - vec4 adsr = get_midi_texel(event_idx, row+3.0); // left as [0.0, 1.0] + vec4 adsr = get_midi_texel(tex, event_idx, row+3.0); // left as [0.0, 1.0] // ====================At some point I'll look back into packing floats==================== // TBD = note_event_supplement.zw; - tremolo/vibrato/noise/pan_lfo/pitchbend/echo remain // ====================At some point I'll look back into packing floats==================== @@ -214,5 +214,5 @@ void fragment() { // uv = (trunc(uv*UV_QUANTIZE)+0.5)/UV_QUANTIZE; // COLOR.xyzw = test_writeback(TEXTURE, uv); ivec2 xy = ivec2(trunc(uv*TEX_SIZE)); - COLOR.xyzw = render_song(xy.x + (xy.y*INT_TEX_SIZE)); + COLOR.xyzw = render_song(TEXTURE, xy.x + (xy.y*INT_TEX_SIZE)); } diff --git a/test/audio_renderer.gd b/test/audio_renderer.gd index 6727d82..0dd51cc 100644 --- a/test/audio_renderer.gd +++ b/test/audio_renderer.gd @@ -5,11 +5,12 @@ const INPUT_FORMAT := Image.FORMAT_RGBA8 # Image.FORMAT_LA8 const INPUT_BYTES_PER_TEXEL := 4 # 2 const OUTPUT_BYTES_PER_TEXEL := 4 const OUTPUT_WIDTH := 4096 +const OUTPUT_HEIGHT := 4096 const QUAD_COLOR := PoolColorArray([Color.white, Color.white, Color.white, Color.white]) var viewport: Viewport var render_queue: Array # of Images var result_queue: Array # of [String, PoolByteArray] -var current_tex: ImageTexture # Needed to prevent GC before draw +var current_textures: Array # of ImageTextures - Needed to prevent GC before draw var waiting_for_viewport: Array var done_first_draw: bool @@ -19,7 +20,7 @@ func _ready() -> void: self.result_queue = [] self.waiting_for_viewport = [] self.done_first_draw = false - self.current_tex = ImageTexture.new() + self.current_textures = [] func push_image(img: Image, uv_rows: int = 4096, desc: String = '') -> void: self.render_queue.append([img, uv_rows, desc]) @@ -51,29 +52,47 @@ func _draw() -> void: if not self.render_queue: return - # Draw the next ImageTexture - var image_and_uv_rows_and_desc = self.render_queue.pop_front() - self.current_tex.create_from_image(image_and_uv_rows_and_desc[0], 0) - self.material.set_shader_param('midi_events', self.current_tex) - self.material.set_shader_param('midi_events_size', self.current_tex.get_size()) - var uv_rows: int = image_and_uv_rows_and_desc[1] - var uv_rows_inv: int = 4096 - uv_rows - var uv_v: float = uv_rows / float(OUTPUT_WIDTH) - var points := PoolVector2Array([Vector2(0, uv_rows_inv), Vector2(OUTPUT_WIDTH, uv_rows_inv), Vector2(OUTPUT_WIDTH, OUTPUT_WIDTH), Vector2(0, OUTPUT_WIDTH)]) - var uvs := PoolVector2Array([Vector2(0, 1-uv_v), Vector2(1, 1-uv_v), Vector2(1, 1), Vector2(0, 1)]) - draw_primitive(points, QUAD_COLOR, uvs, self.current_tex) - self.waiting_for_viewport = [uv_rows, image_and_uv_rows_and_desc[2]] # Grab the result next draw + self.waiting_for_viewport = [] + var rows_drawn := 0 + while self.render_queue: + var draw_rows: int = self.render_queue[0][1] + rows_drawn += draw_rows + if rows_drawn > OUTPUT_HEIGHT: + break + + # Draw the next ImageTexture + var image_and_uv_rows_and_desc = self.render_queue.pop_front() + var i := len(self.waiting_for_viewport) + if len(self.current_textures) < i+1: + self.current_textures.append(ImageTexture.new()) + var tex: ImageTexture = self.current_textures[i] + tex.create_from_image(image_and_uv_rows_and_desc[0], 0) + # self.material.set_shader_param('midi_events', tex) + self.material.set_shader_param('midi_events_size', tex.get_size()) + var y_top: int = OUTPUT_HEIGHT - rows_drawn + var y_bot: int = y_top + draw_rows + var uv_inv_v: float = 1 - (draw_rows / float(OUTPUT_WIDTH)) + var uvs := PoolVector2Array([Vector2(0, uv_inv_v), Vector2(1, uv_inv_v), Vector2(1, 1), Vector2(0, 1)]) + var points := PoolVector2Array([Vector2(0, y_top), Vector2(OUTPUT_WIDTH, y_top), Vector2(OUTPUT_WIDTH, y_bot), Vector2(0, y_bot)]) + draw_primitive(points, QUAD_COLOR, uvs, tex) + self.waiting_for_viewport.append([draw_rows, image_and_uv_rows_and_desc[2]]) # Grab the result next draw + func get_result() -> void: - var result_rows: int = waiting_for_viewport[0] - var result_desc: String = waiting_for_viewport[1] var result_texture := self.viewport.get_texture() var result_image := result_texture.get_data() var result_bytes := result_image.get_data() - var result_byte_count := result_rows * OUTPUT_WIDTH * OUTPUT_BYTES_PER_TEXEL - result_bytes.resize(result_byte_count) - self.result_queue.append([result_desc, result_bytes]) + var retrieved_rows := 0 + for rows_and_desc in self.waiting_for_viewport: + var entry_rows: int = rows_and_desc[0] + var entry_desc: String = rows_and_desc[1] + var bytes_start := retrieved_rows * OUTPUT_WIDTH * OUTPUT_BYTES_PER_TEXEL + var bytes_end := (retrieved_rows + entry_rows) * OUTPUT_WIDTH * OUTPUT_BYTES_PER_TEXEL + var entry_bytes := result_bytes.subarray(bytes_start, bytes_end-1) + self.result_queue.append([entry_desc, entry_bytes]) + retrieved_rows += entry_rows + # result_bytes.resize(result_byte_count) self.waiting_for_viewport = [] # # Debugging: compare a sequence of all the possible 16bit integers diff --git a/test/audio_system.gd b/test/audio_system.gd index a582b69..6898853 100644 --- a/test/audio_system.gd +++ b/test/audio_system.gd @@ -199,27 +199,28 @@ func render_all_bgm(bgms_to_render: int = 64) -> void: const save_prerendered_audio := false func _get_prerendered_audio(): audio_renderer.get_result() - var result = audio_renderer.result_queue.pop_back() - var desc = result[0] - var rendered_audio := AudioStreamSample.new() - rendered_audio.data = result[1] - rendered_audio.stereo = true - rendered_audio.mix_rate = 32000 - rendered_audio.format = AudioStreamSample.FORMAT_16_BITS - if prerendered_bgm_start_and_end_loops[desc][0] >= 0: - rendered_audio.loop_begin = int(round(prerendered_bgm_start_and_end_loops[desc][0])) - rendered_audio.loop_end = int(round(prerendered_bgm_start_and_end_loops[desc][1])) - rendered_audio.loop_mode = AudioStreamSample.LOOP_FORWARD - self.prerendered_bgms[desc] = rendered_audio - if save_prerendered_audio: - var error = rendered_audio.save_to_wav('output/rendered_%s.wav'%desc) - print('@%dms - Saved render of %s (error code %s)' % [get_ms(), desc, globals.ERROR_CODE_STRINGS[error]]) - else: - print('@%dms - Rendered %s without saving' % [get_ms(), desc]) - if self.queued_bgm_playback == desc: - self.audio_player.stream = rendered_audio - self.audio_player.play() - self.queued_bgm_playback = '' + while audio_renderer.result_queue: + var result = audio_renderer.result_queue.pop_front() + var desc = result[0] + var rendered_audio := AudioStreamSample.new() + rendered_audio.data = result[1] + rendered_audio.stereo = true + rendered_audio.mix_rate = 32000 + rendered_audio.format = AudioStreamSample.FORMAT_16_BITS + if prerendered_bgm_start_and_end_loops[desc][0] >= 0: + rendered_audio.loop_begin = int(round(prerendered_bgm_start_and_end_loops[desc][0])) + rendered_audio.loop_end = int(round(prerendered_bgm_start_and_end_loops[desc][1])) + rendered_audio.loop_mode = AudioStreamSample.LOOP_FORWARD + self.prerendered_bgms[desc] = rendered_audio + if save_prerendered_audio: + var error = rendered_audio.save_to_wav('output/rendered_%s.wav'%desc) + print('@%dms - Saved render of %s (error code %s)' % [get_ms(), desc, globals.ERROR_CODE_STRINGS[error]]) + else: + print('@%dms - Rendered %s without saving' % [get_ms(), desc]) + if self.queued_bgm_playback == desc: + self.audio_player.stream = rendered_audio + self.audio_player.play() + self.queued_bgm_playback = '' func get_shader_test_pattern() -> PoolByteArray: diff --git a/test/audio_system.tscn b/test/audio_system.tscn index 17836c1..f54c51c 100644 --- a/test/audio_system.tscn +++ b/test/audio_system.tscn @@ -1,12 +1,9 @@ -[gd_scene load_steps=6 format=2] +[gd_scene load_steps=5 format=2] [ext_resource path="res://test/audio_system.gd" type="Script" id=1] [ext_resource path="res://test/audio_renderer.gd" type="Script" id=3] [ext_resource path="res://shaders/audio_renderer.gdshader" type="Shader" id=4] -[sub_resource type="Curve" id=3] -_data = [ Vector2( 0, 0 ), 0.0, 2.46705, 0, 1, Vector2( 0.335329, 0.827273 ), 2.46705, -1.6562, 1, 1, Vector2( 0.631737, 0.336364 ), -1.6562, 1.80207, 1, 1, Vector2( 1, 1 ), 1.80207, 0.0, 1, 0 ] - [sub_resource type="ShaderMaterial" id=2] shader = ExtResource( 4 ) shader_param/instrument_samples_size = Vector2( 2048, 128 ) @@ -16,7 +13,6 @@ shader_param/midi_events_size = Vector2( 2048, 16 ) [node name="audio_system" type="Node2D"] script = ExtResource( 1 ) -curve = SubResource( 3 ) [node name="viewport_audio_renderer" type="Viewport" parent="."] size = Vector2( 4096, 4096 )