diff options
Diffstat (limited to 'lib/pianosyn.lsp')
-rw-r--r-- | lib/pianosyn.lsp | 579 |
1 files changed, 579 insertions, 0 deletions
diff --git a/lib/pianosyn.lsp b/lib/pianosyn.lsp new file mode 100644 index 0000000..9bcdfa6 --- /dev/null +++ b/lib/pianosyn.lsp @@ -0,0 +1,579 @@ +;; ================================================ +;; Show Program Information +;; ================================================ +(princ "\n\nPiano Synthesizer V1.2 (Feb 2004)\n") +(princ " Original algorithm and program by Zheng (Geoffrey) Hua\n") +(princ " and Jim Beauchamp, University of Illinois. Any publication\n") +(princ " or notes on any composition that utilizes this software\n") +(princ " should credit the original creators. Any software based on\n") +(princ " this algorithm should carry a similar notice and restriction.\n") +(princ " Ported to Nyquist from source code in M4C program by\n") +(princ " Ning Hu and Roger Dannenberg, Carnegie Mellon University\n") +(princ " School of Computer Science\n\n") +(princ " Program Initializing...\n") + +(setf *pianosyn-path* (current-path)) + +;; ================================================ +;; Function definition +;; ================================================ +(defun readdat (filename dim data) + (setf filename (strcat *pianosyn-path* "piano" + (string *file-separator*) filename)) + (setq fp (open-binary filename :direction :input)) + (dotimes (count 4) + (setf (aref dim count) (read-int fp))) + (dotimes (count (aref dim 3)) + (setf (aref data count) (read-float fp))) + (close fp)) + +(defun build-harmonic-phase (n phase size) + (sound-srate-abs size (osc (hz-to-step n) 1 *sine-table* phase))) + + +;; ****************************************** +;; * Build envelope * +;; ****************************************** + +; after the initial envelope, which is stored in a table, +; envelopes are extended by splicing together final segments +; of the real envelope. The final segment is approximately +; exponential, and so each copy of the segments that is +; spliced is scaled by the amount of decay during the segment. +; The long term shape will therefore be exactly exponential, but +; we thought that a bit of variation rather than a perfectly +; smooth exponential decay might be better. +; +; This function takes a segment, the amount of decay in the +; segment (the scale factor for the next segment) and a count +; and builds an envelope +; +(defun decay-env (segment decay count) + (cond ((<= count 1) (cue segment)) + (t (seq (cue segment) + (scale decay (decay-env segment decay (1- count))))))) + +; PIANO-ENVELOPE builds the amplitude envelope for a group of partials. +; igroup is the index of the group +; sc-duration is the score duration +; attack is the sampled portion of the envelope with a duration of +; gmagendtime +; seg-array is the repeating portion of the envelope tacked onto +; attack to make the envelope longer. The duration of a segment +; in seg-array is gmagendtimemini +; the amount by which seg-array[igroup] decays is scalemag1[igroup] +; +; Algorithm: +; figure out how many repetitions of the seq-array[igroup] to +; add onto the attack to make the envelope long enough. Multiply +; by an exponential decay starting at the duration -- effectively +; the damper hits the string at sc-duration. +; +(defun piano-envelope (igroup sc-duration gmagendtime gmagendtimemini + attack seg-array scalegmag1) + (let ((decaycount (1+ (truncate (/ (- (+ sc-duration endingtime) gmagendtime) + gmagendtimemini)))) + pianoenv ) + + (setf pianoenv + (sim (at 0 (cue attack)) + (at gmagendtime (decay-env (aref seg-array igroup) + (aref scalegmag1 igroup) + decaycount)))) + ;; For ending time + (mult (scale (aref scale1 igroup) pianoenv) + (pwlv 1 sc-duration + ; decay to 1/1000: about 60dB + 1 (+ sc-duration endingtime) 0.001)))) + + +;; ****************************************** +;; * Build wavetable * +;; ****************************************** +(defun piano-group (jgroup sc-duration freq table) + (sound-srate-abs *piano-srate* + (osc (hz-to-step freq) sc-duration + (aref table jgroup)))) + +;; ****************************************** +;; * Produce single piano note * +;; ****************************************** +(defun piano-note (duration pitch dynamic) + (let ((ioi (get-duration duration)) + (full-pitch (+ (get-transpose) pitch)) + (full-dynamic (+ (get-loud) dynamic)) + ;; note: the "loud" is nominally in dB, but + ;; piano-note-abs uses something akin to midi velocity + ;; we should probably work out a better conversion + (start-time (local-to-global 0)) + on-dur) + (setf on-dur (* ioi (get-sustain))) + (set-logical-stop + (abs-env (at start-time + (piano-note-abs on-dur full-pitch full-dynamic))) + ioi))) + + +;; PIANO-NOTE-ABS -- private function to do the work; assumes +;; stretch factor of 1, etc. +(defun piano-note-abs (sc-duration sc-pitch sc-dynamic) + (let (attnamp freq key whichone whichone1 ngroup1 ngroup2 dyna smax + dur gmagendtime gmagendtimemini k j envpoint) + ;; ****************************************** + ;; * Initilization for each note * + ;; ****************************************** + (setq attnamp 0.03) + + ; key is midi pitch number + (setq key (truncate (+ sc-pitch 0.000001))) + (cond ((< key 21) ;; 21 is A0, lowest pitch on this piano + (break "piano-note-abs pitch is too low" sc-pitch) + ;; continued -- transpose up to lowest octave + (while (< key 21) + (setf sc-pitch (+ sc-pitch 12)) + (setf key (truncate (+ sc-pitch 0.000001))))) + ((> key 108) ;; 108 is c9, highest pitch on this piano + (break "piano-note-abs pitch is too high" sc-pitch) + ;; continued -- transpose down to highest octave + (while (> key 108) + (setf sc-pitch (- sc-pitch 12)) + (setf key (truncate (+ sc-pitch 0.000001)))))) + (setq freq (step-to-hz sc-pitch)) + + (setq whichone -2) + (dotimes (i GROUPCON) + (if (and (= whichone -2) + (< freq (- (aref fa i) 0.001))) + (setq whichone (- i 1)))) + ;; Have to use (- (aref fa i) 0.001) because of the calculation precision of Nyquist + + (setq whichone1 (1+ whichone)) + (setq ngroup2 (aref ngroup whichone1)) + + (setq dyna (truncate sc-dynamic)) + (setq smax 0.25) + + ; (setq attnpretime (/ (+ (* 0.018 dyna dyna) (* -3.9588 dyna) 244.8139) 1000.0)) + (setq dur (aref durtab (+ (* key 128) dyna))) + (setq ngroup1 (aref ngroup whichone)) + (setq gmagendtime (* (nth whichone hkframe) (aref dt whichone))) + (setq gmagendtimemini (* (aref nptsmini whichone) (aref dtmini whichone))) + + (setq k (* (aref gmaxtabdim 1) (aref gmaxtabdim 2))) + (setq j (+ (* whichone k) (* dyna (aref gmaxtabdim 2)))) + (dotimes (i (aref gmaxtabdim 2)) + (setf (aref gmax1 i) (aref gmaxtab j)) + (incf j)) + + (dotimes (i ngroup1) + (setq envpoint (sref (aref (aref gmagmini whichone) i) 0)) + (if (/= envpoint 0) + (setf (aref scalegmag1 i) + (/ (sref (aref (aref gmagmini whichone) i) + (- gmagendtimemini (aref dtmini whichone))) + envpoint)) + (setf (aref scalegmag1 i) 0.0)) + (setf (aref scale1 i) (* smax (aref gmax1 i)))) + (if (> ngroup2 ngroup1) (setf ngroup2 ngroup1)) + + (if (< dur sc-duration) (setq sc-duration dur)) + ;; ********************** + ;; * now sum the groups * + ;; ********************** + (scale 0.5 + (sim (at 0 (set-logical-stop (cue (scale attnamp attsound)) sc-duration)) + (at 0 (cue (simrep (i ngroup2) + (mult (piano-envelope i sc-duration gmagendtime + gmagendtimemini (aref (aref gmag whichone) i) + (aref gmagmini whichone) scalegmag1) + (piano-group i (+ sc-duration endingtime) freq + (aref wavetab whichone1)))))))) )) +;;;;; This is for debugging -- replace synthesis with a sine tone to study envelope +; (at 0 (cue (mult (piano-envelope 0 sc-duration gmagendtime +; gmagendtimemini (aref (aref gmag whichone) 0) +; (aref gmagmini whichone) scalegmag1) +; (osc c4 2.0)))))))) + + +(defun piano-note-2 (sc-pitch sc-dynamic) + (let ((dur (get-duration 1))) + (stretch-abs 1 (piano-note dur sc-pitch sc-dynamic)))) + + +(defun piano-midi (midiin) + (let (midi-seq midifile) + (setf midi-seq (seq-create)) + (setf midifile (open-binary midiin)) + (seq-read-smf midi-seq midifile) + (close midifile) + (seq-midi midi-seq + (note (channel pitch velocity) + (piano-note-2 pitch velocity))))) + + +;; ****************************************** +;; *Produce wave file according to MIDI file* +;; ****************************************** +(defun piano-midi2file (midiin out-name) + (princ "\nBegin sound production\n") + (princ "=============================================\n") + (s-save (piano-midi midiin) + ny:all (string out-name) :play T) + (princ "=============================================\n") + (princ "End sound production\n")) + + +;; ==================================== +;; Main Program +;; ==================================== +(if (not (boundp '*piano-srate*)) ;; if pianosyn.lsp wasn't loaded already + (expand 70)) ;; we'll allocate a lot of nodes for data, so expand now +(setf *pianosyn-save-gc-flag* *gc-flag*) +(setf *gc-flag* nil) ;; we'll do a lot of gc, so turn off messages +;; Definite some constant +(setq NPITCH 22 GROUPCON 23) +(setq MAXAMP 32767.0) +(setq TWOPI (+ pi pi)) +(setq *piano-srate* *default-sound-srate*) +(setq bits 32) +;; 512 gives pretty good SNR for interpolated sines +;; some tables will be larger: 512 is just the minimum +(setq tabsize 512) + +;; For ending time, use 30 msec. (This was originally 0.1 msec, +;; about 4 samples, but that's too short to avoid clicks.) +;; This not only must avoid clicks but it simulates the damper. +;; This is the time to decay to 0.001 of the original, so it's +;; actually quite a rapid decay. +(setq endingtime 0.03) + +(setf hkframe (list 66 73 82 90 99 108 116 123 130 135 138 140 138 + 133 126 117 107 102 105 127 153 187 200)) +(setf attsratelist (list 8000 11025 16000 22050 32000 44100 48000)) +(setf gmax1 (make-array GROUPCON)) +(setf scalegmag1 (make-array GROUPCON)) +(setf scale1 (make-array GROUPCON)) +(setf wavetab (make-array GROUPCON)) +(setf ti (make-array GROUPCON)) +(setf tstep (make-array GROUPCON)) +(setf gmaxtabdim (make-array 4)) +(setf gmaxtab (make-array 64768)) +(setf durtabdim (make-array 4)) +(setf durtab (make-array 16384)) +(setf rlsratetabdim (make-array 4)) +(setf rlsratetab (make-array 11392)) +(setf fa (make-array GROUPCON)) +(setf dt (make-array GROUPCON)) +(setf ngroup (make-array GROUPCON)) +(setf npts (make-array GROUPCON)) +(setf gmag (make-array GROUPCON)) +(setf nhar (make-array GROUPCON)) + +(setf gmagmini (make-array GROUPCON)) +(setf dtmini (make-array GROUPCON)) +(setf nptsmini (make-array GROUPCON)) + +(setf cw (make-array GROUPCON)) +(setf phase (make-array GROUPCON)) +(setf hfrom (make-array GROUPCON)) +(setf hto (make-array GROUPCON)) + +(setf *zero-table* (scale 0 (build-harmonic 1 tabsize))) + +;; ================================================= +;; run-once initilization: pianoActor construction +;; ================================================= +(princ "\nBegin Instrument-wise initialization...\n") +(princ "=======================================\n") +(princ "Reading source files:\n") + + +;; Read gmax.tab +(readdat "gmax.tab" gmaxtabdim gmaxtab) + +;; Read dur.tab +(readdat "dur.tab" durtabdim durtab) + +;; Read rlsrate.tab +(readdat "rlsrate.tab" rlsratetabdim rlsratetab) + +;; Read cwxx.cwd +(dotimes (pncount GROUPCON) + (format t "~A " pncount) + (setq filename (strcat "pn" + (string (int-char (+ (truncate (/ pncount 10)) 48))) + (string (int-char (+ (rem pncount 10) 48))) + ".cod")) + (setq filename (strcat *pianosyn-path* "piano" + (string *file-separator*) filename)) + (setq fp (open-binary filename)) + + ;; Read cwdHdr in cwxx.cwd + (setq cwdHdr-ckID (read-int fp) cwdHdr-type (read-int fp)) + ;; "CNDN" == 1129202766 + + ;; That is for "FORM"==cwdHdr-ckID + ;;(if (and (= cwdHdr-ckID 1179603533) (= cwdHdr-type 1129202766)) + ;; () + ;; (error "Error in reading chunk header.")) + + ;;That is for "SYNC"==cwdHdr-ckID + (if (and (= cwdHdr-ckID 1398361667) (= cwdHdr-type 1129202766)) + () + (error "Error in reading chunk header.")) + + ;; Read COMMCK in cwxx.cwd + (setq COMMCK-ckID (read-int fp)) + (if (= COMMCK-ckID 1129270605) () (error "COMMCK chunk not found.")) + (setq COMMCK-fa (read-float fp) COMMCK-dt (read-float fp)) + (setf (aref fa pncount) COMMCK-fa) + (setf (aref dt pncount) COMMCK-dt) + (setf (aref dtmini pncount) (* 10 COMMCK-dt)) + (setq COMMCK-npts (read-int fp) COMMCK-ngroup (read-int fp)) + (setf (aref npts pncount) COMMCK-npts) + (setf (aref nptsmini pncount) + (truncate (/ (+ 9 (- COMMCK-npts (nth pncount hkframe))) 10))) + (setf (aref ngroup pncount) COMMCK-ngroup) + + ;; Read DATACK in cwxx.cwd + (setq DATACK-ckID (read-int fp)) + (if (= DATACK-ckID 1346458196) () (error "DATACK chunk not found.")) + (setf (aref nhar pncount) (read-int fp)) + (setf (aref cw pncount) (make-array (aref nhar pncount))) + (setf (aref phase pncount) (make-array (aref nhar pncount))) + (dotimes (count (aref nhar pncount)) + (setf (aref (aref cw pncount) count) (read-float fp))) + (dotimes (count (aref nhar pncount)) + (setf (aref (aref phase pncount) count) (read-float fp))) + + ;; Read GRUPCK in cwxx.cwd + (setq GRUPCK-ckID (read-int fp)) + (if (= GRUPCK-ckID 1196578128) () (error "GRUPCK chunk not found.")) + (setf (aref hfrom pncount) (make-array (aref ngroup pncount))) + (setf (aref hto pncount) (make-array (aref ngroup pncount))) + ;(display "reading grupck" (aref ngroup pncount) (aref nhar pncount) pncount) + (dotimes (count (aref ngroup pncount)) + (setf (aref (aref hfrom pncount) count) + (read-float fp))) + (dotimes (count (aref ngroup pncount)) + (setf (aref (aref hto pncount) count) (read-float fp))) + + ;; Read GMAGCK in cwxx.cwd + (setq GMAGCK-ckID (read-int fp)) + (if (= GMAGCK-ckID 1196245319) + () + (error "GMAGCK chunk not found.")) + (setq gmaghead (read-int fp)) + (close fp) + (setf (aref gmag pncount) (make-array (aref ngroup pncount))) + (setq gmagrate (/ 1 (aref dt pncount))) + (setq gmagdur (/ (nth pncount hkframe) gmagrate)) + + ; (display "gmagmini" pncount (aref ngroup pncount)) + (setf (aref gmagmini pncount) (make-array (aref ngroup pncount))) + (setq gmagratemini (/ 1 (aref dtmini pncount))) + (setq gmagdurmini (/ (aref nptsmini pncount) gmagratemini)) + + (dotimes (i (aref ngroup pncount)) + (let (gmaghead1 samps gmaghead1mini) + (setf gmaghead1 (/ (float gmaghead) (* gmagrate (/ bits 8)))) + ;(display "gmag read" i gmaghead1 gmagrate filename) + (setf samps (s-read filename :time-offset gmaghead1 :srate gmagrate + :dur gmagdur :mode snd-mode-float + :format snd-head-raw :bits bits :endian :big)) + (if samps (snd-length samps ny:all)) ; force read into memory + (setf (aref (aref gmag pncount) i) samps) + (setq gmaghead (+ gmaghead (* 4 (nth pncount hkframe)))) + (setq gmaghead1mini (/ (float gmaghead) (* gmagratemini (/ bits 8)))) + ;(display "gmag read mini" i gmaghead1mini gmagratemini filename) + (setf samps (s-read filename :time-offset gmaghead1mini :srate gmagratemini + :dur gmagdurmini :mode snd-mode-float :format snd-head-raw + :bits bits :endian :big)) + (if samps (snd-length samps ny:all)) ; force read into memory + ;(display "read gmagmini" filename pncount i + ; (if samps (snd-length samps ny:all))) + (setf (aref (aref gmagmini pncount) i) samps) + (setq gmaghead (+ gmaghead (* 4 (aref nptsmini pncount)))) + )) +) + +(setq maxfreq (aref fa (1- GROUPCON))) +(dotimes (i GROUPCON) + (setq ngrouptemp -1) + (dotimes (j (aref ngroup i)) + (if (and (= ngrouptemp -1) + (>= (* (aref (aref hto i) j) (aref fa i)) + (/ *piano-srate* 2))) + (setq ngrouptemp j))) + (if (>= ngrouptemp 0) (setf (aref ngroup i) ngrouptemp))) + +(princ "\nGenerating wavetables...\n") +(setq tempi (/ (* 360 tabsize) (* TWOPI TWOPI))) +(dotimes (h GROUPCON) + (setf (aref wavetab h) (make-array (aref ngroup h))) + (dotimes (i (aref ngroup h)) + ;(FORMAT T "WAVE ~A OF GROUP ~A~%" i h) + (let ((low (aref (aref hfrom h) i)) + (high (aref (aref hto h) i)) + tempphase tempcw + (len tabsize)) + ; table size must be more than twice greatest harmonic number + ; use a factor of three so we have a wider margin of oversampling + (setf len (max len (* 3 high))) + (setf sumwave *zero-table*) + (do ((k (truncate low) (incf k))) + ((> k high)) + (cond ((< k (aref nhar h)) + (setq tempphase (aref (aref phase h) k)) + (setq tempcw (aref (aref cw h) k))) + (t + (setq tempphase 0) + (setq tempcw 0))) + (setf sumwave (sum sumwave (scale tempcw (build-harmonic-phase k + (+ (* tempphase tempi) 90.0) + len)))))) + ;(PRINT "FORCE SUMMATION OF WAVE") + (snd-length sumwave ny:all) ; force summation + ;( "END SUMMATION OF WAVE") + (setf (aref (aref wavetab h) i) (list sumwave (hz-to-step 1) T)))) + +;; Read in attack sound +(princ "\nRead in attack sound...\n") +(setq attndur 0.5) +(setq attnth -1) +(dotimes (count (length attsratelist)) + (if (and (= attnth -1) (<= *piano-srate* (nth count attsratelist))) (setq attnth count))) +(if (or (= attnth -1) (/= (nth attnth attsratelist) *piano-srate*)) + (princ "No attack sound rate corresponds to current sound rate, use the nearest one\n")) +(if (> attnth 0) + (if (<= (- (nth attnth attsratelist) *piano-srate*) (- *piano-srate* (nth (1- attnth) attsratelist))) + (setq attsrate (nth attnth attsratelist)) (setq attsrate (nth (1- attnth) attsratelist))) + (case attnth + (-1 (setq attsrate (last attsratelist))) + (0 (setq attsrate (nth 0 attsratelist))))) +(setq filename (format nil "att~A.pcm" (truncate attsrate))) +(setf filename (strcat *pianosyn-path* "piano" + (string *file-separator*) filename)) +(setf attsound + (s-read filename :srate attsrate :dur attndur :format snd-head-raw + :mode snd-mode-pcm :bits 16 :endian :big)) + +(princ "=============================================\n") +(princ "End instrument-wise initialization\n") +(princ "\n\n=============================================\n") +(princ "Piano Synthesizer function definition:\n") +(princ "(piano-note-2 step dynamic)\n") +(princ "(piano-note duration step dynamic)\n") +(princ "(piano-midi midi-file-name)\n") +(princ "(piano-midi2file midi-file-name sound-file-name)\n\n") +(princ "=============================================\n") +(setf *gc-flag* *pianosyn-save-gc-flag*) ;; restore original value + + +#| + +;;================= DEBUGGING CODE ========================= +;; +;; run (show-cn-file n) to dump some data from pn??.cod +;; +;;========================================================== + + +;; INT-HEX -- convert integer to hex string +;; +(defun int-hex (int) + (let ((result "") ch) + (while (/= int 0) + (setf ch (char "0123456789ABCDEF" (logand int 15))) + (setf result (strcat (string ch) result)) + (setf int (/ int 16))) + (if (equal result "") "0" result))) + +(defun int-4char (int) + (strcat (string (int-char (logand 255 (/ int (* 256 256 256))))) + (string (int-char (logand 255 (/ int (* 256 256))))) + (string (int-char (logand 255 (/ int 256)))) + (string (int-char (logand 255 int))))) + +(defun show-cn-file (pncount) + (let (filename fp cwdhdr-ckid cwdhdr-type) + (setq filename (strcat "pn" + (string (int-char (+ (truncate (/ pncount 10)) 48))) + (string (int-char (+ (rem pncount 10) 48))) + ".cod")) + (setf filename (strcat *pianosyn-path* "piano" + (string *file-separator*) filename)) + (format t "SHOW-CN-FILE ~A (~A)~%" pncount filename) + (setf fp (open-binary filename)) + ;; Read cwdHdr in cwxx.cwd + (setq cwdHdr-ckID (read-int fp) cwdHdr-type (read-int fp)) + (format t "header ckID: ~A (~A)~%" (int-hex cwdhdr-ckid) + (int-4char cwdhdr-ckid)) + (format t "header type: ~A (~A)~%" (int-hex cwdhdr-type) + (int-4char cwdhdr-type)) + (setq COMMCK-ckID (read-int fp)) + (format t "header ckID: ~A (~A)~%" (int-hex commck-ckid) + (int-4char commck-ckid)) + (setq COMMCK-fa (read-float fp) COMMCK-dt (read-float fp)) + (format t "commck-fa ~A commck-dt ~A~%" commck-fa commck-dt) + (setq COMMCK-npts (read-int fp) COMMCK-ngroup (read-int fp)) + (format t "commck-npts ~A commck-ngroup ~A~%" commck-npts commck-ngroup) + (setq DATACK-ckID (read-int fp)) + (format t "header ckID: ~A (~A)~%" (int-hex datack-ckid) + (int-4char datack-ckid)) + (setf datack-nhar (read-int fp)) + (format t "datack-nhar ~A~%cw data:" datack-nhar) + (dotimes (i datack-nhar) + (if (and (zerop (rem i 10)) (or (< i 10) (> i (- datack-nhar 10)))) + (format t "~% ~A:" i)) + (setf data-cw (read-float fp)) + (if (or (< i 10) (>= i (* (/ datack-nhar 10) 10))) + (format t " ~A" data-cw))) + (format t "~%phase data:") + (dotimes (i datack-nhar) + (if (and (zerop (rem i 10)) (or (< i 10) (> i (- datack-nhar 10)))) + (format t "~% ~A:" i)) + (setf data-phase (read-float fp)) + (if (or (< i 10) (> i (- datack-nhar 10))) (format t " ~A" data-cw))) + (format t "~%") + (setf grupck-ckid (read-int fp)) + (format t "header ckID: ~A (~A)~%hfrom data:" + (int-hex grupck-ckid) (int-4char grupck-ckid)) + (dotimes (count commck-ngroup) + (setf data-hfrom (read-float fp)) + (if (zerop (rem count 10)) + (format t "~% ~A:" count)) + (format t " ~A" data-hfrom)) + (format t "~%hto data:") + (dotimes (count commck-ngroup) + (setf data-hto (read-float fp)) + (if (zerop (rem count 10)) + (format t "~% ~A:" count)) + (format t " ~A" data-hto)) + (setf gmagck-ckid (read-int fp)) + (format t "~%header ckID: ~A (~A)~%" + (int-hex gmagck-ckid) (int-4char gmagck-ckid)) + (setf gmaghead (read-int fp)) + (format t "gmaghead ~A" gmaghead) + (format t "~%") + ;; compute range of data to be read + (setf offset gmaghead) + (dotimes (i commck-ngroup) + (format t "gmag: group ~A offset ~A length ~A end ~A~%" + i offset (* 4 (nth pncount hkframe)) + (+ offset (* 4 (nth pncount hkframe)))) + (setf offset (+ offset (* 4 (nth pncount hkframe)))) + (format t "gmagmini: group ~A offset ~A length ~A end ~A~%" + i offset (* 4 (aref nptsmini pncount)) + (+ offset (* 4 (aref nptsmini pncount)))) + (setf offset (+ offset (* 4 (aref nptsmini pncount))))) + + (close fp) + + (setf gmag-and-gmagmini + (s-read filename + :time-offset (* (float gmaghead) 0.25 commck-dt) + :srate (/ 1.0 commck-dt) + :mode snd-mode-float :format snd-head-raw + :bits 32 :endian :big)))) +|# |