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