AY8910 AY-3-891X Chip Sound Simulator
superclass: MultiOutUGen
Emulation of the sound generation hardware of the AY-3-8910 chip by Ville Hallik, Michael Cuddy, Tatsuyuki Satoh, Fabrice Frances, Nicola Salmoria.
This was a very popular sound chip used in many arcade games and consoles (Intellivision, Vectrex) as well as in many home computers (MSX, AtariST, ZX Spectrum 128...)
http://en.wikipedia.org/wiki/AY-3-8910
http://www.atarimagazines.com/v4n7/stsound.html
http://www.howell1964.freeserve.co.uk/parts/ay3891x_datasheet.htm
Note that this ugen outputs 3 separate channels of sound! Often you want to mix them.
For a simplified interface to this class see [AY8910Square]
*ar(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, rA, rB, rC, rD, rate)
r0 - AFINE channel A fine frequency (8bits 0-255)
r1 - ACOARSE channel A coarse frequency (4bits 0-15)
r2 - BFINE channel B fine frequency (8bits 0-255)
r3 - BCOARSE channel B coarse frequency (4bits 0-15)
r4 - CFINE channel C fine frequency (8bits 0-255)
r5 - CCOARSE channel C coarse frequency (4bits 0-15)
r6 - NOISEPER noise channel frequency (5bits 0-31)
r7 - ENABLE voice enable: (5bits 0-31)
bit 5 - channel C noise
bit 4 - channel B noise
bit 3 - channel A noise
bit 2 - channel C tone
bit 1 - channel B tone
bit 0 - channel A tone
r8 - AVOL channel A volume & env: (5bits 0-31)
bit 4 - envelope enable
bits 0-3 - volume
r9 - BVOL channel B volume & env: (5bits 0-31)
bit 4 - envelope enable
bits 0-3 - volume
rA - CVOL channel C volume & env: (5bits 0-31)
bit 4 - envelope enable
bits 0-3 - volume
rB - EFINE envelope fine period (8bits 0-255)
rC - ECOARSE envelope coarse period (8bits 0-255)
rD - ESHAPE envelope shape: (4bits 0-15)
bit 3 - continue
bit 2 - attack
bit 1 - alternate
bit 0 - hold
rate - scale playbackrate for the 3 tones (float 0.0-...)
s.boot;
//one voice
{AY8910.ar(r0:50, r1:0, r7:2r00001000, r8:13)}.play
{AY8910.ar(r0:50, r1:1, r7:2r00001000, r8:13)}.play
//two voices
{AY8910.ar(r0:50, r1:0, r2:75, r3:0, r7:2r00011000, r8:13, r9:13)}.play
//three voices. to listen to all three in a stereo output you'll need to mix
{Mix(AY8910.ar(r0:50, r1:0, r2:75, r3:0, r4:90, r5:0, r7:2r00111000, r8:13, r9:13, rA:13))*0.5}.play
//noise only on first voice + mouse xy countrol
{AY8910.ar(r0:100, r1:0, r6:MouseY.kr(0, 31), r7:2r00000001, r8:MouseX.kr(0, 15))}.play
//looping envelope on voice first voice
{AY8910.ar(r0:100, r1:0, r6:15, r7:2r00001000, r8:31, rB:MouseX.kr(0, 255), rC:1, rD:2r1010)}.play
{AY8910.ar(r0:100, r1:0, r6:15, r7:2r00001001, r8:31, rB:MouseX.kr(0, 255), rC:1, rD:2r1010)}.play
{AY8910.ar(r0:100, r1:0, r6:15, r7:2r00000001, r8:31, rB:MouseX.kr(0, 255), rC:1, rD:2r1010)}.play
//different envelope
{AY8910.ar(r0:100, r1:0, r6:15, r7:2r00000001, r8:31, rB:0, rC:20, rD:2r0001)}.play
//the rate argument
{AY8910.ar(r0:Line.kr(0, 127, 0.15), r1:Line.kr(0, 0, 0.15), r7:2r00001000, r8:15, rate:1)}.play
{AY8910.ar(r0:Line.kr(0, 127, 0.15), r1:Line.kr(0, 0, 0.15), r7:2r00001000, r8:15, rate:2)}.play
{AY8910.ar(r0:Line.kr(0, 127, 0.15), r1:Line.kr(0, 0, 0.15), r7:2r00001000, r8:15, rate:1.5)}.play
{AY8910.ar(r0:Line.kr(0, 127, 0.15), r1:Line.kr(0, 0, 0.15), r7:2r00001000, r8:15, rate:MouseX.kr(0, 10))}.play
//misuse
{AY8910.ar(r0:SinOsc.kr(SinOsc.kr(0.2), 0, 10, 10), r1:0, r2:SinOsc.kr(SinOsc.kr(0.15), 0, 10, 10), r3:0, r7:2r00011000, r8:12, r9:12)}.play
{AY8910.ar(r0:SinOsc.kr(0.25)<0.8*SinOsc.kr(0.2, 0, 25, 25), r1:SinOsc.kr(4, SinOsc.kr(1))>0.3, r2:20, r3:SinOsc.kr(12)>SinOsc.kr(0.2, 0, 0.5, 1), r7:2r00011000, r8:13, r9:SinOsc.kr(0.1, 0, 6, 6).max(0))}.play
{Pan2.ar(Mix(AY8910.ar(r0:50+SinOsc.kr(14, 0, 12), r1:0, r2:60+SinOsc.kr(8, 0, 14), r3:0, r4:70+SinOsc.kr(10, 0, 16), r5:2, r7:2r00111000, r8:31, r9:31, rA:31, rB:SinOsc.kr(0.1, 0, 127.5, 127.5), rC:2, rD:2r1010))*0.6)}.play
{Pan2.ar(Mix(AY8910.ar(r0:SinOsc.kr(0.11)>0.9*10+5, r1:0, r2:SinOsc.kr(0.12)>0.9*2+20, r3:0, r4:SinOsc.kr(0.13)>0.9*25+25, r5:SinOsc.kr(14)>0.9, r7:2r00111000, r8:31, r9:31, rA:31, rB:0, rC:SinOsc.kr(Lag.kr(SinOsc.kr(0.1)>0.9*4+1, 3), 0, LFTri.kr(0.1, 0, 4, 4), 4), rD:2r1110))*0.6)}.play
(
SynthDef(\ay8910, {|out= 0, gate= 1, r0= 0, r1= 0, r2= 0, r3= 0, r4= 0, r5= 0, r6= 0, r7= 0, r8= 0, r9= 0, rA= 0, rB= 0, rC= 0, rD= 0, rate= 1, amp= 1, pan= 0|
var e, z;
e= EnvGen.kr(Env.asr(0.01, amp, 0.05), gate, doneAction:2);
z= Mix(AY8910.ar(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, rA, rB, rC, rD, rate));
Out.ar(out, Pan2.ar(z*e, pan));
}).memStore;
)
(
Pbind(
\instrument, \ay8910,
\dur, 0.125,
\amp, 0.3,
\r0, Pseq([Pn(3, 64), Pn(32, 54), Pn(10, 10)], inf),
\r1, Pseq([Pn(1, 32), Pwhite(0, 3, 12)], inf),
\r2, Pseq([Pn(3, 17), Pn(Prand([10, 20, 30]), 4), Pn(10, 3)], inf),
\r3, Pseq([1, 2, Pwrand([3, 2, 1, 0], [0.1, 0.2, 0.3, 0.4])], inf),
\r6, Pseq([Pseq([10, 20, Pwrand([100, 110], [0.7, 0.3]), 50], 15), Pn(3, 4)], inf),
\r7, 2r00011100,
\r8, 15,
\r9, 15,
\rA, 31,
\rB, 10,
\rC, Pseq([Pseq([1, 0], 24), Pseq([1, 0, 2], 8)], inf),
\rD, 2r0000
).play
)
(
Pbind(
\instrument, \ay8910,
\dur, Pbrown(0.1, 0.15, 0.1),
\amp, 0.8,
\r0, Pseq([100, 130, 160], inf)*Pseq([Pn(1, 32), Pn(0.75, 32)], inf),
\r1, 0,
\r2, Pseq([24, 24, Pwrand([20, 23], [0.6, 0.4])], inf),
\r3, Pseq([0, 2, Pwrand([1, 0], [0.6, 0.4])], inf),
\r7, 2r00011100,
\r8, 10,
\r9, 31,
\rA, 31,
\rB, 10,
\rC, Pseq([Pseq([1, 0], 24), Pseq([1, 0, 2], 8)], inf),
\rD, 2r0000
).play
)
(
Pbind(
\instrument, \ay8910,
\dur, Pseq([0.06, 0.04], inf),
\amp, 0.8,
\r7, 2r00101111,
\r8, 31,
\r9, Pseq([Pn(31, 48), Pn(13, 48)], inf),
\rA, 31,
\rB, Pseq([1, 3, Pwrand([2, 1], [0.6, 0.4])], inf),
\rC, Pseq([Pn(1, 8), Pn(2, 12), Pn(1, 16), Pn(Pwrand([0, 40], [0.8, 0.2]), 12)], inf),
\rD, 2r0000
).play
)
(
Pbind(
\instrument, \ay8910,
\dur, Pseq([0.025, 0.025, 0.025, 0.045], inf),
\amp, 0.8,
\r7, 2r00101111,
\r8, Pseq([Pn(31, 128), Pn(13, 128)], inf),
\r9, Pseq([Pn(31, 48), Pn(13, 48)], inf),
\rA, Pseq([Pn(31, 16), Pn(13, 16)], inf),
\rB, Pseq([1, 3, 2], inf),
\rC, Pseq([Pn(1, 8), Pn(2, 12), Pn(1, 16), Pn(40, 40)], inf),
\rD, 2r0000
).play
)
(
Pbind(
\instrument, \ay8910,
\dur, 0.1,
\amp, 0.8,
\r0, Pseq([Pseq([10, 2], 32), Pseq([1, 9], 32), Pseq([1, 2, 4], 36)], inf),
\r1, Pseq([Pseries(0, 14, 16), Pseries(10, 5, 16)], inf),
\r2, Pseq([Pseries(0, 31, 16), Pseries(27, 31, 16)], inf),
\r3, Pseq([Pseries(0, 31, 16), Pseries(26, 31, 16)], inf),
\r4, Pseq([2, 3, 3, 2], inf),
\r5, 0,
\r6, Pseq([Pseries(0, 2, 120)], inf),
\r7, 2r00111000,
\r8, 12,
\r9, 31,
\rA, 31,
\rB, 10,
\rC, Pseq([Pseq([1, 0, 1, 4], 24), Pseq([1, 1, 4], 8)], inf),
\rD, 2r0000
).play
)
(
Pbind(
\instrument, \ay8910,
\dur, 0.1,
\amp, 0.8,
\legato, 1.5,
\r0, Pseq([Pn(2, 80), Pn(3, 80), Pn(4, 80), Pn(0, 40)], inf),
\r1, Pseq([Pseries(0, 0.01, 10)], inf),
\r2, Pseq([Pseries(5, 0.1, 40)], inf),
\r3, Pseq([Pseries(10, 0.05, 50)], inf),
\r4, 10,
\r5, 0,
\r6, Pseq([Pseries(0, 2, 120)], inf),
\r7, 2r00111000,
\r8, 31,
\r9, 31,
\rA, 31,
\rB, Pseq([Pseries(10, 1, 100)], inf),
\rC, Pseq([Pseq([1, 0, 1, 4], 24), Pseq([1, 1, 4], 8)], inf),
\rD, 2r0000,
\rate, Pseq([Pseries(1, 1, 20)], inf)
).play
)
(
Pbind(
\instrument, \ay8910,
\dur, 0.1,
\amp, 0.8,
\legato, 1.2,
\r0, Pseq([Pn(3, 40), Pwhite(3, 10, 8)], inf),
\r1, 0,
\r7, 2r00001000,
\r8, 14,
\rate, Pseq([Pn(1, 8), Pn(2, 8), Pn(1, 8), Pn(Pwrand([1.1, 1.5], [0.8, 0.2]), 8)], inf)*Pseq([Pn(1, 64), Pn(20, 64)], inf)
).play
)