fyrox_sound/buffer/
streaming.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Streaming buffer.
22//!
23//! # Overview
24//!
25//! Streaming buffers are used for long sounds (usually longer than 15 seconds) to reduce memory usage.
26//! Some sounds in games are very long - music, ambient sounds, voice, etc. and it is too inefficient
27//! to load and decode them directly into memory all at once - it will just take enormous amount of memory
28//! that could be used to something more useful.
29//!
30//! # Usage
31//!
32//! There are almost no difference with generic buffers:
33//!
34//! ```no_run
35//! use std::sync::{Mutex, Arc};
36//! use fyrox_sound::buffer::{SoundBufferResource, DataSource, SoundBufferResourceExtension};
37//! use fyrox_resource::io::FsResourceIo;
38//!
39//! async fn make_streaming_buffer() -> SoundBufferResource {
40//!     let data_source = DataSource::from_file("some_long_sound.ogg", &FsResourceIo).await.unwrap();
41//!     SoundBufferResource::new_streaming(data_source).unwrap()
42//! }
43//! ```
44//!
45//! # Notes
46//!
47//! Streaming buffer cannot be shared across multiple source. On attempt to create a source with a streaming
48//! buffer that already in use you'll get error.
49
50use crate::buffer::generic::Samples;
51use crate::{
52    buffer::{generic::GenericBuffer, DataSource, RawStreamingDataSource},
53    decoder::Decoder,
54    error::SoundError,
55};
56use fyrox_core::{reflect::prelude::*, visitor::prelude::*};
57use std::{
58    ops::{Deref, DerefMut},
59    time::Duration,
60};
61
62/// Streaming buffer for long sounds. Does not support random access.
63#[derive(Debug, Default, Visit, Reflect)]
64pub struct StreamingBuffer {
65    pub(crate) generic: GenericBuffer,
66    /// Count of sources that share this buffer, it is important to keep only one
67    /// user of streaming buffer, because streaming buffer does not allow random
68    /// access.
69    #[visit(skip)]
70    pub(crate) use_count: usize,
71    #[visit(skip)]
72    #[reflect(hidden)]
73    streaming_source: StreamingSource,
74}
75
76#[derive(Debug)]
77enum StreamingSource {
78    Null,
79    Decoder(Decoder),
80    Raw(Box<dyn RawStreamingDataSource>),
81}
82
83impl Default for StreamingSource {
84    fn default() -> Self {
85        Self::Null
86    }
87}
88
89impl StreamingSource {
90    #[inline]
91    fn new(data_source: DataSource) -> Result<Self, DataSource> {
92        match data_source {
93            DataSource::File { .. } | DataSource::Memory(_) => {
94                Ok(Self::Decoder(Decoder::new(data_source)?))
95            }
96            DataSource::RawStreaming(raw) => Ok(Self::Raw(raw)),
97            // It makes no sense to stream raw data which is already loaded into memory.
98            _ => Err(data_source),
99        }
100    }
101
102    #[inline]
103    fn sample_rate(&self) -> usize {
104        match self {
105            StreamingSource::Decoder(decoder) => decoder.get_sample_rate(),
106            StreamingSource::Raw(raw) => raw.sample_rate(),
107            StreamingSource::Null => 0,
108        }
109    }
110
111    #[inline]
112    fn channel_count(&self) -> usize {
113        match self {
114            StreamingSource::Decoder(decoder) => decoder.get_channel_count(),
115            StreamingSource::Raw(raw) => raw.channel_count(),
116            StreamingSource::Null => 0,
117        }
118    }
119
120    fn channel_duration_in_samples(&self) -> usize {
121        match self {
122            StreamingSource::Null => 0,
123            StreamingSource::Decoder(decoder) => decoder.channel_duration_in_samples(),
124            StreamingSource::Raw(raw) => raw.channel_duration_in_samples(),
125        }
126    }
127
128    fn rewind(&mut self) -> Result<(), SoundError> {
129        match self {
130            StreamingSource::Null => Ok(()),
131            StreamingSource::Decoder(decoder) => decoder.rewind(),
132            StreamingSource::Raw(raw) => raw.rewind(),
133        }
134    }
135
136    fn time_seek(&mut self, location: Duration) {
137        match self {
138            StreamingSource::Null => {}
139            StreamingSource::Decoder(decoder) => decoder.time_seek(location),
140            StreamingSource::Raw(raw) => raw.time_seek(location),
141        }
142    }
143
144    #[inline]
145    fn read_next_samples_block_into(&mut self, buffer: &mut Vec<f32>) -> usize {
146        buffer.clear();
147        let count = StreamingBuffer::STREAM_SAMPLE_COUNT * self.channel_count();
148        match self {
149            StreamingSource::Decoder(decoder) => {
150                for _ in 0..count {
151                    if let Some(sample) = decoder.next() {
152                        buffer.push(sample)
153                    } else {
154                        break;
155                    }
156                }
157            }
158            StreamingSource::Raw(raw_streaming) => {
159                for _ in 0..count {
160                    if let Some(sample) = raw_streaming.next() {
161                        buffer.push(sample)
162                    } else {
163                        break;
164                    }
165                }
166            }
167            StreamingSource::Null => (),
168        }
169
170        buffer.len()
171    }
172}
173
174impl StreamingBuffer {
175    /// Defines amount of samples `per channel` which each streaming buffer will use for internal buffer.
176    pub const STREAM_SAMPLE_COUNT: usize = 44100;
177
178    /// Creates new streaming buffer using given data source. May fail if data source has unsupported format
179    /// or it has corrupted data. Length of internal generic buffer cannot be changed but can be fetched from
180    /// `StreamingBuffer::STREAM_SAMPLE_COUNT`
181    ///
182    /// # Notes
183    ///
184    /// This function will return Err if data source is `Raw`. It makes no sense to stream raw data which
185    /// is already loaded into memory. Use Generic source instead!
186    pub fn new(source: DataSource) -> Result<Self, DataSource> {
187        let mut streaming_source = StreamingSource::new(source)?;
188
189        let mut samples = Vec::new();
190        let channel_count = streaming_source.channel_count();
191        streaming_source.read_next_samples_block_into(&mut samples);
192        debug_assert_eq!(samples.len() % channel_count, 0);
193
194        Ok(Self {
195            generic: GenericBuffer {
196                samples: Samples(samples),
197                sample_rate: streaming_source.sample_rate(),
198                channel_count: streaming_source.channel_count(),
199                channel_duration_in_samples: streaming_source.channel_duration_in_samples(),
200            },
201            use_count: 0,
202            streaming_source,
203        })
204    }
205
206    #[inline]
207    pub(crate) fn read_next_block(&mut self) {
208        self.streaming_source
209            .read_next_samples_block_into(&mut self.generic.samples);
210    }
211
212    #[inline]
213    pub(crate) fn rewind(&mut self) -> Result<(), SoundError> {
214        self.streaming_source.rewind()
215    }
216
217    #[inline]
218    pub(crate) fn time_seek(&mut self, location: Duration) {
219        self.streaming_source.time_seek(location);
220    }
221}
222
223impl Deref for StreamingBuffer {
224    type Target = GenericBuffer;
225
226    /// Returns shared reference to internal generic buffer. Can be useful to get some info (sample rate,
227    /// channel count).
228    fn deref(&self) -> &Self::Target {
229        &self.generic
230    }
231}
232
233impl DerefMut for StreamingBuffer {
234    /// Returns mutable reference to internal generic buffer. Can be used to modify it.
235    fn deref_mut(&mut self) -> &mut Self::Target {
236        &mut self.generic
237    }
238}