1. IMPORTANT:
    We launched a new online community and this space is now closed. This community will be available as a read-only resources until further notice.
    JOIN US HERE

Commadore Sequencer .sid creator on Win32

Discussion in 'REAKTOR' started by sly dirk, Sep 7, 2003.

Thread Status:
Not open for further replies.
  1. sly dirk

    sly dirk Forum Member

    Messages:
    200
    this is such good news i'll post it here too...

    for anyone that wants to know how to make complete scores with an essential sequencer design... check this:

    i've just managed to run the commadore sequencer perfectly in an emulator and it sounds great, like raw osc sounds sequencing live... woo. the files that you need to see sids in action and even make you own are appended:

    time has come to regain the synth wisdom of the bygone peoples of the C64, and recreate that wisdom within reaktor to quelch this chaos and bring everlasting happiness to mankind...

    i think that an exact gui-savvy replica of this sequencer should be possible once i manage to make tables that copy and paste images from each other...is this right?

    you can run this emulator:

    http://www.ibiblio.org/pub/micro/commodore/crossplatform/emulators/VICE/WinVICE-1.12.zip

    load this image C64 proggy:
    http://noname.c64.org/download.php/cybertracker1_01-d64.zip

    once it's loaded press ¬` key, and select load musix...
    select the nanotekk song, press yes,

    and then press F1 to play... bish bash bosh it rocks like the most wisest sequencer ever made...

    here's the manual, and please give me some ideas what is the best way to make this sequencer :)

    http://noname.c64.org/tracker/manual_online.php#b2b1b3

    good luck!
     
  2. timothylamb@hotmail.com

    timothylamb@hotmail.com Forum Member

    Messages:
    90
    No, a tracker interface is much too complex for reaktor's image module, or at least yes- but the time it'd take would make it pointless. more importantly, what good is a tracker without the use of a computer keyboard? aside from midi notes, lack of a spacebar and arrow keys as well as function keys = worthless usability.

    now the synthesis of the sid can be duplicated, as i once was worknig on a emulator in reaktor (i'll get back to working on it, ah, my copious ammount of free time)
    the tricky part is jotting down all the parameters, and then the software minuplation as well, adds up to somewhat of a overwhelming task.
     
  3. '

    ' Guest

    Yeah OKI was sublime.

    One thing, the AfxSeq preset sounds nothing like any AFX i've ever heard! :)

    Or am i mistaken?

    mark
    www.darklogik.org
     
  4. sly dirk

    sly dirk Forum Member

    Messages:
    200
    I'm having a good look at this sid sequencer and i think that it should be very easy to make something even faster and with the same paramaters in reaktor...

    each step (tick) can flip between about 8 instruments and 6 effects at 8 levels... on each step you can do things like define arpeggio, modify pitch envelope in 2 ways, step based portamento...

    once you make a 16 step pattern, you can save all data to a song sequencer, or you modify the OX on tables to sequence patterns.

    has anyone even made a sequencer with step arpeggio? this is calssic synth knowledge, it's got to be done, sounds so expressive!

    basically each track is has about 300 possible values, alot to describe in tables, but there are ways, or you can just make an exact replica with number box type knobs and record patterns into tables... easy, somewhere in between :)

    the oscillators have yet to be described in reaktor, with 8 envelopes.
    martin brinkmann did some of the most difficault part, making a basic commadore synth like the c-b-m-synth (brilliant work)...
    i think he tried to acheive arpeggio using some dodgy lfo's, but the arpeggio is actually envelope based normally, like with OKI... i have to expand his design with envelops for res, filter cutoff, pitch1+2, pulsw env etc etc... tim, i'm sure you can make a much more tidy ensemble than me, but someone has to do this emulation to set new standards on reaktor tracking ;), it's just replication...

    ez
     
  5. sly dirk

    sly dirk Forum Member

    Messages:
    200
    i think i understand the exact parameters for a complete perfect sid and tracker SW emulator...

    the tracking interface will be different... but i think that it will not be slow at all because all panels will be immediately accessible instruments, and all the values that you use the keeb for normally will be a combination fo tables...

    Specifications...
    the commadore sid can receive new events at 50hz...the reaktor clock can go a 50 hz, but i dont know wether i should make a hold/value module that works at 50 hz going into the sids, containing information from tables that read at the same speed as commadore software... can anyone clarify this?
    i do know that in commadore programs you can define patches and modulation curves with a max resolution of 50hz, so a saw wave that modulates pitch (pitch env) will be max 50 hz in the commadore hardware, as will i think arp. this correstponds to 50 hz tables.
    commadore chord is an arp that cycles tones very fast.

    other than that you can define envs with as many breakpoints as you like, and draw curves (tables) like in oki for most filter and pitch parameters. these curvs are static for one oscilator-patch and can be used or disgarded at 8 proportions on each step with the tracker. anyonew know what there 8 proportions are numerically?

    for the tracker, all you have to do is create 16/32/xx step (definable zoom and length) event tables for your songs...
    one table (tbl A)covers all octaves and you can slide across different cuts of the keyboard how you like, with midi input recording to cheat abit.

    another two tables are used for each track to control all the sid's parameters:
    one (tbl B) flips between the 8 effects that you want to use on each step, choose one effect per step. and the other (tbl C) table gives a value of 0-7 to say what level the effect in table b is at.

    you can use a quick read function to copy data on a table to another block, with a pretty steps selector under it, and you can choose copy + transpose also if you want as the data is copied.

    one of the most difficult things is what elecropop mentioned a year ago relating to the cmos based filter... the filter was actually a cmos of some kind and is sounds really organic...i'd really like some information about this filter's characteristics, and may try to look at a raw a filtered oscillator to see what it does...lol...i dont know what but if it's possible i'll do it.

    i hope that this all makes sense, and that is how complicated it is to make a good sid-tracker emulator, cabable of making anything tried faithful to the original hardware.

    ez :)
     
  6. sly dirk

    sly dirk Forum Member

    Messages:
    200
    tim, i know what you mean about losing the working method of original trackers on reaktor, maybe we can call it a sequencer with tracker parameters...

    the odd thing is the more i look at it the more it seems the other way round as far as complication goes...

    the tracker's functionality can be replicated with tables and a copy and paste function yet to be used in reaktor...

    but the sid it extremely hard to understand for me:
    i dont know how the sid PAL clock interfaces with the software's microprocessor, and how the oscillators should be emulated to be 8 bit... should i just quantise the osc to 8 bit, or should i place the quantiser after the addition of the 3 tone oscillator's shapes... the strange thing that even at 8 bit... for clock and bit depth i think i may well loose alot of emulation precision because of sync phase probs...

    the really easy thing is placing exact parameters on all the osc controls, 6ms-24s release, 16 level sustain thing..., exact filter parrameters...

    how do i emulate a true 8 bit sid osc and it's clock to keep everything in sync?

    cheers, i'll start uploading the osc prototypes with perfect parameters soon... i can certainly do the tracker, dunno how pro the sid will be ;)
     
  7. sly dirk

    sly dirk Forum Member

    Messages:
    200
    i see i'm all alone and copioulsy verbose on this thred...
    anyway for anyone doing future projects on the commadore, here is some more info as to how the filter can work...

    ------------------------------------------------------
    RESID FILTER SOURCE CODE FORM EXOERIMENT ON A SID CHIP
    ------------------------------------------------------

    #define __FILTER_CC__
    #include "filter.h"

    // Maximum cutoff frequency is specified as
    // FCmax = 2.6e-5/C = 2.6e-5/2200e-12 = 11818.
    //
    // Measurements indicate a cutoff frequency range of approximately
    // 220Hz - 18kHz on a MOS6581 fitted with 470pF capacitors. The function
    // mapping FC to cutoff frequency has the shape of the tanh function, with
    // a discontinuity at FCHI = 0x80.
    // In contrast, the MOS8580 almost perfectly corresponds with the
    // specification of a linear mapping from 30Hz to 12kHz.
    //
    // The mappings have been measured by feeding the SID with an external
    // signal since the chip itself is incapable of generating waveforms of
    // higher fundamental frequency than 4kHz. It is best to use the bandpass
    // output at full resonance to pick out the cutoff frequency at any given
    // FC setting.
    //
    // The mapping function is specified with spline interpolation points and
    // the function values are retrieved via table lookup.
    //
    // NB! Cutoff frequency characteristics may vary, we have modeled two
    // particular Commodore 64s.

    fc_point Filter::f0_points_6581[] =
    {
    // FC f FCHI FCLO
    // ----------------------------
    { 0, 220 }, // 0x00 - repeated end point
    { 0, 220 }, // 0x00
    { 128, 230 }, // 0x10
    { 256, 250 }, // 0x20
    { 384, 300 }, // 0x30
    { 512, 420 }, // 0x40
    { 640, 780 }, // 0x50
    { 768, 1600 }, // 0x60
    { 832, 2300 }, // 0x68
    { 896, 3200 }, // 0x70
    { 960, 4300 }, // 0x78
    { 992, 5000 }, // 0x7c
    { 1008, 5400 }, // 0x7e
    { 1016, 5700 }, // 0x7f
    { 1023, 6000 }, // 0x7f 0x07
    { 1023, 6000 }, // 0x7f 0x07 - discontinuity
    { 1024, 4600 }, // 0x80 -
    { 1024, 4600 }, // 0x80
    { 1032, 4800 }, // 0x81
    { 1056, 5300 }, // 0x84
    { 1088, 6000 }, // 0x88
    { 1120, 6600 }, // 0x8c
    { 1152, 7200 }, // 0x90
    { 1280, 9500 }, // 0xa0
    { 1408, 12000 }, // 0xb0
    { 1536, 14500 }, // 0xc0
    { 1664, 16000 }, // 0xd0
    { 1792, 17100 }, // 0xe0
    { 1920, 17700 }, // 0xf0
    { 2047, 18000 }, // 0xff 0x07
    { 2047, 18000 } // 0xff 0x07 - repeated end point
    };

    fc_point Filter::f0_points_8580[] =
    {
    // FC f FCHI FCLO
    // ----------------------------
    { 0, 0 }, // 0x00 - repeated end point
    { 0, 0 }, // 0x00
    { 128, 800 }, // 0x10
    { 256, 1600 }, // 0x20
    { 384, 2500 }, // 0x30
    { 512, 3300 }, // 0x40
    { 640, 4100 }, // 0x50
    { 768, 4800 }, // 0x60
    { 896, 5600 }, // 0x70
    { 1024, 6500 }, // 0x80
    { 1152, 7500 }, // 0x90
    { 1280, 8400 }, // 0xa0
    { 1408, 9200 }, // 0xb0
    { 1536, 9800 }, // 0xc0
    { 1664, 10500 }, // 0xd0
    { 1792, 11000 }, // 0xe0
    { 1920, 11700 }, // 0xf0
    { 2047, 12500 }, // 0xff 0x07
    { 2047, 12500 } // 0xff 0x07 - repeated end point
    };


    // ----------------------------------------------------------------------------
    // Constructor.
    // ----------------------------------------------------------------------------
    Filter::Filter()
    {
    fc = 0;

    res = 0;

    filt = 0;

    voice3off = 0;

    hp_bp_lp = 0;

    vol = 0;

    // State of filter.
    Vhp = 0;
    Vbp = 0;
    Vlp = 0;
    Vnf = 0;

    enable_filter(true);

    // Create mappings from FC to cutoff frequency.
    set_chip_model(MOS8580);
    interpolate(f0_points, f0_points + f0_count - 1, fc_plotter(), 1.0);
    set_chip_model(MOS6581);
    interpolate(f0_points, f0_points + f0_count - 1, fc_plotter(), 1.0);
    }


    // ----------------------------------------------------------------------------
    // Enable filter.
    // ----------------------------------------------------------------------------
    void Filter::enable_filter(bool enable)
    {
    enabled = enable;
    }


    // ----------------------------------------------------------------------------
    // Set chip model.
    // ----------------------------------------------------------------------------
    void Filter::set_chip_model(chip_model model)
    {
    if (model == MOS6581) {
    // The mixer has a small input DC offset. This is found as follows:
    //
    // The "zero" output level of the mixer measured on the SID audio
    // output pin is 5.50V at zero volume, and 5.44 at full
    // volume. This yields a DC offset of (5.44V - 5.50V) = -0.06V.
    //
    // The DC offset is thus -0.06V/1.05V ~ -1/18 of the dynamic range
    // of one voice. See voice.cc for measurement of the dynamic
    // range.

    mixer_DC = -0xfff*0xff/18 >> 7;

    f0 = f0_6581;
    f0_points = f0_points_6581;
    f0_count = sizeof(f0_points_6581)/sizeof(*f0_points_6581);
    }
    else {
    // No DC offsets in the MOS8580.
    mixer_DC = 0;

    f0 = f0_8580;
    f0_points = f0_points_8580;
    f0_count = sizeof(f0_points_8580)/sizeof(*f0_points_8580);
    }

    set_w0();
    set_Q();
    }


    // ----------------------------------------------------------------------------
    // SID reset.
    // ----------------------------------------------------------------------------
    void Filter::reset()
    {
    fc = 0;

    res = 0;

    filt = 0;

    voice3off = 0;

    hp_bp_lp = 0;

    vol = 0;

    // State of filter.
    Vhp = 0;
    Vbp = 0;
    Vlp = 0;
    Vnf = 0;

    set_w0();
    set_Q();
    }


    // ----------------------------------------------------------------------------
    // Register functions.
    // ----------------------------------------------------------------------------
    void Filter::writeFC_LO(reg8 fc_lo)
    {
    fc = fc & 0x7f8 | fc_lo & 0x007;
    set_w0();
    }

    void Filter::writeFC_HI(reg8 fc_hi)
    {
    fc = (fc_hi << 3) & 0x7f8 | fc & 0x007;
    set_w0();
    }

    void Filter::writeRES_FILT(reg8 res_filt)
    {
    res = (res_filt >> 4) & 0x0f;
    set_Q();

    filt = res_filt & 0x0f;
    }

    void Filter::writeMODE_VOL(reg8 mode_vol)
    {
    voice3off = mode_vol & 0x80;

    hp_bp_lp = (mode_vol >> 4) & 0x07;

    vol = mode_vol & 0x0f;
    }

    // Set filter cutoff frequency.
    void Filter::set_w0()
    {
    const double pi = 3.1415926535897932385;

    // Multiply with 1.048576 to facilitate division by 1 000 000 by right-
    // shifting 20 times (2 ^ 20 = 1048576).
    w0 = static_cast<sound_sample>(2*pi*f0[fc]*1.048576);

    // Limit f0 to 16kHz to keep 1 cycle filter stable.
    const sound_sample w0_max_1 = static_cast<sound_sample>(2*pi*16000*1.048576);
    w0_ceil_1 = w0 <= w0_max_1 ? w0 : w0_max_1;

    // Limit f0 to 4kHz to keep delta_t cycle filter stable.
    const sound_sample w0_max_dt = static_cast<sound_sample>(2*pi*4000*1.048576);
    w0_ceil_dt = w0 <= w0_max_dt ? w0 : w0_max_dt;
    }

    // Set filter resonance.
    void Filter::set_Q()
    {
    // Q is controlled linearly by res. Q has approximate range [0.707, 1.7].
    // As resonance is increased, the filter must be clocked more often to keep
    // stable.

    // The coefficient 1024 is dispensed of later by right-shifting 10 times
    // (2 ^ 10 = 1024).
    _1024_div_Q = static_cast<sound_sample>(1024.0/(0.707 + 1.0*res/0x0f));
    }

    // ----------------------------------------------------------------------------
    // Spline functions.
    // ----------------------------------------------------------------------------

    // ----------------------------------------------------------------------------
    // Return the array of spline interpolation points used to map the FC register
    // to filter cutoff frequency.
    // ----------------------------------------------------------------------------
    void Filter::fc_default(const fc_point*& points, int& count)
    {
    points = f0_points;
    count = f0_count;
    }

    // ----------------------------------------------------------------------------
    // Given an array of interpolation points p with n points, the following
    // statement will specify a new FC mapping:
    // interpolate(p, p + n - 1, filter.fc_plotter(), 1.0);
    // Note that the x range of the interpolation points *must* be [0, 2047],
    // and that additional end points *must* be present since the end points
    // are not interpolated.
    // ----------------------------------------------------------------------------
    PointPlotter<sound_sample> Filter::fc_plotter()
    {
    return PointPlotter<sound_sample>(f0);
    }
    // ---------------------------------------------------------------------------
    // This file is part of reSID, a MOS6581 SID emulator engine.
    // Copyright (C) 2002 Dag Lem <resid@nimrod.no>
    //
    // This program is free software; you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation; either version 2 of the License, or
    // (at your option) any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    // GNU General Public License for more details.
    //
    // You should have received a copy of the GNU General Public License
    // along with this program; if not, write to the Free Software
    // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    // ---------------------------------------------------------------------------
     
  8. '

    ' Guest

Thread Status:
Not open for further replies.