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
// Copyright (c) 2024 Melody Madeline 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 std::ffi::c_ulonglong;
use fmod_sys::*;
use crate::ChannelControl;
use crate::{FmodResultExt, Result};
impl ChannelControl {
/// Retrieves the DSP clock values at this point in time.
///
/// To perform sample accurate scheduling in conjunction with `ChannelControl::setDelay` and `ChannelControl::addFadePoint` query the parentclock value.
pub fn get_dsp_clock(&self) -> Result<(c_ulonglong, c_ulonglong)> {
let mut dsp_clock = 0;
let mut parent_clock = 0;
unsafe {
FMOD_ChannelControl_GetDSPClock(
self.inner.as_ptr(),
&raw mut dsp_clock,
&raw mut parent_clock,
)
.to_result()?;
}
Ok((dsp_clock, parent_clock))
}
/// Sets a sample accurate start (and/or stop) time relative to the parent `ChannelGroup` DSP clock.
///
/// To perform sample accurate scheduling use `ChannelControl::getDSPClock` to query the parent clock value.
/// 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.
pub fn set_delay(
&self,
start: c_ulonglong,
end: c_ulonglong,
stop_channels: bool,
) -> Result<()> {
unsafe {
FMOD_ChannelControl_SetDelay(self.inner.as_ptr(), start, end, stop_channels).to_result()
}
}
/// Retrieves a sample accurate start (and/or stop) time relative to the parent `ChannelGroup` DSP clock.
pub fn get_delay(&self) -> Result<(c_ulonglong, c_ulonglong, bool)> {
let mut dsp_start = 0;
let mut dsp_end = 0;
let mut stop_channels = false;
unsafe {
FMOD_ChannelControl_GetDelay(
self.inner.as_ptr(),
&raw mut dsp_start,
&raw mut dsp_end,
&raw mut stop_channels,
)
.to_result()?;
}
Ok((dsp_start, dsp_end, stop_channels))
}
/// Adds a sample accurate fade point at a time relative to the parent `ChannelGroup` DSP clock.
///
/// Fade points are scaled against other volume settings and in-between each fade point the volume will be linearly ramped.
///
/// To perform sample accurate fading use `ChannelControl::getDSPClock` to query the parent clock value.
/// If a parent `ChannelGroup` changes its pitch, the fade points will still be correct as the parent clock rate is adjusted by that pitch.
///
/// ```rs
/// // Example. Ramp from full volume to half volume over the next 4096 samples
/// let (_, parent) = target.get_dsp_clock();
/// target.add_fade_point(parent, 1.0);
/// target.add_fade_point(parent + 4096, 0.5);
/// ```
pub fn add_fade_point(&self, dsp_clock: c_ulonglong, volume: f32) -> Result<()> {
unsafe {
FMOD_ChannelControl_AddFadePoint(self.inner.as_ptr(), dsp_clock, volume).to_result()
}
}
/// Adds a volume ramp at the specified time in the future using fade points.
///
/// 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.
///
/// Can be use in conjunction with `ChannelControl::SetDelay`.
///
/// All fade points after `dsp_clock` will be removed.
pub fn set_fade_point_ramp(&self, dsp_clock: c_ulonglong, volume: f32) -> Result<()> {
unsafe {
FMOD_ChannelControl_SetFadePointRamp(self.inner.as_ptr(), dsp_clock, volume).to_result()
}
}
/// Removes all fade points between the two specified clock values (inclusive).
pub fn remove_fade_points(
&self,
dsp_clock_start: c_ulonglong,
dsp_clock_end: c_ulonglong,
) -> Result<()> {
unsafe {
FMOD_ChannelControl_RemoveFadePoints(
self.inner.as_ptr(),
dsp_clock_start,
dsp_clock_end,
)
.to_result()
}
}
/// Retrieves information about stored fade points.
pub fn get_fade_points(&self) -> Result<(Vec<c_ulonglong>, Vec<f32>)> {
let mut num_points = 0;
unsafe {
FMOD_ChannelControl_GetFadePoints(
self.inner.as_ptr(),
&raw mut num_points,
std::ptr::null_mut(),
std::ptr::null_mut(),
)
.to_result()?;
}
let mut dsp_clocks = vec![0; num_points as usize];
let mut volumes = vec![0.0; num_points as usize];
unsafe {
FMOD_ChannelControl_GetFadePoints(
self.inner.as_ptr(),
&raw mut num_points,
dsp_clocks.as_mut_ptr(),
volumes.as_mut_ptr(),
)
.to_result()?;
}
Ok((dsp_clocks, volumes))
}
}