SuperCollider CLASSES (extension)

AY
ExtensionExtension

Emulator of the AY (aka YM) soundchip, used in Spectrum/Atari
Inherits from: UGen : AbstractFunction : Object

Description

Emulates the General Instrument AY-3-8910 (a.k.a. the Yamaha YM2149) 3-voice sound chip, as found in the ZX Spectrum 128, the Atari ST, and various other home computers during the 1980s.

NOTE: The chip's inputs are integer values, so non-integer values will be rounded off.

The emulation is provided by the libayemu library: http://sourceforge.net/projects/libayemu - I have merely wrapped it up as a SC UGen.

Class Methods

*ar (tonea: 1777, toneb: 1666, tonec: 1555, noise: 1, control: 7, vola: 15, volb: 15, volc: 15, envfreq: 4, envstyle: 1, chiptype: 0, mul: 1, add: 0)

Arguments:

tonea

integer "tone" value for the first of the three voices, from 0 to 4095 (i.e. 12-bit range). Higher value = lower pitch. For convenience, the *freqtotone method converts a frequency value to something appropriate for the tone input.

toneb

integer "tone" value for the second of the three voices. See description of tonea.

tonec

integer "tone" value for the third of the three voices. See description of tonea.

noise

the period of the pseudo-random noise generator, 0 to 31

control

controls how the noise is mixed into the tone(s), 0 to 32 (0 is mute). This is a binary mask value which masks the noise/tone mixture in each channel, so it's not linear.

vola

volume of the first of the three voices, 0 to 15 (or 0 to 31 if using YM chiptype)

volb

volume of the second of the three voices, 0 to 15 (or 0 to 31 if using YM chiptype)

volc

volume of the third of the three voices, 0 to 15 (or 0 to 31 if using YM chiptype)

envfreq

envelope frequency, 0 to 4095

envstyle

type of envelope used, 0 to 15

chiptype

0 for AY (default), 1 for YM. The models behave slightly differently. This input cannot be modulated - its value is only handled at the moment the UGen starts.

mul

general multiply controls for the resulting signal

add

general add controls for the resulting signal

*freqtotone (freq)

converts a frequency value to something appropriate for the tonea, toneb and tonec inputs.

Inherited class methods

Instance Methods

Inherited instance methods

Examples

s.boot;

// Default...
x = {AY.ar * 0.1}.play(s);
x.free;

// Mouse-controlled tones
(
x = {
    Pan2.ar(AY.ar(
        tonea:     MouseY.kr(10, 3900, 1),
        toneb:     MouseX.kr(10, 3900, 1),
        control:     3,
        vola:     14,
        volb:     14,
        volc:     0,
        mul: 0.1
    ))
}.play;
)

x.free;

// A random walk in a ZX Spectrum
(
x = {
    var rate = MouseX.kr(0.1, 10); // You control your wandering speed
    Pan2.ar(AY.ar(
        tonea:     LFDNoise3.kr(rate).range(10, 3900),
        toneb:     LFDNoise3.kr(rate).range(10, 3900),
        tonec:     LFDNoise3.kr(rate).range(10, 3900),
        noise:     LFDNoise3.kr(rate).range(0, 31),
        control:     LFDNoise0.kr(rate).range(0, 31),
        vola:     LFDNoise3.kr(rate).range(0, 15),
        volb:     LFDNoise3.kr(rate).range(0, 15),
        volc:     LFDNoise3.kr(rate).range(0, 15),
        envfreq:     LFDNoise3.kr(rate).range(0, 4095),
        envstyle:     LFDNoise3.kr(rate).range(0, 15),
        mul: 0.1
    ))
}.play;
)

x.free;

// Now to define a synth which can be used in patterns etc
(
SynthDef(\ay1, { | freqa=440, freqb=550, freqc=660, vola=15, volb=0, volc=0, chink=1, wobbly=1, pan=0, amp=0.1, gate=1|
    var ay, chinkenv, wobblyenv;

    //chinkenv = if(chink>0, EnvGen.kr(Env.new([0.06125, 0.06125, 1, 1], [0.05, 0, 0.1], 0, 4, 4)), 1);
    chinkenv = if(chink>0, EnvGen.kr(Env.new([2, 2, 1, 1], [0.05, 0, 0.1], 0, 4, 4)), 1);
    wobblyenv = LFPulse.kr(10, 0.5, mul:wobbly).range(0.5, 1);

    # freqa, freqb, freqc = [freqa, freqb, freqc] * [1, wobblyenv, wobblyenv] * chinkenv;
    ay = AY.ar(AY.freqtotone(freqa), AY.freqtotone(freqb), AY.freqtotone(freqc),
        0, 3, vola, volb, volc, mul: amp);
    ay = ay * EnvGen.kr(Env.asr(0.01, 1, 0.05), gate, doneAction:2);
    Out.ar(0, Pan2.ar(ay, pan));
}).load(s);
)

x = Synth(\ay1, [\wobbly, 0, \chink, 1, \tonea, 1000.rand]);
x.free;

SynthDescLib.read;

// Use the synth in a jerky lo-fi pattern of some sort...
(
Pbind(
    \instrument, \ay1,
    \freqa,    Pseq((#[55, 55, 57, 58, 57, 55, 58, 50]-12).midicps, inf),
    \freqb,    Pseq([
                    Pseq( (#[55, 55, 54, 55, 54, 55, 58, 57]+12).midicps, 2),
                    Prand((#[55, 55, 54, 55, 54, 55, 58, 57]+12).midicps, 2)
                ], inf),
    \dur,    Pseq(#[3, 0.5, 0.5, 1.5, 0.5, 1, 1, 4] * 0.4, inf),
    \wobbly,    Pstutter(8 * 4, Prand(#[0, 1], inf)),
    \vola,    15,
    \volb,    14,
    \chink,    1,
    \amp,    0.4
).play
)