show_spectrum.gd 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. extends Node2D
  2. const VU_COUNT = 16
  3. const FREQ_MAX = 11050.0
  4. const WIDTH = 800
  5. const HEIGHT = 250
  6. const HEIGHT_SCALE = 8.0
  7. const MIN_DB = 60
  8. const ANIMATION_SPEED = 0.1
  9. var spectrum: AudioEffectSpectrumAnalyzerInstance
  10. var min_values: Array[float] = []
  11. var max_values: Array[float] = []
  12. func _draw() -> void:
  13. @warning_ignore("integer_division")
  14. var w := WIDTH / VU_COUNT
  15. for i in VU_COUNT:
  16. var min_height = min_values[i]
  17. var max_height = max_values[i]
  18. var height = lerp(min_height, max_height, ANIMATION_SPEED)
  19. draw_rect(
  20. Rect2(w * i, HEIGHT - height, w - 2, height),
  21. Color.from_hsv(float(VU_COUNT * 0.6 + i * 0.5) / VU_COUNT, 0.5, 0.6)
  22. )
  23. draw_line(
  24. Vector2(w * i, HEIGHT - height),
  25. Vector2(w * i + w - 2, HEIGHT - height),
  26. Color.from_hsv(float(VU_COUNT * 0.6 + i * 0.5) / VU_COUNT, 0.5, 1.0),
  27. 2.0,
  28. true
  29. )
  30. # Draw a reflection of the bars with lower opacity.
  31. draw_rect(
  32. Rect2(w * i, HEIGHT, w - 2, height),
  33. Color.from_hsv(float(VU_COUNT * 0.6 + i * 0.5) / VU_COUNT, 0.5, 0.6) * Color(1, 1, 1, 0.125)
  34. )
  35. draw_line(
  36. Vector2(w * i, HEIGHT + height),
  37. Vector2(w * i + w - 2, HEIGHT + height),
  38. Color.from_hsv(float(VU_COUNT * 0.6 + i * 0.5) / VU_COUNT, 0.5, 1.0) * Color(1, 1, 1, 0.125),
  39. 2.0,
  40. true
  41. )
  42. func _process(_delta: float) -> void:
  43. var data: Array[float] = []
  44. var prev_hz := 0.0
  45. for i in range(1, VU_COUNT + 1):
  46. var hz := i * FREQ_MAX / VU_COUNT
  47. var magnitude := spectrum.get_magnitude_for_frequency_range(prev_hz, hz).length()
  48. var energy := clampf((MIN_DB + linear_to_db(magnitude)) / MIN_DB, 0, 1)
  49. var height := energy * HEIGHT * HEIGHT_SCALE
  50. data.append(height)
  51. prev_hz = hz
  52. for i in VU_COUNT:
  53. if data[i] > max_values[i]:
  54. max_values[i] = data[i]
  55. else:
  56. max_values[i] = lerpf(max_values[i], data[i], ANIMATION_SPEED)
  57. if data[i] <= 0.0:
  58. min_values[i] = lerpf(min_values[i], 0.0, ANIMATION_SPEED)
  59. # Sound plays back continuously, so the graph needs to be updated every frame.
  60. queue_redraw()
  61. func _ready() -> void:
  62. spectrum = AudioServer.get_bus_effect_instance(0, 0)
  63. min_values.resize(VU_COUNT)
  64. max_values.resize(VU_COUNT)
  65. min_values.fill(0.0)
  66. max_values.fill(0.0)