Wednesday, March 6, 2019

ex8. pluck csound opcode

The csound pluck opcode generates a sound based on the Karpus Strong Algorithm.


We use a python file (rand_gen.py) to generate a random signal of 16k samples.


# rand_gen.py
# random signal of length N

N = 16 * 1024

import numpy as np
from scipy.io import wavfile

amp = 30000 # <= 32768
rate = 44100

sig = np.random.randint(-amp,amp, size=N).astype('int16')
wavfile.write('rand.wav', rate, sig)

We use this file (ex8.py) to generate instrument 1 which we play 200 times, with different parameters. We use the table genertated by rand.wav file.


# ex8.py
# pluck opcode

import random

from csd import CSD
import table
from opcodes import envelope, output, source

csd = CSD(__file__)

csd.begin()

csd.add_instrument(
    num = 1,
    opcodes = [
        envelope.adsr(
            attack = 'p5*idur',
            sustain = 0.99,
            sig_out = 'kadsr'
            ),
        source.pluck(
            sig_out = 'asig',
            amp = 0.5,
            freq = 'p4',
            table = 1,
            method = 1,
            iparam1 = 0,
            iparam2 = 0
        ),
        output.outs(
            sig_in = ['kadsr*asig','kadsr*asig']
        )
               ]
    )

csd.middle()

t = 0
for i in range(200):
    at = 0.01 + .09 * random.random()
    t = t + .5 + random.random()/5
    f = 220 + 440 * random.random()
    csd.add('i 1 %.4f 0.5 %.4f %.4f' % (t, f, at))

csd.add_tables([table.sample(
                    num=1,
                    name='rand.wav'
                    )
                ])

csd.end()

We use pluck from updated source.py file:


# source.py
# ver 1

import sys

#1. lfo
def lfo(**dic):
    ''' A low frequency oscillator of various shapes.
    itype = 0 - sine, itype = 1 - triangles,
    itype = 2 - square (bipolar), itype = 3 - square (unipolar),
    itype = 4 - saw-tooth, itype = 5 - saw-tooth(down)
    sig_out, amp, freq, type '''
    sig_out = dic.get('sig_out','')
    if sig_out=='':
        print('We need sig_out for lfo')
        sys.exit(-1)
    amp = dic.get('amp', 1)
    freq = dic.get('freq', 440)
    itype = dic.get('itype', 0)
    return '%s lfo %s, %s, %s' % (sig_out,amp,freq,itype)

#2. pluck
def pluck(**dic):
    ''' Produces a naturally decaying plucked string or drum sound.
    - sig_out, amp, freq, table
    - method, method of natural decay. There are 6, some of which use
    - the 2 parameters values that follow.
    - 1: simple averaging. A simple smoothing process, uninfluenced by
    - parameter values.
    - 2: stretched averaging. As above, with smoothing time stretched by
    - a factor of iparm1 (>=1).
    - 3: simple drum. The range from pitch to noise is controlled by a
    - 'roughness factor' in iparm1 (0 to 1). Zero gives the plucked string
    - effect, while 1 reverses the polarity of every sample (octave down,
    - odd harmonics). The setting .5 gives an optimum snare drum.
    - 4: stretched drum. Combines both roughness and stretch factors.
    - iparm1 is roughness (0 to 1), and iparm2 the stretch factor (>=1).
    - 5: weighted averaging. As method 1, with iparm1 weighting the
    - current sample (the status quo) and iparm2 weighting the previous
    - adjacent one. iparm1 + iparm2 must be <= 1.
    - 6: 1st order recursive filter, with coefs .5. Unaffected by
    - parameter values. '''
    sig_out = dic.get('sig_out', '')
    if sig_out == '':
        print('We need sig_out for pluck')
        sys.exit(-1)
    amp = dic.get('amp', 1)
    freq = dic.get('freq', 440)
    table = dic.get('table', 1)
    method = dic.get('method', 1)
    iparam1 = dic.get('iparam1', 0)
    iparam2 = dic.get('iparam2', 0)
    t = sig_out,amp,freq,freq,table,method,iparam1,iparam2
    return '%s pluck %s,%s,%s,%s,%s,%s,%s' % t

#3. poscil
def poscil(**dic):
    ''' High precision oscillator
    sig_out, amp, freq, and table '''
    sig_out = dic.get('sig_out','')
    if sig_out == '':
        print('We need sig_out for poscil')
        return
    amp = dic.get('amp', 1)
    freq = dic.get('freq', 440)
    table = dic.get('table', 1)
    return '%s poscil %s, %s, %d' % (sig_out,amp,freq,table)

The link to the audio is here.

Saturday, March 2, 2019

ex7. linseg envelope opcode

The linseg envelope opcode is used to create envelopes for a sound oscillator.


For the python file to write the csound file, we will need a list in pts of levels and duration between levels.


For example for first fourth of note duration we go from 220 to 230. Then for half of note duration, we go from 230 to 260. Finally for last fourth, we go linearly to 240.


This program uses the envelope to control frequency of oscillator.


# ex7.py
# linseg opcode

from csd import CSD
import table
from opcodes import envelope, output, source

csd = CSD(__file__)

csd.begin()

csd.add_instrument(
    num = 1,
    opcodes = [envelope.linseg(
                   sig_out = 'kfreq',
                   pts = [220,'idur/4',230,'idur/2',260,'idur/4',240]
                   ),
               source.lfo(
                   sig_out = 'klfo',
                   amp = 5,
                   freq = 2),
               envelope.adsr(
                   sig_out = 'kadsr'
                   ),
               source.poscil(
                   sig_out = 'aOsc',
                   amp = 'kadsr',
                   freq = 'kfreq+klfo'
                   ),
               output.outs(
                   sig_in = ['aOsc', 'aOsc' ]
                   )
               ]
    )

csd.middle()

csd.add('i 1 0 40')

csd.add_tables([table.sine(
                    num=1,
                    amps=[1,1/2,1/3,1/4,1/5,1/6,1/7,1/8]
                    )
                ])

csd.end()

We use table.py file:



We use output.py from opcodes folder:


# output.py
# ver 0

import sys

#1. out
def out(**dic):
    ''' Writes mono audio data to an external device or stream.
    sig_in '''
    sig_in = dic.get('sig_in', '')
    if len(sig_in) == '':
        print('We need sig_in for out')
        sys.exit(-1)
    return 'out %s' % sig_in

#2. outs
def outs(**dic):
    ''' Writes stereo audio data to an external device or stream.
    sig_in (2-len) '''
    sig_in = dic.get('sig_in', [])
    if len(sig_in) != 2:
        print('We need sig_in (2-len) for outs')
        sys.exit(-1)
    return 'outs %s,%s' % (sig_in[0],sig_in[1])

This is the new envelope.py file from opcodes folder:


# envelope.py
# ver 1

import sys

#1. adsr
def adsr(**dic):
    ''' Calculates the classical ADSR envelope using linear segments.
    sig_out
    attack, duration of attack phase
    decay, duration of decay
    sustain_level, level for sustain phase
    release, duration of release phase
    delay, period of zero before the envelope starts '''
    sig_out = dic.get('sig_out', '')
    if sig_out == '':
        print('We need sig_out for adsr')
        sys.exit(-1)
    attack = dic.get('attack','0.1*idur')
    decay = dic.get('decay', '0.1*idur')
    sustain_level = dic.get('sustain_level', 0.5)
    release = dic.get('release', '0.1*idur')
    delay = dic.get('delay', 0)
    t = sig_out,attack,decay,sustain_level,release,delay
    return '%s adsr %s,%s,%s,%s,%s' % t


#2. line
def line(**dic):
    ''' Trace a straight line between specified points.
    sig_out
    end_pts, [ia, ib] where ia is start value and ib is value after dur
    dur, duration in seconds of segment '''
    sig_out = dic.get('sig_out', '')
    if sig_out == '':
        print('We need sig_out for line')
        sys.exit(-1)
    end_pts = dic.get('end_pts', [])
    if len(end_pts) != 2:
        print('We need end_pts (2-len) for line')
        sys.exit(-1)
    dur = dic.get('dur', 1)
    return '%s line %s,%s,%s' % (sig_out,end_pts[0],dur,end_pts[1])

#3. linen
def linen(**dic):
    ''' Applies a straight line rise and decay pattern to an input amp signal
    sig_out, amp
    rise, rise time in seconds. None, if <= 0.
    dur, overall duration in seconds.
    decay, decay time in seconds. Zero means no decay. '''
    sig_out = dic.get('sig_out','')
    if sig_out == '':
        print('We need sig_out for linen')
        sys.exit(-1)
    amp = dic.get('amp', 1)
    rise = dic.get('rise', '0.1*idur')
    dur = dic.get('dur', 'idur')
    decay = dic.get('decay', '0.1*idur')
    return '%s linen %s,%s,%s,%s' % (sig_out,amp,rise,dur,decay)

#4. linseg
def linseg(**dic):
    ''' Trace a series of line segments between specified points
    sig_out
    pts, [ia,idur1,ib,idur2,ic] where ia is starting level, ib, ic are
    ..levels and idur1, idur2 are duration in seconds between levels.'''
    sig_out = dic.get('sig_out', '')
    if sig_out == '':
        print('We need sig_out for linseg')
        sys.exit(-1)
    pts = dic.get('pts', [])
    if len(pts) == 0:
        print('We need pts for lineseg')
        sys.exit(-1)
    pts_str = [str(p) for p in pts]
    return '%s linseg %s' % (sig_out,','.join(pts_str))

The audio for the output file is here.

Tuesday, February 26, 2019

ex6. csound GEN10 routine

The GEN10 routine is used to generate sine tables.


Depending on the number of parameters, we can have harmonic partials.


We use a helper file, table.py, to create the string for the f statement for the table.


We use amps of [1,0.5]. That means we have fundamental (f) and first partial (at frequency 2f) with relative amp of 0.5. The actual amps will be adjusted by csound normalization.


This program uses the sine with two components in the oscillator.


# ex6.py
# GEN 10 sine table

from csd import CSD
import table
from opcodes import envelope, output, source

csd = CSD(__file__)

csd.begin()

csd.add_instrument(
    num = 1,
    opcodes = [envelope.line(
                   sig_out = 'kfreq',
                   end_pts = [2,8]
                   ),
               source.lfo(
                   sig_out = 'kres',
                   amp = 220,
                   freq = 2
                   ),
               envelope.linen(
                   sig_out = 'kenv',
                   rise = 'idur/40',
                   decay = 'idur/40'
                   ),
               envelope.adsr(
                   sig_out = 'kadsr'
                   ),
               source.poscil(
                   sig_out = 'aOsc',
                   amp = 0.5,
                   freq = 'kfreq+kres'
                   ),
               output.outs(
                   sig_in = ['kenv*aOsc', 'kadsr*aOsc' ]
                   )
               ]
    )

csd.middle()

csd.add('i 1 0 40')

csd.add_tables([table.sine(
                    num=1,
                    amps=[1,0.5]
                    )
                ])

csd.end()

We use table.py file:


# table.py
# ver 0

import sys

#1. sine
def sine(**dic):
    ''' GEN10 — Generate composite waveforms made up of weighted sums of
    .. simple sinusoids.
    num, time(0),
    size(2**14), 2 to power or 2 to power + 1
    norm(True), whether signal should be normalized
    amps, [str1, str2, ...] where str1, str2, are relative strengths of
    .. the fixed harmonic partial numbers 1,2,3, etc., beginning in p5.
    .. Partials not required should be given a strength of zero. If only
    .. 1 component, we can write it as 1 and not [1] for simple sine '''
    num = dic.get('num', 0)
    if num == 0:
        print('We need a table number.')
        sys.exit(-1)
    time = dic.get('time', 0)
    norm = dic.get('norm', True)
    if norm: gen = 1
    else: gen = -1
    amps = dic.get('amps', [])
    size = dic.get('size', 2**14)
    if type(amps) == type(0):
        amps = [amps]
    if len(amps) == 0:
        print('amps must be a list of numbers or a number')
        sys.exit(-1)
    amps = [str(amp) for amp in amps]
    string = 'f %d %d %d %d %s' % (num, time, size, gen*10, ' '.join(amps))
    return string

We use output.py from opcodes folder:


# output.py
# ver 0

import sys

#1. out
def out(**dic):
    ''' Writes mono audio data to an external device or stream.
    sig_in '''
    sig_in = dic.get('sig_in', '')
    if len(sig_in) == '':
        print('We need sig_in for out')
        sys.exit(-1)
    return 'out %s' % sig_in

#2. outs
def outs(**dic):
    ''' Writes stereo audio data to an external device or stream.
    sig_in (2-len) '''
    sig_in = dic.get('sig_in', [])
    if len(sig_in) != 2:
        print('We need sig_in (2-len) for outs')
        sys.exit(-1)
    return 'outs %s,%s' % (sig_in[0],sig_in[1])

We also use source.py from opcodes folder:


# source.py
# ver 0

import sys

#1. lfo
def lfo(**dic):
    ''' A low frequency oscillator of various shapes.
    itype = 0 - sine, itype = 1 - triangles,
    itype = 2 - square (bipolar), itype = 3 - square (unipolar),
    itype = 4 - saw-tooth, itype = 5 - saw-tooth(down)
    sig_out, amp, freq, type '''
    sig_out = dic.get('sig_out','')
    if sig_out=='':
        print('We need sig_out for lfo')
        sys.exit(-1)
    amp = dic.get('amp', 1)
    freq = dic.get('freq', 440)
    itype = dic.get('itype', 0)
    return '%s lfo %s, %s, %s' % (sig_out,amp,freq,itype)

#2. poscil
def poscil(**dic):
    ''' High precision oscillator
    sig_out, amp, freq, and table '''
    sig_out = dic.get('sig_out','')
    if sig_out == '':
        print('We need sig_out for poscil')
        return
    amp = dic.get('amp', 1)
    freq = dic.get('freq', 440)
    table = dic.get('table', 1)
    return '%s poscil %s, %s, %d' % (sig_out,amp,freq,table)

The audio for the output file is here.

ex5. adsr opcode

The adsr opcode is used to create an envelope with attack, decay, release time as well as sustain level.


This program uses an adsr envelope on the right channel as we can see by opening in program like Audacity.


# ex5.py
# adsr envelope function

from csd import CSD
from opcodes import envelope

csd = CSD(__file__)

csd.begin()

csd.add('giSine ftgen 0, 0, 2^10, 10, 1')

csd.add_instrument(
    num = 1,
    opcodes = [envelope.line(
                   sig_out = 'kfreq',
                   end_pts = [2,8]
                   ),
               'kres lfo 220,2',
               envelope.linen(
                   sig_out = 'kenv',
                   rise = 'idur/40',
                   decay = 'idur/40'
                   ),
               envelope.adsr(
                   sig_out = 'kadsr',
                   ),
               'aOsc poscil 0.5, kfreq+kres, giSine',
               'outs kenv*aOsc, kadsr*aOsc' ])

csd.middle()

csd.add('i 1 0 40')

csd.end()

We use envelope.py from opcodes folder.


# envelope.py
# ver 0

import sys

#1. adsr
def adsr(**dic):
    ''' Calculates the classical ADSR envelope using linear segments.
    sig_out
    attack, duration of attack phase
    decay, duration of decay
    sustain_level, level for sustain phase
    release, duration of release phase
    delay, period of zero before the envelope starts '''
    sig_out = dic.get('sig_out', '')
    if sig_out == '':
        print('We need sig_out for adsr')
        sys.exit(-1)
    attack = dic.get('attack','0.1*idur')
    decay = dic.get('decay', '0.1*idur')
    sustain_level = dic.get('sustain_level', 0.5)
    release = dic.get('release', '0.1*idur')
    delay = dic.get('delay', 0)
    t = sig_out,attack,decay,sustain_level,release,delay
    return '%s adsr %s,%s,%s,%s,%s' % t


#2. line
def line(**dic):
    ''' Trace a straight line between specified points.
    sig_out
    end_pts, [ia, ib] where ia is start value and ib is value after dur
    dur, duration in seconds of segment '''
    sig_out = dic.get('sig_out', '')
    if sig_out == '':
        print('We need sig_out for line')
        sys.exit(-1)
    end_pts = dic.get('end_pts', [])
    if len(end_pts) != 2:
        print('We need end_pts (2-len) for line')
        sys.exit(-1)
    dur = dic.get('dur', 1)
    return '%s line %s,%s,%s' % (sig_out,end_pts[0],dur,end_pts[1])

#3. linen
def linen(**dic):
    ''' Applies a straight line rise and decay pattern to an input amp signal
    sig_out, amp
    rise, rise time in seconds. None, if <= 0.
    dur, overall duration in seconds.
    decay, decay time in seconds. Zero means no decay. '''
    sig_out = dic.get('sig_out','')
    if sig_out == '':
        print('We need sig_out for linen')
        sys.exit(-1)
    amp = dic.get('amp', 1)
    rise = dic.get('rise', '0.1*idur')
    dur = dic.get('dur', 'idur')
    decay = dic.get('decay', '0.1*idur')
    return '%s linen %s,%s,%s,%s' % (sig_out,amp,rise,dur,decay)

The video with the sound is here.

Monday, February 25, 2019

ex4. Notes in Ace Song

We play the MIDI notes from a portion of Ace's How Long song.


The first half is over the notes of track with instrument 5 (Electric Piano). The next half is over all instruments including percussion


For example these are the notes for the first half (time offset, MIDI pitch, duration, velocity):


Instr = 5 (Electric Piano)
+ 0.000,46,1.000,75
+ 0.500,56,0.500,65
+ 0.500,58,0.500,65
+ 0.500,60,0.500,65
+ 0.500,63,0.500,65
+ 1.500,46,0.125,80
+ 1.500,58,3.375,90
+ 1.500,62,3.250,90
+ 1.500,65,3.250,90
+ 2.000,46,1.000,80
+ 3.500,46,0.125,75
+ 4.000,46,1.000,80
+ 5.500,46,0.125,90
+ 5.500,56,2.875,90
+ 5.500,60,2.875,80
+ 5.500,63,2.750,80
+ 6.000,46,1.000,90
+ 7.500,46,0.125,90
+ 8.000,46,0.875,90
+ 8.500,56,0.875,90
+ 8.500,58,0.875,65
+ 8.500,60,0.875,75
+ 8.500,63,0.875,75
+ 9.500,46,0.125,80
+ 9.500,58,2.750,80
+ 9.500,62,2.750,90
+ 9.500,65,2.625,80
+ 10.000,46,1.000,80
+ 11.500,46,0.125,75
+ 12.000,46,1.000,90
+ 12.500,58,0.875,90
+ 12.500,62,0.875,80
+ 12.500,65,0.875,75
+ 13.500,46,0.125,80
+ 13.500,56,2.875,80
+ 13.500,58,2.875,75
+ 13.500,60,2.875,80
+ 13.500,63,2.875,80
+ 14.000,46,1.000,90
+ 15.500,46,0.125,80
+ 16.000,46,1.000,80
+ 16.500,56,0.875,90
+ 16.500,58,0.875,80
+ 16.500,60,0.875,90
+ 16.500,63,0.875,75
+ 17.500,46,0.125,90
+ 17.500,58,2.875,75
+ 17.500,62,3.000,75
+ 17.500,65,2.875,65
+ 18.000,46,1.000,90
+ 19.500,46,0.125,90
+ 20.000,46,0.875,80
+ 20.500,58,0.875,75
+ 20.500,65,0.875,75
+ 21.500,46,0.125,90
+ 21.500,56,2.875,80
+ 21.500,58,2.875,75
+ 21.500,60,3.000,75
+ 21.500,63,2.875,65
+ 22.000,46,1.000,90
+ 23.500,46,0.125,90
+ 24.000,46,0.875,90
+ 24.500,56,0.875,75
+ 24.500,58,0.875,75
+ 24.500,63,0.875,75
+ 25.500,46,0.125,90
+ 25.500,58,2.750,75
+ 25.500,62,2.875,80
+ 25.500,65,2.750,80
+ 26.000,46,1.000,80
+ 27.500,46,0.125,90
+ 28.000,46,0.875,90
+ 28.500,58,0.875,80
+ 28.500,62,0.875,90
+ 28.500,65,0.875,60
+ 29.500,46,0.125,80
+ 29.500,60,2.375,75
+ 29.500,63,2.375,90
+ 29.500,68,2.375,80
+ 30.000,46,1.000,90
+ 31.500,46,0.125,80
+ 32.000,46,1.000,90
+ 32.000,60,0.250,80
+ 32.000,63,1.375,90
+ 32.000,68,0.375,80
+ 32.500,58,0.375,75
+ 32.500,67,0.125,60
+ 33.000,60,0.250,60
+ 33.000,68,0.375,75
+ 33.500,46,0.125,80
+ 33.500,58,2.750,80
+ 33.500,62,2.750,90
+ 33.500,65,2.750,75
+ 34.000,46,1.000,80
+ 35.500,46,0.125,90
+ 36.000,46,0.875,80
+ 36.500,58,0.875,80
+ 36.500,62,0.750,80
+ 36.500,65,0.875,80
+ 37.500,46,0.125,75
+ 37.500,60,2.250,90
+ 37.500,63,2.375,80
+ 37.500,68,2.250,80
+ 38.000,46,1.000,90
+ 39.500,46,0.125,90
+ 40.000,46,1.000,80
+ 40.000,60,0.250,80
+ 40.000,63,0.875,90
+ 40.000,68,0.500,90
+ 40.500,58,0.375,60
+ 41.000,60,0.375,80
+ 41.000,63,0.375,60
+ 41.000,68,0.500,75
+ 41.500,46,0.125,80
+ 41.500,58,2.875,75
+ 41.500,62,2.750,75
+ 41.500,65,2.875,80
+ 42.000,46,1.000,80
+ 43.500,46,0.125,90
+ 44.000,46,0.875,80
+ 44.500,58,0.750,65
+ 44.500,62,0.750,75
+ 44.500,65,0.875,75
+ 45.500,46,0.125,75
+ 45.500,60,2.250,90
+ 45.500,63,2.375,90
+ 45.500,68,2.375,75
+ 46.000,46,1.000,80
+ 47.500,46,0.125,90
+ 48.000,46,1.000,75
+ 48.000,60,0.250,90
+ 48.000,63,0.875,90
+ 48.000,68,0.500,90
+ 48.500,58,0.375,75
+ 48.500,67,0.375,80
+ 49.000,60,0.375,75
+ 49.000,63,0.375,65
+ 49.000,68,0.375,80
+ 49.500,46,0.125,75
+ 49.500,58,3.875,80
+ 49.500,62,3.500,90
+ 49.500,65,1.875,80
+ 50.000,46,1.000,80
+ 51.500,46,0.125,80
+ 51.500,65,0.750,75
+ 52.000,46,0.875,90
+ 52.500,65,1.000,90
+ 53.500,46,0.125,90
+ 53.500,60,2.250,80
+ 53.500,63,2.250,80
+ 53.500,68,2.250,75
+ 54.000,46,1.000,80
+ 55.500,46,0.125,80
+ 56.000,46,0.875,80
+ 56.000,60,0.250,80
+ 56.000,63,1.375,80
+ 56.000,68,0.375,80
+ 56.500,58,0.375,60
+ 56.500,67,0.375,65
+ 57.000,60,0.375,65
+ 57.000,68,0.375,80
+ 57.500,46,0.125,80
+ 57.500,58,2.000,90
+ 57.500,62,1.875,90
+ 57.500,65,1.875,65
+ 58.000,46,1.000,90
+ 59.500,62,1.250,75
+ 61.000,62,1.000,75
+ 62.000,48,1.125,80
+ 62.000,60,3.125,90
+ 62.000,63,2.875,90
+ 62.000,67,2.750,90
+ 63.500,48,0.125,90
+ 64.000,48,1.875,90
+ 66.000,43,2.625,80
+ 66.000,55,1.125,65
+ 66.000,58,1.125,75
+ 66.000,62,1.125,65
+ 66.000,65,1.125,75
+ 67.500,55,1.375,75
+ 67.500,58,1.500,75
+ 67.500,62,1.375,80
+ 67.500,65,1.375,75
+ 69.000,43,0.750,80
+ 70.000,41,4.000,90
+ 70.000,53,3.875,60
+ 70.000,56,3.875,65
+ 70.000,60,4.000,65
+ 70.000,63,3.750,65
+ 74.000,53,1.625,65
+ 74.000,56,1.625,75
+ 74.000,63,1.625,75
+ 76.000,53,0.625,80
+ 76.000,56,0.625,75
+ 76.000,60,0.625,75
+ 76.000,63,0.625,90
+ 77.000,46,0.750,90
+ 77.000,53,0.750,80
+ 77.000,58,0.875,80
+ 77.000,62,0.750,90
+ 78.000,48,1.125,80
+ 78.000,55,3.000,80
+ 78.000,60,3.000,75
+ 78.000,63,2.875,90
+ 79.500,48,0.250,90
+ 80.000,48,1.875,90
+ 81.000,63,0.875,80
+ 82.000,43,1.000,80
+ 82.000,55,1.375,75
+ 82.000,58,1.375,75
+ 82.000,62,1.250,75
+ 83.500,43,0.125,80
+ 83.500,55,2.375,80
+ 83.500,58,2.375,80
+ 83.500,62,2.375,90
+ 84.000,43,1.875,80
+ 86.000,41,1.125,75
+ 86.000,53,3.750,65
+ 86.000,56,3.875,75
+ 86.000,60,3.875,75
+ 86.000,63,3.750,80
+ 87.500,41,1.625,75
+ 90.000,41,1.875,80
+ 90.000,53,1.750,60
+ 90.000,56,1.750,65
+ 90.000,60,1.750,80
+ 90.000,63,1.625,80
+ 92.000,53,0.875,75
+ 92.000,56,0.750,75
+ 92.000,60,0.625,75
+ 92.000,63,0.750,75
+ 93.000,46,0.625,90
+ 93.000,53,0.875,80
+ 93.000,58,1.000,75
+ 93.000,62,0.875,80
+ 94.000,48,3.750,80
+ 94.000,55,1.125,75
+ 94.000,60,1.125,80
+ 94.000,63,1.125,75
+ 95.500,55,2.250,75
+ 95.500,60,2.125,80
+ 95.500,63,2.125,75
+ 98.000,43,3.500,90
+ 98.000,55,2.750,75
+ 98.000,58,2.750,75
+ 98.000,62,2.750,65
+ 98.000,65,2.750,75
+ 101.000,55,0.750,60
+ 101.000,58,0.750,65
+ 101.000,62,0.500,65
+ 101.000,65,0.625,75
+ 102.000,41,4.000,90
+ 102.000,53,3.875,60
+ 102.000,56,3.875,65
+ 102.000,60,3.875,60
+ 102.000,63,3.750,60
+ 106.000,53,1.750,75
+ 106.000,56,1.750,75
+ 106.000,60,1.750,80
+ 106.000,63,1.625,75
+ 108.000,53,0.875,65
+ 108.000,56,0.750,75
+ 108.000,60,0.750,80
+ 108.000,63,0.750,65
+ 109.000,46,0.750,90
+ 109.000,53,0.875,75
+ 109.000,58,0.875,80
+ 109.000,62,0.625,90
+ 110.000,48,3.875,90
+ 110.000,55,2.875,65
+ 110.000,60,2.875,75
+ 110.000,63,2.750,75
+ 113.000,55,1.000,75
+ 113.000,60,0.875,80
+ 113.000,63,0.875,80
+ 114.000,43,3.500,90
+ 114.000,58,2.875,75
+ 114.000,62,2.875,65
+ 117.000,55,0.750,65
+ 117.000,58,0.750,60
+ 117.000,62,0.750,75
+ 118.000,41,4.000,80
+ 118.000,53,1.125,75
+ 118.000,56,1.000,75
+ 118.000,60,1.125,75
+ 118.000,63,1.125,75
+ 119.500,53,2.250,75
+ 119.500,56,2.250,75
+ 119.500,60,2.250,65
+ 119.500,63,2.250,75
+ 122.000,53,1.750,65
+ 122.000,56,1.750,80
+ 122.000,60,1.750,80
+ 122.000,63,1.750,75
+ 124.000,53,0.750,90
+ 124.000,56,0.750,80
+ 124.000,60,0.625,75
+ 124.000,63,0.750,90
+ 125.000,46,0.750,90
+ 125.000,53,0.750,75
+ 125.000,58,0.750,80
+ 125.000,62,0.500,80

A score will have to be generated by another program such as a Digital Audio Workstation or pygame or tkinter program. We usually only have a few patterns (5-10) per instrument track (usually less than 10). Then the patterns are arranged in time.


We have the video here.