bpm_sync.gd 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. extends Panel
  2. enum SyncSource {
  3. SYSTEM_CLOCK,
  4. SOUND_CLOCK,
  5. }
  6. const BPM = 116
  7. const BARS = 4
  8. const COMPENSATE_FRAMES = 2
  9. const COMPENSATE_HZ = 60.0
  10. var playing := false
  11. var sync_source := SyncSource.SYSTEM_CLOCK
  12. # Used by system clock.
  13. var time_begin: float
  14. var time_delay: float
  15. func _process(_delta: float) -> void:
  16. if not playing or not $Player.playing:
  17. return
  18. var time := 0.0
  19. if sync_source == SyncSource.SYSTEM_CLOCK:
  20. # Obtain from ticks.
  21. time = (Time.get_ticks_usec() - time_begin) / 1000000.0
  22. # Compensate.
  23. time -= time_delay
  24. elif sync_source == SyncSource.SOUND_CLOCK:
  25. time = $Player.get_playback_position() + AudioServer.get_time_since_last_mix() - AudioServer.get_output_latency() + (1 / COMPENSATE_HZ) * COMPENSATE_FRAMES
  26. var beat := int(time * BPM / 60.0)
  27. var seconds := int(time)
  28. var seconds_total := int($Player.stream.get_length())
  29. @warning_ignore("integer_division")
  30. $Label.text = str("BEAT: ", beat % BARS + 1, "/", BARS, " TIME: ", seconds / 60, ":", str(seconds % 60).pad_zeros(2), " / ", seconds_total / 60, ":", str(seconds_total % 60).pad_zeros(2))
  31. func _on_PlaySystem_pressed() -> void:
  32. sync_source = SyncSource.SYSTEM_CLOCK
  33. time_begin = Time.get_ticks_usec()
  34. time_delay = AudioServer.get_time_to_next_mix() + AudioServer.get_output_latency()
  35. playing = true
  36. $Player.play()
  37. func _on_PlaySound_pressed() -> void:
  38. sync_source = SyncSource.SOUND_CLOCK
  39. playing = true
  40. $Player.play()