Karya, built on 2022-03-21T01:30:44 (patch 89d1651424c35e564138d93424a157ff87457245)
Safe HaskellSafe-Inferred



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



checkpointDir :: FilePath Source #

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


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 details
Show State Source # 
Instance details

Defined in Synth.Lib.Checkpoint


showsPrec :: Int -> State -> ShowS #

show :: State -> String #

showList :: [State] -> ShowS #

Eq State Source # 
Instance details

Defined in Synth.Lib.Checkpoint


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

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

Pretty State Source # 
Instance details

Defined in Synth.Lib.Checkpoint


skipCheckpoints Source #


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


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


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


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 #




Instances details
Show Span Source # 
Instance details

Defined in Synth.Lib.Checkpoint


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

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

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