Skip to content

Commit

Permalink
Add enable button for spectrum analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
bakana808 committed Jul 9, 2024
1 parent 262af8b commit d18ae00
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 104 deletions.
51 changes: 25 additions & 26 deletions project/audio_spectrum.gd
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,36 @@ enum Type {BAR, CIRCLE}

@export_range(0.0, 1.0) var spectrum_smoothing: float = 0.5

var spectrum_analyzer: AudioEffectSpectrumAnalyzerInstance
var main: M8SceneDisplay

var last_peaks := []

func _fft(from_hz: float, to_hz: float) -> float:
var magnitude := spectrum_analyzer.get_magnitude_for_frequency_range(
from_hz,
to_hz,
AudioEffectSpectrumAnalyzerInstance.MAGNITUDE_MAX
).length()
return clamp(magnitude, 0, 1)

func _ready():
func _ready() -> void:
last_peaks.resize(spectrum_res)
last_peaks.fill(0.0)
spectrum_analyzer = AudioServer.get_bus_effect_instance(1, 0)

func _process(_delta):
func init(p_main: M8SceneDisplay) -> void:
main = p_main

func _process(_delta: float) -> void:
if visible:
print("drawing spectrum")
queue_redraw()

func _draw():
func _draw() -> void:
if !main.audio_is_spectrum_analyzer_enabled(): return

var bar_width := spectrum_width / spectrum_res
var logspace = logrange(spectrum_freq_min, spectrum_freq_max, spectrum_res + 1)
var logspace := logrange(spectrum_freq_min, spectrum_freq_max, spectrum_res + 1)

var polygon_points = []
var polygon_points := []

for i in range(logspace.size() - 1):

var magnitude = _fft(logspace[i], logspace[i + 1])
var height = clamp((spectrum_db_min + linear_to_db(magnitude)) / spectrum_db_min, 0.0, 1.0) * spectrum_height
var magnitude := main.audio_fft(logspace[i], logspace[i + 1])
var height: float = clamp((spectrum_db_min + linear_to_db(magnitude)) / spectrum_db_min, 0.0, 1.0) * spectrum_height

# var height_avg = max(height, lerp(height, last_peaks[i], spectrum_smoothing))
var height_avg = lerp(height, last_peaks[i], spectrum_smoothing)
var height_avg: float = lerp(height, last_peaks[i], spectrum_smoothing)
last_peaks[i] = height_avg

if type == Type.BAR:
Expand All @@ -72,7 +67,9 @@ func _draw():
# polygon_points[0].y = 0
if mirror:
# polygon_points[- 1].y = 0
var mirrored_points = polygon_points.map(func(vec: Vector2): return vec.reflect(Vector2.UP))
var mirrored_points := polygon_points.map(func(vec: Vector2) -> Vector2:
return vec.reflect(Vector2.UP)
)
polygon_points.reverse()
polygon_points.append_array(mirrored_points)
# for point in polygon_points:
Expand All @@ -87,7 +84,9 @@ func _draw():

if type == Type.CIRCLE:
# add mirrored points to polygon
var mirrored_points = polygon_points.map(func(vec: Vector2): return vec.reflect(Vector2.UP))
var mirrored_points := polygon_points.map(func(vec: Vector2) -> Vector2:
return vec.reflect(Vector2.UP)
)
mirrored_points.reverse()
mirrored_points.pop_back()
mirrored_points.pop_front()
Expand All @@ -96,12 +95,12 @@ func _draw():
draw_colored_polygon(polygon_points, Color.WHITE)
# draw_polyline(polygon_points, Color.WHITE, 4, true)

func logrange(a, b, step) -> Array:
var pow_a = log(a) / log(10) # convert to 10^a form
var pow_b = log(b) / log(10) # convert to 10^b form
var d = (pow_b - pow_a) / float(step)
func logrange(a: float, b: float, step: float) -> Array:
var pow_a := log(a) / log(10) # convert to 10^a form
var pow_b := log(b) / log(10) # convert to 10^b form
var d := (pow_b - pow_a) / float(step)

var logspace = []
var logspace := []

for i in range(step):
logspace.append(pow(10, pow_a + (i * d)))
Expand Down
1 change: 1 addition & 0 deletions project/config_file.gd
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var version: int = 0
@export var crt_filter := false

# visualizer settings
@export var audio_analyzer_enabled := false
@export var audio_analyzer_min_freq: int = 800
@export var audio_analyzer_max_freq: int = 1200
@export var audio_to_brightness := 0.1
Expand Down
2 changes: 1 addition & 1 deletion project/default_bus_layout.tres
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ bus/1/bypass_fx = false
bus/1/volume_db = 0.0
bus/1/send = &"Master"
bus/1/effect/0/effect = SubResource("AudioEffectSpectrumAnalyzer_e5840")
bus/1/effect/0/enabled = true
bus/1/effect/0/enabled = false
99 changes: 58 additions & 41 deletions project/main.gd
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func m8_audio_connect(device: String) -> void:

if is_audio_connecting: return
is_audio_connecting = true
AudioServer.set_bus_mute(0, true)
audio_set_muted(true)

# if audio_monitor and is_instance_valid(audio_monitor):
# audio_monitor.stream = null
Expand All @@ -228,7 +228,7 @@ func m8_audio_connect(device: String) -> void:
audio_monitor.playing = true
m8_audio_connected = true
is_audio_connecting = false
AudioServer.set_bus_mute(0, false)
audio_set_muted(false)

current_audio_device = device
print("audio: connected to device %s" % device)
Expand Down Expand Up @@ -340,61 +340,38 @@ func m8_send_keyjazz(note: int, velocity: int) -> void:
func m8_send_control(keys: int) -> void:
m8_client.send_input(keys)

func m8_is_key_pressed(bit: int) -> bool:
return m8_keystate&bit

func audio_get_level() -> float:
return audio_level

func audio_get_spectrum_analyzer() -> AudioEffectSpectrumAnalyzerInstance:
return AudioServer.get_bus_effect_instance(1, 0)

func audio_set_spectrum_analyzer_enabled(enabled: bool) -> void:
AudioServer.set_bus_effect_enabled(1, 0, enabled)

func audio_is_spectrum_analyzer_enabled() -> bool:
return AudioServer.is_bus_effect_enabled(1, 0)

func audio_set_muted(muted: bool) -> void:
AudioServer.set_bus_mute(0, muted)

func audio_set_volume(volume_db: float) -> void:
AudioServer.set_bus_volume_db(0, volume_db)

func audio_fft(from_hz: float, to_hz: float) -> float:
var magnitude := audio_get_spectrum_analyzer().get_magnitude_for_frequency_range(
from_hz,
to_hz,
AudioEffectSpectrumAnalyzerInstance.MAGNITUDE_AVERAGE
)
return (magnitude.x + magnitude.y) / 2.0

func m8_is_key_pressed(bit: int) -> bool:
return m8_keystate&bit

func _physics_process(delta: float) -> void:

# calculate peaks for visualizations

# var audio_peak_raw = linear_to_db(audio_fft(1000, 2000) * 100.0)
var audio_peak_raw := audio_fft(visualizer_frequency_min, visualizer_frequency_max)
if is_nan(audio_peak_raw) or is_inf(audio_peak_raw):
audio_peak_raw = 0.0

# calculate ranges for audio level
# var audio_peak_raw = (AudioServer.get_bus_peak_volume_left_db(1, 0) + AudioServer.get_bus_peak_volume_right_db(1, 0)) / 2.0
audio_peak = max(audio_peak_raw, lerp(audio_peak_raw, last_peak, 0.70))

# if audio_peak_max_timer.time_left == 0.0:
audio_peak_max = lerp(audio_peak_raw, last_peak_max, 0.90)

if audio_peak_max < audio_peak_raw:
audio_peak_max = audio_peak_raw

last_peak = audio_peak
last_peak_max = audio_peak_max

# convert range from (audio_peak_raw, audio_peak_max) to (0, 1) and apply smoothing
# audio_level = pow(clamp(db_to_linear(audio_peak), 0.0, 1.0), 2)
audio_level_raw = clamp((audio_peak - audio_peak_raw) / (audio_peak_max - audio_peak_raw), 0.0, 1.0)
if is_nan(audio_level_raw):
audio_level_raw = 0.0
audio_level = max(audio_level_raw, lerp(audio_level_raw, last_audio_level, 0.95))
last_audio_level = audio_level

%LabelAudioPeak.text = "%06f" % audio_peak_raw
%LabelAudioPeakAvg.text = "%06f" % audio_peak
%LabelAudioPeakMax.text = "%06f" % audio_peak_max
%LabelAudioLevel.text = "%06f" % audio_level
update_audio_analyzer()

%RectAudioLevel.size.x = (audio_level_raw) * 200
%RectAudioLevelAvg.position.x = (audio_level) * 200.0 + 88.0

# do shader parameter responses to audio

var material_crt_filter: ShaderMaterial = %CRTShader.material
Expand Down Expand Up @@ -452,6 +429,46 @@ func _process(_delta: float) -> void:

if Input.is_action_just_pressed("force_read"): m8_client.update_texture()

func update_audio_analyzer() -> void:

if !audio_is_spectrum_analyzer_enabled():
audio_level = 0.0
return

# calculate peaks for visualizations

# var audio_peak_raw = linear_to_db(audio_fft(1000, 2000) * 100.0)
var audio_peak_raw := audio_fft(visualizer_frequency_min, visualizer_frequency_max)
if is_nan(audio_peak_raw) or is_inf(audio_peak_raw):
audio_peak_raw = 0.0

# calculate ranges for audio level
audio_peak = max(audio_peak_raw, lerp(audio_peak_raw, last_peak, 0.70))

# if audio_peak_max_timer.time_left == 0.0:
audio_peak_max = lerp(audio_peak_raw, last_peak_max, 0.90)

if audio_peak_max < audio_peak_raw:
audio_peak_max = audio_peak_raw

last_peak = audio_peak
last_peak_max = audio_peak_max

# convert range from (audio_peak_raw, audio_peak_max) to (0, 1) and apply smoothing
audio_level_raw = clamp((audio_peak - audio_peak_raw) / (audio_peak_max - audio_peak_raw), 0.0, 1.0)
if is_nan(audio_level_raw):
audio_level_raw = 0.0
audio_level = max(audio_level_raw, lerp(audio_level_raw, last_audio_level, 0.95))
last_audio_level = audio_level

%LabelAudioPeak.text = "%06f" % audio_peak_raw
%LabelAudioPeakAvg.text = "%06f" % audio_peak
%LabelAudioPeakMax.text = "%06f" % audio_peak_max
%LabelAudioLevel.text = "%06f" % audio_level

%RectAudioLevel.size.x = (audio_level_raw) * 200
%RectAudioLevelAvg.position.x = (audio_level) * 200.0 + 88.0

func update_keystate(keystate: int, write: bool=false) -> void:

if keystate != m8_keystate_last:
Expand Down
7 changes: 1 addition & 6 deletions project/main.tscn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[gd_scene load_steps=22 format=3 uid="uid://b265ke8cr3dgr"]
[gd_scene load_steps=21 format=3 uid="uid://b265ke8cr3dgr"]

[ext_resource type="Script" path="res://main.gd" id="1_4g2n0"]
[ext_resource type="Shader" path="res://shaders/post_process.gdshader" id="1_tjung"]
Expand Down Expand Up @@ -129,9 +129,6 @@ corner_radius_bottom_left = 8
corner_detail = 4
anti_aliasing_size = 0.5

[sub_resource type="CompressedTexture2D" id="CompressedTexture2D_n5fsj"]
load_path = "res://.godot/imported/splash_logo.png-bc4fafe7056a0f6fe87f3c5574907244.ctex"

[node name="Main" type="Node"]
script = ExtResource("1_4g2n0")

Expand Down Expand Up @@ -438,8 +435,6 @@ offset_top = -4.0
offset_right = 159.0
offset_bottom = 111.0
scale = Vector2(2, 2)
texture = SubResource("CompressedTexture2D_n5fsj")
stretch_mode = 6

[node name="RichTextLabel" type="RichTextLabel" parent="UI/SplashContainer/PanelContainer/MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(320, 0)
Expand Down
65 changes: 37 additions & 28 deletions project/main_menu.gd
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ func init(p_main: M8SceneDisplay) -> void:
main.reload_scene()
)

# Audio settings
# Audio Tab
#--------------------------------------------------------------------------

# volume

slider_volume.value_changed.connect(func(value: float) -> void:
var volume_db: float=linear_to_db(pow(value, 2))
print("volume = %f" % volume_db)
AudioServer.set_bus_volume_db(0, volume_db)
main.audio_set_volume(volume_db)
%LabelVolume.text="%d%% (%05.2f dB)" % [round(slider_volume.value / slider_volume.max_value * 100), volume_db]
config.volume=value
)
Expand Down Expand Up @@ -101,6 +101,41 @@ func init(p_main: M8SceneDisplay) -> void:
%LineEditAudioLatency.placeholder_text="%f ms" % AudioServer.get_output_latency()
)

%CheckButtonEnableSA.toggled.connect(func(toggled_on: bool) -> void:
main.audio_set_spectrum_analyzer_enabled(toggled_on)
config.audio_analyzer_enabled=toggled_on
)
%CheckButtonEnableSA.button_pressed = config.audio_analyzer_enabled

%SpinBoxAVMinFreq.value_changed.connect(func(value: int) -> void:
main.visualizer_frequency_min=value
config.audio_analyzer_min_freq=value
)
%SpinBoxAVMinFreq.value = config.audio_analyzer_min_freq

%SpinBoxAVMaxFreq.value_changed.connect(func(value: int) -> void:
main.visualizer_frequency_max=value
config.audio_analyzer_max_freq=value
)
%SpinBoxAVMaxFreq.value = config.audio_analyzer_max_freq

%SliderAVBrightness.value_changed.connect(func(value: float) -> void:
main.visualizer_brightness_amount=value
%LabelAVBrightness.text="%d%%" % (value * 100.0)
config.audio_to_brightness=value
)
%SliderAVBrightness.value = config.audio_to_brightness

%SliderAVCA.value_changed.connect(func(value: float) -> void:
main.visualizer_ca_amount=value
%LabelAVCA.text="%d%%" % (value * 1000.0)
config.audio_to_ca=value
)
%SliderAVCA.value = config.audio_to_ca

# Video Tab
#--------------------------------------------------------------------------

# video

%CheckButtonFullscreen.toggled.connect(func(toggled_on: bool) -> void:
Expand Down Expand Up @@ -240,32 +275,6 @@ func init(p_main: M8SceneDisplay) -> void:
)
%CheckButtonFilter5.button_pressed = config.crt_filter

%SpinBoxAVMinFreq.value_changed.connect(func(value: int) -> void:
main.visualizer_frequency_min=value
config.audio_analyzer_min_freq=value
)
%SpinBoxAVMinFreq.value = config.audio_analyzer_min_freq

%SpinBoxAVMaxFreq.value_changed.connect(func(value: int) -> void:
main.visualizer_frequency_max=value
config.audio_analyzer_max_freq=value
)
%SpinBoxAVMaxFreq.value = config.audio_analyzer_max_freq

%SliderAVBrightness.value_changed.connect(func(value: float) -> void:
main.visualizer_brightness_amount=value
%LabelAVBrightness.text="%d%%" % (value * 100.0)
config.audio_to_brightness=value
)
%SliderAVBrightness.value = config.audio_to_brightness

%SliderAVCA.value_changed.connect(func(value: float) -> void:
main.visualizer_ca_amount=value
%LabelAVCA.text="%d%%" % (value * 1000.0)
config.audio_to_ca=value
)
%SliderAVCA.value = config.audio_to_ca

# Keybindings
# --------------------------------------------------------------------

Expand Down
Loading

0 comments on commit d18ae00

Please sign in to comment.