The idea is pretty simple, and surprisingly works very well..
It saves memory, and also saves CPU time, lots of CPU time in the case of higher sample rates..
Instead of the conventional packed nybbles of samples, packing 2 4 bits samples into one byte, I had the idea of storing a length in one of the nybbles..
Now, you might think this is a bit silly, but you'd be wrong
In a bunch of 15.6K 4bit samples, every single one of them compresses to less, not one is bigger..
In the below data, remember that the source size listed on each sample is as 8bit samples, so the regular 4bit version is half that size.. I've not been delicate about what I've given it, and it's a right old mixture..
Now, look at the numbers.. It's giving you some quite cool results..
The individual drums sounds compress amazingly well, 6:1 in some cases!!
General, very noisy, speech does okay, in the region of 1.5:1
A recording of some SID music, 2:1
So there you have it.. A lovely simple way to get more samples in your games, with less CPU overhead
Playback is dead simple, you just use the POKEY timers, or 6522/6 to set the delay after setting each sample..
So, the playback code is literally..
lax SampleData and #$0f ora #$10 sta AUDCx lda LSR4,x sta AUDFxI'll knock up some tests today when I've got a few hours, but the playback scheme is exactly what I'm doing in the Pulse sounds stuff I've been working on..
Granted, this really only works well for one channel of sample playback, but there's means and ways to mix compressed sample data in realtime
Anyway.. Thought I'd share this...
No doubt someone will be along in a second to piss on the bonfire..
But until then..
Loaded 'samples\606BASS.pcm' size 3800 bytes 4 bit length - Compressed size: 328 bytes Loaded 'samples\606CHAT.pcm' size 3500 bytes 4 bit length - Compressed size: 1258 bytes Loaded 'samples\606CYMB.pcm' size 15000 bytes 4 bit length - Compressed size: 6760 bytes Loaded 'samples\606HTOM.pcm' size 5000 bytes 4 bit length - Compressed size: 580 bytes Loaded 'samples\606LTOM.pcm' size 5000 bytes 4 bit length - Compressed size: 544 bytes Loaded 'samples\606SNAR.pcm' size 4374 bytes 4 bit length - Compressed size: 1034 bytes Loaded 'samples\Jeff-Evolver6581r4.pcm' size 320000 bytes 4 bit length - Compressed size: 77292 bytes Loaded 'samples\die_hard_yippee2.pcm' size 591830 bytes 4 bit length - Compressed size: 149822 bytes Loaded 'samples\circle_is_complete_x.pcm' size 240744 bytes 4 bit length - Compressed size: 94618 bytes Loaded 'samples\apxtwin.pcm' size 1239887 bytes 4 bit length - Compressed size: 492018 bytes Total source size: 2429135 bytes 4bit size: 824254 bytes
If you got this far, then I also did a bunch of tests that also used different bit sizes for the lengths, a little more work decoding..
Interestingly the best bit size is 3bits.. On average it's about 10% better than 4bits, but that means you have 8 length values packed into 3 bytes, then the 8 samples packed as nybbles, so every 8 samples you'd need to unravel the next 8 length values.. Not a biggy, but not as elegant as 4 bits, and for only a small gain..
I also did results with other convenient bits sizes that work well, namely, 1, 2, 3, 4, 6, 8 bit lengths values..
Here's the results for all of them in case you're curious..
Loaded 'samples\606BASS.pcm' size 3800 bytes 1 bit length - Compressed size: 1215 bytes 2 bit length - Compressed size: 763 bytes 3 bit length - Compressed size: 490 bytes 4 bit length - Compressed size: 328 bytes 6 bit length - Compressed size: 210 bytes 8 bit length - Compressed size: 205 bytes Loaded 'samples\606CHAT.pcm' size 3500 bytes 1 bit length - Compressed size: 1357 bytes 2 bit length - Compressed size: 1198 bytes 3 bit length - Compressed size: 1198 bytes 4 bit length - Compressed size: 1258 bytes 6 bit length - Compressed size: 1480 bytes 8 bit length - Compressed size: 1746 bytes Loaded 'samples\606CYMB.pcm' size 15000 bytes 1 bit length - Compressed size: 6261 bytes 2 bit length - Compressed size: 5682 bytes 3 bit length - Compressed size: 6125 bytes 4 bit length - Compressed size: 6760 bytes 6 bit length - Compressed size: 8290 bytes 8 bit length - Compressed size: 9915 bytes Loaded 'samples\606HTOM.pcm' size 5000 bytes 1 bit length - Compressed size: 1625 bytes 2 bit length - Compressed size: 1059 bytes 3 bit length - Compressed size: 742 bytes 4 bit length - Compressed size: 580 bytes 6 bit length - Compressed size: 500 bytes 8 bit length - Compressed size: 577 bytes Loaded 'samples\606LTOM.pcm' size 5000 bytes 1 bit length - Compressed size: 1623 bytes 2 bit length - Compressed size: 1042 bytes 3 bit length - Compressed size: 710 bytes 4 bit length - Compressed size: 544 bytes 6 bit length - Compressed size: 455 bytes 8 bit length - Compressed size: 519 bytes Loaded 'samples\606SNAR.pcm' size 4374 bytes 1 bit length - Compressed size: 1558 bytes 2 bit length - Compressed size: 1212 bytes 3 bit length - Compressed size: 1067 bytes 4 bit length - Compressed size: 1034 bytes 6 bit length - Compressed size: 1153 bytes 8 bit length - Compressed size: 1366 bytes Loaded 'samples\Jeff-Evolver6581r4.pcm' size 320000 bytes 1 bit length - Compressed size: 113287 bytes 2 bit length - Compressed size: 82620 bytes 3 bit length - Compressed size: 72915 bytes 4 bit length - Compressed size: 77292 bytes 6 bit length - Compressed size: 95088 bytes 8 bit length - Compressed size: 114073 bytes Loaded 'samples\die_hard_yippee2.pcm' size 591830 bytes 1 bit length - Compressed size: 210877 bytes 2 bit length - Compressed size: 164604 bytes 3 bit length - Compressed size: 147731 bytes 4 bit length - Compressed size: 149822 bytes 6 bit length - Compressed size: 177745 bytes 8 bit length - Compressed size: 212863 bytes Loaded 'samples\circle_is_complete_x.pcm' size 240744 bytes 1 bit length - Compressed size: 95233 bytes 2 bit length - Compressed size: 84858 bytes 3 bit length - Compressed size: 86459 bytes 4 bit length - Compressed size: 94618 bytes 6 bit length - Compressed size: 117175 bytes 8 bit length - Compressed size: 140556 bytes Loaded 'samples\apxtwin.pcm' size 1239887 bytes 1 bit length - Compressed size: 485787 bytes 2 bit length - Compressed size: 431052 bytes 3 bit length - Compressed size: 442900 bytes 4 bit length - Compressed size: 492018 bytes 6 bit length - Compressed size: 612777 bytes 8 bit length - Compressed size: 735333 bytes Total source size: 2429135 bytes 1bit size: 918823 bytes 2bit size: 774090 bytes 3bit size: 760337 bytes 4bit size: 824254 bytes 6bit size: 1014873 bytes 8bit size: 1217153 bytes
If raw compression was your goal then you could easily implement a single player to handle all of those modes, wouldn't be a huge job at all..
But personally, I think the simplicity of the 4bit length wins the race
















