* Call `Sink::clear`/`Sink::skip_one` on an empty `Sink` will permanently skip any `Source` append to it
* Call `Sink::clear` on an non-empty `Sink` can't reset it's length().
* Clear and Skip functionality added
Added a clear() and skip_one() method to the Sink impl
* Use one lock for clear
Return the length in the queue clear function so that we don't have to get a lock twice.
* Rework skip to mark all sources as skippable
---------
Co-authored-by: Nathan Abel <abel8706@kettering.edu>
Co-authored-by: Ivar Kamsvåg <ivaka037@student.liu.se>
Co-authored-by: est31 <est31@users.noreply.github.com>
Addressing issues #462 and #315 and #171
Given how the sink's queue is drained on stop I made some modifications in sink.append(). I added a check to ensure the sink was flushed completely (not sure this is necessary? I think it is, to avoid race conditions) and to restart the sink on append (when stopped.)
I added a test demonstrating correctness, as well as performing some trials on my own.
This example plays a C Major 6th chord by adding four sources, sine waves frequencies of C, E, G, and A, to a `DynamicMixerController`, and appends its respective `DynamicMixer` to a sink.
As I understand it, this is the issue:
* Previously, when a queue has `keep_alive_if_empty` set to true, and it becomes empty, then it will push a silence lasting 10ms onto the queue.
* This is an issue because `current_frame_len` would have returned the worst case, `512`, and the silence lasts less than that.
* This means that unless the source is added immediately to the queue, and so a silence is never played, then the first actual source could start playing at a frame that is not aligned to its channels, or play at the wrong sample rate.
* This is only determined by when the source is added to the queue after its initialization. This explains why the issue was inconsistent, as it relied on the speed of execution of code which is basically random.
Solution
* Change the functionality of `Zero` to add a method to create a silence with a certain number of frames.
* Replace the 10ms silence with a silence the length of `THRESHOLD`
* Change queue's `current_frame_len` to return `THRESHOLD` if a silence will be played next.
ignore NaNs when setting the volume of each ear. min will return its value if self is a NaN. Also adds a check with debug_assert to help with debugging.
The types `Frame` and `FrameData` are mutually recursive, and the
incidental linked lists that can be formed as a result can be long (at
least in the order of thousands of elements). As a result, when a frame
is deallocated, rust appears to recursively call `drop_in_place` down
the list, causing stack overflows for long lists.
* Skip no more than 3 consecutive decode errors
* missing delimiter
* Corrections after build
* use const
* reorganize second loop
Co-authored-by: Rrogntudju <rrogntudju@example.com>
I think this makes the next() function easier to understand. We can
write this more efficiently by reusing a Vec on the struct rather than
allocating each time and a mem::swap to avoid shifting elements in a Vec.
For example, if a stereo source starts playing on an odd-numbered call
to DynamicMixer::next() then the output stream will play its first
sample in the right channel, its second in the left, etc. This is wrong.
The first sample should be played in the left channel.
If the source we are skipping runs out of data, it will return Some(0)
as the frame length. Before, this would cause an infinite loop because
we would skip zero samples forever. This commit fixes it by checking
explicitly if the frame length is zero and bailing out if it is.
Implementing the Display trait on a type, and calling self.to_string()
in its implementation results in infinite recursion.
The default implementation of ToString for sized types that implement
Display relies on the Display trait in its implementation.
Consequently, calling `self.to_string()` in the implementation of
Display leads to infinite recursion.
This failure has been directly observed on the DecoderError type, and
the fix here is to move the logic for rendering the error as text out of
`Error::description()` and into `impl Display`. As it stands, the
`Error` trait provides a default implementation for `description()`
based on the `Display` trait if provided, so this is a simple, clean
change.
The failure is presumed to exist for Mp4Type, as it follows a similar
pattern of invoking `self.to_string()` in the `Display` implementation.
The solution there is basically to reverse the logic for `from_str()`.
* add symphonia decoder
* add symphonia-flac
* better compile errors
* remove unsafe send
* update ci
* sudo
* disable duration check because symphonia does not support it
* add error handling
* cleanup
* update symphonia and fix breaking changes
* update to published symphonia version
* update docs
* reduce namespace duplication
* remove extra reference to current frame
* pr comments
* exclude decoders from module if unused
* fix flac test
* recommend disabling default features with symphonia