LISP code for the mixer

from/for Christopher Bailey's Dissertation



(setf piano-notes-directory "/bark/chris/PNONOTES.new/")
(setf concrete-sounds-directory "/bark/chris/allsoundsfinal/")
(setf section-number '0)

;
;
;  note also:
;    re-write-flag  =   (first (last (nth note-number note-list))
;    duration       =   (nth (- (length note-number note-list) 2) (nth note-number note-list))
;    filename of
;     output sound  =   (nth (- (length note-number note-list) 3) (nth note-number note-list))
;
;
;
;   PARAMETER LOCATIONS in  NOTES
; for everyone
(setf instrument-name-par '0)
(setf start-msr-par '1)
(setf start-beat-par '2)
(setf start-div-par '3)
;  for pitches
(setf pitch-dur-msr-par '4)
(setf pitch-dur-beat-par '5)
(setf pitch-dur-div-par '6)
(setf pitch-octave-par '7)
(setf pitch-pc-par '8)
(setf pitch-register-lyne-par '9)
(setf pitch-dyn-par '10)
(setf pitch-spatq-par '11)
(setf pitch-stereo-par '12)
(setf pitch-artic-par '13)
(setf pitch-droneq-par '14)
;  for wwave only
(setf wwave-waveform-par '15)
(setf wwave-filename-par '16)
(setf wwave-dur-par '17)
(setf wwave-rewrite-par '18)
;  for piano only
(setf piano-attq-par '15)
(setf piano-filename-par '16)
(setf piano-dur-par '17)
(setf piano-rewrite-par '18)
; for filter only
(setf filt-noisiness-par '15)
(setf filt-filename-par '16)
(setf filt-dur-par '17)
(setf filt-rewrite-par '18)
; for concrete only
(setf conc-list-par '4)
(setf conc-amp-par '5)
(setf conc-spatq-par '6)
(setf conc-stereo-par '7)
(setf conc-attq-par '8)
(setf conc-makegen-curve-par '9)
(setf conc-loud-hard-amp-par '10)
(setf conc-soundnumber-par '11)
(setf conc-file-par '12)
(setf conc-dur-par '13)
(setf conc-rewrite-par '14)
; for arb only
(setf arb-inst-type-par '4)
(setf arb-pitch-register-lyne-par '5)
(setf arb-pitch-pc-par '6)
(setf arb-pitch-dyn-par '7)
(setf arb-pitch-spatq-par '8)
(setf arb-pitch-droneq-par '9)
(setf arb-pitch-file-par '10)
(setf arb-pitch-dur-par '11)
(setf arb-conc-stereo-par '5)
(setf arb-conc-loud-hard-par '6)
(setf arb-conc-file-par '7)
(setf arb-conc-dur-par '8)


;**************************************************************
;**************************************************************
;**************************************************************
;**************************************************************
;**************************************************************
;            BASIC CLASS DEFINITIONS        
;**************************************************************
;**************************************************************
;**************************************************************
;**************************************************************
;**************************************************************
;**************************************************************



(defclass articulation ()
      ((desired-dur  :accessor desired-dur  :initarg :desired-dur)
       (frequency    :accessor frequency    :initarg :frequency)
       (dynamic      :accessor dynamic      :initarg :dynamic)
       (extra-params :accessor extra-params :initarg :extra-params)
       (note-number  :accessor note-number  :initarg :note-number)
       (this-source  :accessor this-source  :initarg :this-source)))


(defclass inst () ())


;****************************************************************
;****************************************************************
;****************************************************************
;****************************************************************
;       LOAD STUFF RELEVANT TO EACH INSTRUMENT
;****************************************************************
;****************************************************************
;****************************************************************
;****************************************************************


(load "init.lsp")
(load "sdata.lisp")
(load "wwavestuff.lisp")
(load "filtstuff.lisp")
(load "pianostuff.lisp")
(load "concretestuff.lisp")


;
;
;  note-list is a global special variable  with the "score" for the whole piece
;



(defun process-notes ()
  (let ((elle ()))
        (dotimes (ctr (length note-list))
           (setf elle (nth ctr note-list))
           (if (or (eq (nth instrument-name-par elle) 'bang)
                  (eq (nth instrument-name-par elle) 'arb)
                  (if (numberp (first (last elle))) (= (first (last elle)) 0) ()))
               ()
               (make-note ctr)))))


(defun make-note (note-number)
   (let  ((type 'hi))
   (setf type (nth instrument-name-par (nth note-number note-list)))
   (case type
       ('wave   (make-wave note-number))
       ('filt   (make-filt note-number))
       ('piano  (make-piano note-number))
       ('conc   (make-conc note-number))
       (otherwise (format t "A note around # ~a, it's type is muffed up." note-number) (bye)))))




;*************************************************************
;*************************************************************
;*************************************************************
;*************************************************************
;*************************************************************
;*************************************************************
;*************************************************************
;*************************************************************
;*************************************************************
;
;   MISCELLAENEOUS USEFUL FUNCTIONS
;
;*************************************************************
;*************************************************************
;*************************************************************
;*************************************************************
;*************************************************************




    ; for octave, pitch, calculates frequency in 19 TET
(defun pitch-to-freq (octave pitch)
     ;   1.037155 is the ratio for 19-TET
     ;  octave 8 is middle C, pitch 0 = 261.6256
     ;  octave 0 is  pitch 0 = 1.021974864
     ;  octave 4 is pitch 0 = 16.351601
     ;   how many chromatic steps up from 0 0?
     ;       1.021975 * (1.037155 ^ X)
    (setf stepsup (+ (* octave 19) pitch))
    (* 1.021974864 (expt 1.037155044 stepsup)))




     ; slightly adjusts a list of floats, random-deviates them
(defun piddle (list-of-numbers deviance)
         (dotimes (ctr (length list-of-numbers))
               (setf (nth ctr list-of-numbers)
                   (* (nth ctr list-of-numbers) 
                      (const-frandom (- 1.0 deviance) (+ 1.0 deviance)))))
         list-of-numbers)
              


(defun convert-dur-from-mbd-sec (list-of-three)
 (/ 
  (* 18 
    (+ (third list-of-three) 
    (* (second list-of-three) 6) 
    (* (first list-of-three) 114)))
 1000.0))


                          
                
(defun get-smallest-largest (lipst)
    (let ((largest  (first lipst))
          (smallest (first lipst)))
       (append
                (list
         (setf smallest
              (dolist (elle lipst smallest)
                      (if (< elle smallest)
                          (setf smallest elle)))))
                (list
         (setf largest
              (dolist (elle lipst largest)
                      (if (> elle largest)
                          (setf largest elle))))))))
 



(defun put-notes-in-order ()
; takes the notes in note-list, and puts them in  chronological order.
; make another list of pairs of (note-number in original, time in total divs)
;    sort that list by div-pairs
;  construct a 3rd list by 
;         moving each note of note-list into it, in the new order.
;
  (let ((index-div-list ())
        (new-note-list)
       )
    (dotimes (counter (length note-list))
      (setf index-div-list
        (append index-div-list
          (list 
            (append
             (list counter)
             (list  (+
               (* (* 6 19) (nth start-msr-par (nth counter note-list)))
               (* 6 (nth start-beat-par (nth counter note-list)))
               (nth start-div-par (nth counter note-list))))
            )))))
;
    (setf index-div-list (sort index-div-list #'< :key #'second))
;
    (dolist (elle index-div-list)
       (setf new-note-list
         (append new-note-list
            (list
              (nth (first elle) note-list)))))
;
;  
    (setf note-list new-note-list)))
;
;
;













               
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;    MIXER
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************

(defun mix-em ()
  (let (
       (cmix-score-filename ())
       (cmix-sound-filename ())
       (start '0.0)
       (last-element-index '0)
       (filename ())
       (dur '0.0)
       (type-for-interface '0)
       (spatq-for-interface '0)
       (droneq-for-interface '0)
       (pinst-for-interface '0)
       (prcs-lyne-number '0)
       (pdcl-lyne-number '0)
       (prcs-lyne-coll-file ())
       (pdcl-lyne-coll-file ())
       (prcs (make-array '(6) :initial-element '0))
       (pdcl (make-array '(6) :initial-element '0))
       )

;  clear all old versions of colls and score-file
 
  (setf cmix-score-filename (concatenate 'string "sec." 
             (princ-to-string section-number) 
             ".buff.sco"))
  (setf cmix-sound-filename (concatenate 'string "sec." 
             (princ-to-string section-number) 
             ".buff.aiff")) 

  (shell (concatenate 'string "rm " cmix-score-filename))
  (shell (concatenate 'string "rm " cmix-sound-filename))
  (dotimes (lyne-number '6)
     (shell (concatenate 'string "rm sec" 
             (princ-to-string section-number) 
             "reglyne" 
             (princ-to-string lyne-number)))
     (shell (concatenate 'string "rm sec" 
             (princ-to-string section-number) 
             "dynlyne" 
             (princ-to-string lyne-number))))
;  set up the CMIX buffer-creation score
;      clears it automatically
  (with-open-file (cmix-score cmix-score-filename :direction :output)
     (format cmix-score "rtsetparams(44100, 2)~%
                         rtoutput(\"~a\")~%
                         makegen(1, 24, 200, 0,1,1,1)~%"
                     cmix-sound-filename))
;
;******************************
;  main loop for the notes
;******************************
;
  (dolist (elle note-list)


;
;
;a test to make sure the notes are in temporal order
;
     (setf last-element-index (- (length elle) 1))
;  write to the CMIX buffer-creation score
     (setf filename (nth (- last-element-index 2) elle))
     (setf dur (nth (- last-element-index 1) elle))
     (with-open-file (cmix-score cmix-score-filename 
                 :direction :output :if-exists :append)
        (format cmix-score "rtinput(\"~a\")~%
                   MIX(~a, 0.0, ~a, 1.0, 0, 1)~%~%"
                 filename  
                 start 
                 dur))
;
;***************************************************************************************
;  write to the pitch-register/concrete-stereopos coll
;***************************************************************************************
;
     (setf prcs-lyne-number
         (case (first elle)
              ((wave piano filt) (setf type-for-interface '0)
                                 (setf spatq-for-interface (nth pitch-spatq-par elle))
                                 (setf droneq-for-interface (nth pitch-droneq-par elle))
                                 (setf pinst-for-interface (case (first elle)
                                                 (wave '0) (piano '1) (filt '2)))
                                 (nth pitch-register-lyne-par elle))
              (conc (setf type-for-interface '1) 
                    (setf spatq-for-interface (nth conc-spatq-par elle))
                    (setf droneq-for-interface '0)
                    (setf pinst-for-interface '0)
; map extreme channels of concrete to extremes of register
                    (nth (nth conc-stereo-par elle) '(0 5 2 3 4 1)))
              (arb  (case
                      (nth arb-inst-type-par elle)
                        ((wave piano filt) (setf type-for-interface '0)
                               (setf spatq-for-interface (nth arb-pitch-spatq-par elle))
                               (setf droneq-for-interface (nth arb-pitch-droneq-par elle))
                               (setf pinst-for-interface (case (first elle)
                                                 (wave '0) (piano '1) (filt '2)))
                               (nth arb-pitch-register-lyne-par elle))
                        (conc  (setf type-for-interface '1) 
                               (setf spatq-for-interface (nth arb-conc-spatq-par elle))
                               (setf droneq-for-interface '0)
                               (setf pinst-for-interface '0)
;  map extreme channels of concrete to extremes of register
                               (nth (nth arb-conc-stereo-par elle) '(0 5 2 3 4 1)))))))
;
;
    (setf prcs-lyne-coll-file (concatenate 'string "sec" 
                                    (princ-to-string section-number)
                                                    "reglyne"
                                    (princ-to-string prcs-lyne-number)))
;           write to it
     (with-open-file (prcs-lyne-coll-stream prcs-lyne-coll-file 
                        :direction :output :if-exists :append
                        :if-does-not-exist :create)
        (format prcs-lyne-coll-stream 
               "~a, ~a ~a ~a ~a ~a ~a ~a ~a ~a ~a;~%"
               (aref prcs prcs-lyne-number)
               (nth start-msr-par elle) 
               (nth start-beat-par elle) 
               (nth start-div-par elle)
               (* start 1000.0)
               (+ (* start 1000.0) (* dur 1000.0))
               (* dur 1000.0)
               spatq-for-interface
               type-for-interface
               droneq-for-interface
               pinst-for-interface))
;
;***************************************************************************************
;   write to pitch-dynamic concrete-loudness/hardness coll
;***************************************************************************************
;
     (setf pdcl-lyne-number
         (case (first elle)
               ((wave piano filt) (nth pitch-dyn-par elle))
               (conc              (nth conc-loud-hard-amp-par elle))
               (arb  (case
                      (nth arb-inst-type-par elle)
                         ((wave piano filt) (nth arb-pitch-dyn-par elle))
                         (conc  (nth arb-conc-loud-hard-par elle))))))
     (setf pdcl-lyne-coll-file (concatenate 'string "sec" 
                                    (princ-to-string section-number) 
                                                    "dynlyne"
                                    (princ-to-string pdcl-lyne-number)))
;           write to it
     (with-open-file (pdcl-lyne-coll-stream pdcl-lyne-coll-file 
                        :direction :output :if-exists :append
                        :if-does-not-exist :create) 
        (format pdcl-lyne-coll-stream
               "~a, ~a ~a ~a ~a ~a ~a ~a ~a ~a ~a;~%"
               (aref pdcl pdcl-lyne-number)  
               (nth start-msr-par elle) 
               (nth start-beat-par elle) 
               (nth start-div-par elle)
               (* start 1000.0)
               (+ (* start 1000.0) (* dur 1000.0))
               (* dur 1000.0)
               spatq-for-interface
               type-for-interface
               droneq-for-interface
               pinst-for-interface))
;
;*************************************************************************************************
;
;*************************************************************************************************
;
; update start time for next note
     (setf start (+ start (nth (- last-element-index 1) elle) '.01))
     (setf (aref prcs prcs-lyne-number) (+ (aref prcs prcs-lyne-number) 1))
     (setf (aref pdcl pdcl-lyne-number) (+ (aref pdcl pdcl-lyne-number) 1))
  )
;
; synthesize the buffer
;  
  (shell (concatenate 'string "CMIX < " cmix-score-filename))
;
; write empty colls to any non-existant ones
;
;

))




(defun resolve-bang-trees ()
     (format t "write the bang-tree procedure some day, eh?~%~%"))

(defun print-used-and-unused-concrete-sounds () 
     (format t "write the print unused conrete sounds function some day, ok?~%~%"))

(defun undo-bang-trees ()
     (format t "write the undo bang-trees function some day, ok?~%~%"))



;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;         MAIN PROCEDURE
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************
;*****************************************************************


(format t "~%~%~% should we start at the VERY VERY beginning, with an 
           ~% initial score file, or ~%
              are you coming back, after having 
              modified a few notes, or you're just ready to mix?  ~%
              Type 1 or 2: ")
(case (read)
      ('1 
          (load "note-list")
          (put-notes-in-order)
          (process-notes)
;  print updated working version of note-list to a working-version file
          (with-open-file (score-file "working.note.list" :direction :output)
                          (format score-file "(setf note-list ~%'")
		          (prin1 note-list score-file)
                          (format score-file "~% ) ~%"))
          (format t "~% To mix, run this again, and type 2. ~%")
          (bye)
      )
      ('2
          (load "working.note.list")
          (process-notes)   
          (with-open-file (score-file "working.note.list" :direction :output)
                          (format score-file "(setf note-list ~%'")
		          (prin1 note-list score-file)
                          (format score-file " ) ~%"))
          (format t "I have re-written the notes you requested, if any. ~%  Do you want to go on and mix?  1/0 ~%")
          (if (= (read) 1)
              (progn
                 (format t "What section-number of the piece am I about to mix down?")
                 (setf section-number (read))
                 (if (null (numberp section-number))
                     (progn (format t "Enter a fraokine number, you bosturd!!") (bye))) 
                 (resolve-bang-trees)
                 (mix-em)
                 (print-used-and-unused-concrete-sounds)
                 (undo-bang-trees)
                 (format t "All done.  Yay! ~%~%~% Bye. ")
                 (bye))
              (progn (format t "OK.  See ya later.") (bye)))
      )
      (otherwise (format t "~%~% Don't try to get wise with me!! ~%
                             Answer my question correctly next time! ~%") (bye)))




;
;   mixing methods:
;
;  pitch-register and  concrete-stereo  OR
;
;  pitch-dynamics and  concrete-loudness/hardness
;
;   BASIC METRO SPEED === 18 milliseconds/div
;
;
;  all time is  measured in measures of 19/16, the BEAT of the measure, and the DIVision of the beat
;
;
;******************************************************************************************
;******************************************************************************************
;******************************************************************************************
;******************************************************************************************
;******************************************************************************************
;******************************************************************************************
;******************************************************************************************
;******************************************************************************************
;******************************************************************************************
;
;  User writes an Initial Score File  
;
;     run it:                <-------------------------------ENTER HERE
;
;
;************************************
;
;FOR ALL NOTES IN SCORE:
;  {
;     skip any bang-attach-block commands
;     skip any arbitrary soundfiles     
;     skip any 0-flagged notes  :  0-flag means we've written the note,
;                     and don't want to write it again.
;     write a given note  ---write its soundfile 
;     AND add parameters to it's list:
;        note its filename  ---test if already exists
;        note its duration
;        note its concrete soundnumber, if applic.
;        possibly other stuff depending on instrument  
;        0-flag it--it won't be written again, unless we 
;             explicitly change the flag to 1, to get a new
;             version.
;  }
;
;
;    write Working-Version of Score-file to disk--
;
;
;******************************************************
;    the program continues below, but we can also 
;    start using it at this point, essentially asking
;    to find/make new versions of given 1-flagged notes
; 
;        In the Working Score File, we flag the notes
;        we want re-written or changed.
;        we can also insert a note into the Working Score File
;
;******************************************************
;
;
;   MIXING -------- we can enter here.  <--------------------------- POSS. ENTER HERE
;
;
;   This time we work with the Working Version of the Score-file
;  {
;     skip any bang-attach-block commands
;     skip any arbitrary soundfiles     
;     skip any 0-flagged notes  :  0-flag means we've written the note,
;                     and don't want to write it again.
;                1-flag, or lack of flag, means write the note.
;     write a given note  ---write its soundfile 
;     AND add parameters to it's list:
;        note its filename  ---test if already exists
;        note its duration
;        note its concrete soundnumber, if applic.
;        possibly other stuff depending on instrument  
;        0-flag it--it won't be written again, unless we 
;             explicitly change the flag to 1, to get a new
;             version.
;  }
;
;
;     stop, ask if you want to go on? ------------------------> EXIT HERE TO TEST REWRITTEN SOUND FILES
;
;
;
;
;*********************************************************
;
;
; BANG ATTACH-PROCESSOR
;     This reads a bang-tree.
;        It then takes the following listed sounds, 
;        that are involved in the tree,  and
;         adds necessary "padding" to the beginning
;         of those soundfiles, so the bangs will line up;
;         (OR OR OR OR:  change start times to approximate
;            bang line-up). 
;         changing their durations (start-times should
;              already be ALL THE SAME for all sounds in a 
;              given tree)
;         note: pitches have only one bang each---you can't attach stuff to them,
;             (except on the 0'th bang?)
;      Keep track of what we do, so we can un-do it later (see bottom).
;   maybe remove bangs-list from note-list before is goes into the mixer.
;
;
; FINAL-MIXER
;
;    uses "working.note.list"
;
; Mix all notes into one buffer-soundfile
;   create colls---12 colls, 
;           building several files:  12 colls, a CMIX-score to make the buffer,   
;          
;           counters:  which note in each coll, a "pointer" into the buffer 
; 
;
;
;
;
; LOOP:
;  MIX IN A NOTE:
;    {
;     make coll entries, add to appropriate colls (2, for each type of mix)
;      add to CMIX STEREO score that will create buffer
;         keep track of which concrete sounds used
;     }
;
;
;
; RUN CMIX score to produce buffer.
;
; print list of used concrete sounds to a file
;    (we can combine this with other files later
;      to figure out sounds are left).
;
; IMPORTANT:  now UN-PAD the bang-attached sounds, so that if we mix down
;      again, they will not be "double-padded".
;
;
;**************************************************************************************
;**********************************************************************************
;*****************************************************************************
;*********************************************************************************
;*************************************************************************************
;**************************************************************************************
;**********************************************************************************
;*****************************************************************************
;*********************************************************************************
;*************************************************************************************
;
;
;
;
;
;Articulation/agitation.  might be a list:
;------------------------------------------
; (staccatto: short duration)
; accent/ten
; Fp
; TRemolo  --- internal rate changes determined by random row form
;"Bartok Pizz"
; random adsr
; vibrato  (on wave & filt)  --- internal rate changes determined by random row form
; random Gliss  (on wave & filt)  (you could include end pitch)
; changing trem. , from more to less
; cresc.    (list includes start and end dynamic)
; decresc.  (list includes start and end dynamic)
; cresc./decresc (list of low dynamic, hi dynamic, temporal proportion like 0 1 9 or 0 5 11
; soft-attack (uses a cresc./decresc preset)
;-------------------------------------------
;***************************************
;  FOR WWAVE INSTRUMENT:
;
;
;    0            1   2   3          4   5   6      7     8    9                 10       11      12         13
;   Inst  start: msr beat div  dur: msr beat div  Octve  PC   registral-lyne#   Dyn-lvl  Spatlztn stereo    Artic 
;   name           0   0    0         1   0    0    5     17   0-5               0-5      0-1      0-5     word     
;  
;
;          14               15                       16             17            18           
;                     filter        wave
;       is-it-drone? (noisiness or wave-form)  (soundfile-name) (final duration)  (rewrite-flag)
;        0-1             word (oboe, clar)                        in seconds      0-1           
;
;******************************************************
;
;  FOR PIANO INSTRUMENT:
;    0            1   2   3          4   5   6      7     8    9                 10       11      12         13
;   Inst  start: msr beat div  dur: msr beat div  Octve  PC   registral-lyne#   Dyn-lvl  Spatlztn stereo    Artic 
;   name           0   0    0         1   0    0    5     17   0-5               0-5      0-1      0-5     word     
;  
;
;
;          14               15                          16                17             18         
;       is-it-drone?    cut to start              (soundfile-name) (final duration)  (rewrite-flag)
;        0-1         or full attack  ?                                   in seconds      0-1           
;
;*********************************************************
;   CONCRETE INSTRUMENT
;
; instr  msr beat div par-list  amp-fac spat? stereo   cut/full makegen-curve  loud/hard/amp ||| conc-sound# filename dur re-write?
;   0    1    2    3     4        5      6        7      8             9               10          11         12      13   14 
;
;*****************************************************************************************************
;
;   FOR ARBITRARY SOUNDFILES:
;  
;  start:  msr beat div       type:      
;                             conc      
;                            wave or piano or filt
;
;                                  if pitch, we need to know register, pitch, dynamic, spat, part-o-drone?
;                                  if concrete, we need to know stereo-pos, loud/hardness
;
;
;     other data needed?   soundfile-name   duration 
;                                           in seconds
;
;   (arb 0 0 0 wave  0-5 14 0-5 0-1 0-1 "2.3.4.5.aiff" 1.234)
;   (arb 0 0 0 piano 0-5 14 0-5 0-1 0-1 "2.3.4.5.aiff" 1.234)
;   (arb 0 1 2 conc  0-5 0-5            "2.3.4.7.aiff" 2.345)
;
;
;
;****************************************************************************8
;
;
;
;  FOR BANG-ATTACH COMMAND-BLOCKS
;
;
; (bang 5
;     (bang-tree here))
;
;  (note    . . . .)  first should be defined regularly
;  (note . . . . . .) the next ones should have the keyword "bang" in place of all start parameters
;                 OR, maybe, all notes have the same start time----so only the "padding" changes when
;                      they happen.
;
;
;  (shell "ls")
;
;  abort
;  backtrace   (?)
;