File: lpc-orig.lsp

package info (click to toggle)
nyquist 3.20%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 58,008 kB
  • sloc: ansic: 74,743; lisp: 17,929; java: 10,723; cpp: 6,690; sh: 171; xml: 58; makefile: 40; python: 15
file content (151 lines) | stat: -rw-r--r-- 5,171 bytes parent folder | download | duplicates (7)
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)))