fyrox_sound/buffer/generic.rs
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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
//! Generic buffer module.
//!
//! # Overview
//!
//! Generic buffer is just an array of raw samples in IEEE float format with some additional info (sample rate,
//! channel count, etc.). All samples stored in interleaved format, which means samples for each channel are
//! near - `LRLRLR...`.
//!
//! # Usage
//!
//! Generic source can be created like so:
//!
//! ```no_run
//! use std::sync::{Mutex, Arc};
//! use fyrox_sound::buffer::{SoundBufferResource, DataSource, SoundBufferResourceExtension};
//! use fyrox_resource::io::FsResourceIo;
//!
//! async fn make_buffer() -> SoundBufferResource {
//! let data_source = DataSource::from_file("sound.wav", &FsResourceIo).await.unwrap();
//! SoundBufferResource::new_generic(data_source).unwrap()
//! }
//! ```
#![allow(clippy::manual_range_contains)]
use crate::{buffer::DataSource, decoder::Decoder};
use fyrox_core::{reflect::prelude::*, visitor::prelude::*};
use std::time::Duration;
/// Generic sound buffer that contains decoded samples and allows random access.
#[derive(Debug, Default, Visit, Reflect)]
pub struct GenericBuffer {
/// Interleaved decoded samples (mono sounds: L..., stereo sounds: LR...)
/// For streaming buffers it contains only small part of decoded data
/// (usually something around 1 sec).
#[visit(skip)]
pub(crate) samples: Vec<f32>,
#[visit(skip)]
pub(crate) channel_count: usize,
#[visit(skip)]
pub(crate) sample_rate: usize,
#[visit(skip)]
pub(crate) channel_duration_in_samples: usize,
}
impl GenericBuffer {
/// Creates new generic buffer from specified data source. May fail if data source has unsupported
/// format, corrupted, etc.
///
/// # Notes
///
/// `DataSource::RawStreaming` is **not** supported with generic buffers, use streaming buffer
/// instead!
///
/// Data source with raw samples must have sample count multiple of channel count, otherwise this
/// function will return `Err`.
pub fn new(source: DataSource) -> Result<Self, DataSource> {
match source {
DataSource::Raw {
sample_rate,
channel_count,
samples,
} => {
if channel_count < 1 || channel_count > 2 || samples.len() % channel_count != 0 {
Err(DataSource::Raw {
sample_rate,
channel_count,
samples,
})
} else {
Ok(Self {
channel_duration_in_samples: samples.len() / channel_count,
samples,
channel_count,
sample_rate,
})
}
}
DataSource::RawStreaming(_) => Err(source),
_ => {
// Store cursor to handle errors.
let (is_memory, external_cursor) = if let DataSource::Memory(cursor) = &source {
(true, cursor.clone())
} else {
(false, Default::default())
};
let decoder = Decoder::new(source)?;
if decoder.get_channel_count() < 1 || decoder.get_channel_count() > 2 {
if is_memory {
return Err(DataSource::Memory(external_cursor));
} else {
// There is not much we can do here: if the user supplied DataSource::File,
// they probably do not want us to re-read the file again in
// DataSource::from_file.
return Err(DataSource::Raw {
sample_rate: decoder.get_sample_rate(),
channel_count: decoder.get_channel_count(),
samples: vec![],
});
}
}
Ok(Self {
sample_rate: decoder.get_sample_rate(),
channel_count: decoder.get_channel_count(),
channel_duration_in_samples: decoder.channel_duration_in_samples(),
samples: decoder.into_samples(),
})
}
}
}
/// Checks if buffer is empty or not.
#[inline]
pub fn is_empty(&self) -> bool {
self.samples.is_empty()
}
/// Returns shared reference to an array with samples.
#[inline]
pub fn samples(&self) -> &[f32] {
&self.samples
}
/// Returns mutable reference to an array with samples that could be modified.
pub fn samples_mut(&mut self) -> &mut [f32] {
&mut self.samples
}
/// Returns exact amount of channels in the buffer.
#[inline]
pub fn channel_count(&self) -> usize {
self.channel_count
}
/// Returns sample rate of the buffer.
#[inline]
pub fn sample_rate(&self) -> usize {
self.sample_rate
}
/// Returns exact time length of the buffer.
#[inline]
pub fn duration(&self) -> Duration {
Duration::from_nanos(
(self.channel_duration_in_samples as u64 * 1_000_000_000u64) / self.sample_rate as u64,
)
}
/// Returns exact duration of each channel (in samples) of the buffer. The returned value represents the entire length
/// of each channel in the buffer, even if it is streaming and its content is not yet fully decoded.
#[inline]
pub fn channel_duration_in_samples(&self) -> usize {
self.channel_duration_in_samples
}
}