;;; -*- Mode: LISP; Syntax: Common-lisp -*- ;;; ;;; Cut and Paste instrument ;;; ;;; ;;; Parameters ;;; (defparameter cut-soundfile nil) (defparameter cut-sound-start 0.0) (defparameter cut-sound-end 1.0) (defparameter cut-sound-start-time nil) (defparameter cut-sound-end-time nil) (defparameter cut-segment nil) (defparameter cut-segment-slice nil) (defparameter cut-duration nil) (defparameter cut-sample-rate '(0 1 1 1)) (defparameter cut-sample-rate-mult 1.0) (defparameter cut-amp-func '(0 0 5 1 95 1 100 0)) (defparameter cut-vib-osc-freq 6.0) (defparameter cut-vib-osc-freq-dev 3.0) (defparameter cut-vib-osc-amp 0.1) (defparameter cut-vib-noi-freq 15) (defparameter cut-vib-noi-amp 0.1) (defparameter cut-vib-osc-amp-func '(0 0 50 0.2 100 1)) (defparameter cut-vib-noi-amp-func '(0 0.2 50 1 100 0)) (defparameter cut-vib-osc-freq-func '(0 1 50 2.0 100 0.8)) (defparameter cut-reverb-amount 0.015) ;;; ;;; Instrument definition (duration) ;;; (defun one-cut-duration (&key (soundfile cut-soundfile) (sound-start cut-sound-start) (sound-end cut-sound-end) (sound-start-time cut-sound-start-time) (sound-end-time cut-sound-end-time) (segment cut-segment) (segment-slice cut-segment-slice) (duration cut-duration) (sample-rate cut-sample-rate) (sample-rate-mult cut-sample-rate-mult) &allow-other-keys) (let* ((in-file (open-input soundfile)) (in-file-sr (snd-srate in-file)) (srate-ratio (/ in-file-sr sampling-rate)) (in-file-dur (if segment (* (- (second segment)(first segment)) (if segment-slice (- (second segment-slice)(first segment-slice)) 1.0)) (if (and sound-start-time sound-end-time) (- sound-end-time sound-start-time) (* (- sound-end sound-start)(snd-duration in-file))))) ;; average sample rate for the whole note (average-rate (* srate-ratio sample-rate-mult (let ((xo (car sample-rate)) (yo (cadr sample-rate))) (loop for x in sample-rate by #'cddr for y in (cdr sample-rate) by #'cddr sum (+ (- (* x y)(* xo y))(- (* x yo)(* xo yo))) into s do (setf xo x yo y) finally (return (/ s 2 x))))))) (close-input in-file) (let ((estimated (/ in-file-dur average-rate))) (if (and duration (< duration estimated)) duration estimated)))) ;;; ;;; Instrument definition ;;; (definstrument one-cut (start-time amp &key (soundfile cut-soundfile) (sound-start cut-sound-start) (sound-end cut-sound-end) (sound-start-time cut-sound-start-time) (sound-end-time cut-sound-end-time) (segment cut-segment) (segment-slice cut-segment-slice) (duration cut-duration) (sample-rate cut-sample-rate) (sample-rate-mult cut-sample-rate-mult) (amp-func cut-amp-func) (vib-osc-freq cut-vib-osc-freq) (vib-osc-freq-dev cut-vib-osc-freq-dev) (vib-osc-amp cut-vib-osc-amp) (vib-noi-freq cut-vib-noi-freq) (vib-noi-amp cut-vib-noi-amp) (vib-osc-amp-func cut-vib-osc-amp-func) (vib-noi-amp-func cut-vib-noi-amp-func) (vib-osc-freq-func cut-vib-osc-freq-func) (degree 45) (distance 1) (reverb-amount cut-reverb-amount)) (let* ((in-file (open-input soundfile)) (in-file-sr (snd-srate in-file)) (srate-ratio (/ in-file-sr sampling-rate)) (in-file-dur (if segment (* (- (second segment)(first segment)) (if segment-slice (- (second segment-slice)(first segment-slice)) 1.0)) (if (and sound-start-time sound-end-time) (- sound-end-time sound-start-time) (* (- sound-end sound-start)(snd-duration in-file))))) (in-file-start (if segment (+ (first segment) (if segment-slice (* (first segment-slice) (- (second segment)(first segment))) 0.0)) (if sound-start-time sound-start-time (* sound-start (snd-duration in-file))))) ;; average sample rate assuming cancellation of vibrato component (average-rate (* srate-ratio sample-rate-mult (let ((xo (car sample-rate)) (yo (cadr sample-rate))) (loop for x in sample-rate by #'cddr for y in (cdr sample-rate) by #'cddr sum (+ (- (* x y)(* xo y))(- (* x yo)(* xo yo))) into s do (setf xo x yo y) finally (return (/ s 2 x)))))) (out-file-dur (let ((estimated (/ in-file-dur average-rate))) (if (and duration (< duration estimated)) duration estimated))) (src-gen (make-src :file in-file :start-time in-file-start :srate 0)) (amp-env (make-env :envelope amp-func :start-time start-time :scaler amp :duration out-file-dur)) (srate-env (make-env :envelope sample-rate :scaler (* srate-ratio sample-rate-mult) :start-time start-time :duration out-file-dur)) (vib-osc (make-oscil :frequency vib-osc-freq)) (vib-noi (make-randi :frequency vib-noi-freq)) (vib-osc-amp-env (make-env :envelope vib-osc-amp-func :scaler (* average-rate vib-osc-amp) :start-time start-time :duration out-file-dur)) (vib-noi-amp-env (make-env :envelope vib-noi-amp-func :scaler (* average-rate vib-noi-amp) :start-time start-time :duration out-file-dur)) (vib-osc-freq-env (make-env :envelope vib-osc-freq-func :scaler (in-Hz vib-osc-freq-dev) :start-time start-time :duration out-file-dur)) (loc (make-locsig :degree degree :distance distance :revscale reverb-amount)) (beg (floor (* start-time sampling-rate))) (end (+ beg (floor (* sampling-rate out-file-dur))))) (format t "<~,3F-~,3F>~10Tone-cut rate: ~,3F dur: ~,3F~%" start-time (+ start-time out-file-dur) average-rate out-file-dur) (Run (loop for i from beg to end do (let ((sample (* (env amp-env) (src src-gen (+ (env srate-env) (* (env vib-osc-amp-env) (oscil vib-osc (env vib-osc-freq-env))) (* (env vib-noi-amp-env) (randi vib-noi))))))) (locsig loc i sample)))) (close-input in-file) (End-Run))) ;;; ;;; ;;; (defun cuts (start-time amp &key (rate 1.0) (soundfile cut-soundfile) (sound-start 0.1) (sound-end 0.8) (sound-slac (/ (- sound-end sound-start) 2)) (cuts 6)) (let* ((file (open-input soundfile))) (loop repeat cuts for s-start from sound-start by (/ sound-slac 3 cuts) for s-end from sound-end by (- (/ sound-slac 3 cuts)) do (one-cut start-time amp :sound-start s-start :sound-end s-end :sample-rate rate)) (close-input file))) ;;; ;;; ;;; (defparameter cut-partials '(1 1.33 2 4 5.55)) (defparameter cut-coincidence 0.95) (defun collect-items (label start end elements) (if (and start end) (loop for i from start to end by (/ (- end start)(- elements 1)) collect (list label i)) '())) (defun partial-cuts (start-time amp &rest rest &key (multiplier 1.0) (partials cut-partials) (coincidence cut-coincidence) (start-vib-freq nil) (start-vib-amp nil) (end-vib-freq nil) (end-vib-amp nil) (soundfile cut-soundfile) &allow-other-keys) (declare (ignore soundfile)) (let* ((max-dur 0) (curr-dur 0)) (mapcar #'(lambda (p)(remf rest p)) '(:partials :coincidence :multiplier :start-vib-freq :end-vib-freq :start-vib-amp :end-vib-amp)) (setf partials (mapcar #'(lambda (m)(* multiplier m)) partials)) (let* ((vib-freqs (collect-items :vib-osc-freq start-vib-freq end-vib-freq (length partials))) (vib-amps (collect-items :vib-osc-amp start-vib-amp end-vib-amp (length partials)))) (setf max-dur (* coincidence (apply #'one-cut-duration `(:sample-rate-mult ,(car partials) ,@rest)))) (apply #'one-cut `(,start-time ,amp :sample-rate-mult ,(pop partials) ,@(pop vib-amps) ,@(pop vib-freqs) ,@rest)) (loop for partial in partials do (setf curr-dur (* coincidence (apply #'one-cut-duration `(:sample-rate-mult ,partial ,@rest)))) (apply #'one-cut `(,(+ start-time (- max-dur curr-dur)) ,amp :sample-rate-mult ,partial ,@(pop vib-amps) ,@(pop vib-freqs) ,@rest))))))