fmod/core/channel_control/
scheduling.rs

1// Copyright (c) 2024 Lily Lyons
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7use std::ffi::c_ulonglong;
8
9use fmod_sys::*;
10
11use crate::ChannelControl;
12
13impl ChannelControl {
14    /// Retrieves the DSP clock values at this point in time.
15    ///
16    /// To perform sample accurate scheduling in conjunction with ChannelControl::setDelay and ChannelControl::addFadePoint query the parentclock value.
17    pub fn get_dsp_clock(&self) -> Result<(c_ulonglong, c_ulonglong)> {
18        let mut dsp_clock = 0;
19        let mut parent_clock = 0;
20        unsafe {
21            FMOD_ChannelControl_GetDSPClock(self.inner, &mut dsp_clock, &mut parent_clock)
22                .to_result()?;
23        }
24        Ok((dsp_clock, parent_clock))
25    }
26
27    /// Sets a sample accurate start (and/or stop) time relative to the parent ChannelGroup DSP clock.
28    ///
29    /// To perform sample accurate scheduling use ChannelControl::getDSPClock to query the parent clock value.
30    /// If a parent ChannelGroup changes its pitch, the start and stop times will still be correct as the parent clock rate is adjusted by that pitch.
31    pub fn set_delay(
32        &self,
33        start: c_ulonglong,
34        end: c_ulonglong,
35        stop_channels: bool,
36    ) -> Result<()> {
37        unsafe { FMOD_ChannelControl_SetDelay(self.inner, start, end, stop_channels).to_result() }
38    }
39
40    /// Retrieves a sample accurate start (and/or stop) time relative to the parent ChannelGroup DSP clock.
41    pub fn get_delay(&self) -> Result<(c_ulonglong, c_ulonglong, bool)> {
42        let mut dsp_start = 0;
43        let mut dsp_end = 0;
44        let mut stop_channels = false;
45        unsafe {
46            FMOD_ChannelControl_GetDelay(
47                self.inner,
48                &mut dsp_start,
49                &mut dsp_end,
50                &mut stop_channels,
51            )
52            .to_result()?;
53        }
54        Ok((dsp_start, dsp_end, stop_channels))
55    }
56
57    /// Adds a sample accurate fade point at a time relative to the parent ChannelGroup DSP clock.
58    ///
59    /// Fade points are scaled against other volume settings and in-between each fade point the volume will be linearly ramped.
60    ///
61    /// To perform sample accurate fading use ChannelControl::getDSPClock to query the parent clock value.
62    /// If a parent ChannelGroup changes its pitch, the fade points will still be correct as the parent clock rate is adjusted by that pitch.
63    ///
64    /// ```rs
65    /// // Example. Ramp from full volume to half volume over the next 4096 samples
66    /// let (_, parent) = target.get_dsp_clock();
67    /// target.add_fade_point(parent, 1.0);
68    /// target.add_fade_point(parent + 4096, 0.5);
69    /// ```
70    pub fn add_fade_point(&self, dsp_clock: c_ulonglong, volume: f32) -> Result<()> {
71        unsafe { FMOD_ChannelControl_AddFadePoint(self.inner, dsp_clock, volume).to_result() }
72    }
73
74    /// Adds a volume ramp at the specified time in the future using fade points.
75    ///
76    /// This is a convenience function that creates a scheduled 64 sample fade point ramp from the current volume level to volume arriving at `dsp_clock` time.
77    ///
78    /// Can be use in conjunction with ChannelControl::SetDelay.
79    ///
80    /// All fade points after `dsp_clock` will be removed.
81    pub fn set_fade_point_ramp(&self, dsp_clock: c_ulonglong, volume: f32) -> Result<()> {
82        unsafe { FMOD_ChannelControl_SetFadePointRamp(self.inner, dsp_clock, volume).to_result() }
83    }
84
85    /// Removes all fade points between the two specified clock values (inclusive).
86    pub fn remove_fade_points(
87        &self,
88        dsp_clock_start: c_ulonglong,
89        dsp_clock_end: c_ulonglong,
90    ) -> Result<()> {
91        unsafe {
92            FMOD_ChannelControl_RemoveFadePoints(self.inner, dsp_clock_start, dsp_clock_end)
93                .to_result()
94        }
95    }
96
97    /// Retrieves information about stored fade points.
98    pub fn get_fade_points(&self) -> Result<(Vec<c_ulonglong>, Vec<f32>)> {
99        let mut num_points = 0;
100        unsafe {
101            FMOD_ChannelControl_GetFadePoints(
102                self.inner,
103                &mut num_points,
104                std::ptr::null_mut(),
105                std::ptr::null_mut(),
106            )
107            .to_result()?;
108        }
109
110        let mut dsp_clocks = vec![0; num_points as usize];
111        let mut volumes = vec![0.0; num_points as usize];
112        unsafe {
113            FMOD_ChannelControl_GetFadePoints(
114                self.inner,
115                &mut num_points,
116                dsp_clocks.as_mut_ptr(),
117                volumes.as_mut_ptr(),
118            )
119            .to_result()?;
120        }
121        Ok((dsp_clocks, volumes))
122    }
123}