Repository navigation
feat: add TTA as a Stream-to-Stream ConvertFile/CutFile destination - #127
Merged
Merged
Conversation
TtaEncoderSession.OpenSession gained a Stream-based overload, mirroring WavWriter/AiffWriter/AuWriter/FlacEncoder's own Create(Stream, ...)/ OpenSession(Stream, ...) overloads. Unlike FLAC (the only prior destination that needs CanSeek), TTA needs no CanSeek at all despite also needing no exactTotalFrames up front: TtaEncoderSession already holds every compressed frame in memory until Finish(), at which point TtaWriter writes the header, seek table, and frame data in one single forward pass -- no patch-up ever needed. Confirmed directly (not just assumed from the absence of a CanSeek check) via a test that writes through a destination whose Seek/Position throw. TtaEncoderSession's own destination field was widened from FileStream to Stream plus a leaveOpen flag (mirroring WavWriter's own convention) so Dispose() only closes a stream this type actually owns. Channel/bit-depth/ sample-rate validation was factored into a shared private helper so the path-based and Stream-based OpenSession overloads can't drift apart. Wired into AudioCutter.Stream.cs's OpenSinkStream as the AudioFormat.Tta destination case -- no DeferredFixedHeaderSink needed, same reasoning as FLAC's own case. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Continues
docs/feature-roadmap.mditem 1's own "destination-Stream" half (WAV/AIFF/AU/FLAC already done — see #108, #122). This item: TTA.TtaEncoderSession.OpenSession(Stream destStream, ...)-- a new overload, mirroringWavWriter/AiffWriter/AuWriter/FlacEncoder's ownCreate(Stream, ...)/OpenSession(Stream, ...)overloads. Needs noStream.CanSeekat all -- unlike FLAC (the only prior destination that genuinely requires it), TTA already holds every compressed frame in memory untilFinish()(TtaEncoderSession's own pre-existing design, sinceTtaWriter's own seek table needs every frame's final size up front regardless), at which pointTtaWriter.Writewrites the header, seek table, and frame data in a single forward pass with no patch-up ever needed. Confirmed directly via a test that writes through a destination whoseSeek/Positionthrow, not just assumed from the absence of aCanSeekcheck.TtaEncoderSession's own destination field was widened fromFileStreamtoStreamplus aleaveOpenflag (mirroringWavWriter's own convention) soDispose()only closes a stream this type actually owns.OpenSessionoverloads can't drift apart on what's valid.AudioCutter.Stream.cs'sOpenSinkStreamas theAudioFormat.Ttadestination case -- noDeferredFixedHeaderSinkneeded, same reasoning as FLAC's own case.Docs synced:
CLAUDE.md,README.md,llms.txt,llms-full.txt,docs/feature-roadmap.mditem 1's own status note.Test plan
TtaEncoderSessionTestcases: null stream, unsupported channel count/bit depth/sample rate, exact round-trip via aMemoryStreamdestination, a genuinely non-seekable destination (confirms noCanSeekrequirement end-to-end, not just an absent check), andDispose()not disposing the caller's stream.AudioCutterStreamTestcases: WAV source → TTAStreamdestination round-trip (exact samples, lossless), and a non-seekable TTA destination succeeding through the fullAudioCutter.Convertcall.dotnet test --configuration Release(net10.0 locally): 1759 passed (1750 baseline + 9 new), 2 pre-existing skips (1 WMA, 1 the already-tracked MP3 synthesis-filter bug), 0 failed.dotnet build --configuration Release: 0 warnings, 0 errors, all target frameworks.🤖 Generated with Claude Code