### Project Structure Setup for FMOD GDExtension Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/advanced/1-compiling.md Defines the required directory hierarchy for FMOD GDExtension project setup, showing where to place FMOD libraries for different platforms and the relationship between the main project and plugin components. ```Text └── Project root ├── libs | └── fmod | └── {platform} | └── specific platform fmod api goes here └── fmod-gdextension (this repo, consider using it as a submodule of you GDExtensions repo) ├── CMakeLists.txt (Here for CLion) ├── LICENSE ├── README.md ├── SConstruct (here to build on Windows, Linux, OSX and IOS ├── godot-cpp (gdextension bindings, submodule) └── src ``` -------------------------------- ### Profile FMOD Performance Data Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/8-other-low-level-examples.md Demonstrates how to retrieve and print FMOD performance data, including CPU, memory, and file streaming usage for both FMOD Studio and the Core System. The `get_performance_data()` function is called, typically every frame, to get the latest stats. ```gdscript # called every frame var perf_data = FmodServer.get_performance_data() print(perf_data.CPU) print(perf_data.memory) print(perf_data.file) ``` -------------------------------- ### Basic SCons Build Command Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/advanced/1-compiling.md Standard SCons compilation command for building FMOD GDExtension with platform and target specifications, supporting multiple platforms and debug/release configurations. ```Shell scons platform= target= debug_symbols --jobs= ``` -------------------------------- ### Control FmodEvent Instance Playback Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt This example shows how to create, control, and clean up FMOD event instances. It covers setting 2D attributes, parameters, volume, pitch, starting playback, handling pause/resume, updating attributes per frame, checking playback state, and stopping/releasing the event. Dependencies: FmodServer, FmodEvent. ```gdscript extends Sprite2D var event: FmodEvent = null var isPlaying: bool = true func _ready(): # Create event instance event = FmodServer.create_event_instance("event:/Vehicles/Car Engine") # Set initial position and parameters event.set_2d_attributes(self.global_transform) event.set_parameter_by_name("RPM", 600) event.set_volume(2.0) event.set_pitch(1.0) # Start playback event.start() # Alternative: create from GUID var event_by_guid = FmodServer.create_event_instance_with_guid( "{9aa2ecc5-ea4b-4ebe-85c3-054b11b21dcd}" ) func _process(_delta): # Toggle pause if Input.is_action_just_pressed("space"): isPlaying = !isPlaying event.set_paused(!isPlaying) # Update position every frame var time = Time.get_ticks_msec() / 1000.0 self.position.x = 300 * sin(time) event.set_2d_attributes(self.global_transform) # Check playback state var state = event.get_playback_state() if state == FmodServer.FMOD_STUDIO_PLAYBACK_PLAYING: print("Currently playing") # Control parameters by ID var param_desc = FmodServer.get_event("event:/Vehicles/Car Engine").get_parameter_by_name("RPM") event.set_parameter_by_id(param_desc.get_id(), 800.0) func _exit_tree(): # Clean up if event: event.stop(FmodServer.FMOD_STUDIO_STOP_ALLOWFADEOUT) event.release() ``` -------------------------------- ### Custom FMOD Library Directory Build Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/advanced/1-compiling.md Advanced SCons build configuration allowing specification of custom FMOD library directory path, useful when libraries are placed in non-standard locations relative to project root. ```Shell scons platform=windows arch=x86_64 target=editor fmod_lib_dir=libs/ ``` -------------------------------- ### Manage Global FMOD Parameters Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt This example illustrates how to set and get global parameters that affect all FMOD events in the game. It covers setting parameters by name (float and label), updating them over time, retrieving their current values, and listing all available global parameter descriptions. Dependencies: FmodServer. ```gdscript extends Node func _ready(): # Set global parameters by name FmodServer.set_global_parameter_by_name("Time of Day", 12.0) # Noon FmodServer.set_global_parameter_by_name("Combat Intensity", 0.0) # Set with label instead of float FmodServer.set_global_parameter_by_name_with_label("Weather", "Rainy") func _process(_delta): # Update time of day var time = fmod(Time.get_ticks_msec() / 1000.0, 24.0) FmodServer.set_global_parameter_by_name("Time of Day", time) # Get current value var combat_intensity = FmodServer.get_global_parameter_by_name("Combat Intensity") # Increase during combat if is_in_combat(): combat_intensity = min(combat_intensity + 0.1, 100.0) FmodServer.set_global_parameter_by_name("Combat Intensity", combat_intensity) func list_all_parameters(): # Get all global parameter descriptions var param_count = FmodServer.get_global_parameter_desc_count() var param_list = FmodServer.get_global_parameter_desc_list() for param_desc in param_list: var name = param_desc.get_name() var min_val = param_desc.get_minimum() var max_val = param_desc.get_maximum() var default_val = param_desc.get_default_value() print("%s: [%f - %f] default=%f" % [name, min_val, max_val, default_val]) # Check if labeled parameter if param_desc.is_labeled(): var labels = FmodServer.get_event("event:/SomeEvent").get_parameter_labels_by_name(name) print(" Labels: ", labels) func is_in_combat() -> bool: return false # Placeholder ``` -------------------------------- ### Windows SCons Build with Architecture Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/advanced/1-compiling.md Platform-specific SCons build command for Windows requiring architecture parameter (x86_64 or x86_32) and target specification for editor or template builds. ```Shell scons platform=windows arch=x86_64 target=editor ``` -------------------------------- ### Pause and Unpause All FMOD Events Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/8-other-low-level-examples.md Demonstrates pausing all FMOD events with `pause_all_events(true)` and resuming them with `pause_all_events(false)`. This is useful for temporarily stopping all audio playback without stopping individual events. ```gdscript func _ready(): # set up FMOD FmodServer.set_software_format(0, FmodServer.FMOD_SPEAKERMODE_STEREO, 0) FmodServer.init(1024, FmodServer.FMOD_STUDIO_INIT_LIVEUPDATE, FmodServer.FMOD_INIT_NORMAL) FmodServer.set_sound_3d_settings(1/0, 64.0, 1.0) # load banks FmodServer.load_bank("res://Master.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL) FmodServer.load_bank("res://Master.strings.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL) FmodServer.load_bank("res://Music.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL) # register listener FmodServer.add_listener(0, self) # play some events FmodServer.play_one_shot("event:/Music/Level 02", self) var my_music_event = FmodServer.create_event_instance("event:/Music/Level 01") FmodServer.start_event(my_music_event) var t = Timer.new() t.set_wait_time(3) t.set_one_shot(true) self.add_child(t) t.start() yield(t, "timeout") FmodServer.pause_all_events(true) t = Timer.new() t.set_wait_time(3) t.set_one_shot(true) self.add_child(t) t.start() yield(t, "timeout") FmodServer.pause_all_events(false) ``` -------------------------------- ### Load Banks - FmodBankLoader Node Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt Demonstrates using the high-level FmodBankLoader node to load multiple FMOD banks with automatic setup. This approach provides simple bank management for common use cases with minimal code required. ```gdscript extends Node func _ready(): # Create bank loader node var bank_loader = FmodBankLoader.new() bank_loader.bank_paths = [ "res://assets/Banks/Master.strings.bank", "res://assets/Banks/Master.bank", "res://assets/Banks/Music.bank", "res://assets/Banks/Vehicles.bank" ] add_child(bank_loader) # Wait for banks to finish loading await get_tree().create_timer(0.5).timeout if FmodServer.banks_still_loading(): FmodServer.wait_for_all_loads() ``` -------------------------------- ### Reduce Audio Latency with FMOD DSP Buffer Settings Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/8-other-low-level-examples.md Explains how to reduce audio playback latency by adjusting the DSP buffer size before FMOD initialization using `set_dsp_buffer_size()`. It also shows how to retrieve the current DSP buffer length and number of buffers using `get_dsp_buffer_length()` and `get_dsp_num_buffers()` respectively. ```gdscript FmodServer.set_dsp_buffer_size(512, 4) # retrieve the buffer length FmodServer.get_dsp_buffer_length() # retrieve the number of buffers FmodServer.get_dsp_num_buffers() ``` -------------------------------- ### Change Default Audio Output Device using FMOD Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/8-other-low-level-examples.md Shows how to change the default audio output device in FMOD. It involves retrieving available drivers using `get_available_drivers()` and then setting a new driver using its ID with `set_driver()`. The current driver ID can be retrieved with `get_driver()`. ```gdscript # retrieve all available audio drivers var drivers = FmodServer.get_available_drivers() # change the audio driver # you must pass in the id of the respective driver FmodServer.set_driver(id) # retrieve the id of the currently set driver var id = FmodServer.get_driver() ``` -------------------------------- ### Configure FmodListener3D Node Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt This example shows how to set up and configure an FmodListener3D node in a 3D scene. It covers setting the listener index, weight, and lock status, and explains that the listener's position automatically updates when attached to a node, but can be manually controlled if locked. Dependencies: FmodListener3D. ```gdscript extends Node3D @onready var listener: FmodListener3D = $FmodListener3D @onready var player: CharacterBody3D = $Player func _ready(): # Listener properties can be set in editor or code listener.listener_index = 0 # 0-7, up to 8 listeners listener.weight = 1.0 listener.is_locked = false func _process(_delta): # Listener position updates automatically when attached to node # But you can lock it if needed if Input.is_action_just_pressed("lock_listener"): listener.is_locked = !listener.is_locked ``` -------------------------------- ### Mute and Unmute All FMOD Events Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/8-other-low-level-examples.md Demonstrates how to mute all FMOD events using `mute_all_events()` and then unmute them with `unmute_all_events()`. This function mutes the master bus. It's typically used to temporarily silence all audio output. ```gdscript func _ready(): FmodServer.set_software_format(0, FmodServer.FMOD_SPEAKERMODE_STEREO, 0) FmodServer.init(1024, FmodServer.FMOD_STUDIO_INIT_LIVEUPDATE, FmodServer.FMOD_INIT_NORMAL) FmodServer.set_sound_3d_settings(1.0, 64.0, 1.0) # load banks FmodServer.load_bank("res://Master.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL) FmodServer.load_bank("res://Master.strings.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL) FmodServer.load_bank("res://Music.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL) # register listener FmodServer.add_listener(0, self) # play some events FmodServer.play_one_shot("event:/Music/Level 02", self) var my_music_event = FmodServer.create_event_instance("event:/Music/Level 01") FmodServer.start_event(my_music_event) var t = Timer.new() t.set_wait_time(3) t.set_one_shot(true) self.add_child(t) t.start() yield(t, "timeout") FmodServer.mute_all_events(); t = Timer.new() t.set_wait_time(3) t.set_one_shot(true) self.add_child(t) t.start() yield(t, "timeout") FmodServer.unmute_all_events() ``` -------------------------------- ### Set and Get Fmod Event Parameters in GDScript Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/5-playing-events.md Demonstrates how to dynamically adjust Fmod event parameters like 'RPM' using object operators and specific getter/setter methods in GDScript. This is useful for real-time audio adjustments based on game events. ```gdscript extends FmodEventEmitter2D func _process(_delta): if Input.is_action_pressed("engine_power_up"): self["fmod_parameters/RPM"] = self["fmod_parameters/RPM"] + 10 if Input.is_action_pressed("engine_power_down"): self["fmod_parameters/RPM"] = self["fmod_parameters/RPM"] - 10 ``` ```gdscript emitter.set_parameter("RPM", 1000) emitter.set_parameter_by_id(5864137074015534804, 1000) emitter.get_parameter("RPM") emitter.get_parameter_by_id(5864137074015534804) ``` -------------------------------- ### Get FMOD Performance Stats in GDScript Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt Retrieves and prints FMOD performance metrics such as CPU usage, memory consumption, and channel information. This function is typically called within the `_process` loop or on a specific input action. It relies on the `FmodServer` singleton and the `FmodPerformanceData` structure. ```gdscript extends Node func _process(_delta): if Input.is_action_just_pressed("show_performance"): show_performance_stats() func show_performance_stats(): var perf_data: FmodPerformanceData = FmodServer.get_performance_data() # CPU usage print("=== FMOD Performance ===") print("DSP Usage: %.2f%%" % perf_data.dsp_usage) print("Stream Usage: %.2f%%" % perf_data.stream_usage) print("Geometry Usage: %.2f%%" % perf_data.geometry_usage) print("Update Usage: %.2f%%" % perf_data.update_usage) print("Convolution1 Usage: %.2f%%" % perf_data.convolution1_usage) print("Convolution2 Usage: %.2f%%" % perf_data.convolution2_usage) # Memory usage print("Current Memory: %d bytes" % perf_data.current_memory) print("Max Memory: %d bytes" % perf_data.max_memory) # Channel info print("Channels: %d" % perf_data.channels) func get_dsp_buffer_info(): var dsp_settings: FmodDspSettings = FmodServer.get_system_dsp_buffer_settings() var buffer_length = FmodServer.get_system_dsp_buffer_length() var num_buffers = FmodServer.get_system_dsp_num_buffers() print("DSP Buffer Length: ", buffer_length) print("DSP Number of Buffers: ", num_buffers) ``` -------------------------------- ### FMOD Event with Callback and Area Interaction in GDScript Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/5-playing-events.md This GDScript example shows how to create an FMOD event, attach a callback for timeline events, and connect signals for area entry and exit to control event pausing. The callback function dynamically changes the node's color on timeline beats. ```gdscript func _ready(): event = FmodServer.create_event_instance("event:/Music/Level 02") event.set_callback(Callable(self, "change_color"), FmodServer.FMOD_STUDIO_EVENT_CALLBACK_ALL) body_entered.connect(enter) body_exited.connect(leave) event.start() event.paused = true func enter(_area): print("enter") event.paused = false func leave(_area): print("leave") event.paused = true func change_color(_dict: Dictionary, type: int): if type == FmodServer.FMOD_STUDIO_EVENT_CALLBACK_TIMELINE_BEAT: $icon.self_modulate = Color(randf_range(0,1), randf_range(0,1), randf_range(0,1), 1) ``` -------------------------------- ### Configure FMOD Initialization and Audio Settings in GDScript Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt Initializes FMOD with custom audio settings, including software format, 3D sound properties, and DSP buffer configurations. It also lists available audio drivers and selects the default one. This configuration is typically done in the `_ready` function of a node. ```gdscript extends Node func _ready(): configure_fmod() func configure_fmod(): # Software format settings var software_settings = FmodSoftwareFormatSettings.new() software_settings.sample_rate = 48000 software_settings.speaker_mode = FmodServer.FMOD_SPEAKERMODE_STEREO software_settings.num_raw_speakers = 0 FmodServer.set_software_format(software_settings) # 3D settings var sound_3d_settings = FmodSound3DSettings.new() sound_3d_settings.doppler_scale = 1.0 sound_3d_settings.distance_factor = 1.0 sound_3d_settings.rolloff_scale = 1.0 FmodServer.set_sound_3d_settings(sound_3d_settings) # DSP buffer settings var dsp_settings = FmodDspSettings.new() dsp_settings.buffer_length = 512 dsp_settings.num_buffers = 4 FmodServer.set_system_dsp_buffer_size(dsp_settings) # Audio driver selection var drivers = FmodServer.get_available_drivers() print("Available audio drivers:") for i in range(drivers.size()): print(" %d: %s" % [i, drivers[i]]) # Set specific driver FmodServer.set_driver(0) # Initialize FMOD (done automatically by plugin) # var init_settings = FmodGeneralSettings.new() # FmodServer.init(init_settings) func _exit_tree(): # Shutdown handled automatically by plugin # FmodServer.shutdown() ``` -------------------------------- ### Play Sound Files Directly with FMOD Server Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt Illustrates direct sound file playback without FMOD Studio events. Shows loading sounds and music with streaming options, creating sound instances, and controlling playback parameters. Includes proper cleanup procedures for resource management. ```gdscript extends Node var sound_file: FmodFile var sound_instance: FmodSound func _ready(): # Load sound file (not streaming) sound_file = FmodServer.load_file_as_sound("res://assets/Audio/explosion.wav") # Load music file (streaming) var music_file = FmodServer.load_file_as_music("res://assets/Music/menu_music.mp3") func play_sound(): # Create sound instance sound_instance = FmodServer.create_sound_instance("res://assets/Audio/explosion.wav") # Control playback sound_instance.set_volume(0.8) sound_instance.set_pitch(1.2) sound_instance.play() # Check state if sound_instance.is_playing(): print("Sound is playing") func stop_sound(): if sound_instance and sound_instance.is_valid(): sound_instance.stop() sound_instance.release() func _exit_tree(): # Unload file FmodServer.unload_file("res://assets/Audio/explosion.wav") ``` -------------------------------- ### Play Sound with FmodServer in GDScript Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/7-playing-sounds.md This script demonstrates playing an OGG sound file using FmodServer in Godot. It loads the file, creates a sound instance, plays it when a body enters an area, and releases the instance when the body exits. The file is unloaded when the node is removed from the scene tree. It utilizes GDScript and Godot's signal system. ```gdscript extends Area2D var music: FmodSound = null func _ready(): FmodServer.load_file_as_music("res://assets/Music/jingles_SAX07.ogg") body_entered.connect(enter) body_exited.connect(leave) func enter(_area): print("enter") music = FmodServer.create_sound_instance("res://assets/Music/jingles_SAX07.ogg") music.play() func leave(_area): print("leave") music.release() func _exit_tree(): FmodServer.unload_file("res://assets/Music/jingles_SAX07.ogg") ``` -------------------------------- ### Define and configure library in CMake Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/CMakeLists.txt This snippet defines the library target, includes directories, and sets up platform-specific configurations. It handles different operating systems and build types. ```CMake add_library(${PROJECT_NAME} SHARED ${SOURCES} ${HEADERS}) target_include_directories(${PROJECT_NAME} SYSTEM PRIVATE src/ ${CPP_BINDINGS_PATH}/include ${CPP_BINDINGS_PATH}/include/godot_cpp ${CPP_BINDINGS_PATH}/gen/include ${CPP_BINDINGS_PATH}/gen/include/godot_cpp ${GODOT_GDEXTENSION_DIR} ) link_directories("../libs/fmod/${OS}/core/lib/") link_directories("../libs/fmod/${OS}/studio/lib/") include_directories(../libs/fmod/${OS}/core/inc ../libs/fmod/${OS}/studio/inc) ``` ```CMake set(BITS 32) if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(BITS 64) endif(CMAKE_SIZEOF_VOID_P EQUAL 8) if(CMAKE_BUILD_TYPE MATCHES Debug) set(GODOT_CPP_BUILD_TYPE Debug) else() set(GODOT_CPP_BUILD_TYPE Release) endif() string(TOLOWER ${CMAKE_SYSTEM_NAME} SYSTEM_NAME) string(TOLOWER ${GODOT_CPP_BUILD_TYPE} BUILD_TYPE) if(ANDROID) set(SYSTEM_NAME ${SYSTEM_NAME}.${ANDROID_ABI}) endif() ``` ```CMake if(CMAKE_VERSION VERSION_GREATER "3.13") target_link_directories(${PROJECT_NAME} PRIVATE ${CPP_BINDINGS_PATH}/bin/ ) target_link_libraries(${PROJECT_NAME} godot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}$<$>:.${BITS}> ) else() target_link_libraries(${PROJECT_NAME} ${CPP_BINDINGS_PATH}/bin/libgodot-cpp.${SYSTEM_NAME}.${BUILD_TYPE}$<$>:.${BITS}>.a ) endif() ``` ```CMake if (${OS} EQUAL "osx") target_link_libraries(${PROJECT_NAME} libgodot-cpp.osx.64.a libfmod.dylib libfmodstudio.dylib) endif () if (${OS} EQUAL "windows") target_link_libraries(${PROJECT_NAME} libgodot-cpp.windows.64.lib fmod64.dll fmodstudio64.dll) endif () if (${OS} EQUAL "linux") target_link_libraries(${PROJECT_NAME} libgodot-cpp.linux.64.a libfmod.so libfmodstudio.so) endif() ``` ```CMake set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY COMPILE_FLAGS ${GODOT_COMPILE_FLAGS}) set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY LINK_FLAGS ${GODOT_LINKER_FLAGS}) set_property(TARGET ${PROJECT_NAME} PROPERTY OUTPUT_NAME "GodotFmod") ``` -------------------------------- ### Load Bank and Play FMOD Programmer Callback Event in GDScript Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/5-playing-events.md This GDScript snippet illustrates how to load an FMOD bank containing dialogue, create an event instance from that bank, and then set a specific programmer callback key (e.g., 'welcome') to trigger a particular sound or dialogue line. ```gdscript FmodServer.load_bank("res://assets/Banks/Dialogue_EN.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL) var event_instance = FmodServer.create_event_instance("event:/Character/Dialogue") # event from sfx bank. event_instance.set_programmer_callback("welcome") # welcome key in audio table from Dialogue bank. event_instance.start() ``` -------------------------------- ### Play and Control FMOD Sound Event in GDScript Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/5-playing-events.md This script demonstrates creating an FMOD event instance, setting its 3D attributes, adjusting parameters like RPM and volume, and controlling playback (play/pause) via input actions. It also handles event termination. ```gdscript func _ready(): event = FmodServer.create_event_instance("event:/Vehicles/Car Engine") event.set_2d_attributes(self.global_transform) event.set_parameter_by_name("RPM", 600) event.volume = 2 event.start() func _process(_delta): if Input.is_action_just_pressed("space"): isPlaying = !isPlaying if(isPlaying): print("Mower playing") event.paused = false else: print("Mower paused") event.paused = true elif Input.is_action_just_pressed("kill_event"): self.queue_free() ``` -------------------------------- ### Low-Level Listener API Management with FmodServer Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt Manages audio listeners in a 3D scene using the FmodServer API. Allows adding, setting transform, locking, and removing listeners. Supports multiple listeners for scenarios like split-screen. ```gdscript extends CharacterBody3D var listener_index: int = 0 func _ready(): # Add this node as listener FmodServer.add_listener(listener_index, self) FmodServer.set_listener_weight(listener_index, 1.0) func _process(_delta): # Manually update listener transform FmodServer.set_listener_transform3d(listener_index, global_transform) # Get current transform var current_transform = FmodServer.get_listener_transform3d(listener_index) # Lock/unlock listener if Input.is_action_just_pressed("lock"): var is_locked = FmodServer.get_listener_lock(listener_index) FmodServer.set_listener_lock(listener_index, !is_locked) func setup_multiple_listeners(): # Setup for split-screen or multi-listener scenarios FmodServer.set_listener_number(2) # Use 2 listeners # First listener (player 1) FmodServer.add_listener(0, $Player1) FmodServer.set_listener_weight(0, 0.5) # Second listener (player 2) FmodServer.add_listener(1, $Player2) FmodServer.set_listener_weight(1, 0.5) func _exit_tree(): FmodServer.remove_listener(listener_index, self) ``` -------------------------------- ### Output Directory Configuration (CMake) Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/CMakeLists.txt Configures the output directories for archives, libraries, and runtime files. It ensures these are all set to a platform-specific 'bin' directory, and also sets these for both Debug and Release build types. ```cmake # Change the output directory to the bin directory set(BUILD_PATH ${CMAKE_SOURCE_DIR}/bin/${TARGET_PATH}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${BUILD_PATH}") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${BUILD_PATH}") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${BUILD_PATH}") SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${BUILD_PATH}") SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${BUILD_PATH}") SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BUILD_PATH}") SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${BUILD_PATH}") SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${BUILD_PATH}") SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${BUILD_PATH}") ``` -------------------------------- ### Source and Header File Discovery (CMake) Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/CMakeLists.txt This snippet uses CMake's `file(GLOB_RECURSE ...)` command to find all C/C++ source files and header files within the 'src' directory and its subdirectories. This is a common way to automatically include all project files in the build. ```cmake # Get Sources file(GLOB_RECURSE SOURCES src/*.c** src/**/*.c**) file(GLOB_RECURSE HEADERS src/*.h** src/**/*.h**) ``` -------------------------------- ### Implement Low-Level FMOD Event Callbacks Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt Shows low-level approach to audio event handling using FmodEvent and callback bitmask. Demonstrates setting up callbacks for timeline beats, markers, and playback state changes. Uses a manual callback method with type matching to process different event types. ```gdscript extends Node var music_event: FmodEvent func _ready(): music_event = FmodServer.create_event_instance("event:/Music/Dynamic") # Set callback with bitmask for specific event types music_event.set_callback( Callable(self, "_on_event_callback"), FmodServer.FMOD_STUDIO_EVENT_CALLBACK_TIMELINE_BEAT | FmodServer.FMOD_STUDIO_EVENT_CALLBACK_TIMELINE_MARKER | FmodServer.FMOD_STUDIO_EVENT_CALLBACK_STARTED | FmodServer.FMOD_STUDIO_EVENT_CALLBACK_STOPPED ) music_event.start() func _on_event_callback(event_data: Dictionary, callback_type: int): match callback_type: FmodServer.FMOD_STUDIO_EVENT_CALLBACK_TIMELINE_BEAT: print("Beat callback: ", event_data) FmodServer.FMOD_STUDIO_EVENT_CALLBACK_TIMELINE_MARKER: print("Marker: ", event_data.name) FmodServer.FMOD_STUDIO_EVENT_CALLBACK_STARTED: print("Event started") FmodServer.FMOD_STUDIO_EVENT_CALLBACK_STOPPED: print("Event stopped") FmodServer.FMOD_STUDIO_EVENT_CALLBACK_CREATE_PROGRAMMER_SOUND: print("Programmer sound created") FmodServer.FMOD_STUDIO_EVENT_CALLBACK_DESTROY_PROGRAMMER_SOUND: print("Programmer sound destroyed") ``` -------------------------------- ### Loading Localized Dialogue with Programmer Callbacks Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt Dynamically loads localized dialogue banks and plays dialogue using programmer callbacks. Supports loading banks for different languages and associating audio table keys with specific dialogue lines. ```gdscript extends Node var dialogue_bank: FmodBank var current_language: String = "EN" func _ready(): # Load dialogue bank for specific language load_language("EN") func load_language(lang_code: String): # Unload previous language bank if dialogue_bank: FmodServer.unload_bank("res://assets/Banks/Dialogue_%s.bank" % current_language) # Load new language bank var bank_path = "res://assets/Banks/Dialogue_%s.bank" % lang_code dialogue_bank = FmodServer.load_bank(bank_path, FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL) current_language = lang_code print("Loaded language: ", lang_code) func play_dialogue(audio_table_key: String): # Using high-level node var event_emitter = FmodEventEmitter2D.new() event_emitter.event_guid = "{9aa2ecc5-ea4b-4ebe-85c3-054b11b21dcd}" event_emitter.attached = false event_emitter.autoplay = true event_emitter.auto_release = true event_emitter.set_programmer_callback(audio_table_key) # Key from FMOD audio table add_child(event_emitter) func play_dialogue_low_level(audio_table_key: String): # Using low-level API var event = FmodServer.create_event_instance("event:/Character/Dialogue") event.set_programmer_callback(audio_table_key) event.start() # Examples of audio table keys # play_dialogue_low_level("welcome") # play_dialogue_low_level("goodbye") # play_dialogue_low_level("quest_complete") func switch_language_example(): # Player changes language in settings load_language("FR") # Switch to French play_dialogue("welcome") # Plays French version ``` -------------------------------- ### GUT Doubled Script Initialization and Utilities (GDScript) Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/demo/addons/gut/double_templates/script_template.txt This GDScript code initializes a doubled object for testing using the GUT framework. It sets up internal variables with paths, IDs, and configuration for doubled methods, and loads the 'double_tools.gd' utility script. It also includes essential cleanup functions like '__gutdbl_check_method__' and '__gutdbl_done' to manage the lifecycle of the doubled object during testing. ```GDScript var __gutdbl_values = { thepath = '{path}', subpath = '{subpath}', stubber = {stubber_id}, spy = {spy_id}, gut = {gut_id}, from_singleton = '{singleton_name}', is_partial = {is_partial}, doubled_methods = {doubled_methods}, } var __gutdbl = load('res://addons/gut/double_tools.gd').new(self) # Here so other things can check for a method to know if this is a double. func __gutdbl_check_method__(): pass # Cleanup called by GUT after tests have finished. Important for RefCounted # objects. Nodes are freed, and won't have this method called on them. func __gutdbl_done(): __gutdbl = null __gutdbl_values.clear() ``` -------------------------------- ### Programmer Callback for Fmod Events in GDScript Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/5-playing-events.md Shows how to set up a programmer callback for an Fmod event using the FmodEventEmitter node in GDScript. This involves loading the appropriate bank and then associating a callback key with the emitter. ```gdscript var event_emitter = FmodEventEmitter2D.new() event_emitter.event_guid = "{9aa2ecc5-ea4b-4ebe-85c3-054b11b21dcd}" # event:/Character/Dialogue from sfx bank. event_emitter.autoplay = true event_emitter.set_programmer_callback("welcome") # welcome key from audio table in Dialogue_EN.bank, Dialogue_JP.bank and Dialogue_CN.bank. One of those bank should be loaded. add_child(event_emitter) ``` -------------------------------- ### Handle Timeline Beats and Markers with FmodEventEmitter2D Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt Demonstrates high-level audio event handling using FmodEventEmitter2D. Connects built-in signals for timeline beats, markers, and playback state changes. Extracts parameters like beat position, tempo, and time signature for gameplay synchronization. ```gdscript extends FmodEventEmitter2D var beat_counter: int = 0 func _ready(): event_name = "event:/Music/Level01" autoplay = true # Connect built-in signals (high-level approach) timeline_beat.connect(_on_beat) timeline_marker.connect(_on_marker) started.connect(_on_started) stopped.connect(_on_stopped) func _on_beat(params: Dictionary): # Params contains: bar, beat, position, tempo, time_signature_upper, time_signature_lower beat_counter += 1 print("Beat %d | Bar %d | Tempo: %f | Position: %d" % [ params.beat, params.bar, params.tempo, params.position ]) # Sync gameplay to beat if params.beat == 1: # First beat of bar spawn_enemy() func _on_marker(params: Dictionary): # Params contains: name, position print("Marker reached: %s at position %d" % [params.name, params.position]) # Trigger events based on marker names match params.name: "Intro_End": start_gameplay() "Boss_Phase_2": transition_to_phase_2() "Music_End": return_to_menu() func _on_started(): print("Music started") func _on_stopped(): print("Music stopped") func spawn_enemy(): pass # Gameplay logic func start_gameplay(): pass func transition_to_phase_2(): pass func return_to_menu(): pass ``` -------------------------------- ### Load Banks using FmodServer API (GDScript) Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/4-loading-banks.md This snippet demonstrates how to load FMOD banks programmatically using the FmodServer singleton in Godot. It shows the correct order for loading dependency banks like Master.bank and Master.strings.bank. Ensure you store the returned bank references to prevent them from being unloaded. ```gdscript var banks := Array() func _ready(): banks.append(FmodServer.load_bank("res://Master.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL)) banks.append(FmodServer.load_bank("res://Master.strings.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL)) banks.append(FmodServer.load_bank("res://Music.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL)) ``` -------------------------------- ### Load Banks - FmodServer API with Error Handling Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt Shows advanced bank loading using the FmodServer API with blocking and non-blocking modes, loading state checking, and proper error handling. Provides fine-grained control over bank management for complex audio systems. ```gdscript extends Node var master_string_bank: FmodBank var master_bank: FmodBank var music_bank: FmodBank func _enter_tree(): # Load banks with NORMAL flag (blocking) master_string_bank = FmodServer.load_bank( "res://assets/Banks/Master.strings.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL ) master_bank = FmodServer.load_bank( "res://assets/Banks/Master.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL ) # Load with non-blocking flag music_bank = FmodServer.load_bank( "res://assets/Banks/Music.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NONBLOCKING ) # Check loading state if music_bank.get_loading_state() == FmodServer.FMOD_STUDIO_LOADING_STATE_LOADING: print("Music bank still loading...") # Get all loaded banks var all_banks = FmodServer.get_all_banks() print("Total banks loaded: ", all_banks.size()) func _exit_tree(): # Unload banks when done FmodServer.unload_bank("res://assets/Banks/Music.bank") ``` -------------------------------- ### Play Events - FmodEventEmitter2D with Parameters Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt Implements high-level event playback using FmodEventEmitter2D with parameter control, signal handling, and input-based interaction. Demonstrates both property-based and programmatic parameter management for dynamic audio control. ```gdscript extends FmodEventEmitter2D var isPlaying: bool = true func _ready(): # Properties can be set in editor or in code event_name = "event:/Vehicles/Car Engine" autoplay = true attached = true # Automatically update position allow_fadeout = true # Connect to signals timeline_beat.connect(_on_beat) timeline_marker.connect(_on_marker) started.connect(_on_started) stopped.connect(_on_stopped) # Set initial parameter value self["fmod_parameters/RPM"] = 600 func _process(_delta): # Control playback if Input.is_action_just_pressed("space"): isPlaying = !isPlaying paused = !isPlaying # Control parameters dynamically if Input.is_action_pressed("engine_power_up"): self["fmod_parameters/RPM"] = self["fmod_parameters/RPM"] + 10 if Input.is_action_pressed("engine_power_down"): self["fmod_parameters/RPM"] = self["fmod_parameters/RPM"] - 10 # Alternative parameter control set_parameter("RPM", 800.0) var current_rpm = get_parameter("RPM") func _on_beat(params: Dictionary): print("Beat: ", params.beat, " Bar: ", params.bar) func _on_marker(params: Dictionary): print("Marker: ", params.name, " Position: ", params.position) func _on_started(): print("Event started playing") func _on_stopped(): print("Event stopped") ``` -------------------------------- ### Play One-Shot Sound Effects Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt This section demonstrates various ways to play one-shot sound effects using FMOD. It includes simple playback, playback with parameters, attaching sounds to nodes for positional audio, and using FmodEventEmitter2D nodes. Dependencies: FmodServer, FmodEventEmitter2D. ```gdscript extends Node2D func _ready(): # Simple one-shot FmodServer.play_one_shot("event:/UI/Click") func shoot(): # One-shot with parameters FmodServer.play_one_shot_with_params("event:/Weapons/Gunshot", { "Weapon Type": 2, "Distance": 15.0 }) func explosion(): # One-shot attached to node (follows node position) FmodServer.play_one_shot_attached("event:/Explosions/Large", self) func footstep(): # One-shot attached with parameters FmodServer.play_one_shot_attached_with_params( "event:/Player/Footstep", self, { "Surface": 1, # 0=Grass, 1=Concrete, 2=Wood "Speed": 1.5 } ) func using_emitter_node(): # Alternative: Create one-shot using node var event_emitter = FmodEventEmitter2D.new() event_emitter.event_name = "event:/Explosions/Small" event_emitter.attached = false event_emitter.autoplay = true event_emitter.auto_release = true # Node destroys itself when done add_child(event_emitter) ``` -------------------------------- ### Playing Fmod Events with FmodServer API in GDScript Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/5-playing-events.md Illustrates how to play Fmod events using the global FmodServer API in GDScript. This method is suitable for managing global audio events or when direct node management is not desired. ```gdscript extends Sprite2D var isPlaying: bool = true var event: FmodEvent = null ``` -------------------------------- ### Platform-Specific Target and OS Detection (CMake) Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/CMakeLists.txt This snippet detects the target platform (Linux, Windows, macOS) and sets corresponding variables for the build path and operating system identifier. It includes a fatal error message for unsupported systems. ```cmake if(CMAKE_SYSTEM_NAME STREQUAL "Linux") set(TARGET_PATH x11) set(OS "linux") elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") set(TARGET_PATH win64) set(OS "windows") elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") set(TARGET_PATH macos) set(OS "osx") else() message(FATAL_ERROR "Not implemented support for ${CMAKE_SYSTEM_NAME}") endif() ``` -------------------------------- ### Add FMOD Listener using FmodServer API Source: https://github.com/utopia-rise/fmod-gdextension/blob/master/docs/src/doc/user-guide/6-listeners.md This code snippet demonstrates how to add an FMOD listener to a Godot project using the FmodServer API. It attaches a listener with a specific index to the current node, typically within the _ready() function. This requires the FmodServer module to be available. ```gdscript func _ready(): FmodServer.add_listener(0, self) ``` -------------------------------- ### Manage FMOD Bank Loading and Introspection with GDScript Source: https://context7.com/utopia-rise/fmod-gdextension/llms.txt Load FMOD banks, check their loading status, and introspect their contents, including events, buses, and VCAs. This functionality is crucial for managing audio assets and ensuring they are ready for playback. ```gdscript extends Node var master_bank: FmodBank func _ready(): master_bank = FmodServer.load_bank( "res://assets/Banks/Master.bank", FmodServer.FMOD_STUDIO_LOAD_BANK_NORMAL ) # Check loading state var state = master_bank.get_loading_state() match state: FmodServer.FMOD_STUDIO_LOADING_STATE_LOADING: print("Bank is loading...") FmodServer.FMOD_STUDIO_LOADING_STATE_LOADED: print("Bank loaded successfully") FmodServer.FMOD_STUDIO_LOADING_STATE_ERROR: print("Bank failed to load") # Get bank contents var event_count = master_bank.get_event_description_count() var bus_count = master_bank.get_bus_count() var vca_count = master_bank.get_vca_count() var string_count = master_bank.get_string_count() print("Bank contains: %d events, %d buses, %d VCAs" % [ event_count, bus_count, vca_count ]) # Get all events in bank var event_descriptions = master_bank.get_description_list() for event_desc in event_descriptions: print("Event: ", event_desc.get_path()) # Get all buses in bank var buses = master_bank.get_bus_list() for bus in buses: print("Bus: ", bus.get_path()) # Get all VCAs in bank var vcas = master_bank.get_vca_list() for vca in vcas: print("VCA: ", vca.get_path()) func preload_event_samples(): # Preload sample data for specific event var event_desc = FmodServer.get_event("event:/Music/Level01") event_desc.load_sample_data() # Check loading state var state = event_desc.get_sample_loading_state() while state == FmodServer.FMOD_STUDIO_LOADING_STATE_LOADING: await get_tree().create_timer(0.1).timeout state = event_desc.get_sample_loading_state() print("Samples loaded") func unload_event_samples(): var event_desc = FmodServer.get_event("event:/Music/Level01") event_desc.unload_sample_data() ```