extends Node2D #warning-ignore-all:return_value_discarded const MusicPlayer := preload('res://scripts/MusicPlayer.gd') var MusicLoader := preload('res://scripts/loaders/snes/music_ff5.gd').new() var inst_buttons = [] var sfx_buttons = [] func _create_sfx_buttons(): var disable_btn := !SoundLoader.has_loaded_audio_samples for i in SoundLoader.INST_NUM: var btn = Button.new() btn.text = 'Inst #%02X' % i btn.align = Button.ALIGN_CENTER btn.set_position(Vector2((i%7)*50, (i/7)*24)) btn.rect_min_size.x = 48 add_child(btn) btn.connect('pressed', SoundLoader, 'play_sample', [i]) inst_buttons.append(btn) btn.disabled = disable_btn for i in SoundLoader.SFX_NUM: var btn = Button.new() btn.text = 'SFX #%02X' % i btn.align = Button.ALIGN_CENTER btn.set_position(Vector2((i%4)*50, 130 + (i/4)*24)) btn.rect_min_size.x = 48 add_child(btn) btn.connect('pressed', SoundLoader, 'play_sfx', [i]) sfx_buttons.append(btn) btn.disabled = disable_btn if disable_btn: SoundLoader.connect('audio_samples_loaded', self, '_enable_sfx_buttons') SoundLoader.connect('audio_inst_sample_loaded', self, '_enable_inst_button') SoundLoader.connect('audio_sfx_sample_loaded', self, '_enable_sfx_button') func _enable_sfx_buttons(): for btn in sfx_buttons: btn.disabled = false for btn in inst_buttons: btn.disabled = false func _enable_sfx_button(id: int): # NB: This assumes sequential loading (may change, probably won't) for i in id+1: sfx_buttons[i].disabled = false func _enable_inst_button(id: int): # NB: This assumes sequential loading (may change, probably won't) for i in id+1: inst_buttons[i].disabled = false const NUM_CHANNELS := 8 var music_player = null var inst_sample_map := {} var bgm_tracksets := {} func evaluate_bgm(id: int): var buffer: StreamPeerBuffer = RomLoader.snes_buffer.duplicate() var bgm_song_ptr: int = RomLoader.snes_data.bgm_song_pointers[id] & 0x3FFFFF var bank_offset: int = bgm_song_ptr & 0x3F0000 buffer.seek(bgm_song_ptr) var length := buffer.get_u16() var rom_address_base := buffer.get_u16() var track_ptrs := PoolIntArray() for i in NUM_CHANNELS: var track_ptr := buffer.get_u16() + bank_offset if track_ptr < bgm_song_ptr: track_ptr += 0x010000 # next bank track_ptrs.append(track_ptr) var end_ptr := buffer.get_u16() + bank_offset if end_ptr < bgm_song_ptr: end_ptr += 0x010000 # next bank var tracks := [] for i in NUM_CHANNELS: var track_ptr := track_ptrs[i] # var channel: MusicChannel = self.channels[i] # print('Unrolling BGM track %02d:%02d at 0x%06X:0x%06X:0x%06X' % [id, i, bgm_song_ptr, track_ptr, end_ptr]) tracks.append(MusicLoader.unroll_track(buffer.duplicate(), bgm_song_ptr, track_ptr, end_ptr, '%02d:%02d'%[id, i])) bgm_tracksets[id] = tracks func play_bgm(id: int) -> void: var inst_indices = RomLoader.snes_data.bgm_instrument_indices[id] for i in 16: var inst_idx: int = inst_indices[i]-1 if inst_idx < 0: self.inst_sample_map[i + 0x20] = null else: if SoundLoader.HACK_EXTEND_LOOP_SAMPLE_playback: self.inst_sample_map[i + 0x20] = SoundLoader.instrument_samples_HACK_EXTENDED_LOOPS[inst_idx] else: self.inst_sample_map[i + 0x20] = SoundLoader.instrument_samples[inst_idx] if self.music_player: remove_child(music_player) self.music_player = MusicPlayer.new(bgm_tracksets[id], self.inst_sample_map) add_child(self.music_player) self.music_player.is_playing = true print('Playing BGM%02d' % id) func _play_bgm() -> void: self.play_bgm($sb_bgm.value) func _create_bgm_playback() -> void: $sb_bgm.max_value = SoundLoader.BGM_NUM $btn_bgm.connect('pressed', self, '_play_bgm') for i in SoundLoader.SFX_NUM: self.inst_sample_map[i] = SoundLoader.sfx_samples[i] for i in SoundLoader.BGM_NUM: evaluate_bgm(i) func _stop_all() -> void: if self.music_player: self.music_player.queue_free() self.music_player = null SoundLoader.player.stop() func _update_loop_hack_status(enabled: bool) -> void: SoundLoader.HACK_EXTEND_LOOP_SAMPLE_playback = enabled # Called when the node enters the scene tree for the first time. func _ready() -> void: self._create_sfx_buttons() self._create_bgm_playback() $btn_stop.connect('pressed', self, '_stop_all') $btn_hack_loop_extension.connect('toggled', self, '_update_loop_hack_status') $btn_hack_loop_extension.text += ' (%dms)'%SoundLoader.HACK_EXTEND_LOOP_SAMPLE_EXTRA_MS for i in len(RomLoader.snes_data.bgm_song_pointers): var pointer = RomLoader.snes_data.bgm_song_pointers[i] # print('BGM 0x%02X (%02d) at 0x%06X' % [i, i, pointer]) self.test_rendering() onready var audio_renderer := $'%audio_renderer' func test_rendering() -> void: SoundLoader.samples_to_texture() audio_renderer.material.set_shader_param('instrument_samples', SoundLoader.samples_tex) audio_renderer.material.set_shader_param('instrument_samples_size', SoundLoader.samples_tex.get_size()) var midi_events_bytes := StreamPeerBuffer.new() var midi_events_bytes2 := StreamPeerBuffer.new() var midi_events_bytes3 := StreamPeerBuffer.new() var midi_events_bytes4 := StreamPeerBuffer.new() for i in 2048: var t = i * 3.0 midi_events_bytes.put_32(t*32000) # t_start midi_events_bytes2.put_32((t+2.75)*32000) # t_end midi_events_bytes3.put_u8((i%35)) # instrument midi_events_bytes3.put_u8(71) # pitch_idx # midi_events_bytes.put_float((35 + (i%40))) # pitch_idx midi_events_bytes3.put_u8(255) # velocity midi_events_bytes3.put_u8(i%256) # pan midi_events_bytes4.put_32(0) # ADSR var channel_data = midi_events_bytes.data_array + midi_events_bytes2.data_array + midi_events_bytes3.data_array + midi_events_bytes4.data_array audio_renderer.push_bytes(channel_data) # + channel_data + channel_data + channel_data + channel_data + channel_data + channel_data + channel_data) # var test_payload := PoolByteArray() # test_payload.resize(4096*4096*2) # # for i in 5: # # test_payload.fill(i*2+10) # # audio_renderer.render_queue.append(test_payload) # test_payload.fill(0) # for i in 65536: # test_payload.set(i*2, i%256) # test_payload.set(i*2+1, i/256) # audio_renderer.render_queue.append(test_payload) # # audio_renderer.render_queue.append(test_payload) func _process(_delta): update() func _draw() -> void: if audio_renderer.waiting_for_viewport: audio_renderer.get_result() var result = audio_renderer.result_queue[0] var rendered_audio := AudioStreamSample.new() rendered_audio.data = result rendered_audio.stereo = true rendered_audio.mix_rate = 32000 rendered_audio.format = AudioStreamSample.FORMAT_16_BITS var error = rendered_audio.save_to_wav('output/rendered_audio.wav') print(error) pass