Wednesday, October 28, 2009

Full AY emu prototype

Well I've talked about this before, but I'll say it again.
Designing a synthesizer that claims full chip authenticity and playability at the same time is the toughest challenge I'm faced with.

It hard to give access to powerful sound tweaking possibilities available on some chips when the synth paradigm you are basing your whole design on is of the standard
[voice0 + voice1 + voice2 + (...) + voiceN = mix]

Look at this signal path for instance:

It becomes clear that something like this doesn't fit that particular mold.

The AY has five generators: 3 tones, 1 noise, and 1 envelope.
It also has three independent audio output pins, that are mixed in the analog world differently in all the AY-based systems.

Now each of the output has its own tone generator, but it can also be mixed with the lone noise pattern (either, or combined with a binary AND). On top of that each output can have its volume changed independently (16 log steps), or be amp-modulated by the LONE Envelope generator. (more in the spec)

Anyone who's messed with an AY knows that the fun comes from mixing the env/tone+noise in certain ways which can make unique drones/beats that any IDM/Experimental student would enjoy.

But you can't currently do these in chipsounds v1.0 due to voice paradigm its based on. From recent user questions on the AY matter, it surprised me how programming a straight chip emu sounds like a hard task.
But in reality, in comparison to trying to make it fit in ARIA/SFZ, making a separate module that purely emulates the chip in bit perfect manner (and with all its limitations) is really not the challenge it appears to be.

The AY is a relatively simple digital state machine

Here is a snapshot of my current prototype (made using Bidule's C++ SDK):

And the type of drones you can dynamically make by moving the sliders here:
Example A
Example B

Its currently unclear if/how this will be integrated in chipsounds, or given for free for Bidule users. Please stay tuned!

Saturday, October 17, 2009

How I recorded and decoded POKEY's polynomial counters;Open Pokey Recipe for the curious


This is a "reprint" of the comments inside "POKEY.sfz", the chipsounds POKEY configuration file. (the original date is March 2009)


Was I naive to think that POKEY was just "another TIA", and I spent enough evenings to regret it. Making the breadboard and having Pokey spew some tones was the easy part, but soon realized that various frequencies gave me different patterns (sometimes after retriggereing the SAME note!)

So I tried many things, recorded GB's of tests and had a few ideas.

After lots of trials and loss of sanity:
Here is the FINAL methodology that I used to get usable data:

A)Clock a POKEY with a VERY SLOW clock (I used a +- 10Khz 50/50 PWM signal from a PIC)

B)Set Bit 6 of AUDC1 ( "1.79Mhz" or cpu clock)

C)Play the highest notes you can for each pattern: AUDF1=0 then AUDF1=1, (...), AUDF1=4

D)Record each bit pattern and pass it through our patternfinder util.

Now since the results are NOT the source pattern, but a "resampled" pattern made after skipping 4+AUDF source pulses for each destination pulse (according to the POKEY spec's "MODIFIED FORMULA"), we must derive the actual SOURCE pattern from the results.

The trivial thing to try is this:

void Shuffler(const char*in, char*out, size_t len, size_t shufsize){

size_t cnt=0;
(size_t i=0;i<len;++i){

out[i] = in[cnt];

cnt = cnt % len;

In this case my recorded AUDF1=0's 4, 9 and 17 bit patterns gave the exact same results as source OR destination (with added offset before looping of course), which kinda proves that AUDF1=0 can give you the full pattern, and that there is magic somewhere (try that with any other random bit pattern for fun). With this source pattern I was able to verify my own "software resampling" using AUDF1=1,2,3... and so forth from my recordings for a match.

4bit poly: 000011101100101

However, and that's where the fun ends, the 5bit pattern was a pain. Patternfinder kept giving me a 62 bit long repeated pattern:


and NOT a 31 bit pattern like I expected!

I noticed that the former 31 bit half of that pattern was always the inverse of the later (whatever point at which you start).A "hint" that the results im getting use some form of inversion. Schematics show that the source pattern passes through the same circuit logic as the "plain square" so it is used as a "please invert previous bit" matrix

SO: Inverting THAT pattern (fill/skip_4 a 31 bit pattern) gave me the following from my 62 pattern: "1101001100000111001000101011110". Which, as with the 4,9,17 case was used to test for the generation of AUDF1=1 and other frequencies.

chipsounds specific:

A few unique oscillators have been made just for this chip.
One and Two Stream AND-ers and One Stream Differentiators were required to emulate the inner process of the POKEY chip.

Invaluable help from "DeRe Atari Chapter 7", and from the official specs.
And for the various Pinouts/Skematics found online.

Thursday, October 1, 2009

Last minute addition: Odyssey 2 (P824x) VDC chip!

Building a software product and analyzing hardware are two very important facets of a product like chipsounds. Do mostly the analysis and you have a very techy app that no one understands, do only the former and you miss that that hands on feeling and the smell of printed circuit boards.

So this weekend I took a little break from coding (which is very close to done anyway) And looked at the few consoles in my lot that are not fully analyzed yet (I will add more chips in updates). And decided that chipsounds 1.0 required the Odyssey2.

The interesting thing is that there is no sound-coder-friendly documentation on the P8244/P8245 online yet, so I figured might as well publish everything I've learned so far.

My research consisted in confirming Sören Gust's info from g7kbios.pdf and to go further in trying various combination of tones and timbres that would be possible on the console itself without using IRQ based resynchs and also to check on MESS's source code theory of the "OR"ING of tone and noise, and to check for their claim of a 16 bit LFSR used for the noise channel.

On top of his great commented Bios document, Gust kindly provided the community with example assembler "Hello Worlds" for the console and even an improved the BIOS sound player which I then used to run tests on the "real thing", using a ripped apart Baseball Cart and a 2732 eprom (2k code is mirrored twice)... don't have 2716's at hand yet

The available docs mention a 24 bit shift register that is clocked by only two dividers: 983Hz 3933Hz, without any concrete info on how those two frequencies are achieved by the hardware from the master clocks in the first place.

So what is the main clock divisors for this chip?

Before trying to hack in assembly/eprom, I played with the few cartridges I had, and found out that pressing (and holding) the reset button stalls the CPU, but not the VDC, which keeps playing the current tone (or noise) - very handy indeed.

Long tone segments were recorded by tapping the audio signal at the junction of the main board and the RF box. (a tad bit of LP filtering at this point but nothing heavy)

Various NTSC Recorded pitches (Bidule FFT/PVOC Loudest freq analysis)

Assuming 1966.572266Hz came from this pattern: 101010101010101010101010 this means a high freq of would be generated from a clock of 3933.144532 (2x) Which tends to confirm the 3933 value. (note: 983 is just 3933/4)

The preliminary docs for the Intel VDC included in Arnim Läuger's
mcs-48.pdf Mentions the 3933 value comes from 15734/4 but nothing else. Looking around for the source of this frequency:

NTSC television scans 525 lines about 29.97* times a second = 15734.25)
SO -> Precise (theoretic) NTSC values would then be:
15734.25/4 = 3933.5625 (high from now on)
15734.25/16 = 983.390625 (low from now on)

(PAL television scans 625 lines * 25 times a second = 15625)
Precise (theoretic) PAL values would then be:
15625/4 = 3906.25
15625/16 = 976.5625
(would love a Videopak machine to confirm)


Using Gust's improved BIOS player:

We can verify that:

1)DAC is linear, from recordings of a programmed ramp of the 16 volume values

2)Noise is a LFSR-based 16383 bit long repeating pattern.
I haven't yet taken the time to find the exact LFSR formula,
but i've added it as a table.

3)We can indeed generate any looping 24 bit patterns we want:
Example: 0xFFFF00 (2/3 duty)
0x080000 (1/24 duty)
0x001403 (000000000001010000111011 or padded TIA pattern)
Byte Order check with output:
0x010203 (000000010000001000000011)
Recorded output: from left to right starts with:

Listen to those here

4) Possible pitches (using 50% duty as guide):

24 bit
000000000000111111111111:(low) 40.9746Hz
000000000000111111111111:(high) 163.8984Hz

000000111111000000111111:(low) 81.9492Hz
000000111111000000111111:(high) 327.7969Hz

000011110000111100001111:(low) 122.9238Hz
000011110000111100001111:(high) 491.6953Hz

000111000111000111000111:(low) 163.8984Hz
000111000111000111000111:(high) 655.5938Hz

001100110011001100110011:(low) 245.8477Hz
001100110011001100110011:(high) 983.3906Hz

010101010101010101010101:(low) 491.6953Hz
010101010101010101010101:(high) 1966.7813Hz

That's all well and good, but what about 24/8=3 bits?
yes that would make another pitch frequency available,
but could only play 011 and 001 (1/3 and 2/3 duty)

011011011011011011011011:(low) 327.7969Hz
011011011011011011011011:(high) 1311.1875Hz New freq!!!!

in pitch order:
000000000000111111111111:(low) 40.9746Hz MIDI:28( E2): 41.20344543
000000111111000000111111:(low) 81.9492Hz MIDI:40( E3): 82.40689087
000011110000111100001111:(low) 122.9238Hz MIDI:47( B3): 123.4708252
000000000000111111111111:(high) 163.8984Hz MIDI:52( E4): 164.8137817
000111000111000111000111:(low) 163.8984Hz MIDI:52( E4): 164.8137817
001100110011001100110011:(low) 245.8477Hz MIDI:59( B4): 246.9416504
011011011011011011011011:(low) 327.7969Hz MIDI:64( E5): 329.6275635
000000111111000000111111:(high) 327.7969Hz MIDI:64( E5): 329.6275635
010101010101010101010101:(low) 491.6953Hz MIDI:71( B5): 493.8833008
000011110000111100001111:(high) 491.6953Hz MIDI:71( B5): 493.8833008
000111000111000111000111:(high) 655.5938Hz MIDI:76( E6): 659.2551270
001100110011001100110011:(high) 983.3906Hz MIDI:83( B6): 987.7666016
011011011011011011011011:(high) 1311.1875Hz MIDI:88( E7): 1318.510254
010101010101010101010101:(high) 1966.7813Hz MIDI:95( B7): 1975.533203

So there are 10 UNIQUE 50/50 pitches, plus one 2/3 pitch, but LOTS more different _timbres_ using other patterns. The BIOS engineers only included the 10 "different" (to the ear) 50/50 ones...

At least they found a right divider/pattern length to generate a mostly tuned E5 Scale
( -9.6417 to -7.6867 cents off Equal Temperament in NTSC)
(-21.7044 to -19.7494 cents off Equal Temperament in PAL)

Just enough for a PO-LING :)
Back to possible Timbres Lets fill some timbre void shall we?
A pitch is perceived by the repetition of a pattern:

2^24= 16777216 possible timbres for 40.9746Hz and 163.898560Hz
2^12= 4096 possible timbres for 81.951134Hz and 327.796722Hz
2^8 = 256 possible timbres for 122.919807Hz and 491.694153Hz
2^6 = 64 possible timbres for 163.898621Hz and 655.593628Hz
2^4 = 16 possible timbres for 245.850220Hz and 983.390808Hz
2^3 = 8 possible timbres for 327.7969Hz and 1311.1875Hz
2^2 = 4 possible timbres for 491.696228Hz and 1966.781128Hz

case 2^2 can only really do 50/50 since 01 and 10 sounds the same
... in a monophonic console. 00 is silence; 11 is a DC offset click

case 2^4 following the previous logic can only do 25% 50% and 75% duty...

We did not map them all in chipsounds, but this could be added in the future in a more specific oscillator ...