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}