1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
;---------------------------------------------------------------------
; LPANAL. Performs LPC analysis
;
; snd sound for analysis
; an-dur duration of analysis (= duration of sound)
; skiptime step frame to frame
; npoles number of poles
;
; RESULT: analysis data in list format.
; Every element of the list is a list of the form
;
; (RMS1 RMS2 ERR FILTER-COEFS)
;
; RMS1 Energy (not rms value) of input signal
; RMS2 Energy (not rms value) of residual signal
; ERR = sqrt(RMS2/RMS1) If it is small then VOICED sound,
; else UNVOICED
; FILTER-COEFS Array of filter coefs.
;
;
; The z transform of filter is H(z) = 1/A(z)
;
; where A(z) is a polynome of the form:
;
;
; A(z) = 1 + a1 z + a2 z^2 + a3 z^3 + ... + aP z^P
;
; FILTER-COEFS is the array
;
; #(-aP -aP-1 -aP-2 ... a3 a2 a1)
;
; (this format is suited for the filter ALLPOLES)
;
(defun lpanal (snd an-dur skiptime npoles)
(let* ((sr (snd-srate snd))
(skipsize (round (* sr skiptime)))
(numframes (round (- (/ (* sr an-dur) skipsize) 0.5)))
(sndcpy (snd-copy snd))
(result (make-array numframes)))
(dotimes (i numframes)
(setf (aref result i)
(snd-lpanal
(snd-fetch-array sndcpy (* 2 skipsize) skipsize)
npoles)))
(format t "LPANAL: duration: ~A frames: ~A framedur: ~A skip: ~A poles ~A\n"
an-dur numframes (* skiptime 2) skiptime npoles)
result))
;; this code is based on fft_demo.lsp -- the idea is that an object
;; will return a stream of LPC frames. Other objects can manipulate
;; these frames, creating a new stream, or turn the frames back into
;; sound.
(setf lpc-class (send class :new '(sound framesize skipsize npoles)))
(send lpc-class :answer :isnew '(snd framedur skiptime np) '(
(let ((sr (snd-srate snd)))
(setf sound snd)
(setf framesize (round (* sr framedur)))
(setf skiptime (round (* sr skiptime)))
(setf npoles np)))
(send lpc-class :next '() '(
(let ((samps (snd-fetch-array framesize skipsize)))
(cond ((null samps) nil)
(t
(snd-lpanal samps npoles)))))
(defun make-lpanal-iterator (sound framedur skiptime npoles)
(send lpc-class :new (snd-copy sound) framedur skiptime npoles))
;---------------------------------------------------------------------
; SHOW-LPC-DATA. Show values of LPC analysis frames
;
; lpc-data data generated by LPANAL
; iniframe first frame to show
; endframe last frame to show
; poles? T or NIL show or not filter coefs
(defun show-lpc-data (lpc-data iniframe endframe &optional (poles? NIL))
(if (> endframe (length lpc-data)) (setf endframe (length lpc-data)))
(dotimes (i (- endframe iniframe))
(if poles? (format t "FRM ~A : ~A\n" (+ i iniframe) (aref lpc-data (+ i iniframe)))
(format t "FRM ~A : ~A\n" (+ i iniframe) (reverse (cdr (reverse (aref lpc-data (+ i iniframe)))))))))
;----------------------------------------------------------------------
; LPC-FREQ. Show frequency response of ALLPOLES filter.
; NEEDS MATLAB or OCTAVE
;
;
; HELPER FUNS : GET-FILTER-COEFS from a LPC analysis data
; lpc-data: data generated by LPCANAL
; numframe: index of frame data
;
; LPC-COEFS-TO-MATLAB : transforms LPC coefs format to Matlab format
;
; LPC-FREQ.
;
; varname : the name of variable that holds coef array in MATLAB
; lpc-data : as above
; numframe : as above
;
(defun get-filter-coefs (lpc-data numframe)
(nth 3 (aref lpc-data numframe)))
(defun lpc-coefs-to-matlab (lpc-data numframe)
(let* ((lpc-coefs (get-filter-coefs lpc-data numframe))
(lencoefs (length lpc-coefs))
(result (make-array (1+ lencoefs))))
(setf (aref result 0) 1.0)
(dotimes (i lencoefs)
(setf (aref result (1+ i))
(- (aref lpc-coefs (- lencoefs i 1)))))
result))
(defun lpc-freq (varname lpc-data numframe)
(octave (list (list (lpc-coefs-to-matlab lpc-data numframe) varname 'ARR))))
;----------------------------------------------------------------------------
; ALLPOLES
;
(defun get-allpoles-gain (lpc-data numframe)
(nth 2 (aref lpc-data numframe))) ; se toma ERR para que la amplitud de
; la salida se aproxime a 1
(defun allpoles-from-lpc (snd lpc-data numframe)
(snd-allpoles snd (get-filter-coefs lpc-data numframe) (get-allpoles-gain lpc-data numframe)))
;-------------------------------------------------------------------------------
; LPRESON
(defun get-lpreson-gain (lpc-data numframe)
(sqrt (nth 1 (aref lpc-data numframe)))) ; se toma (sqrt RMS2) para que la amplitud se
; aproxime a la original
(defun get-lpreson-coefs (lpc-data numframe)
(nth 3 (aref lpc-data numframe)))
|