1#![allow(clippy::float_cmp)]
32
33use crate::{
34 buffer::{streaming::StreamingBuffer, SoundBufferResource, SoundBufferState},
35 error::SoundError,
36 source::{SoundSource, Status},
37};
38use rg3d_core::{
39 inspect::{Inspect, PropertyInfo},
40 visitor::{Visit, VisitResult, Visitor},
41};
42use rg3d_resource::ResourceState;
43use std::time::Duration;
44
45#[derive(Debug, Clone, Inspect)]
47pub struct GenericSource {
48 name: String,
49 buffer: Option<SoundBufferResource>,
50 #[inspect(skip)]
55 buf_read_pos: f64,
56 #[inspect(skip)]
58 playback_pos: f64,
59 #[inspect(min_value = 0.0, step = 0.05)]
60 panning: f32,
61 #[inspect(min_value = 0.0, step = 0.05)]
62 pitch: f64,
63 #[inspect(min_value = 0.0, step = 0.05)]
64 gain: f32,
65 looping: bool,
66 #[inspect(read_only)]
75 resampling_multiplier: f64,
76 status: Status,
77 play_once: bool,
78 #[inspect(skip)]
85 pub(in crate) last_left_gain: Option<f32>,
86 #[inspect(skip)]
87 pub(in crate) last_right_gain: Option<f32>,
88 #[inspect(skip)]
89 pub(in crate) frame_samples: Vec<(f32, f32)>,
90 #[inspect(skip)]
92 prev_buffer_sample: (f32, f32),
93}
94
95impl Default for GenericSource {
96 fn default() -> Self {
97 Self {
98 name: Default::default(),
99 buffer: None,
100 buf_read_pos: 0.0,
101 playback_pos: 0.0,
102 panning: 0.0,
103 pitch: 1.0,
104 gain: 1.0,
105 looping: false,
106 resampling_multiplier: 1.0,
107 status: Status::Stopped,
108 play_once: false,
109 last_left_gain: None,
110 last_right_gain: None,
111 frame_samples: Default::default(),
112 prev_buffer_sample: (0.0, 0.0),
113 }
114 }
115}
116
117impl GenericSource {
118 pub fn set_name<N: AsRef<str>>(&mut self, name: N) {
120 self.name = name.as_ref().to_owned();
121 }
122
123 pub fn name(&self) -> &str {
125 &self.name
126 }
127
128 pub fn name_owned(&self) -> String {
130 self.name.to_owned()
131 }
132
133 pub fn set_buffer(
136 &mut self,
137 buffer: Option<SoundBufferResource>,
138 ) -> Result<Option<SoundBufferResource>, SoundError> {
139 self.buf_read_pos = 0.0;
140 self.playback_pos = 0.0;
141
142 if let Some(buffer) = self.buffer.clone() {
145 if let SoundBufferState::Streaming(ref mut streaming) = *buffer.data_ref() {
146 streaming.use_count = streaming.use_count.saturating_sub(1);
147 }
148 }
149
150 if let Some(buffer) = buffer.clone() {
151 match *buffer.state() {
152 ResourceState::LoadError { .. } => return Err(SoundError::BufferFailedToLoad),
153 ResourceState::Ok(ref mut locked_buffer) => {
154 if let SoundBufferState::Streaming(ref mut streaming) = *locked_buffer {
156 if streaming.use_count != 0 {
157 return Err(SoundError::StreamingBufferAlreadyInUse);
158 }
159 streaming.use_count += 1;
160 }
161
162 let device_sample_rate = f64::from(crate::context::SAMPLE_RATE);
164 let sample_rate = locked_buffer.sample_rate() as f64;
165 self.resampling_multiplier = sample_rate / device_sample_rate;
166 }
167 ResourceState::Pending { .. } => unreachable!(),
168 }
169 }
170
171 Ok(std::mem::replace(&mut self.buffer, buffer))
172 }
173
174 pub fn buffer(&self) -> Option<SoundBufferResource> {
176 self.buffer.clone()
177 }
178
179 pub fn set_play_once(&mut self, play_once: bool) {
187 self.play_once = play_once;
188 }
189
190 pub fn is_play_once(&self) -> bool {
192 self.play_once
193 }
194
195 pub fn set_gain(&mut self, gain: f32) -> &mut Self {
203 self.gain = gain;
204 self
205 }
206
207 pub fn gain(&self) -> f32 {
209 self.gain
210 }
211
212 pub fn set_panning(&mut self, panning: f32) -> &mut Self {
215 self.panning = panning.max(-1.0).min(1.0);
216 self
217 }
218
219 pub fn panning(&self) -> f32 {
221 self.panning
222 }
223
224 pub fn status(&self) -> Status {
226 self.status
227 }
228
229 pub fn play(&mut self) -> &mut Self {
231 self.status = Status::Playing;
232 self
233 }
234
235 pub fn pause(&mut self) -> &mut Self {
237 self.status = Status::Paused;
238 self
239 }
240
241 pub fn set_looping(&mut self, looping: bool) -> &mut Self {
244 self.looping = looping;
245 self
246 }
247
248 pub fn is_looping(&self) -> bool {
250 self.looping
251 }
252
253 pub fn set_pitch(&mut self, pitch: f64) -> &mut Self {
255 self.pitch = pitch.abs();
256 self
257 }
258
259 pub fn pitch(&self) -> f64 {
261 self.pitch
262 }
263
264 pub fn stop(&mut self) -> Result<(), SoundError> {
266 self.status = Status::Stopped;
267
268 self.buf_read_pos = 0.0;
269 self.playback_pos = 0.0;
270
271 if let Some(buffer) = self.buffer.as_ref() {
272 let mut buffer = buffer.data_ref();
273 if let SoundBufferState::Streaming(ref mut streaming) = *buffer {
274 streaming.rewind()?;
275 }
276 }
277
278 Ok(())
279 }
280
281 pub fn playback_time(&self) -> Duration {
283 if let Some(buffer) = self.buffer.as_ref() {
284 let buffer = buffer.data_ref();
285 Duration::from_secs_f64(self.playback_pos / (buffer.sample_rate() as f64))
286 } else {
287 Duration::from_secs(0)
288 }
289 }
290
291 pub fn set_playback_time(&mut self, time: Duration) {
293 if let Some(buffer) = self.buffer.as_ref() {
294 let mut buffer = buffer.data_ref();
295 if let SoundBufferState::Streaming(ref mut streaming) = *buffer {
296 streaming.time_seek(time);
298 }
299 self.playback_pos = time.as_secs_f64() * buffer.sample_rate as f64;
301 self.buf_read_pos = match *buffer {
303 SoundBufferState::Streaming(ref mut streaming) => {
304 streaming.read_next_block();
306 self.playback_pos % (StreamingBuffer::STREAM_SAMPLE_COUNT as f64)
309 }
310 SoundBufferState::Generic(_) => self.playback_pos,
311 };
312 assert!(
313 self.buf_read_pos * (buffer.channel_count() as f64) < buffer.samples().len() as f64
314 );
315 }
316 }
317
318 pub(in crate) fn render(&mut self, amount: usize) {
319 if self.frame_samples.capacity() < amount {
320 self.frame_samples = Vec::with_capacity(amount);
321 }
322
323 self.frame_samples.clear();
324
325 if let Some(buffer) = self.buffer.clone() {
326 let mut state = buffer.state();
327 if let ResourceState::Ok(ref mut buffer) = *state {
328 if self.status == Status::Playing && !buffer.is_empty() {
329 self.render_playing(buffer, amount);
330 }
331 }
332 }
333 self.frame_samples.resize(amount, (0.0, 0.0));
335 }
336
337 fn render_playing(&mut self, buffer: &mut SoundBufferState, amount: usize) {
338 let mut count = 0;
339 loop {
340 count += self.render_until_block_end(buffer, amount - count);
341 if count == amount {
342 break;
343 }
344
345 let channel_count = buffer.channel_count();
346 let len = buffer.samples().len();
347 let mut end_reached = true;
348 if let SoundBufferState::Streaming(streaming) = buffer {
349 if len != channel_count * StreamingBuffer::STREAM_SAMPLE_COUNT {
351 let _ = streaming.rewind();
352 } else {
353 end_reached = false;
354 }
355 self.prev_buffer_sample = get_last_sample(streaming);
356 streaming.read_next_block();
357 }
358 if end_reached {
359 if !self.looping {
360 self.status = Status::Stopped;
361 return;
362 }
363 self.buf_read_pos = 0.0;
364 self.playback_pos = 0.0;
365 } else {
366 self.buf_read_pos -= len as f64 / channel_count as f64;
367 }
368 }
369 }
370
371 fn render_until_block_end(
374 &mut self,
375 buffer: &mut SoundBufferState,
376 mut amount: usize,
377 ) -> usize {
378 let step = self.pitch * self.resampling_multiplier;
379 if step == 1.0 {
380 if self.buf_read_pos < 0.0 {
381 self.frame_samples.push(self.prev_buffer_sample);
383 self.buf_read_pos = 0.0;
384 amount -= 1;
385 }
386 let from = self.buf_read_pos as usize;
388 let buffer_len = buffer.samples.len() / buffer.channel_count;
389 let rendered = (buffer_len - from).min(amount);
390 if buffer.channel_count == 2 {
391 for i in from..from + rendered {
392 self.frame_samples
393 .push((buffer.samples[i * 2], buffer.samples[i * 2 + 1]))
394 }
395 } else {
396 for i in from..from + rendered {
397 self.frame_samples
398 .push((buffer.samples[i], buffer.samples[i]))
399 }
400 }
401 self.buf_read_pos += rendered as f64;
402 self.playback_pos += rendered as f64;
403 rendered
404 } else {
405 self.render_until_block_end_resample(buffer, amount, step)
406 }
407 }
408
409 fn render_until_block_end_resample(
411 &mut self,
412 buffer: &mut SoundBufferState,
413 amount: usize,
414 step: f64,
415 ) -> usize {
416 let mut rendered = 0;
417
418 while self.buf_read_pos < 0.0 {
419 let w = (self.buf_read_pos - self.buf_read_pos.floor()) as f32;
423 let cur_first_sample = if buffer.channel_count == 2 {
424 (buffer.samples[0], buffer.samples[1])
425 } else {
426 (buffer.samples[0], buffer.samples[0])
427 };
428 let l = self.prev_buffer_sample.0 * (1.0 - w) + cur_first_sample.0 * w;
429 let r = self.prev_buffer_sample.1 * (1.0 - w) + cur_first_sample.1 * w;
430 self.frame_samples.push((l, r));
431 self.buf_read_pos += step;
432 self.playback_pos += step;
433 rendered += 1;
434 }
435
436 let buffer_base_idx = self.buf_read_pos as usize;
440 let mut buffer_rel_pos = (self.buf_read_pos - buffer_base_idx as f64) as f32;
441 let start_buffer_rel_pos = buffer_rel_pos;
442 let rel_step = step as f32;
443 let buffer_last = buffer.samples.len() / buffer.channel_count - 1;
446 if buffer.channel_count == 2 {
447 while rendered < amount {
448 let (idx, w) = {
449 let idx = buffer_rel_pos as usize;
450 (idx + buffer_base_idx, buffer_rel_pos - idx as f32)
453 };
454 if idx >= buffer_last {
455 break;
456 }
457 let l = buffer.samples[idx * 2] * (1.0 - w) + buffer.samples[idx * 2 + 2] * w;
458 let r = buffer.samples[idx * 2 + 1] * (1.0 - w) + buffer.samples[idx * 2 + 3] * w;
459 self.frame_samples.push((l, r));
460 buffer_rel_pos += rel_step;
461 rendered += 1;
462 }
463 } else {
464 while rendered < amount {
465 let (idx, w) = {
466 let idx = buffer_rel_pos as usize;
467 (idx + buffer_base_idx, buffer_rel_pos - idx as f32)
469 };
470 if idx >= buffer_last {
471 break;
472 }
473 let v = buffer.samples[idx] * (1.0 - w) + buffer.samples[idx + 1] * w;
474 self.frame_samples.push((v, v));
475 buffer_rel_pos += rel_step;
476 rendered += 1;
477 }
478 }
479
480 self.buf_read_pos += (buffer_rel_pos - start_buffer_rel_pos) as f64;
481 self.playback_pos += (buffer_rel_pos - start_buffer_rel_pos) as f64;
482 rendered
483 }
484
485 pub(in crate) fn frame_samples(&self) -> &[(f32, f32)] {
486 &self.frame_samples
487 }
488}
489
490fn get_last_sample(buffer: &StreamingBuffer) -> (f32, f32) {
491 let len = buffer.samples.len();
492 if len == 0 {
493 return (0.0, 0.0);
494 }
495 if buffer.channel_count == 2 {
496 (buffer.samples[len - 2], buffer.samples[len - 1])
497 } else {
498 (buffer.samples[len - 1], buffer.samples[len - 1])
499 }
500}
501
502impl Drop for GenericSource {
503 fn drop(&mut self) {
504 if let Some(buffer) = self.buffer.as_ref() {
505 let mut buffer = buffer.data_ref();
506 if let SoundBufferState::Streaming(ref mut streaming) = *buffer {
507 streaming.use_count = streaming.use_count.saturating_sub(1);
508 }
509 }
510 }
511}
512
513impl Visit for GenericSource {
514 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
515 visitor.enter_region(name)?;
516
517 let _ = self.name.visit("Name", visitor);
518 self.buffer.visit("Buffer", visitor)?;
519 self.buf_read_pos.visit("BufReadPos", visitor)?;
520 self.playback_pos.visit("PlaybackPos", visitor)?;
521 self.panning.visit("Pan", visitor)?;
522 self.pitch.visit("Pitch", visitor)?;
523 self.gain.visit("Gain", visitor)?;
524 self.looping.visit("Looping", visitor)?;
525 self.resampling_multiplier
526 .visit("ResamplingMultiplier", visitor)?;
527 self.status.visit("Status", visitor)?;
528 self.play_once.visit("PlayOnce", visitor)?;
529
530 visitor.leave_region()
531 }
532}
533
534pub struct GenericSourceBuilder {
567 buffer: Option<SoundBufferResource>,
568 gain: f32,
569 pitch: f32,
570 name: String,
571 panning: f32,
572 looping: bool,
573 status: Status,
574 play_once: bool,
575}
576
577impl Default for GenericSourceBuilder {
578 fn default() -> Self {
579 Self::new()
580 }
581}
582
583impl GenericSourceBuilder {
584 pub fn new() -> Self {
586 Self {
587 buffer: None,
588 gain: 1.0,
589 pitch: 1.0,
590 name: Default::default(),
591 panning: 0.0,
592 looping: false,
593 status: Status::Stopped,
594 play_once: false,
595 }
596 }
597
598 pub fn with_buffer(mut self, buffer: SoundBufferResource) -> Self {
600 self.buffer = Some(buffer);
601 self
602 }
603
604 pub fn with_gain(mut self, gain: f32) -> Self {
606 self.gain = gain;
607 self
608 }
609
610 pub fn with_pitch(mut self, pitch: f32) -> Self {
612 self.pitch = pitch;
613 self
614 }
615
616 pub fn with_panning(mut self, panning: f32) -> Self {
618 self.panning = panning;
619 self
620 }
621
622 pub fn with_looping(mut self, looping: bool) -> Self {
624 self.looping = looping;
625 self
626 }
627
628 pub fn with_status(mut self, status: Status) -> Self {
630 self.status = status;
631 self
632 }
633
634 pub fn with_play_once(mut self, play_once: bool) -> Self {
636 self.play_once = play_once;
637 self
638 }
639
640 pub fn with_name<N: AsRef<str>>(mut self, name: N) -> Self {
642 self.name = name.as_ref().to_owned();
643 self
644 }
645
646 pub fn build(self) -> Result<GenericSource, SoundError> {
648 let mut source = GenericSource {
649 buffer: self.buffer.clone(),
650 gain: self.gain,
651 pitch: self.pitch as f64,
652 play_once: self.play_once,
653 panning: self.panning,
654 status: self.status,
655 looping: self.looping,
656 name: self.name,
657 frame_samples: Default::default(),
658 ..Default::default()
659 };
660
661 source.set_buffer(self.buffer)?;
662
663 Ok(source)
664 }
665
666 pub fn build_source(self) -> Result<SoundSource, SoundError> {
668 Ok(SoundSource::Generic(self.build()?))
669 }
670}