annotate implementations/tabcode/tabcode-import.lisp @ 330:2fbff655ba47 tip

Removed cpitch-adj and cents SQL columns
author Jeremy Gow <jeremy.gow@gmail.com>
date Mon, 21 Jan 2013 11:08:11 +0000
parents 470e83242576
children
rev   line source
c@43 1 (in-package :amuse-tabcode)
c@43 2
c@43 3 (defun word-duration (word default)
d@179 4 (if (typep word 'rhythmic-word)
c@43 5 (let ((flag (tabcode::flag word))
c@43 6 (dots (tabcode::dots word)))
c@43 7 (if flag
c@43 8 (* (car (rassoc flag tabcode::*rhythms*))
c@43 9 (if dots 3/2 1))
c@43 10 default))
c@43 11 0))
c@43 12
c@43 13 (defun word-causes-stop-p (word course)
c@43 14 (or (typep word 'tabcode::rest)
d@179 15 (typep word 'barline)
d@179 16 (and (typep word 'chord)
d@179 17 (member course (playing word) :key #'course))))
d@179 18 #+nil
c@43 19 (defun duration-for-course (course buffer start initial-duration)
c@43 20 (let ((duration initial-duration)
c@43 21 (default-duration initial-duration))
c@43 22 (do ((i start (+ i 1)))
c@43 23 ((>= i (drei-buffer:size buffer)) duration)
c@43 24 (let* ((object (drei-buffer:buffer-object buffer i))
c@43 25 (word (tabcode-syntax::tabword-word object)))
c@43 26 (when (word-causes-stop-p word course)
c@43 27 (return-from duration-for-course duration))
c@43 28 (let ((word-duration (word-duration word default-duration)))
c@43 29 (incf duration word-duration)
c@43 30 (when (> word-duration 0)
c@43 31 (setf default-duration word-duration)))))))
c@43 32
c@43 33 ;;; FIXME: like GET-COURSE-TUNING/GET-TUNING only more hardcoded
c@43 34 (defun fret-to-number (char)
c@43 35 (let ((fret-num (- (char-code char) 97)))
c@43 36 (cond
c@43 37 ((> fret-num 20) (- fret-num 2))
c@43 38 ((> fret-num 8) (- fret-num 1))
c@43 39 (t fret-num))))
c@43 40 (defun midi-pitch-for-playing (course fret)
c@43 41 (let ((tuning #(67 62 57 53 48 43)))
c@43 42 (+ (aref tuning (1- course))
c@43 43 (fret-to-number fret))))
d@179 44 (defvar *default-tuning* #(67 -5 -5 -4 -5 -5 -2 -3))
d@179 45 (defun midi-pitch-with-tuning (course fret current-tuning)
d@179 46 (unless current-tuning
d@179 47 (setf current-tuning *default-tuning*))
d@179 48 (let ((open-course (aref current-tuning 0)))
d@179 49 (when (= open-course 0)
d@179 50 (case (aref current-tuning 1)
d@179 51 (0 ;; no info
d@179 52 (setf current-tuning *default-tuning*
d@179 53 open-course (aref current-tuning 0)))
d@179 54 (-5 ;; prob renaissance
d@179 55 (setf open-course 67))
d@179 56 (-3 ;; prob baroque
d@179 57 (setf open-course 65))
d@179 58 (t ;; probably weird transitional. Just guess.
d@179 59 (setf open-course 67))))
d@179 60 (do ((i 1 (1+ i)))
d@179 61 ((< course i) (+ (fret-to-number fret) open-course))
d@179 62 (setf open-course (+ open-course (aref current-tuning i))))))
d@179 63
d@179 64 (defparameter *current-tuning* nil)
d@179 65 (defmethod get-composition ((identifier tabcode-file-identifier))
d@179 66 (get-composition-from-tabwords
d@179 67 (parse-tabcode-file (tabcode-pathname identifier))))
c@43 68
d@179 69 (defun get-composition-from-tabwords (tabwords)
d@179 70 (let ((time 0)
d@179 71 (notes)
d@179 72 (result)
d@179 73 (current-duration 1)
d@179 74 (current-tuning (copy-seq *current-tuning*))
d@179 75 (rules)
d@179 76 (metres)
d@179 77 (bars (list (make-instance 'tabcode-bar :start nil
d@179 78 :time 0 :interval 0))))
d@179 79 (do* ((tabwords tabwords (cdr tabwords))
d@179 80 (tabword (car tabwords) (car tabwords)))
d@179 81 ((null tabwords)
d@179 82 (setq notes (nreverse result)))
d@179 83 (let* ((duration (word-duration tabword current-duration)))
d@179 84 (when (typep tabword 'rhythmic-word)
d@179 85 (setf current-duration duration))
d@179 86 (typecase tabword
d@179 87 (barline
d@179 88 (setf (end-tabword (car bars)) tabword
d@179 89 (duration (car bars)) (- time
d@179 90 (timepoint
d@179 91 (onset
d@179 92 (car bars))))
d@179 93 bars (cons (make-instance 'tabcode-bar
d@179 94 :start tabword
d@179 95 :time time)
d@179 96 bars)))
d@179 97 (comment
d@179 98 (when (rulep tabword)
d@179 99 (when rules
d@179 100 (setf (duration (car rules))
d@179 101 (- time
d@179 102 (timepoint (onset (car rules))))))
d@179 103 (push (make-instance 'tabcode-ruleset
d@179 104 :rules (parse-rules tabword)
d@179 105 :time time)
d@179 106 rules)
d@179 107 (setf current-tuning (update-tuning (ruleset-rules (car rules))
d@179 108 current-tuning))))
d@179 109 (metre
d@179 110 (when metres
d@179 111 (setf (duration (car metres))
d@179 112 (- time (timepoint (onset (car metres))))))
d@179 113 (push (make-instance 'tabcode-time-signature
d@179 114 :time time
d@179 115 :word tabword)
d@179 116 metres))
d@179 117 (chord
d@179 118 (dolist (playing (playing tabword))
d@179 119 (let* ((course (course playing))
d@179 120 (fret (fret playing))
d@179 121 (note-duration current-duration))
d@179 122 (push (make-instance 'tabcode-pitched-event
d@179 123 :course course
d@179 124 :fret fret
d@179 125 :word tabword ; object?
d@179 126 :number (midi-pitch-with-tuning (1- course) fret current-tuning)
d@179 127 :time time
d@179 128 :interval note-duration
d@179 129 :bar (car bars))
d@179 130 result)))))
d@179 131 (incf time duration)))
d@179 132 (if (= (timepoint (car bars)) time)
d@179 133 (setf bars (cdr bars))
d@179 134 (setf (duration (car bars))
d@179 135 (- time (timepoint (onset (car bars))))))
d@179 136 (when rules
d@179 137 (setf (duration (car rules))
d@179 138 (- time (timepoint (onset (car rules))))))
d@179 139 (when metres
d@179 140 (setf (duration (car metres))
d@179 141 (- time (timepoint (onset (car metres))))))
d@179 142 (let ((composition (make-instance 'tabcode-composition
d@179 143 :time 0
d@179 144 :interval time
d@179 145 :bars (reverse bars)
d@179 146 :rules rules
d@179 147 :metres metres)))
d@179 148 (sequence:adjust-sequence composition (length notes)
d@179 149 :initial-contents notes))))
d@179 150 #+nil
c@43 151 (defun make-tabcode-composition (tabword-buffer)
c@43 152 (let ((time 0)
c@43 153 (notes)
c@43 154 (result)
c@43 155 (current-duration 1))
c@43 156 (dotimes (i (drei-buffer:size tabword-buffer) (setq notes (nreverse result)))
c@43 157 (let* ((object (drei-buffer:buffer-object tabword-buffer i))
c@43 158 (tabword (tabcode-syntax::tabword-word object))
c@43 159 (duration (word-duration tabword current-duration)))
c@43 160 (when (typep tabword 'tabcode::rhythmic-word)
c@43 161 (setf current-duration duration))
c@43 162 (when (typep tabword 'tabcode::chord)
c@43 163 (dolist (playing (tabcode::playing tabword))
c@43 164 (let* ((course (tabcode::course playing))
c@43 165 (fret (tabcode::fret playing))
c@43 166 (note-duration (duration-for-course course tabword-buffer (1+ i) current-duration)))
c@43 167 (push (make-instance 'tabcode-pitched-event
c@43 168 :course course
c@43 169 :fret fret
c@43 170 :word tabword ; object?
c@43 171 :number (midi-pitch-for-playing course fret)
c@43 172 :time time
c@43 173 :interval note-duration)
c@43 174 result))))
c@43 175 (incf time duration)))
c@43 176 (let ((composition (make-instance 'tabcode-composition
c@43 177 :time 0
c@43 178 :interval time)))
c@43 179 (sequence:adjust-sequence composition (length notes)
c@43 180 :initial-contents notes))))
c@43 181
d@179 182 (defun update-tuning (rules current-tuning)
d@179 183 (unless current-tuning
d@179 184 (setf current-tuning (make-array 15 :element-type 'integer)))
d@179 185 ;; First, get reference pitch
d@179 186 (when (assoc "pitch" rules :test #'string=)
d@179 187 (setf (aref current-tuning 0)
d@179 188 (parse-integer (cdr (assoc "pitch" rules :test #'string=)) :junk-allowed t)))
d@179 189 (cond
d@179 190 ((assoc "tuning" rules :test #'string=)
d@179 191 (setf current-tuning
d@179 192 (apply-tuning (cdr (assoc "tuning" rules :test #'string=))
d@179 193 current-tuning)))
d@182 194 ((or (assoc "tuning-named" rules :test #'string=)
d@182 195 (assoc "tuning_named" rules :test #'string=))
d@179 196 (setf current-tuning
d@182 197 (apply-tuning (cdr (assoc (string-downcase
d@182 198 (cdr (or (assoc "tuning-named"
d@182 199 rules :test #'string=)
d@182 200 (assoc "tuning_named"
d@182 201 rules :test #'string=))))
d@179 202 *tuning-names* :test #'string=))
d@179 203 current-tuning))))
d@179 204 (cond
d@182 205 ((or (assoc "bass-tuning" rules :test #'string=)
d@182 206 (assoc "bass_tuning" rules :test #'string=))
d@179 207 (setf current-tuning
d@182 208 (apply-tuning (cdr (or (assoc "bass-tuning" rules :test #'string=)
d@182 209 (assoc "bass_tuning" rules :test #'string=)))
d@182 210 current-tuning 6)))
d@182 211 ((or (assoc "bass-tuning-named" rules :test #'string=)
d@182 212 (assoc "bass_tuning_named" rules :test #'string=))
d@179 213 (setf current-tuning
d@182 214 (apply-tuning (cdr (assoc (string-downcase
d@182 215 (cdr (or (assoc "bass-tuning-named"
d@182 216 rules :test #'string=)
d@182 217 (assoc "bass_tuning_named"
d@182 218 rules :test #'string=))))
d@179 219 *tuning-names* :test #'string=))
d@179 220 current-tuning
d@179 221 6))))
d@179 222 current-tuning)
d@179 223
d@179 224 (defun apply-tuning (interval-string current-tuning &optional (start-course 1))
d@179 225 (do* ((pointer (1+ (or (position #\( interval-string)
d@179 226 -1))
d@179 227 (+ 1 pointer (length (princ-to-string interval))))
d@179 228 (course start-course (1+ course))
d@179 229 (interval (parse-integer interval-string :start pointer :junk-allowed t)
d@179 230 (parse-integer interval-string :start pointer :junk-allowed t)))
d@179 231 ((not interval) current-tuning)
d@179 232 (when (>= course (length current-tuning))
d@179 233 (setf current-tuning (adjust-array current-tuning (1+ course))))
d@179 234 (setf (aref current-tuning course) interval)))
d@179 235
d@179 236
d@179 237
c@43 238 #|
c@43 239 (in-package :clim-user)
c@43 240
c@43 241 (defvar *composition*)
c@43 242
c@43 243 (define-command (com-set-amuse-composition
c@43 244 :name t :command-table tabcode-syntax::tabcode-table)
c@43 245 ()
c@43 246 (let* ((window (esa:current-window))
c@43 247 (buffer (drei-buffer:buffer window))
c@43 248 (syntax (climacs::syntax buffer))
c@43 249 (tabwords (slot-value syntax 'tabcode-syntax::tabwords)))
c@43 250 (setq *composition* (amuse-tabcode::make-tabcode-composition tabwords))))
csr21@58 251
csr21@58 252 (define-command (com-amuse-play
csr21@58 253 :name t :command-table tabcode-syntax::tabcode-table)
csr21@58 254 ()
csr21@58 255 (let* ((window (esa:current-window))
csr21@58 256 (buffer (drei-buffer:buffer window))
csr21@58 257 (syntax (climacs::syntax buffer))
csr21@58 258 (tabwords (slot-value syntax 'tabcode-syntax::tabwords))
csr21@58 259 (composition (amuse-tabcode::make-tabcode-composition tabwords)))
csr21@58 260 ;; HACK: emulate background playing.
csr21@58 261 (sb-thread:make-thread (lambda () (amuse-utils:play composition)))))
csr21@58 262
csr21@58 263 (define-command (com-infer-key
csr21@58 264 :name t :command-table tabcode-syntax::tabcode-table)
csr21@58 265 ()
csr21@58 266 (let* ((window (esa:current-window))
csr21@58 267 (buffer (drei-buffer:buffer window))
csr21@58 268 (syntax (climacs::syntax buffer))
csr21@58 269 (tabwords (slot-value syntax 'tabcode-syntax::tabwords))
csr21@58 270 (composition (amuse-tabcode::make-tabcode-composition tabwords))
c@94 271 (result (amuse-harmony:krumhansl-key-finder composition composition))
csr21@58 272 (name (aref #("C" "C#" "D" "Eb" "E" "F" "F#" "G" "Ab" "A" "Bb" "B") (car result)))
csr21@58 273 (string (format nil "{<key>~A ~(~A~)</key>}~%" name (cadr result))))
csr21@58 274 (drei-buffer:insert-buffer-sequence buffer 0 string)))
csr21@55 275 |#