Friday, July 29, 2011

fmss

Copperbox revision 2505.

I've added error handling to the Spec monad so it detects if variable names are used twice (Csound has no shadowing). Also I've added a more sophisticated example - FM bell, though it is not yet complete.

majalan-core

Copperbox revision 2504.

Some tidying up of the Score datatypes.

Thursday, July 28, 2011

majalan-symbolic

Copperbox revision 2503.

Adding "symbolic" modules for scale representation. Hopefully there are other useful symbolic objects as well as scales / pitches...

majalan-basic

Copperbox revision 2501.

Updated to match the changes to Timespan in Majalan-Core.

majalan-core

Copperbox revision 2501.

I've made Timespan a separate module, and added more operations that work on Timespans.

Wednesday, July 27, 2011

majalan-basic

Copperbox revision 2500.

I've separated the instrument number table from the context in the event types. This has made the types more complicated, but it does seem the right thing to do.

majalan

Copperbox revision 2499.

I've added a port of ZSnd-Basic - now majalan-basic. 

The example works, but the code is currently problematic. One of Majalan-Core's design principles is that instrument numbers should be resolved at "link time". This is to increase the modularity of scores, it should be possible to code an instrument's performance with out hard coding the instrument number. For example I might want to code a drum part without knowing that a snare drum will always be instrument 7 in the orchestra.

In Majalan-Core, I specify instrument numbers only when I link together all the parts of a score. Majalan-Basic roughly supports this but it is mixed up with the Context code and it is messy.

Tuesday, July 26, 2011

majalan

Copperbox revision 2498.

I've started a new project Majalan - this is a replacement for ZSnd that will only generate Csound scores. Instrument definitions will either be hand coded or generated by FMSS. 

Sunday, July 24, 2011

fmss

Copperbox revision 2497.

I've added the capability for cycles to the oscillator configuration.

A downside - the translation code is becoming very clunky, at some point I'll probably redo it entirely.

fmss

Copperbox revision 2496.

I've added a second monad which supports variable binding - this is so a single envelope declaration can be shared by multiple oscillators.

I've called the new monad Spec which was the name I used yesterday for the other monad. Yesterday's monad is now called Config. Config is the patching of oscillators cf. an algorithm in DX7 terminology. Spec is an FM instrument that instantiates a Config with particular oscillators.

Saturday, July 23, 2011

fmss

Copperbox revision 2495.

I've added a monad for specifying modulator-carrier connection patterns. A DX7 style algorithm will look something like this (cycles not yet implemented):


algo28 :: Config6 -> Spec ()
algo28 (Config6 o1 o2 o3 o4 o5 o6) = do
    m2 <- modulator o2
    m5 <- modulator o5
    m4 <- modulator o4
    c1 <- carrier   o1
    c3 <- carrier   o3
    c6 <- carrier   o6
    m2 =>- c1
    m5 =>= m4
    m4 =>- c3
    -- m5 should be cycled
    return ()

Friday, July 22, 2011

fmss

Copperbox revision 2494.

I've put the translation code in a monad so I can handle failure properly.

Thursday, July 21, 2011

fmss

Copperbox revision 2493.

New project fmss - fm synthesizer synthesizer.

fmss aims to generate only FM synthesizers in Csound, rather than be a general DSL for Csound instruments. FM instruments in Csound can be implemented fairly uniformly which indicates a generator might be promising. Particularly, the input descriptions should be more succinct than the Csound they generate. My previous attempts with Zsnd had the problem that the instrument definitions were always much bigger than the equivalent Csound instruments. The sole benefit (not always realized) was that ZSnd instruments could be a bit more modular.

Tuesday, July 19, 2011

fm-bell

Orch:
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1

;
; This is fm-bell written by Michael McNabb and distributed with 
; CLM (Common Lisp Music). The CLM original is in the file 
; fmex.ins. 
;

; TODO - the envelopes are parametric in CLM. 
; Potentially they should be put in a table in the score. 

instr 1
  isinetbl      = 1
  idur          = p3
  iamp          = p4
  ifreq         = p5
  indx          = p6
  ifm1index     = 32.0 * ifreq
  ifm2index     = 4.0 * (8.0 - ifreq / 50.0)
  ifm3index     = ifm2index * 0.705 * (1.4 - ifreq / 250.0)
  ifm4index     = 32.0 * (20.0 - ifreq / 20.0)
  imod1freq     = ifreq * 2.0
  imod2freq     = ifreq * 1.41
  imod3freq     = ifreq * 2.82
  imod4freq     = ifreq * 2.4
  icar1freq     = ifreq
  icar2freq     = ifreq
  icar3freq     = ifreq * 2.4

  ; index envelope
  kindxenv  expseg 1.0, idur, .01


  ; amp envelope
  kampenv   expseg .01, .002, 1, idur-.002, .01


  ; modulator 1
  amod1phs  phasor  imod1freq
  amod1sig  tablei  amod1phs, isinetbl, 1, 0, 1

  amod1sig  = (ifm1index * indx * kindxenv) * amod1sig

  ; carrier 1
  acar1phs  phasor icar1freq + amod1sig
  acar1sig  tablei acar1phs, isinetbl, 1, 0, 1


  ; modulator 2
  amod2phs  phasor  imod2freq
  amod2sig  tablei  amod2phs, isinetbl, 1, 0, 1

  ; modulator 3
  amod3phs  phasor  imod3freq
  amod3sig  tablei  amod3phs, isinetbl, 1, 0, 1

  ; amod2sig now sums amod2sig and amod3sig
  amod2sig  = kindxenv * ((ifm2index * amod2sig) + (ifm3index * amod3sig))

  ; carrier 2
  acar2phs  phasor icar2freq + amod2sig
  acar2sig  tablei acar2phs, isinetbl, 1, 0, 1


  ; modulator 4
  amod4phs  phasor  imod4freq
  amod4sig  tablei  amod4phs, isinetbl, 1, 0, 1

  amod4sig  = (ifm4index * indx * kindxenv) * amod4sig


  ; carrier 3
  acar3phs  phasor  icar3freq + amod4sig
  acar3sig  tablei  acar3phs, isinetbl, 1, 0, 1

            out iamp * kampenv * (acar1sig + (0.15 * acar2sig) + (0.15 * acar3sig))

endin


Score:
; Table #1: sinewave
f 1 0 1024 10 1

; 1   2    3    4      5       6    
; #   st   drn  amp    freq    index
i 1   0    5.0  20000  233.046 0.750

e

fm-tubular-bell

Orch:

Note I haven't given much attention to the envelopes.
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1

;
; This is fm-tubular-bell from Nicky Hind\'s CLM tutorials:
; https://ccrma.stanford.edu/software/clm/compmus/clm-tutorials/fm2.html
; 
; Note - amplitude in CLM is 0..1 in Csound it is 0..2^15 (I think...)

instr 1
  isinetbl      = 1
  idur          = p3
  iamp          = p4
  ifreq         = p5
  iampfrac      = iamp / 32768
  iamp1         = p6                    ; default 0.5
  iamp2         = p7                    ; default 0.25
  iamp3         = p8                    ; default 0.25
  iamp1level    = iamp * iamp1
  iamp2level    = iamp * iamp2
  iamp3level    = iamp * iamp3
  ic1rat        = p9                    ; default 2.0
  im1rat        = p10                   ; default 5.0
  ic2rat        = p11                   ; default 0.6
  im2rat        = p12                   ; default 4.8
  ic3rat        = p13                   ; default 0.22
  im3rat        = p14                   ; default 0.83
  indxmin       = p15                   ; default 0.15
  indx1scl      = p16                   ; default 3.0
  indx2scl      = p17                   ; default 2.0
  indx3scl      = p18                   ; default 1.0
  indx1max      = iampfrac * indx1scl * ((261.5 / ifreq) ^ 3) 
  indx2max      = iampfrac * indx2scl * ((261.5 / ifreq) ^ 3) 
  indx3max      = iampfrac * indx3scl * ((261.5 / ifreq) ^ 3) 
  imod1scaler   = (indx1max - indxmin) * im1rat * ifreq
  imod2scaler   = (indx2max - indxmin) * im2rat * ifreq
  imod3scaler   = (indx3max - indxmin) * im3rat * ifreq
  imod1offset   = indxmin * im1rat * ifreq
  imod2offset   = indxmin * im2rat * ifreq
  imod3offset   = indxmin * im3rat * ifreq


  ; index envelope
  kindxenv  expseg 1.0, idur, .01


  ; amp envelope
  kampenv   expseg .01, .002, 1, idur-.002, .01

  ; modulator 1
  amod1phs  phasor  ifreq * im1rat
  amod1sig  tablei  amod1phs, isinetbl, 1, 0, 1

  amod1sig  = (imod1offset + imod1scaler * kindxenv) * amod1sig

  ; carrier 1
  acar1phs  phasor (ifreq * ic1rat) + amod1sig
  acar1sig  tablei acar1phs, isinetbl, 1, 0, 1

  acar1sig  = iamp1level * kampenv * acar1sig

  ; modulator 2
  amod2phs  phasor  ifreq * im2rat
  amod2sig  tablei  amod2phs, isinetbl, 1, 0, 1

  amod2sig  = (imod2offset + imod2scaler * kindxenv) * amod2sig

  ; carrier 1
  acar2phs  phasor (ifreq * ic2rat) + amod2sig
  acar2sig  tablei acar2phs, isinetbl, 1, 0, 1

  acar2sig  = iamp2level * kampenv * acar2sig


  ; modulator 3
  amod3phs  phasor  ifreq * im1rat
  amod3sig  tablei  amod3phs, isinetbl, 1, 0, 1

  amod3sig  = (imod3offset + imod3scaler * kindxenv) * amod3sig


  ; carrier 3
  acar3phs  phasor  (ifreq * ic2rat) + amod2sig
  acar3sig  tablei  acar3phs, isinetbl, 1, 0, 1

  acar3sig  = iamp3level * kampenv * acar3sig

            out acar1sig + acar2sig + acar3sig

endin


Score:
; Table #1: sinewave
f 1 0 1024 10 1

; 1   2    3    4      5       6     7     8     9      10
; #   st   drn  amp    freq    amp1  amp2  amp3  c1rat  m1rat
i 1   0    3.0  20000  261.61  0.5   0.25  0.25  2.0    5.0
         ; 11     12     13     14     15     16      17      18
         ; c2rat  m2rat  c3rat  m3rat  ixmin  ixscl1  ixscl2  ixscl3 
           0.6    4.8    0.22   0.83   0.15   3.0     2.0     1.0

e

Monday, July 18, 2011

fm-gong

Here's a transliteration of the fm-gong from the CLM distribution:

Orch:
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1

;
; This is fm-gong written by Paul Weineke and distributed with
; CLM (Common Lisp Music). The CLM original is in the file 
; fmex.ins. 
;


instr 1
  isinetbl      = 1
  idur          = p3
  iamp          = p4
  ifreq         = p5
  imod1fq       = ifreq * 1.16
  imod2fq       = ifreq * 3.14
  imod3fq       = ifreq * 1.005 
  indx1a        = .01 * imod1fq
  indx1b        = .30 * imod1fq
  indx1scaler   = indx1b - indx1a
  indx2a        = .01 * imod2fq
  indx2b        = .38 * imod2fq
  indx2scaler   = indx2b - indx2a
  indx3a        = .01 * imod3fq
  indx3b        = .50 * imod3fq
  indx3scaler   = indx3b - indx3a  


  ; mod1 envelope (CLM fmup)
  kmod1env  linseg  0, idur*0.75, 1, idur*.23, 1, idur*.02, 0

  ; mod2 envelope (CLM fmdwn)
  kmod2env  linseg  0, idur*.02, 1, idur*.98, 0

  ; mod3 envelope (CLM rise)
  kmod3env  linseg  0, idur*.15, 0.3, idur*.15, 1, idur*.45, 0.5, idur*.25, 0

  ; amp envelope
  kampenv   expseg .01, .002, 1, idur-.002, .01

  ; modulator1
  amod1phs  phasor  imod1fq
  amod1sig  tablei  amod1phs, isinetbl, 1, 0, 1

  amod1sig  = (indx1a + indx1scaler * kmod1env) * amod1sig

  ; modulator2
  amod2phs  phasor  imod2fq
  amod2sig  tablei  amod2phs, isinetbl, 1, 0, 1

  amod2sig  = (indx2a + indx2scaler * kmod2env) * amod2sig

  ; modulator3
  amod3phs  phasor  imod3fq
  amod3sig  tablei  amod3phs, isinetbl, 1, 0, 1

  amod3sig  = (indx3b + indx3scaler * kmod3env) * amod3sig


  ; carrier
  acarrphs  phasor  ifreq + amod1sig + amod2sig + amod3sig
  acarrsig  tablei  acarrphs, isinetbl, 1, 0, 1


            out iamp * kampenv * acarrsig


endin

Score:
; Table #1: sinewave
f 1 0 1024 10 1

; #   st   drn  amp    freq
i 1   0    3.0  20000  261.61



It was a lot easier to make this one than the fm-drum.

fm-drum

Vis the previous post, the code is a translation to Csound of Jan Mattox's fm drum that is distributed with CLM (Common Lisp Music).

The "low" drum seems sonically pretty close to the original, the "high" drum sounds somewhat different, though I can't work out why.

It turned out to be a lot of effort porting from CLM (which I didn't know at all) to Csound (which I clearly didn't know that well...), hence I haven't updated Copperbox recently. Developing instruments does seem to need a lot of domain knowledge which is perhaps not easy to acquire, certainly if you view instrument building as a "programming" exercise. Maybe it is easier for electronic engineers.

fm-drum

Orch:
sr = 44100
kr = 4410
ksmps = 10
nchnls = 1

;
; This is fm-drum written by Jan Mattox and distributed with
; CLM (Common Lisp Music). The CLM original is in the file 
; fmex.ins. 
;
; Note - the low drum is pretty close to the CLM original, but the 
; high drum is some way off.
;


instr 1
  isinetbl      = 1
  idur          = p3
  iamp          = p4
  ifreq         = p5
  iindx         = p6
  ihigh         = p7
  inoiseamp     = 1000.0
  icasrat       = (ihigh > 0 ? 8.525 : 3.515)
  imodrat       = (ihigh > 0 ? 3.414 : 1.414)
  iamprise      = 0.015
  iamp1decay    = (idur < 0.18 ? 0.5 * idur : 0.18)
  iamp2decay    = idur - (iamprise + iamp1decay)
  icascadehz    = ifreq * icasrat
  imodhz        = ifreq * imodrat
  icarrhz       = ifreq
  idevscaler    = 7000
  icascscaler   = iindx * icascadehz 
  imodscaler    = iindx * imodhz
  iglsscaler    = (ihigh > 0 ? 66.0 : 0.0)

  

  ; modulator indices
  kindxenv    transeg .01, .015, 2,  1, .085, -1, 0.333,  idur-.10, -1, .012

  ; noise envelope does not decay to zero...
  ; In CLM there is a minor difference for high and low but it 
  ; seems to do little in the generated waveform.
  knoiseenv   expseg  .01, .015, 1, .005, 1, .010, .1, .040, .002, idur-.070, 0.01

  ; amplitude envelope...
  kampenv     transeg .01, iamprise, 1, 1.0, iamp1decay, 2, .75, iamp2decay, -8, .001


  ; gls envelope
  kgls        linseg 0, idur*0.25, 0, idur*.5, 1, idur*.25, 1

  ; deviation
  adev1     rand inoiseamp
  adevsig   = idevscaler * knoiseenv * adev1
  adevsig   = (icasrat * iglsscaler * kgls) + adevsig 

  ; cacasade 
  acascphs  phasor  icascadehz + adevsig
  acascsig  tablei  acascphs, isinetbl, 1, 0, 1

  acascsig  = icascscaler * kindxenv * acascsig 
  acascsig  = (imodrat * iglsscaler * kgls) + acascsig

  ; modulator
  amodphs   phasor  imodhz + acascsig
  amodsig   tablei  amodphs, isinetbl, 1, 0, 1

  amodsig   = imodscaler * kindxenv * amodsig
  amodsig   = (iglsscaler * kgls) + amodsig

  ; carrier
  acarrphs  phasor  icarrhz + amodsig
  acarrsig  tablei  acarrphs, isinetbl, 1, 0, 1
  
            out iamp * acarrsig * kampenv

endin


Score:
; Table #1: sinewave
f 1 0 1024 10 1

; #   st   drn  amp    hz  ix   hi
i 1   0    1.5  20000  55  5    0
i 1   2    1.5  20000  66  4    1

Saturday, July 9, 2011

zsnd-core

Copperbox revision 2492.

I've added the zak opcodes and fixed a couple of bugs in the score generation code.

Friday, July 8, 2011

zsnd-core

Copperbox revision 2491.

I've changed the Score language so instrument parameters are CsValues - this means they can be Ints or Doubles. It also means they can be Strings, though I don't know that there is a need for this. Maybe I'll have to restrict to just Int - Double at some point.

zsnd

Copperbox revision 2490.

Updates fleshing out the monadic layer of the new Inst language so it can handle the Xanadu instrument. Tidying up some code in ZSnd-Basic.

Thursday, July 7, 2011

zsnd-core

Copperbox revision 2488.

I've re-implemented the instrument language, no longer is it based on Click. The new version is significantly lower level, but it can manage control flow via labels and goto - not handling control flow was a significant deficiency of the Click version and the reason for its scrapping.

Quite a few of the details still need to be worked out in the monadic layer, though I've updated all the opcodes which is a significant effort and the simple demo instrument works.


Revision 2489 - deleted old files from the Click version.

Tuesday, July 5, 2011

zsnd-core

Copperbox revision 2486.

I've added composition operators - scoOver, scoBeside - to combine scores and hopefully debugged the score output code that was stopping them work correctly.

Update - revision 2487.

I've changed the score output so it now works for both overlay and sequential append. I'm not entirely happy with the generated scores as they probably aren't very efficient Csound, but they will do for the time being.

Monday, July 4, 2011

zsnd-basic

Copperbox revision 2485.

I've removed the Onset notelist - it had bad properties that weren't easy to rectify so its removal seems better. It is superseded by TraceLoc, which doesn't suffer from the same problems though it is more limited as a structure.

zsnd-basic

Copperbox revision 2484.

Updates to work  with ZSnd-Core changes.

Note, OnsetNotelist has a bug where the placement of notes is wrong after a tempo change - while I've identified where the bug lies, I'm currently stumped as to how to fix it...

Sunday, July 3, 2011

zsnd-core

Copperbox revision 2483.

I've remade the score datatypes so they are closer to the picture datatypes in Wumpus-Core - scores now have a Timespan (analogue to a bounding box) and a frame that abstracts the first event time. This allows scores to be moved cheaply so I can implement "picture language" like operations to combine scores.

Saturday, July 2, 2011

zsnd-core

Copperbox revision 2482.

Following up the last commit, I've added table-offset  to the monadic builder so table indexing within an instrument is parametric. Generally numbers will be contiguous within an instrument from some start point.

zsnd-core

Copperbox revision 2481.

I've changed table references (in Csound fields named ifn or similar) so they are distinct from ports in the syntax. This is should improve the modularity of Inst definitions which were otherwise liable to have table number conflicts when multiple instruments were used.

Note, I still have to improve the build monad so it treats table numbers as offsets rather than absolute values.

Friday, July 1, 2011

zsnd-symbolic

Copperbox revision 2480.

Preliminary work on pitch / scale support. I've replaced the PitchClass module with one for 12 tone EqualTemperament and added a module for Kraig Grady's Centaur scale - I want to consider alternative scales from the start rather than shoe horn them in later.

Blog Archive

About Me

My photo
Disambiguating biog as there are a few Stephen Tetley's in the world. I'm neither a cage fighter or yachtsman. I studied Fine Art in the nineties (foundation Bradford 1992, degree Cheltenham 1992 - 95) then Computing part-time at Leeds Met graduating in 2003. I'm the Stephen Tetley on Haskell Cafe and Stackoverflow.