Back in April I had asked a question about methods of toggling a single bit as a flag. The suggestions were very helpful and some clever alternatives were proposed. This was for a C64 'DIGI' player I had starting working on in January. I was finally able to incorporate the suggestions this past weekend so only 6 months to finish the project.
The thread is here:
viewtopic.php?f=2&t=6093 Typically for a DIGI player each sample is a 4bit value with two samples packed in a byte. You play the low byte in the first ISR call, shift the high nibble down and play the high nibble the second ISR, etc.
I had though to a couple ideas to decrease the memory footprint of the digital sample. The one I tried months ago an a simple RLE. While the encoding is the hard part it was simple and quick on a modern PC. I wrote the decoder side for the C64 but alas it took too much processor time when trying to play an 8khz sample.
I got to thinking about trying an interpolation scheme this past weekend. This would halve the memory foot print but it makes the player side much more interesting. After several ideas which would not work it occurred to me that it can be done with what amounts to four 'separate ISR routines'. The trick will be how to select the correct one.
An outline of what each ISR does:
Code:
; init - load sample A, separate hi & lo nibbles
; we have three storage bytes in zero page hi, mid, low
; ISR #1 - play lo, calc mid point of hiA-loA save to lo, move hi to mid
; ISR #2, play lo, move mid to lo
; ISR #3, play lo, calc mid point of loB-hiA save to lo
; ISR #4, load sample B, separate hi & lo nibbles
This arrangement of tasks for each ISR evens out the number of cycles each one requires which should range between 40-60 cycles.
One way to 'select which ISR' is used is to use a counter to determine the branch target. This would require two or more comparisons to select between four possibilities unless someone had a trick for this.
Code:
;enter ISR
;play lo sample
; branch to correct block
;
;
; correct block code
; INC counter, AND counter with #$03 (2 bits only)
; RTI
Another idea is to change the ISR address each time. Since we always need to cycle through the ISRs in the order 0, 1, 2, 3 this should work. We will always be at the end of the sample data at ISR #3 so will can always decide to disable the NMI at that point. I kind of like this idea as it seems simple. If the entire ISR can fit in 256 bytes we would only need to change the low byte of the NIM vector as well.
Code:
;enter ISR #0
;play lo sample
; change NMI address to ISR #1
; RTI
;enter ISR #1
;play lo sample
; change NMI address to ISR #2
; RTI
I'm curious what ideas other have. There is always more than a few ways to accomplish something.
Thanks