Safe Haskell | Safe-Inferred |
---|
Functions to do incremental render. It hashes Note.Note
s to skip
rerendering when possible.
Synopsis
- checkpointDir :: FilePath
- newtype State = State ByteString.ByteString
- encodeState :: State -> String
- skipCheckpoints :: FilePath -> State -> [(Config.ChunkNum, Note.Hash)] -> IO ([FilePath], [(Config.ChunkNum, Note.Hash)], Maybe State)
- findLastState :: Set FilePath -> State -> [(Config.ChunkNum, Note.Hash)] -> ([FilePath], ([(Config.ChunkNum, Note.Hash)], FilePath))
- write :: Bool -> FilePath -> Set Id.TrackId -> Config.ChunkNum -> Frames -> [(Config.ChunkNum, Note.Hash)] -> IO State -> AUtil.Audio -> IO (Either Text (Config.ChunkNum, Config.ChunkNum))
- getFilename :: FilePath -> IO State -> (Config.ChunkNum, Note.Hash) -> IO FilePath
- writeState :: IO State -> FilePath -> IO ()
- linkOutput :: Bool -> FilePath -> FilePath -> IO Config.ChunkNum
- clearRemainingOutput :: FilePath -> Config.ChunkNum -> IO ()
- outputPast :: Config.ChunkNum -> [FilePath] -> [FilePath]
- filenameToOutput :: FilePath -> FilePath
- filenameOf :: Config.ChunkNum -> Note.Hash -> State -> FilePath
- filenameOf2 :: Config.ChunkNum -> Note.Hash -> String -> FilePath
- maxChunk :: Config.ChunkNum
- zeroPad :: Show a => Int -> a -> ByteString.ByteString
- extendHashes :: [(Int, Note.Hash)] -> [(Int, Note.Hash)]
- noteHashes :: Frames -> [Span] -> [(Int, Note.Hash)]
- data Span = Span {}
- hashOverlapping :: RealTime -> RealTime -> [Span] -> [Note.Hash]
- overlappingHashes :: RealTime -> RealTime -> [Span] -> [[Note.Hash]]
- groupOverlapping :: RealTime -> RealTime -> [(a, Span)] -> [[(a, Span)]]
- splitOverlapping :: RealTime -> RealTime -> [(a, Span)] -> ([(a, Span)], [(a, Span)])
Documentation
checkpointDir :: FilePath Source #
This subdirectory in the outputDirectory / instrument has the fingerprinted audio files.
state
This is the opaque state for a synthesizer or signal processor. It should be possible to resume synthesis by saving and restoring it.
TODO maybe [ByteString] for multiple states
encodeState :: State -> String Source #
checkpoints
:: FilePath | |
-> State | |
-> [(Config.ChunkNum, Note.Hash)] | |
-> IO ([FilePath], [(Config.ChunkNum, Note.Hash)], Maybe State) | (skipped chunks, remaining notes, state at that point) |
Find where the checkpoints begin to differ from the given Note.Hash
s.
:: Set FilePath | |
-> State | |
-> [(Config.ChunkNum, Note.Hash)] | |
-> ([FilePath], ([(Config.ChunkNum, Note.Hash)], FilePath)) | ([skipped], (remainingHashes, resumeState)) |
Find the first Note.Hash
that doesn't have a matching filename.
Since the output state of the previous filename needs to match the input
state of the next one as described in writeState
, this has to follow the
files in sequence.
write
:: Bool | |
-> FilePath | |
-> Set Id.TrackId | |
-> Config.ChunkNum | |
-> Frames | |
-> [(Config.ChunkNum, Note.Hash)] | |
-> IO State | |
-> AUtil.Audio | get current audio state, see NOTE [audio-state] |
-> IO (Either Text (Config.ChunkNum, Config.ChunkNum)) | Either Error (writtenChunks, total) |
Write the audio with checkpoints.
getFilename :: FilePath -> IO State -> (Config.ChunkNum, Note.Hash) -> IO FilePath Source #
writeState :: IO State -> FilePath -> IO () Source #
Write synth state to the checkpointDir. The filename is derived from the audio chunk filename, which presumably has already been written.
Each chunk writes two files:
- - $hash over the chunk, and $state at beginning of .wav 000.$hash.$state.wav
- - file contains the state at the end of the .wav, fingerprint is $endState 000.$hash.$state.state.$endState
- $hash.$state.wav -- $state == previous $endState
- $hash.$state.state.$endState -- as before
linkOutput :: Bool -> FilePath -> FilePath -> IO Config.ChunkNum Source #
Link the audio chunk output (presumably already written) from the checkpointDir to its position in the output sequence.
000.wav -> checkpoint/000.$hash.$state.wav
clearRemainingOutput :: FilePath -> Config.ChunkNum -> IO () Source #
Remove any remaining output symlinks past the final chunk.
outputPast :: Config.ChunkNum -> [FilePath] -> [FilePath] Source #
filenameToOutput :: FilePath -> FilePath Source #
filenameOf :: Config.ChunkNum -> Note.Hash -> State -> FilePath Source #
- $hash.$state.wav
filenameOf2 :: Config.ChunkNum -> Note.Hash -> String -> FilePath Source #
filenameOf
but with State
already encoded.
maxChunk :: Config.ChunkNum Source #
Crash after this chunk number. It's not an inherent limitation, but
it indicates that something has probably gone off the rails. Also
Config.isOutputLink
doesn't want to parse more than 3 digits.
hash
extendHashes :: [(Int, Note.Hash)] -> [(Int, Note.Hash)] Source #
Extend the [(index, hash)] list with mempty hashes.
Audio.File.writeCheckpoints
needs this because it still wants states
while rendering the decay of the last note. Previously, I just had
hashOverlapping
return an infinite list with 0s on the end, but I want
skipCheckpoints
to be able to detect when it ran out of notes so I can
avoid rerendering the decay in that case, and it's hard to do that when it
can't tell the difference between out of notes, and just no notes at this
moment in time.