rg3d_sound/buffer/
streaming.rs

1//! Streaming buffer.
2//!
3//! # Overview
4//!
5//! Streaming buffers are used for long sounds (usually longer than 15 seconds) to reduce memory usage.
6//! Some sounds in games are very long - music, ambient sounds, voice, etc. and it is too inefficient
7//! to load and decode them directly into memory all at once - it will just take enormous amount of memory
8//! that could be used to something more useful.
9//!
10//! # Usage
11//!
12//! There are almost no difference with generic buffers:
13//!
14//! ```no_run
15//! use std::sync::{Mutex, Arc};
16//! use rg3d_sound::buffer::{SoundBufferResource, DataSource};
17//!
18//! async fn make_streaming_buffer() -> SoundBufferResource {
19//!     let data_source = DataSource::from_file("some_long_sound.ogg").await.unwrap();
20//!     SoundBufferResource::new_streaming(data_source).unwrap()
21//! }
22//! ```
23//!
24//! # Notes
25//!
26//! Streaming buffer cannot be shared across multiple source. On attempt to create a source with a streaming
27//! buffer that already in use you'll get error.
28
29use crate::buffer::RawStreamingDataSource;
30use crate::{
31    buffer::{generic::GenericBuffer, DataSource},
32    decoder::Decoder,
33    error::SoundError,
34};
35use rg3d_core::visitor::{Visit, VisitResult, Visitor};
36use std::ops::{Deref, DerefMut};
37use std::time::Duration;
38
39/// Streaming buffer for long sounds. Does not support random access.
40#[derive(Debug, Default)]
41pub struct StreamingBuffer {
42    pub(in crate) generic: GenericBuffer,
43    /// Count of sources that share this buffer, it is important to keep only one
44    /// user of streaming buffer, because streaming buffer does not allow random
45    /// access.
46    pub(in crate) use_count: usize,
47    streaming_source: StreamingSource,
48}
49
50#[derive(Debug)]
51enum StreamingSource {
52    Null,
53    Decoder(Decoder),
54    Raw(Box<dyn RawStreamingDataSource>),
55}
56
57impl Default for StreamingSource {
58    fn default() -> Self {
59        Self::Null
60    }
61}
62
63impl StreamingSource {
64    #[inline]
65    fn new(data_source: DataSource) -> Result<Self, DataSource> {
66        match data_source {
67            DataSource::File { .. } | DataSource::Memory(_) => {
68                Ok(Self::Decoder(Decoder::new(data_source)?))
69            }
70            DataSource::RawStreaming(raw) => Ok(Self::Raw(raw)),
71            // It makes no sense to stream raw data which is already loaded into memory.
72            _ => Err(data_source),
73        }
74    }
75
76    #[inline]
77    fn sample_rate(&self) -> usize {
78        match self {
79            StreamingSource::Decoder(decoder) => decoder.get_sample_rate(),
80            StreamingSource::Raw(raw) => raw.sample_rate(),
81            StreamingSource::Null => 0,
82        }
83    }
84
85    #[inline]
86    fn channel_count(&self) -> usize {
87        match self {
88            StreamingSource::Decoder(decoder) => decoder.get_channel_count(),
89            StreamingSource::Raw(raw) => raw.channel_count(),
90            StreamingSource::Null => 0,
91        }
92    }
93
94    fn duration(&self) -> Option<Duration> {
95        match self {
96            StreamingSource::Null => None,
97            StreamingSource::Decoder(decoder) => decoder.duration(),
98            StreamingSource::Raw(raw) => raw.duration(),
99        }
100    }
101
102    fn rewind(&mut self) -> Result<(), SoundError> {
103        match self {
104            StreamingSource::Null => Ok(()),
105            StreamingSource::Decoder(decoder) => decoder.rewind(),
106            StreamingSource::Raw(raw) => raw.rewind(),
107        }
108    }
109
110    fn time_seek(&mut self, location: Duration) {
111        match self {
112            StreamingSource::Null => {}
113            StreamingSource::Decoder(decoder) => decoder.time_seek(location),
114            StreamingSource::Raw(raw) => raw.time_seek(location),
115        }
116    }
117
118    #[inline]
119    fn read_next_samples_block_into(&mut self, buffer: &mut Vec<f32>) -> usize {
120        buffer.clear();
121        let count = StreamingBuffer::STREAM_SAMPLE_COUNT * self.channel_count();
122        match self {
123            StreamingSource::Decoder(decoder) => {
124                for _ in 0..count {
125                    if let Some(sample) = decoder.next() {
126                        buffer.push(sample)
127                    } else {
128                        break;
129                    }
130                }
131            }
132            StreamingSource::Raw(raw_streaming) => {
133                for _ in 0..count {
134                    if let Some(sample) = raw_streaming.next() {
135                        buffer.push(sample)
136                    } else {
137                        break;
138                    }
139                }
140            }
141            StreamingSource::Null => (),
142        }
143
144        buffer.len()
145    }
146}
147
148impl StreamingBuffer {
149    /// Defines amount of samples `per channel` which each streaming buffer will use for internal buffer.
150    pub const STREAM_SAMPLE_COUNT: usize = 44100;
151
152    /// Creates new streaming buffer using given data source. May fail if data source has unsupported format
153    /// or it has corrupted data. Length of internal generic buffer cannot be changed but can be fetched from
154    /// `StreamingBuffer::STREAM_SAMPLE_COUNT`
155    ///
156    /// # Notes
157    ///
158    /// This function will return Err if data source is `Raw`. It makes no sense to stream raw data which
159    /// is already loaded into memory. Use Generic source instead!
160    pub fn new(source: DataSource) -> Result<Self, DataSource> {
161        let external_source_path = if let DataSource::File { path, .. } = &source {
162            path.clone()
163        } else {
164            Default::default()
165        };
166
167        let mut streaming_source = StreamingSource::new(source)?;
168
169        let mut samples = Vec::new();
170        let channel_count = streaming_source.channel_count();
171        streaming_source.read_next_samples_block_into(&mut samples);
172        debug_assert_eq!(samples.len() % channel_count, 0);
173
174        Ok(Self {
175            generic: GenericBuffer {
176                samples,
177                sample_rate: streaming_source.sample_rate(),
178                channel_count: streaming_source.channel_count(),
179                external_source_path,
180            },
181            use_count: 0,
182            streaming_source,
183        })
184    }
185
186    /// Returns total duration of data. Can be `None` if internal decoder does not supports seeking.
187    pub fn duration(&self) -> Option<Duration> {
188        self.streaming_source.duration()
189    }
190
191    #[inline]
192    pub(in crate) fn read_next_block(&mut self) {
193        self.streaming_source
194            .read_next_samples_block_into(&mut self.generic.samples);
195    }
196
197    #[inline]
198    pub(in crate) fn rewind(&mut self) -> Result<(), SoundError> {
199        self.streaming_source.rewind()
200    }
201
202    #[inline]
203    pub(in crate) fn time_seek(&mut self, location: Duration) {
204        self.streaming_source.time_seek(location);
205    }
206}
207
208impl Deref for StreamingBuffer {
209    type Target = GenericBuffer;
210
211    /// Returns shared reference to internal generic buffer. Can be useful to get some info (sample rate,
212    /// channel count).
213    fn deref(&self) -> &Self::Target {
214        &self.generic
215    }
216}
217
218impl DerefMut for StreamingBuffer {
219    /// Returns mutable reference to internal generic buffer. Can be used to modify it.
220    fn deref_mut(&mut self) -> &mut Self::Target {
221        &mut self.generic
222    }
223}
224
225impl Visit for StreamingBuffer {
226    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
227        visitor.enter_region(name)?;
228
229        self.generic.visit("Generic", visitor)?;
230
231        visitor.leave_region()
232    }
233}