audioplayer.gd 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. extends Control
  2. @onready var audio_player = $AudioStreamPlayer
  3. @onready var file_dialog = $FileDialog
  4. @onready var waveform_display = $WaveformPreview
  5. var outfile_path = "not_loaded"
  6. var rect_focus = false
  7. var mouse_pos_x
  8. #Used for waveform preview
  9. var voice_preview_generator : Node = null
  10. var stream : AudioStreamWAV = null
  11. var autoplay
  12. signal setnodetitle
  13. func _ready():
  14. #Setup file dialogue to access system files and only accept wav files
  15. #get_window().files_dropped.connect(_on_files_dropped)
  16. file_dialog.access = FileDialog.ACCESS_FILESYSTEM
  17. file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE
  18. file_dialog.filters = ["*.wav ; WAV audio files"]
  19. file_dialog.connect("file_selected", Callable(self, "_on_file_selected"))
  20. audio_player.connect("finished", Callable(self, "_on_audio_finished"))
  21. if get_meta("loadenable") == false:
  22. #$PlayButton.size.x = 192
  23. #$PlayButton.position.x = 208
  24. $PlayButton.size.x = $Panel.size.x
  25. $PlayButton.position.x = $LoadButton.position.x
  26. $LoadButton.hide()
  27. $RecycleButton.hide()
  28. #else:
  29. #$Autoplay.hide()
  30. $WavError.hide()
  31. # Load the voice preview generator for waveform visualization
  32. voice_preview_generator = preload("res://addons/audio_preview/voice_preview_generator.tscn").instantiate()
  33. add_child(voice_preview_generator)
  34. voice_preview_generator.texture_ready.connect(_on_texture_ready)
  35. #setup meta to say the player is empty and no trim points have been set
  36. set_meta("trimfile", false)
  37. #func _on_files_dropped(files):
  38. #if files[0].get_extension() == "wav" or files[0].get_extension() == "WAV":
  39. #audio_player.stream = AudioStreamWAV.load_from_file(files[0])
  40. #if audio_player.stream.stereo == true: #checks if stream is stereo, not sure what this will do with a surround sound file
  41. #audio_player.stream = null #empties audio stream so stereo audio cant be played back
  42. #$WavError.show()
  43. #else:
  44. #voice_preview_generator.generate_preview(audio_player.stream) #this generates the waveform graphic
  45. #Global.infile = files[0] #this sets the global infile variable to the audio file path
  46. #print(Global.infile)
  47. #else:
  48. #$WavError.show()
  49. func _on_close_button_button_down() -> void:
  50. $WavError.hide()
  51. func _on_load_button_button_down() -> void:
  52. file_dialog.popup_centered()
  53. func _on_file_selected(path: String):
  54. audio_player.stream = AudioStreamWAV.load_from_file(path, {
  55. "compress/mode" = 0,
  56. "edit/loop_mode" = 1})
  57. voice_preview_generator.generate_preview(audio_player.stream)
  58. if audio_player.stream != null:
  59. var length = convert_length(audio_player.stream.get_length())
  60. $EndLabel.text = length
  61. setnodetitle.emit(path.get_file())
  62. else:
  63. $EndLabel.text = "00:00.00"
  64. set_meta("inputfile", path)
  65. reset_playback()
  66. #output signal that the input has loaded and it is safe to continue with running thread
  67. #Used for preview nodes in run_thread to avoid deleting the input file before it is done loading
  68. func reset_playback():
  69. $LoopRegion.size.x = 0
  70. $Playhead.position.x = 0
  71. $PlayButton.text = "Play"
  72. $Timer.stop()
  73. if get_meta("loadenable") == true:
  74. set_meta("timefile", false)
  75. func play_outfile(path: String):
  76. outfile_path = path
  77. audio_player.stream = AudioStreamWAV.load_from_file(path, {
  78. "compress/mode" = 0,
  79. "edit/loop_mode" = 1})
  80. print(audio_player.stream)
  81. if audio_player.stream == null:
  82. voice_preview_generator._reset_to_blank()
  83. reset_playback()
  84. return
  85. await voice_preview_generator.generate_preview(audio_player.stream)
  86. if audio_player.stream != null:
  87. var length = convert_length(audio_player.stream.get_length())
  88. $EndLabel.text = length
  89. else:
  90. $EndLabel.text = "00:00.00"
  91. reset_playback()
  92. if autoplay == true:
  93. _on_play_button_button_down()
  94. func recycle_outfile():
  95. print("recycle pressed")
  96. print(Global.cdpoutput)
  97. if Global.cdpoutput != "no_file":
  98. _on_file_selected(Global.cdpoutput)
  99. func _on_play_button_button_down() -> void:
  100. var playhead_position
  101. #check if trim markers are set and set playhead position to correct location
  102. if $LoopRegion.size.x == 0:
  103. playhead_position = 0
  104. else:
  105. playhead_position = $LoopRegion.position.x
  106. $Playhead.position.x = playhead_position
  107. #check if audio is playing, to decide if this is a play or stop button
  108. if audio_player.stream:
  109. if audio_player.playing:
  110. audio_player.stop()
  111. $Timer.stop()
  112. $PlayButton.text = "Play"
  113. else:
  114. $PlayButton.text = "Stop"
  115. if $LoopRegion.size.x == 0: #loop position is not set, play from start of file
  116. audio_player.play()
  117. else:
  118. var length = $AudioStreamPlayer.stream.get_length()
  119. var pixel_to_time = length / 399
  120. audio_player.play(pixel_to_time * $LoopRegion.position.x)
  121. if $LoopRegion.position.x + $LoopRegion.size.x < 399:
  122. $Timer.start(pixel_to_time * $LoopRegion.size.x)
  123. #timer for ending playback at end of loop
  124. func _on_timer_timeout() -> void:
  125. _on_play_button_button_down() #"press" stop button
  126. func _on_audio_finished():
  127. $PlayButton.text = "Play"
  128. # This function will be called when the waveform texture is ready
  129. func _on_texture_ready(image_texture: ImageTexture):
  130. # Set the generated texture to the TextureRect (waveform display node)
  131. waveform_display.texture = image_texture
  132. # Called every frame. 'delta' is the elapsed time since the previous frame.
  133. func _process(delta: float) -> void:
  134. if $AudioStreamPlayer.playing:
  135. var length = $AudioStreamPlayer.stream.get_length()
  136. var total_distance = 399.0
  137. var speed = total_distance / length
  138. $Playhead.position.x += speed * delta
  139. if $Playhead.position.x >= 399:
  140. $Playhead.position.x = 0
  141. if rect_focus == true:
  142. if get_local_mouse_position().x > mouse_pos_x:
  143. $LoopRegion.size.x = clamp(get_local_mouse_position().x - mouse_pos_x, 0, $Panel.size.x - (mouse_pos_x - $Panel.position.x))
  144. else:
  145. $LoopRegion.size.x = clamp(mouse_pos_x - get_local_mouse_position().x, 0, (mouse_pos_x - $Panel.position.x))
  146. $LoopRegion.position.x = clamp(get_local_mouse_position().x, $Panel.position.x, $Panel.position.x + $Panel.size.x)
  147. #func _on_recycle_button_button_down() -> void:
  148. #if outfile_path != "not_loaded":
  149. #recycle_outfile_trigger.emit(outfile_path)
  150. func _on_button_button_down() -> void:
  151. if audio_player.stream:
  152. if audio_player.playing: #if audio is playing allow user to skip around the sound file
  153. $Timer.stop()
  154. var length = $AudioStreamPlayer.stream.get_length()
  155. var pixel_to_time = length / 399
  156. $Playhead.position.x = get_local_mouse_position().x
  157. if $LoopRegion.size.x == 0 or get_local_mouse_position().x > $LoopRegion.position.x + $LoopRegion.size.x: #loop position is not set or click is after loop position, play to end of file
  158. audio_player.seek(pixel_to_time * get_local_mouse_position().x)
  159. else: #if click position is before the loop position play from there and stop at the end of the loop position
  160. audio_player.seek(pixel_to_time * get_local_mouse_position().x)
  161. if $LoopRegion.position.x + $LoopRegion.size.x < 399:
  162. $Timer.start(pixel_to_time * ($LoopRegion.position.x + $LoopRegion.size.x - get_local_mouse_position().x))
  163. else:
  164. mouse_pos_x = get_local_mouse_position().x
  165. $LoopRegion.position.x = mouse_pos_x
  166. rect_focus = true
  167. func _on_button_button_up() -> void:
  168. rect_focus = false
  169. if get_meta("loadenable") == true:
  170. if $LoopRegion.size.x > 0:
  171. set_meta("trimfile", true)
  172. var length = $AudioStreamPlayer.stream.get_length()
  173. var pixel_to_time = length / 399
  174. var start = pixel_to_time * $LoopRegion.position.x
  175. var starttime = convert_length(start)
  176. $StartLabel.text = starttime
  177. var end = start + (pixel_to_time * $LoopRegion.size.x)
  178. var endtime = convert_length(end)
  179. $EndLabel.text = endtime
  180. set_meta("trimpoints", [start, end])
  181. else:
  182. set_meta("trimfile", false)
  183. $StartLabel.text = "00:00.00"
  184. var end = convert_length($AudioStreamPlayer.stream.get_length())
  185. $EndLabel.text = end
  186. func convert_length(reportedseconds: float) -> String:
  187. var converted_length = reportedseconds
  188. var hours
  189. var minutes
  190. var seconds = int(reportedseconds) % 60
  191. seconds = seconds + (reportedseconds - int(reportedseconds))
  192. if reportedseconds > 3600:
  193. hours = reportedseconds / 3600
  194. minutes = (int(reportedseconds) % 3600) / 60
  195. converted_length = "%.0f:%02.0f:%05.2f" % [hours, minutes, seconds, 0.01]
  196. else:
  197. minutes = int((int(reportedseconds) % 3600) / 60)
  198. converted_length = "%02.0f:%05.2f" % [minutes, seconds]
  199. return converted_length