1use crate::block::{Block, Chunk, FRAMES_PER_BLOCK, Tick};
2use crate::node::{AudioNodeEngine, AudioScheduledSourceNodeMessage, BlockInfo, OnEndedCallback};
3use crate::node::{AudioNodeType, ChannelInfo, ShouldPlay};
4use crate::param::{Param, ParamType};
5
6#[derive(Debug, Clone)]
8pub enum AudioBufferSourceNodeMessage {
9 SetBuffer(Option<AudioBuffer>),
11 SetLoopEnabled(bool),
13 SetLoopEnd(f64),
15 SetLoopStart(f64),
17 SetStartParams(f64, Option<f64>, Option<f64>),
19}
20
21#[derive(Debug, Clone)]
23pub struct AudioBufferSourceNodeOptions {
24 pub buffer: Option<AudioBuffer>,
26 pub detune: f32,
28 pub loop_enabled: bool,
30 pub loop_end: Option<f64>,
32 pub loop_start: Option<f64>,
34 pub playback_rate: f32,
36}
37
38impl Default for AudioBufferSourceNodeOptions {
39 fn default() -> Self {
40 AudioBufferSourceNodeOptions {
41 buffer: None,
42 detune: 0.,
43 loop_enabled: false,
44 loop_end: None,
45 loop_start: None,
46 playback_rate: 1.,
47 }
48 }
49}
50
51#[derive(AudioScheduledSourceNode, AudioNodeCommon)]
54#[allow(dead_code)]
55pub(crate) struct AudioBufferSourceNode {
56 channel_info: ChannelInfo,
57 buffer: Option<AudioBuffer>,
59 buffer_duration: f64,
61 buffer_pos: f64,
66 detune: Param,
68 initialized_pos: bool,
70 loop_enabled: bool,
73 loop_end: Option<f64>,
76 loop_start: Option<f64>,
79 playback_rate: Param,
83 start_at: Option<Tick>,
85 start_offset: Option<f64>,
87 start_duration: Option<f64>,
89 start_when: f64,
92 stop_at: Option<Tick>,
94 pub onended_callback: Option<OnEndedCallback>,
96}
97
98impl AudioBufferSourceNode {
99 pub fn new(options: AudioBufferSourceNodeOptions, channel_info: ChannelInfo) -> Self {
100 Self {
101 channel_info,
102 buffer: options.buffer,
103 buffer_pos: 0.,
104 detune: Param::new_krate(options.detune),
105 initialized_pos: false,
106 loop_enabled: options.loop_enabled,
107 loop_end: options.loop_end,
108 loop_start: options.loop_start,
109 playback_rate: Param::new_krate(options.playback_rate),
110 buffer_duration: std::f64::INFINITY,
111 start_at: None,
112 start_offset: None,
113 start_duration: None,
114 start_when: 0.,
115 stop_at: None,
116 onended_callback: None,
117 }
118 }
119
120 pub fn handle_message(&mut self, message: AudioBufferSourceNodeMessage, _: f32) {
121 match message {
122 AudioBufferSourceNodeMessage::SetBuffer(buffer) => {
123 self.buffer = buffer;
124 },
125 AudioBufferSourceNodeMessage::SetLoopEnabled(loop_enabled) => {
128 self.loop_enabled = loop_enabled
129 },
130 AudioBufferSourceNodeMessage::SetLoopEnd(loop_end) => self.loop_end = Some(loop_end),
131 AudioBufferSourceNodeMessage::SetLoopStart(loop_start) => {
132 self.loop_start = Some(loop_start)
133 },
134 AudioBufferSourceNodeMessage::SetStartParams(when, offset, duration) => {
135 self.start_when = when;
136 self.start_offset = offset;
137 self.start_duration = duration;
138 },
139 }
140 }
141}
142
143impl AudioNodeEngine for AudioBufferSourceNode {
144 fn node_type(&self) -> AudioNodeType {
145 AudioNodeType::AudioBufferSourceNode
146 }
147
148 fn input_count(&self) -> u32 {
149 0
150 }
151
152 fn process(&mut self, mut inputs: Chunk, info: &BlockInfo) -> Chunk {
153 debug_assert!(inputs.len() == 0);
154
155 if self.buffer.is_none() {
156 inputs.blocks.push(Default::default());
157 return inputs;
158 }
159
160 let (start_at, stop_at) = match self.should_play_at(info.frame) {
161 ShouldPlay::No => {
162 inputs.blocks.push(Default::default());
163 return inputs;
164 },
165 ShouldPlay::Between(start, end) => (start.0 as usize, end.0 as usize),
166 };
167
168 let buffer = self.buffer.as_ref().unwrap();
169
170 let (mut actual_loop_start, mut actual_loop_end) = (0., buffer.len() as f64);
171 if self.loop_enabled {
172 let loop_start = self.loop_start.unwrap_or(0.);
173 let loop_end = self.loop_end.unwrap_or(0.);
174
175 if loop_start >= 0. && loop_end > loop_start {
176 actual_loop_start = loop_start * (buffer.sample_rate as f64);
177 actual_loop_end = loop_end * (buffer.sample_rate as f64);
178 }
179 }
180
181 self.playback_rate.update(info, Tick(0));
183 self.detune.update(info, Tick(0));
184 let computed_playback_rate =
186 self.playback_rate.value() as f64 * (2.0_f64).powf(self.detune.value() as f64 / 1200.);
187 let forward = computed_playback_rate >= 0.;
188
189 if !self.initialized_pos {
190 self.initialized_pos = true;
191
192 if let Some(start_offset) = self.start_offset {
196 self.buffer_pos = start_offset * (buffer.sample_rate as f64);
197 if self.buffer_pos < 0. {
198 self.buffer_pos = 0.
199 } else if self.buffer_pos > buffer.len() as f64 {
200 self.buffer_pos = buffer.len() as f64;
201 }
202 }
203
204 if self.loop_enabled {
205 if forward && self.buffer_pos >= actual_loop_end {
206 self.buffer_pos = actual_loop_start;
207 }
208 if !forward && self.buffer_pos < actual_loop_start {
210 self.buffer_pos = actual_loop_end;
211 }
212 }
213
214 if let Some(start_duration) = self.start_duration {
215 self.buffer_duration = start_duration * (buffer.sample_rate as f64);
216 }
217
218 if self.start_when > info.time - 1. / info.sample_rate as f64 {
228 let first_time = info.time + start_at as f64 / info.sample_rate as f64;
229 if self.start_when <= first_time {
230 let subsample_offset = (first_time - self.start_when)
231 * (buffer.sample_rate as f64)
232 * computed_playback_rate;
233 self.buffer_pos += subsample_offset;
234 self.buffer_duration -= subsample_offset.abs();
235 }
236 }
237 }
238
239 let mut buffer_offset_per_tick =
240 computed_playback_rate * (buffer.sample_rate as f64 / info.sample_rate as f64);
241
242 if self.loop_enabled && actual_loop_end > actual_loop_start {
253 let loop_length = actual_loop_end - actual_loop_start;
254 if loop_length > 0. {
255 let step = buffer_offset_per_tick.abs();
256 if step >= loop_length {
257 let mut wrapped = step.rem_euclid(loop_length);
258 if wrapped == 0. {
259 wrapped = loop_length;
260 }
261 buffer_offset_per_tick = wrapped.copysign(buffer_offset_per_tick);
262 }
263 }
264 }
265
266 let frames_to_output = stop_at - start_at;
268
269 if frames_to_output == FRAMES_PER_BLOCK.0 as usize
272 && forward
273 && buffer_offset_per_tick == 1.
274 && self.buffer_pos.trunc() == self.buffer_pos
275 && self.buffer_pos + (FRAMES_PER_BLOCK.0 as f64) <= actual_loop_end
276 && FRAMES_PER_BLOCK.0 as f64 <= self.buffer_duration
277 {
278 let mut block = Block::empty();
279 let pos = self.buffer_pos as usize;
280
281 for chan in 0..buffer.chans() {
282 block.push_chan(&buffer.buffers[chan as usize][pos..(pos + frames_to_output)]);
283 }
284
285 inputs.blocks.push(block);
286 self.buffer_pos += FRAMES_PER_BLOCK.0 as f64;
287 self.buffer_duration -= FRAMES_PER_BLOCK.0 as f64;
288 } else {
289 let mut block = Block::default();
291 block.repeat(buffer.chans());
292 block.explicit_repeat();
293
294 debug_assert!(buffer.chans() > 0);
295
296 for chan in 0..buffer.chans() {
297 let data = block.data_chan_mut(chan);
298 let (_, data) = data.split_at_mut(start_at);
299 let (data, _) = data.split_at_mut(frames_to_output);
300
301 let mut pos = self.buffer_pos;
302 let mut duration = self.buffer_duration;
303
304 for sample in data {
305 if duration <= 0. {
306 break;
307 }
308
309 if self.loop_enabled {
310 if forward && pos >= actual_loop_end {
311 pos -= actual_loop_end - actual_loop_start;
312 } else if !forward && pos < actual_loop_start {
313 pos += actual_loop_end - actual_loop_start;
314 }
315 } else if pos < 0. || pos >= buffer.len() as f64 {
316 break;
317 }
318
319 *sample = buffer.interpolate(chan, pos);
320 pos += buffer_offset_per_tick;
321 duration -= buffer_offset_per_tick.abs();
322 }
323
324 if chan == buffer.chans() - 1 {
326 self.buffer_pos = pos;
327 self.buffer_duration = duration;
328 }
329 }
330
331 inputs.blocks.push(block);
332 }
333
334 if !self.loop_enabled && (self.buffer_pos < 0. || self.buffer_pos >= buffer.len() as f64)
335 || self.buffer_duration <= 0.
336 {
337 self.maybe_trigger_onended_callback();
338 }
339
340 inputs
341 }
342
343 fn get_param(&mut self, id: ParamType) -> &mut Param {
344 match id {
345 ParamType::PlaybackRate => &mut self.playback_rate,
346 ParamType::Detune => &mut self.detune,
347 _ => panic!("Unknown param {:?} for AudioBufferSourceNode", id),
348 }
349 }
350
351 make_message_handler!(
352 AudioBufferSourceNode: handle_message,
353 AudioScheduledSourceNode: handle_source_node_message
354 );
355}
356
357#[derive(Debug, Clone)]
358pub struct AudioBuffer {
359 pub buffers: Vec<Vec<f32>>,
361 pub sample_rate: f32,
362}
363
364impl AudioBuffer {
365 pub fn new(chan: u8, len: usize, sample_rate: f32) -> Self {
366 assert!(chan > 0);
367 let mut buffers = Vec::with_capacity(chan as usize);
368 let single = vec![0.; len];
369 buffers.resize(chan as usize, single);
370 AudioBuffer {
371 buffers,
372 sample_rate,
373 }
374 }
375
376 pub fn from_buffers(buffers: Vec<Vec<f32>>, sample_rate: f32) -> Self {
377 for buf in &buffers {
378 assert_eq!(buf.len(), buffers[0].len())
379 }
380
381 Self {
382 buffers,
383 sample_rate,
384 }
385 }
386
387 pub fn from_buffer(buffer: Vec<f32>, sample_rate: f32) -> Self {
388 AudioBuffer::from_buffers(vec![buffer], sample_rate)
389 }
390
391 pub fn len(&self) -> usize {
392 self.buffers[0].len()
393 }
394
395 pub fn chans(&self) -> u8 {
396 self.buffers.len() as u8
397 }
398
399 pub fn interpolate(&self, chan: u8, pos: f64) -> f32 {
404 debug_assert!(pos >= 0. && pos < self.len() as f64);
405
406 let prev = pos.floor() as usize;
407 let offset = pos - pos.floor();
408 match self.buffers[chan as usize].get(prev + 1) {
409 Some(next_sample) => {
410 ((1. - offset) * (self.buffers[chan as usize][prev] as f64)
411 + offset * (*next_sample as f64)) as f32
412 },
413 _ => {
414 if prev > 0 {
416 ((1. + offset) * (self.buffers[chan as usize][prev] as f64)
417 - offset * (self.buffers[chan as usize][prev - 1] as f64))
418 as f32
419 } else {
420 self.buffers[chan as usize][prev]
421 }
422 },
423 }
424 }
425
426 pub fn data_chan_mut(&mut self, chan: u8) -> &mut [f32] {
427 &mut self.buffers[chan as usize]
428 }
429}