Karya, built on 2023-08-29T07:47:28 (patch 7a412d5d6ba4968ca4155ef276a062ccdeb9109a)
Safe HaskellSafe-Inferred

Synth.Lib.Checkpoint

Description

Functions to do incremental render. It hashes Note.Notes to skip rerendering when possible.

Synopsis

Documentation

checkpointDir :: FilePath Source #

This subdirectory in the outputDirectory / instrument has the fingerprinted audio files.

state

newtype State Source #

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

Instances

Instances details
Show State Source # 
Instance details

Defined in Synth.Lib.Checkpoint

Methods

showsPrec :: Int -> State -> ShowS #

show :: State -> String #

showList :: [State] -> ShowS #

Eq State Source # 
Instance details

Defined in Synth.Lib.Checkpoint

Methods

(==) :: State -> State -> Bool #

(/=) :: State -> State -> Bool #

Pretty State Source # 
Instance details

Defined in Synth.Lib.Checkpoint

checkpoints

skipCheckpoints Source #

Arguments

:: 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.Hashs.

findLastState Source #

Arguments

:: 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

write Source #

Arguments

:: 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.

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
  1. $hash.$state.wav -- $state == previous $endState
  2. $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.

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.

zeroPad :: Show a => Int -> a -> ByteString.ByteString Source #

zeroPad for ByteString.

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.

data Span Source #

Constructors

Span 

Instances

Instances details
Show Span Source # 
Instance details

Defined in Synth.Lib.Checkpoint

Methods

showsPrec :: Int -> Span -> ShowS #

show :: Span -> String #

showList :: [Span] -> ShowS #

Pretty Span Source # 
Instance details

Defined in Synth.Lib.Checkpoint

groupOverlapping :: RealTime -> RealTime -> [(a, Span)] -> [[(a, Span)]] Source #

Group all Spans that overlap the given range. So:

0   1   2   3   4   5   6   7   8
|=======|=======|=======|
    a------
        b---c-----
                 d---

Should be: [[a], [a, b, c], [c, d]]

splitOverlapping :: RealTime -> RealTime -> [(a, Span)] -> ([(a, Span)], [(a, Span)]) Source #