Page 1 of 1

PCM Playback on PSG

Posted: Tue May 20, 2008 8:41 pm
by Jeff
Has anyone seen this? http://www.msx.org/PCM-Encoder-0.01.newspost3520.html

Here's a quote from the docs:

"Each input sample is approximated by the sum of 3 PSG channels. As the z80 can vary only one channel at time, the encoder, using a Viterbi search, finds the best sequence of PSG channel variations that approximate (MSE) the input sequence. The output of pcmenc is a sequence of PSG levels for the 3 channels that best approximate the input sequence. "

I was wondering if something similar could be done on the Genesis.

Posted: Tue May 20, 2008 8:49 pm
by Shiru
I seen. That may work, but it take all Z80 time and all PSG channels. And I doubt that it's possible to mix few digital channels to output through PSG this way.

Posted: Wed May 21, 2008 2:11 am
by HardWareMan
After Burner on MD does drums that way. And some other games.

Posted: Wed May 21, 2008 2:30 am
by Shiru
HardWareMan, that's not about playing digital sound on PSG, that's about Viterbi search algorithm, which allows to improve playback quality significally.

Posted: Wed May 21, 2008 3:15 am
by Nemesis
Wow, that sample is impressive. I wonder if the Z80 in the Mega Drive would be fast enough to make the changes at the required rate though. At 44.1kHz, the Z80 would only have around 27 cycles to update each channel. That's 27 cycles to load the next sample data from the source, and write it to the PSG. Best case is probably 6 LD8 opcodes per channel per sample. You can't do 18 LD8's in 27 cycles (7 cycles per opcode at a minimum I think), and that doesn't even count adjusting the read location. If you wanted to do this on the Mega Drive, it might have to be the M68000 that's dedicated to the task.

Posted: Wed May 21, 2008 3:40 am
by Shiru
Why Z80 on SMD could be not fast enough? MSX has same Z80 on 3.58 MHz, with one wait state every M1 cycle. There is difference between systems - MSX has bigger directly addressable memory; SN76489 and AY-3-8910 has different control scheme (memory mapped with one register vs. I/O mapped with addr/data registers), but it's not so significant.

Posted: Wed May 21, 2008 4:22 am
by Nemesis
I wasn't aware of the specs for the MSX; I've never looked into it. Well, reading the thread on the MSX forum, it looks like they had the same problem initially. The initial implementation took 447 T-cycles for each sample, giving a max of around 8KHz playback. Obviously they managed to improve on that over time. I don't know how they managed to pull off a 44KHz playback though.

EDIT: My math was off anyway. I was calculating for changing all 3 channels 3 times each sample. :roll: In reality, they've got 80 cycles for each sample. That sounds like more of a possibility, and seeing as they've done it, it obviously is.

Posted: Wed May 21, 2008 8:23 am
by TmEE co.(TM)
Z80 is very capable once you know how to max it... I started with a lousy 8KHz single channel WAV player and thought its best I could do and later I ended up creating a full fledged sound engine that could do over 50KHz dual channel PCM playback !!!

Posted: Wed May 21, 2008 7:56 pm
by Chilly Willy
It should be easier to reach the 44KHz goal on the MD - the MD PSG only takes one store to change the amp, whereas the MSX takes two outputs. If you look over the MSX code, it does one output to $A0 to set the channel, then another to $A1 to set the amplitude. Those can be combined into a single store in the MD. Also, looking at the MSX code, the 44KHz was only possible on the MSX by only changing one channel per input sample, so the output was never exactly the same as the input. That requires changing all three channels per input sample.

Posted: Wed May 21, 2008 8:04 pm
by Shiru
Isn't Viterbi algorithm used exactly to solve this problem - to get best results with changing only one channel per sample?

Changing all three channels at once (if that could be possible) - it's just sum of DAC's, so not needs for complex algorithms to encode samples.

Posted: Wed May 21, 2008 11:38 pm
by Chilly Willy
Shiru wrote:Isn't Viterbi algorithm used exactly to solve this problem - to get best results with changing only one channel per sample?

Changing all three channels at once (if that could be possible) - it's just sum of DAC's, so not needs for complex algorithms to encode samples.
You use the Viterbi algorithm regardless of how many channels you change per input sample to minimize the noise. Remember, you can only change one channel at a time, so you ALWAYS have noise. The algo used minimizes the noise by telling you which channel to change to what value to get nearer to what you want with the least noise. Changing all three channels per input sample means that you replicate the waveform more precisely, but you get one third the output sample rate because you have to change all three channels. Changing one channel for each input sample means you get three times the output sample rate, but since you're only changing one channel, you get more noise as you never (or rarely) precisely match the input samples.

This conversion with Viterbi is done BEFORE hand on a PC. It's not done on the fly on the MSX. Basically, this method is a way to precompute data to play through the PSG for pre-existing samples. That way you can play digital sounds out of a chip not normally capable of digital playback. It does not handle playing arbitrary digital audio as the Z80 cannot compute it on the fly.