voltage schedule based on the last value of the previous opcode.
In candidate_opcodes, return the hash of pruned_opcodes as well (since
this is relatively expensive to recompute), so this can be used to
precompute and cache partial results of applying the opcodes.
(indirect) takes 5 cycles not 6! It should be possible to also
accommodate 6502 timings in a followup.
h/t to Scott Duensing who noticed that my sample audio sounded "a tad
slow", which turned out to be due to this 1-cycle difference (which
added up to almost an extra minute playback to an 8-minute song).
Add comments and tidy up the code a bit.
Flesh out README some more.
- we simulate the speaker at full 1-cycle resolution, and
evaluate all possible opcodes that can be scheduled for the
given position in the TCP stream
- this lets us tick the speaker at any cycle interval >=9 (except 10
cycles)
I split out preprocess_audio because scipy/librosa don't run under
pypy and I was hoping that would speed up the encoding, but it does
not for some reason (maybe numpy interactions?)
Anyway, I should be able to vectorize the slow path which will likely
help a lot.
(moved over from rewolf repository).
Using a 13-cycle period neatly divides the 65-cycle 'long cycle'
period of the Apple II which avoids audio transients when playing
'silence'. This also aligns with the horizontal refresh period which
should make it possible to do some interesting visual effects.
TODO
- implement predictive encoding that looks ahead to next N samples and
minimizes average error. This should improve quality
- get page-flipping effects looking nice