-
Notifications
You must be signed in to change notification settings - Fork 329
Phase1b of audio engine rewrite #904
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
yara-blue
wants to merge
11
commits into
master
Choose a base branch
from
phase1b
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
a365e10
Warn for in progress rewrite in Readme
yara-blue 3f086ff
land const source
yara-blue 8ed9f6e
Add silence generator (only for const source)
yara-blue f4e9464
add seeking
yara-blue a5e02a9
Extract code shared between sources to common/source
yara-blue 49a3fa0
review feedback
yara-blue 3708b06
expand fixed source to match const
yara-blue ca4f014
Add fixed source 'adapter' to ConstSource
yara-blue b457874
add fixedsource to silence generator
yara-blue 900d34d
add seeking and deduplicate
yara-blue ddfa50f
review feedback
yara-blue File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| //! Code shared between source types. | ||
| //! | ||
| //! Since we have three source types there is a lot of code duplication. We | ||
| //! combat that by placing whatever can be shared here. | ||
| //! | ||
| //! This can be: | ||
| //! - shared types like error enums | ||
| //! - shared free functions | ||
| //! - shared members / impl blocks through macro_rules | ||
| //! | ||
| //! # Note | ||
| //! Effects are defined through a macro and do not need this kind of | ||
| //! deduplication | ||
| //! | ||
| //! This modules structure mirrors that of what it deduplicates. For example | ||
| //! the code shared between [fixed_source::chain] and [const_source::chain] is in | ||
| //! common/source/chain.rs | ||
|
|
||
| pub(crate) mod buffer; | ||
| pub(crate) mod chain; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| macro_rules! source_impl { | ||
| () => { | ||
| /// # Panics | ||
| /// If the length of the buffer is larger than approximately 16 billion elements. | ||
| /// This is because the calculation of the duration would overflow. | ||
| #[inline] | ||
| fn total_duration(&self) -> Option<Duration> { | ||
| use crate::math::NANOS_PER_SEC; | ||
|
|
||
| let duration_ns = NANOS_PER_SEC | ||
| .checked_mul(self.data.len() as u64) | ||
| .expect("slices longer then 16 billion elements are not supported") | ||
| / self.sample_rate().get() as u64 | ||
| / self.channels().get() as u64; | ||
| let duration = Duration::new( | ||
| duration_ns / NANOS_PER_SEC, | ||
| (duration_ns % NANOS_PER_SEC) as u32, | ||
| ); | ||
|
|
||
| Some(duration) | ||
| } | ||
|
|
||
| /// This jumps in memory to the sample corresponding to `pos`. | ||
| #[inline] | ||
| fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> { | ||
| // This is fast because all the samples are in memory already | ||
| // and due to the constant sample_rate we can jump to the right | ||
| // sample directly. | ||
|
|
||
| let curr_channel = self.pos % self.channels().get() as usize; | ||
| let new_pos = crate::math::duration_to_float(pos) | ||
| * self.sample_rate().get() as crate::Float | ||
| * self.channels().get() as crate::Float; | ||
| // saturate pos at the end of the source | ||
| let new_pos = new_pos as usize; | ||
| let new_pos = new_pos.min(self.data.len()); | ||
|
|
||
| // make sure the next sample is for the right channel | ||
| let new_pos = new_pos.next_multiple_of(self.channels().get() as usize); | ||
| let new_pos = new_pos + curr_channel; | ||
|
|
||
| self.pos = new_pos; | ||
| Ok(()) | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| macro_rules! iter_impl { | ||
| () => { | ||
| type Item = Sample; | ||
| #[inline] | ||
| fn next(&mut self) -> Option<Self::Item> { | ||
| let sample = self.data.get(self.pos)?; | ||
| self.pos += 1; | ||
| Some(*sample) | ||
| } | ||
| #[inline] | ||
| fn size_hint(&self) -> (usize, Option<usize>) { | ||
| let remaining = self.data.len().saturating_sub(self.pos); | ||
| (remaining, Some(remaining)) | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| pub(crate) use iter_impl; | ||
| pub(crate) use source_impl; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| use crate::source::SeekError; | ||
|
|
||
| #[derive(Debug, thiserror::Error)] | ||
| pub enum ChainSeekError { | ||
| #[error("Could not get duration of first source ({ty})")] | ||
| NoTotalDurationForFirst { ty: &'static str }, | ||
| #[error("Could not seek in first source ({ty})")] | ||
| FailedToSeekInFirst { | ||
| ty: &'static str, | ||
| #[source] | ||
| error: SeekError, | ||
| }, | ||
| #[error("Could not reset first source ({ty}) to start")] | ||
| FailedToResetFirst { | ||
| ty: &'static str, | ||
| #[source] | ||
| error: SeekError, | ||
| }, | ||
| #[error("Could not seek in second source ({ty})")] | ||
| FailedToSeekInSecond { | ||
| ty: &'static str, | ||
| #[source] | ||
| error: SeekError, | ||
| }, | ||
| } | ||
|
|
||
| macro_rules! source_impl { | ||
| () => { | ||
| fn channels(&self) -> crate::ChannelCount { | ||
| self.first.channels() | ||
| } | ||
|
|
||
| fn sample_rate(&self) -> crate::SampleRate { | ||
| self.first.sample_rate() | ||
| } | ||
|
|
||
| fn total_duration(&self) -> Option<std::time::Duration> { | ||
| self.first | ||
| .total_duration() | ||
| .and_then(|d| self.second.total_duration().map(|d2| d2 + d)) | ||
| } | ||
|
|
||
| fn try_seek(&mut self, pos: std::time::Duration) -> Result<(), crate::source::SeekError> { | ||
| use crate::source::SeekError; | ||
| use std::any::type_name_of_val; | ||
| use std::sync::Arc; | ||
|
|
||
| let Some(first) = self.first.total_duration() else { | ||
| return Err(ChainSeekError::NoTotalDurationForFirst { | ||
| ty: type_name_of_val(&self.first), | ||
| }) | ||
| .map_err(Arc::new) | ||
| .map_err(|e| SeekError::Other(e)); | ||
| }; | ||
|
|
||
| if pos < first { | ||
| // Reset first source to prevent a jump to the current position | ||
| // after the first source completes again. | ||
| if !self.playing_first { | ||
| // FIXME(yara): implement Seekable trait for all sources and extract | ||
| // this to a function. (all sources are required to impl Seekable). | ||
| // Might wanna do a similar thing for other shared functionality | ||
| // like total duration | ||
| self.second | ||
| .try_seek(std::time::Duration::ZERO) | ||
| .map_err(|error| ChainSeekError::FailedToResetFirst { | ||
| ty: type_name_of_val(&self.first), | ||
| error, | ||
| }) | ||
| .map_err(Arc::new) | ||
| .map_err(|e| SeekError::Other(e))?; | ||
| } | ||
|
|
||
| self.first | ||
| .try_seek(pos) | ||
| .map_err(|error| ChainSeekError::FailedToSeekInFirst { | ||
| ty: type_name_of_val(&self.first), | ||
| error, | ||
| }) | ||
| .map_err(Arc::new) | ||
| .map_err(|e| SeekError::Other(e))?; | ||
| self.playing_first = true; | ||
| Ok(()) | ||
| } else { | ||
| self.second | ||
| .try_seek(pos - first) | ||
| .map_err(|error| ChainSeekError::FailedToSeekInSecond { | ||
| ty: type_name_of_val(&self.second), | ||
| error, | ||
| }) | ||
| .map_err(Arc::new) | ||
| .map_err(|e| SeekError::Other(e))?; | ||
| self.playing_first = false; | ||
| Ok(()) | ||
| } | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| macro_rules! iter_impl { | ||
| () => { | ||
| type Item = Sample; | ||
|
|
||
| fn next(&mut self) -> Option<Self::Item> { | ||
| if self.playing_first { | ||
| match self.first.next() { | ||
| Some(sample) => Some(sample), | ||
| None => { | ||
| self.playing_first = false; | ||
| self.second.next() | ||
| } | ||
| } | ||
| } else { | ||
| self.second.next() | ||
| } | ||
| } | ||
|
|
||
| #[inline] | ||
| fn size_hint(&self) -> (usize, Option<usize>) { | ||
| let (lower_bound_a, upper_bound_a) = self.first.size_hint(); | ||
| let (lower_bound_b, upper_bound_b) = self.second.size_hint(); | ||
|
|
||
| let lower_bound = lower_bound_a + lower_bound_b; | ||
| let upper_bound = upper_bound_a.zip(upper_bound_b).map(|(a, b)| a + b); | ||
| (lower_bound, upper_bound) | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| pub(crate) use iter_impl; | ||
| pub(crate) use source_impl; | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should re-add
size_hint().