Fix FLAC playback auto-stop issues and reset frame buffer on seek#910
Fix FLAC playback auto-stop issues and reset frame buffer on seek#910axel10 wants to merge 2 commits into
Conversation
|
Thanks for the PR! I am not sure whether the sample file conforms to the FLAC specification. Running it through and I will take a closer look at the file structure to see what is going on. Do you know where this file came from (which encoder/editor)? Clearing |
|
I've forgotten where this file came from; it was probably downloaded from some forum or obscure website. This song plays fine with Rust's Rodio, but mainstream players do exhibit inconsistent behavior when playing it. foobar2000 or IINA loop the last few seconds of the 10-second song. Android's Poweramp, however, freezes at the end. I have a music player project that uses rust-ffmpeg to call ffmpeg for audio decoding on Windows and Linux, which can be used for testing. https://github.com/axel10/vibe_flow |
|
Since the total duration of a FLAC file is calculated using STREAMINFO, the total_samples in STREAMINFO should be considered complete after playback, ignoring any remaining data. As a mandatory metadata block, STREAMINFO is included in most FLAC files to record the actual song length, so a total_samples value less than the actual length is almost never found. Because the FLAC specification is somewhat lenient, some software may overload the song with metadata. Using total_samples to limit sampling is a robust approach, in my opinion. |
|
I took a closer look at the file's structure and the second metadata block (at file offset 42) has an illegal header. The first bit is 0 indicating the metadata block is not the last one and the remaining 7 bits encode the block type which is 127- an illegal value. I believe I haven't worked through the FLAC frames to see what causes the loss of sync after 14078484 frames. According to the stream info block the file consists of 14078484 frames so perhaps there is trailing garbage at the end of the file. Your suggestion to limit decoding to the number of samples contained in the stream info block (if non-zero) is an interesting one. Another option I'm investigating is whether errors reported through calls to |
Description
This pull request addresses two distinct issues in
SFBFLACDecoder:For certain FLAC files (e.g., those containing trailing metadata, ID3v2 tags, or padding blocks after the audio frames), the underlying decoder continues to process non-audio blocks via
FLAC__stream_decoder_process_single()successfully. BecauseFLAC__stream_decoder_get_state()does not yet returnFLAC__STREAM_DECODER_END_OF_STREAMduring these calls, the decode loop indecodeIntoBuffer:frameLength:error:can get stuck in a spin or fail to immediately signal EOF (returning a buffer frame length of 0)._streamInfo.total_samplesis known, we clamp the requestedframeLengthto the remaining samples. If_framePositionis already at or past the total sample count, we return early, signaling EOF.When
seekToFrame:error:is called, the internal push-to-pull buffer_frameBuffermay still contain leftover decoded frames from the pre-seek position. If these are not cleared, the nextdecodeIntoBuffer:call will read these stale frames first, resulting in brief audio artifacts or incorrect position tracking immediately after a seek._frameBuffer.frameLengthto0upon a successful seek to ensure the next read pulls fresh data from the seek target.Changes
Sources/CSFBAudioEngine/Decoders/SFBFLACDecoder.mm:_framePositionagainst_streamInfo.total_samplesand clampframeLengthindecodeIntoBuffer:frameLength:error:._frameBuffer.frameLengthto0inseekToFrame:error:.This is the test file: https://drive.google.com/file/d/1Jk7PvfMK9YmMoQaWv29iQbxch0d9dtm8/view?usp=sharing