diff --git a/src/Autoload/Export.gd b/src/Autoload/Export.gd index b60545e0b..ca839dcd6 100644 --- a/src/Autoload/Export.gd +++ b/src/Autoload/Export.gd @@ -536,15 +536,15 @@ func export_video(export_paths: PackedStringArray, project: Project) -> bool: var audio_layer_count := 0 var max_audio_duration := 0 var adelay_string := "" - for layer in project.layers: - if layer is AudioLayer and is_instance_valid(layer.audio) and layer.audio is AudioStreamMP3: + for layer in project.get_all_audio_layers(): + if layer.audio is AudioStreamMP3: var temp_file_name := str(audio_layer_count + 1).pad_zeros(number_of_digits) + ".mp3" var temp_file_path := temp_path_real.path_join(temp_file_name) var temp_audio_file := FileAccess.open(temp_file_path, FileAccess.WRITE) temp_audio_file.store_buffer(layer.audio.data) ffmpeg_combine_audio.append("-i") ffmpeg_combine_audio.append(temp_file_path) - var delay: int = layer.playback_position * 1000 + var delay := floori(layer.playback_position * 1000) # [n]adelay=delay_in_ms:all=1[na] adelay_string += ( "[%s]adelay=%s:all=1[%sa];" % [audio_layer_count, delay, audio_layer_count] diff --git a/src/Autoload/OpenSave.gd b/src/Autoload/OpenSave.gd index d8fac67fe..868d25ee1 100644 --- a/src/Autoload/OpenSave.gd +++ b/src/Autoload/OpenSave.gd @@ -201,7 +201,7 @@ func handle_loading_video(file: String) -> bool: var output_audio_file := temp_path_real.path_join("audio.mp3") # ffmpeg -y -i input_file -vn audio.mp3 var ffmpeg_execute_audio: PackedStringArray = ["-y", "-i", file, "-vn", output_audio_file] - var success_audio := OS.execute(Global.ffmpeg_path, ffmpeg_execute_audio, [], true) + OS.execute(Global.ffmpeg_path, ffmpeg_execute_audio, [], true) if FileAccess.file_exists(output_audio_file): open_audio_file(output_audio_file) temp_dir.remove("audio.mp3") @@ -448,6 +448,14 @@ func save_pxo_file( zip_packer.start_file(tileset_path.path_join(str(j))) zip_packer.write_file(tile.image.get_data()) zip_packer.close_file() + var audio_layers := project.get_all_audio_layers() + for i in audio_layers.size(): + var layer := audio_layers[i] + var audio_path := "audio/%s" % i + if layer.audio is AudioStreamMP3: + zip_packer.start_file(audio_path) + zip_packer.write_file(layer.audio.data) + zip_packer.close_file() zip_packer.close() if temp_path != path: @@ -914,7 +922,6 @@ func set_new_imported_tab(project: Project, path: String) -> void: func open_audio_file(path: String) -> void: var audio_stream: AudioStream - var file_ext := path.get_extension().to_lower() var file := FileAccess.open(path, FileAccess.READ) audio_stream = AudioStreamMP3.new() audio_stream.data = file.get_buffer(file.get_length()) diff --git a/src/Classes/Layers/AudioLayer.gd b/src/Classes/Layers/AudioLayer.gd index b1da55b0a..2bf49607d 100644 --- a/src/Classes/Layers/AudioLayer.gd +++ b/src/Classes/Layers/AudioLayer.gd @@ -26,14 +26,26 @@ func get_audio_length() -> float: return -1.0 +func get_audio_type() -> String: + if not is_instance_valid(audio): + return "" + return audio.get_class() + + # Overridden Methods: func serialize() -> Dictionary: - var data := {"name": name, "type": get_layer_type()} + var data := { + "name": name, + "type": get_layer_type(), + "playback_frame": playback_frame, + "audio_type": get_audio_type() + } return data func deserialize(dict: Dictionary) -> void: super.deserialize(dict) + playback_frame = dict.get("playback_frame", playback_frame) func get_layer_type() -> int: diff --git a/src/Classes/Project.gd b/src/Classes/Project.gd index 438401031..fcec8ee2a 100644 --- a/src/Classes/Project.gd +++ b/src/Classes/Project.gd @@ -360,6 +360,7 @@ func deserialize(dict: Dictionary, zip_reader: ZIPReader = null, file: FileAcces tileset.deserialize(saved_tileset) tilesets.append(tileset) if dict.has("frames") and dict.has("layers"): + var audio_layers := 0 for saved_layer in dict.layers: match int(saved_layer.get("type", Global.LayerTypes.PIXEL)): Global.LayerTypes.PIXEL: @@ -370,6 +371,18 @@ func deserialize(dict: Dictionary, zip_reader: ZIPReader = null, file: FileAcces layers.append(Layer3D.new(self)) Global.LayerTypes.TILEMAP: layers.append(LayerTileMap.new(self, null)) + Global.LayerTypes.AUDIO: + var layer := AudioLayer.new(self) + var audio_path := "audio/%s" % audio_layers + if zip_reader.file_exists(audio_path): + var audio_data := zip_reader.read_file(audio_path) + var stream: AudioStream + if saved_layer.get("audio_type", "") == "AudioStreamMP3": + stream = AudioStreamMP3.new() + stream.data = audio_data + layer.audio = stream + layers.append(layer) + audio_layers += 1 var frame_i := 0 for frame in dict.frames: @@ -394,6 +407,8 @@ func deserialize(dict: Dictionary, zip_reader: ZIPReader = null, file: FileAcces var tileset := tilesets[tileset_index] var new_cel := CelTileMap.new(tileset, image) cels.append(new_cel) + Global.LayerTypes.AUDIO: + cels.append(AudioCel.new()) cel["pxo_version"] = pxo_version cels[cel_i].deserialize(cel) _deserialize_metadata(cels[cel_i], cel) @@ -662,6 +677,18 @@ func get_all_pixel_cels() -> Array[PixelCel]: return cels +func get_all_audio_layers(only_valid_streams := true) -> Array[AudioLayer]: + var audio_layers: Array[AudioLayer] + for layer in layers: + if layer is AudioLayer: + if only_valid_streams: + if is_instance_valid(layer.audio): + audio_layers.append(layer) + else: + audio_layers.append(layer) + return audio_layers + + ## Reads data from [param cels] and appends them to [param data], ## to be used for the undo/redo system. ## It adds data such as the images of [PixelCel]s,