Page 1 of 2

Ideas for compressing BRR samples further

Posted: Thu Jun 11, 2020 5:34 pm
by psycopathicteen
In my SNES music program I'm making I just added an LZ4 compression feature, and these are the compression rates.

Synth patch with 4 detuned sawtooth oscillators:
BRR: 18432 bytes
LZ4: 12690 bytes

Synth patch with 4 detuned pulse waves
BRR: 18432 bytes
LZ4: 6139 bytes

The pulse waves look promising, but the sawtooth waves look like they can use a little more work. Any suggestions?

Re: Ideas for compressing BRR samples further

Posted: Thu Jun 11, 2020 6:01 pm
by 93143
Interesting. The conventional wisdom was that this doesn't work. I'm not surprised that it depends somewhat on the nature of the sample; sawtooth waves do have twice as many harmonics as square waves...

Those LZ4 numbers are for packed BRR, not packed PCM, right? Those numbers are comparable to what you'd see on graphics.

Is this for S-CPU decompression, or are you trying to pack more sample data into audio RAM?

Re: Ideas for compressing BRR samples further

Posted: Thu Jun 11, 2020 6:20 pm
by psycopathicteen
It's to pack more in the audio RAM.

Re: Ideas for compressing BRR samples further

Posted: Thu Jun 11, 2020 6:34 pm
by 93143
Found another post by the same guy saying that he's tried it and it doesn't work. I wonder if the disappointing saw results are indicative of what might happen if you try to generalize this to more information-dense waveforms...

Of course there are sounds that one might wish to play on a SNES that are not significantly/at all more complex than a supersaw but can't easily be single-cycle looped. I have my eye on that chorused square at 1/3 the size of the BRR...

How fast is the decompression on the SPC700? Is this a sample swapping technique or a sample streaming technique?

Re: Ideas for compressing BRR samples further

Posted: Thu Jun 11, 2020 8:47 pm
by lidnariq
... I really wonder what bregalad's test set was, because if you look at a histogram of BRR data it looks both extremely non-uniform
dx-10.png
dx-10.png (950 Bytes) Viewed 1696 times
and its spectrum has huge peaks indicating BRR's period of 9:
dx-10-spectrum.png
dx-10-spectrum.png (5.8 KiB) Viewed 1696 times
Specifically testing with the BRR (i.e. bytes 17673 through 65792) in "dx-10.spc" from the Dracula X soundtrack, naive compressors shave off 10% to 20%. (Gzip: 18.9%, bzip2: 14.8%, lzma: 20.7%, lz4: 9.6%)

Re: Ideas for compressing BRR samples further

Posted: Thu Jun 11, 2020 11:28 pm
by nocash
Yes, that's interesting. Two basic questions:
- Is it lossless compression, allowing to restore the exact original BRR data?
- Did you already test different BRR files, including speech and other random sounds?

Re: Ideas for compressing BRR samples further

Posted: Fri Jun 12, 2020 5:22 pm
by Nikku4211
psycopathicteen wrote:
Thu Jun 11, 2020 6:20 pm
It's to pack more in the audio RAM.
The data has to be decompressed from LZ4 into BRR before being played by the SPC700. That's exactly what the general consensus that this method 'doesn't work' means: that it's not going to pack more in the audio RAM because the decompressed result will ultimately have to be stored in the audio RAM.
nocash wrote:
Thu Jun 11, 2020 11:28 pm
Yes, that's interesting. Two basic questions:
- Is it lossless compression, allowing to restore the exact original BRR data?
- Did you already test different BRR files, including speech and other random sounds?
LZ4 is lossless compression, yes.

Re: Ideas for compressing BRR samples further

Posted: Fri Jun 12, 2020 6:06 pm
by 93143
Nikku4211 wrote:
Fri Jun 12, 2020 5:22 pm
The data has to be decompressed from LZ4 into BRR before being played by the SPC700. That's exactly what the general consensus that this method 'doesn't work' means: that it's not going to pack more in the audio RAM because the decompressed result will ultimately have to be stored in the audio RAM.
No, what "doesn't work" means is that your average BRR sample isn't going to get significantly smaller when compressed again, with the possible exception of the header bytes. This is pretty clear from Bregalad's posts, and lidnariq's results honestly aren't too far off that assertion.

The idea psycopathicteen is proposing seems to be that you could pack a bunch of compressed samples into ARAM and decompress each one with the SPC700 when required; they wouldn't ever have to all be uncompressed at the same time. This is likely why he picked LZ4; it's very fast on 8-bit processors. If the decompression is fast enough, it might not even be necessary to store the whole decompressed sample; it might be possible to use a small ring buffer.

This technique could replace or extend the effectiveness of I/O streaming from the CPU bus. On the flip side, it does mean that less sample space is available for simultaneous playback, so unless the SPC700 can keep several ring buffers fed at the same time, its applicability may be less universal.

Now, it is obvious that this technique could also be useful to save ROM, regardless of whether the SPC700 ends up saddled with the decompression or not. Depending on the material being compressed, it might not save much, and if you're computationally bound you may not want to bother, but it's good to know it isn't always just a pure loss.

Re: Ideas for compressing BRR samples further

Posted: Fri Jun 12, 2020 6:43 pm
by Nikku4211
93143 wrote:
Fri Jun 12, 2020 6:06 pm
The idea psycopathicteen is proposing seems to be that you could pack a bunch of compressed samples into ARAM and decompress each one with the SPC700 when required; they wouldn't ever have to all be uncompressed at the same time. This is likely why he picked LZ4; it's very fast on 8-bit processors. If the decompression is fast enough, it might not even be necessary to store the whole decompressed sample; it might be possible to use a small ring buffer.
I don't know. It still doesn't sound so good, especially when the LZ4 compressed samples, the sequencing data, the sound engine code, and whatever sample is being uncompressed are all in ARAM at the same time. I don't think the SPC700 can execute instructions directly from ROM without the S-CPU putting it into ARAM, right? If, for example, the song uses all 8 channels, each one playing a different sample, all playing a note simultaneously, than won't that mean you'll need to decompress 8 samples?

Boom.

Re: Ideas for compressing BRR samples further

Posted: Fri Jun 12, 2020 9:47 pm
by 93143
Not necessarily. Why should every sample played have to be decompressed live? It could be that a number of the instruments are short or low-frequency samples that don't take up much space and therefore don't need compression. Maybe some samples are complex waveforms that don't compress well so there's no point. Perhaps it's only a few large samples that play at widely separated times that are compressed, so the SPC700 has plenty of time to completely decompress each one before it's needed, or if it can handle real-time decompression it can just feed a single ring buffer* while uncompressed BRR samples play on the rest of the channels. Or perhaps there are a lot of different relatively small instrument sets that can be swapped out between songs, or between sections of a song, without involving the S-CPU.

There's no need to assume an all-or-nothing approach. This scheme sounds like it scales pretty gracefully, unlike (say) blargg's PCM streaming technique which only works at all if there's nothing else happening...

Also, you've got 64 KB for everything, which is way more than you need for the engine code and song data. Most of the space is taken by samples and echo buffer. LZ4 is nowhere near complicated enough to take more than an insignificant fraction of the available memory.

*It should be noted that any ring buffer would have to be long enough so that the decompressor can still work, or rather the compressor would have to be designed for the desired ring buffer size - LZ4 works by copying duplicate data from earlier in the output stream.

Re: Ideas for compressing BRR samples further

Posted: Sat Jun 13, 2020 12:16 am
by calima
For the decompression speed, my NES lz4 unpacker does about 40kb/s. We could guesstimate spc700 at half a NES.

Re: Ideas for compressing BRR samples further

Posted: Sat Jun 13, 2020 9:43 am
by Bregalad
93143 wrote:
Fri Jun 12, 2020 6:06 pm
No, what "doesn't work" means is that your average BRR sample isn't going to get significantly smaller when compressed again, with the possible exception of the header bytes. This is pretty clear from Bregalad's posts, and lidnariq's results honestly aren't too far off that assertion.
Indeed that's what I was originally saying in the linked posts. But let's forget that and assume that it's feasible to compress BRR samples further in the ARAM.

For this to be any useful, you have to remember that all the following items will typically stand simultaneously in ARAM
  • Sound engine
  • Sound effect and sequence data
  • Echo buffer (optional)
  • BRR sample bank
  • Compressed sample bank
Note that a compressed sample which is currently playing back has to be stored twice in ARAM, once compressed and once in BRR format.

For this to make any sense, the compressed samples need to compress very well, and the compressed sample bank has to be much larger than the rest of the data present in the ARAM. I'm dubious...
Synth patch with 4 detuned sawtooth oscillators:
BRR: 18432 bytes
LZ4: 12690 bytes

Synth patch with 4 detuned pulse waves
BRR: 18432 bytes
LZ4: 6139 bytes
Just wondering, if those sounds like synth patches, could the BRR version possibly be generated algoritmically by software ? This would save the hassle to deal with compression in the first place.

Re: Ideas for compressing BRR samples further

Posted: Sat Jun 13, 2020 4:13 pm
by Nikku4211
Bregalad wrote:
Sat Jun 13, 2020 9:43 am
Just wondering, if those sounds like synth patches, could the BRR version possibly be generated algoritmically by software ? This would save the hassle to deal with compression in the first place.
Yeah, it'd be awesome to use the SPC700 itself to generate samples. I imagine it could be possible to even do software synth mixing on the SPC700 itself too, right?

Re: Ideas for compressing BRR samples further

Posted: Sat Jun 13, 2020 4:15 pm
by lidnariq
I'm pretty certain I remember psycopathicteen having done that in the past. Some FM synth. He was trying to figure out how to pick which BRR filter.

Certainly the sizecoding approach is algorithmic generation for everything.

Re: Ideas for compressing BRR samples further

Posted: Sat Jun 13, 2020 7:23 pm
by psycopathicteen
I just tested this same algorithm with the BRR block header bytes rearranged at the front and here are the results:

12517 bytes for sawtooth patch
6013 bytes for pulse patch

With software generating, my main concern is the SPC700's Mhz speed. LZ4 decompressing is mostly just block moves.

I forgot to mentioned this in the OP but my LZ4 algorithm was slightly modified because my SNES music tool runs on the SNES itself. I'm using an 8-bit block match offset, instead of a 16-bit offset because comparing that many bytes took way too long. Of course, I'm not going to use this convoluted scheme for my game. My plan is to save all the sample data in save-RAM, and copy and paste the save-RAM file of the music program into my homebrew game ROM using tile molester.