1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
// Copyright (c) 2024 Lily Lyons
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
use fmod_sys::*;
use std::{ffi::c_int, mem::MaybeUninit};
use crate::{ChannelGroup, PortType, ReverbProperties, System, Vector};
impl System {
/// Sets the position, velocity and orientation of the specified 3D sound listener.
///
/// The forward and up vectors must be perpendicular and be of unit length (magnitude of each vector should be 1).
///
/// Vectors must be provided in the correct handedness.
///
/// For velocity, remember to use units per second, and not units per frame.
/// This is a common mistake and will make the doppler effect sound wrong if velocity is based on movement per frame rather than a fixed time period.
/// If velocity per frame is calculated, it can be converted to velocity per second by dividing it by the time taken between frames as a fraction of a second.
/// i.e.
///
/// `velocity_units_per_second = (position_currentframe - position_lastframe) / time_taken_since_last_frame_in_seconds`.
///
/// At 60fps the formula would look like `velocity_units_per_second = (position_current_frame - position_last_frame) / 0.0166667`.
///
/// Users of the Studio API should call [`crate::studio::System::set_listener_attributes`] instead of this function.
pub fn set_3d_listener_attributes(
&self,
listener: c_int,
position: Option<Vector>,
velocity: Option<Vector>,
forward: Option<Vector>,
up: Option<Vector>,
) -> Result<()> {
// these casts are ok as Vector is layout equivalent with FMOD_VECTOR
let position = position
.as_ref()
.map_or(std::ptr::null(), std::ptr::from_ref)
.cast();
let velocity = velocity
.as_ref()
.map_or(std::ptr::null(), std::ptr::from_ref)
.cast();
let forward = forward
.as_ref()
.map_or(std::ptr::null(), std::ptr::from_ref)
.cast();
let up = up
.as_ref()
.map_or(std::ptr::null(), std::ptr::from_ref)
.cast();
unsafe {
FMOD_System_Set3DListenerAttributes(
self.inner, listener, position, velocity, forward, up,
)
.to_result()
}
}
/// Retrieves the position, velocity and orientation of the specified 3D sound listener.
///
/// Users of the Studio API should call [`crate::studio::System::get_listener_attributes`] instead of this function.
pub fn get_3d_listener_attributes(
&self,
listener: c_int,
) -> Result<(Vector, Vector, Vector, Vector)> {
let mut position = MaybeUninit::zeroed();
let mut velocity = MaybeUninit::zeroed();
let mut forward = MaybeUninit::zeroed();
let mut up = MaybeUninit::zeroed();
unsafe {
FMOD_System_Get3DListenerAttributes(
self.inner,
listener,
position.as_mut_ptr(),
velocity.as_mut_ptr(),
forward.as_mut_ptr(),
up.as_mut_ptr(),
)
.to_result()?;
let position = position.assume_init();
let velocity = velocity.assume_init();
let forward = forward.assume_init();
let up = up.assume_init();
Ok((position.into(), velocity.into(), forward.into(), up.into()))
}
}
/// Sets parameters for the global reverb environment.
///
/// To assist in defining reverb properties there are several presets available,
/// see the associated constants on [`ReverbProperties.`].
///
/// When using each instance for the first time,
/// FMOD will create an SFX reverb [`Dsp`] unit that takes up several hundred kilobytes of memory and some CPU.
pub fn set_reverb_properties(
&self,
instance: c_int,
properties: Option<ReverbProperties>,
) -> Result<()> {
let properties = properties
.as_ref()
.map_or(std::ptr::null(), std::ptr::from_ref)
.cast();
unsafe { FMOD_System_SetReverbProperties(self.inner, instance, properties).to_result() }
}
/// Retrieves the current reverb environment for the specified reverb instance.
pub fn get_reverb_properties(&self, instance: c_int) -> Result<ReverbProperties> {
let mut properties = MaybeUninit::zeroed();
unsafe {
FMOD_System_GetReverbProperties(self.inner, instance, properties.as_mut_ptr())
.to_result()?;
let properties = properties.assume_init().into();
Ok(properties)
}
}
/// Connect the output of the specified [`ChannelGroup`] to an audio port on the output driver.
///
/// Ports are additional outputs supported by some [`OutputType`] plugins and can include things like controller headsets or dedicated background music streams.
/// See the Port Support section (where applicable) of each platform's getting started guide found in the platform details chapter.
pub fn attach_channel_group_to_port(
&self,
kind: PortType,
index: Option<FMOD_PORT_INDEX>,
channel_group: ChannelGroup,
pass_through: bool,
) -> Result<()> {
unsafe {
FMOD_System_AttachChannelGroupToPort(
self.inner,
kind.into(),
index.unwrap_or(FMOD_PORT_INDEX_NONE as FMOD_PORT_INDEX),
channel_group.into(),
pass_through.into(),
)
.to_result()
}
}
/// Disconnect the output of the specified [`ChannelGroup`] from an audio port on the output driver.
///
/// Removing a [`ChannelGroup`] from a port will reroute the audio back to the main mix.
pub fn detach_channel_group_from_port(&self, channel_group: ChannelGroup) -> Result<()> {
unsafe {
FMOD_System_DetachChannelGroupFromPort(self.inner, channel_group.into()).to_result()
}
}
}