3 * Revision 1.2 1996/08/20 20:37:55 jaf
4 * Removed all static local variables that were SAVE'd in the Fortran
5 * code, and put them in struct lpc10_encoder_state that is passed as an
8 * Removed init function, since all initialization is now done in
9 * init_lpc10_encoder_state().
11 * Revision 1.1 1996/08/19 22:31:18 jaf
17 /* -- translated by f2c (version 19951025).
18 You must link the resulting object file with the libraries:
19 -lf2c -lm (in that order)
24 extern int onset_(real
*pebuf
, integer
*osbuf
, integer
*osptr
, integer
*oslen
, integer
*sbufl
, integer
*sbufh
, integer
*lframe
, struct lpc10_encoder_state
*st
);
26 /* Table of constant values */
28 static real c_b2
= 1.f
;
30 /* ****************************************************************** */
32 /* ONSET Version 49 */
34 /* Revision 1.2 1996/08/20 20:37:55 jaf
35 * Removed all static local variables that were SAVE'd in the Fortran
36 * code, and put them in struct lpc10_encoder_state that is passed as an
39 * Removed init function, since all initialization is now done in
40 * init_lpc10_encoder_state().
42 * Revision 1.1 1996/08/19 22:31:18 jaf
45 /* Revision 1.5 1996/03/15 16:41:01 jaf */
46 /* Just rearranged INITONSET assignment orders to be consistent with */
47 /* order of DATA statements in ONSET. */
49 /* Revision 1.4 1996/03/15 15:48:27 jaf */
50 /* Changed some comments, and only reordered the DATA statements (their */
51 /* meaning wasn't changed). */
53 /* Revision 1.3 1996/03/14 23:53:06 jaf */
54 /* Added an entry INITONSET that reinitializes the local state variables */
55 /* of subroutine ONSET. */
57 /* Rearranged quite a few comments, adding more explaining which */
58 /* arguments were inputs, and how the modified ones can be changed. */
60 /* Revision 1.2 1996/03/12 23:53:00 jaf */
61 /* Lots of comments added about the local state of this subroutine that */
62 /* must be saved from one invocation to the next. */
64 /* One constant 180 replaced with LFRAME, which should be "more general", */
65 /* even though it would probably require many more changes than this to */
66 /* get this coder to work for other frame sizes. */
68 /* Revision 1.1 1996/02/07 14:48:09 jaf */
69 /* Initial revision */
72 /* ****************************************************************** */
74 /* Floating point version */
77 /* Detection of onsets in (or slightly preceding) the futuremost frame */
82 /* PEBUF(SBUFL:SBUFH) - Preemphasized speech */
83 /* Indices SBUFH-LFRAME through SBUFH are read. */
84 /* OSLEN - Maximum number of onsets that can be stored in OSBUF. */
85 /* SBUFL, SBUFH - Range of PEBUF */
86 /* LFRAME - length of a frame, in samples */
88 /* OSBUF(OSLEN) - Buffer which holds sorted indexes of onsets */
89 /* Indices A through B are modified, where A */
90 /* is the original value of OSPTR, and B is the final */
91 /* value of OSPTR-1. B is at most OSLEN. */
92 /* OSPTR - Free pointer into OSBUF */
93 /* Initial value should be .LE. OSLEN+1. */
94 /* If so, final value grows by one for each new onset */
95 /* found, and final value will be .LE. OSLEN+1. */
97 /* This subroutine maintains local state from one call to the next. If */
98 /* you want to switch to using a new audio stream for this subroutine, or */
99 /* reinitialize its state for any other reason, call the ENTRY INITONSET. */
101 /* Subroutine */ int onset_(real
*pebuf
, integer
*osbuf
, integer
*
102 osptr
, integer
*oslen
, integer
*sbufl
, integer
*sbufh
, integer
*
103 lframe
, struct lpc10_encoder_state
*st
)
105 /* Initialized data */
115 /* System generated locals */
116 integer pebuf_offset
, i__1
;
119 /* Builtin functions */
120 double r_sign(real
*, real
*);
122 /* Local variables */
130 /* LPC Configuration parameters: */
131 /* Frame size, Prediction order, Pitch period */
132 /* Parameters/constants */
133 /* Parameters for onset detection algorithm: */
134 /* L2 Threshold for filtered slope of FPC (function of L2WID!) */
135 /* L2LAG Lag due to both filters which compute filtered slope of FPC */
136 /* L2WID Width of the filter which computes the slope of FPC */
137 /* OSHYST The number of samples of slope(FPC) which must be below */
138 /* the threshold before a new onset may be declared. */
139 /* Local variables that need not be saved */
142 /* N, D Numerator and denominator of prediction filters */
143 /* FPC Current prediction coefs */
144 /* L2BUF, L2SUM1, L2SUM2 State of slope filter */
145 /* The only "significant" change I've made is to change L2SUM2 out
147 /* of the list of local variables that need to be saved, since it */
148 /* didn't need to be. */
149 /* L2SUM1 need not be, but avoiding saving it would require a small
151 /* change to the body of the code. See comments below for an */
152 /* example of how the code could be changed to avoid saving L2SUM1.
154 /* FPC and LASTI are saved from one invocation to the next, but */
155 /* they are not given initial values. This is acceptable, because
157 /* FPC will be assigned a value the first time that this function */
158 /* is called after D is initialized to 1, since the formula to */
159 /* change D will not change it to 0 in one step, and the IF (D */
160 /* .NE. 0) statement will execute its THEN part, initializing FPC.
163 /* LASTI's value will not be used until HYST is .TRUE., and */
164 /* whenever HYST is changed from its initial value of .FALSE., */
165 /* LASTI is assigned a value. */
166 /* In a C version of this coder, it would be nice if all of these */
167 /* saved things, in this and all other subroutines, could be stored
169 /* in a single struct lpc10_coder_state_t, initialized with a call
171 /* to a function like lpc10_init(&lpc10_coder_state). In this way,
173 /* a program that used these functions could conveniently alternate
175 /* coding more than one distinct audio stream. */
180 l2buf
= &(st
->l2buf
[0]);
181 l2sum1
= &(st
->l2sum1
);
182 l2ptr1
= &(st
->l2ptr1
);
183 l2ptr2
= &(st
->l2ptr2
);
184 lasti
= &(st
->lasti
);
187 /* Parameter adjustments */
192 pebuf_offset
= *sbufl
;
193 pebuf
-= pebuf_offset
;
198 /* The following line subtracted a hard-coded "180" from LASTI, */
199 /* instead of using a variable like LFRAME or a constant like */
200 /* MAXFRM. I changed it to LFRAME, for "generality". */
205 for (i__
= *sbufh
- *lframe
+ 1; i__
<= i__1
; ++i__
) {
206 /* Compute FPC; Use old FPC on divide by zero; Clamp FPC to +/- 1.
208 *n
= (pebuf
[i__
] * pebuf
[i__
- 1] + (*n
) * 63.f
) / 64.f
;
209 /* Computing 2nd power */
210 r__1
= pebuf
[i__
- 1];
211 *d__
= (r__1
* r__1
+ (*d__
) * 63.f
) / 64.f
;
213 if (abs(*n
) > (*d__
)) {
214 *fpc
= r_sign(&c_b2
, n
);
216 *fpc
= (*n
) / (*d__
);
220 /* In order to allow L2SUM1 not to be saved from one invocation
222 /* this subroutine to the next, one could change the sequence of
224 /* assignments below, up to the IF statement, to the following.
226 /* addition, the initial value of L2PTR2 should be changed to */
227 /* L2WID/2 instead of L2WID/2+1. */
229 /* L2SUM1 = L2BUF(L2PTR2) */
230 /* L2PTR2 = MOD(L2PTR2,L2WID)+1 */
231 /* L2SUM1 = L2SUM1 - L2BUF(L2PTR2) + FPC */
232 /* L2BUF(L2PTR2) = L2SUM1 */
234 /* * The following lines didn't change from the original: */
235 /* L2SUM2 = L2BUF(L2PTR1) */
236 /* L2BUF(L2PTR1) = FPC */
237 /* L2PTR1 = MOD(L2PTR1,L2WID)+1 */
239 l2sum2
= l2buf
[*l2ptr1
- 1];
240 *l2sum1
= *l2sum1
- l2buf
[*l2ptr2
- 1] + *fpc
;
241 l2buf
[*l2ptr2
- 1] = *l2sum1
;
242 l2buf
[*l2ptr1
- 1] = *fpc
;
243 *l2ptr1
= *l2ptr1
% 16 + 1;
244 *l2ptr2
= *l2ptr2
% 16 + 1;
245 if ((r__1
= *l2sum1
- l2sum2
, abs(r__1
)) > 1.7f
) {
247 /* Ignore if buffer full */
248 if (*osptr
<= *oslen
) {
249 osbuf
[*osptr
] = i__
- 9;
255 /* After one onset detection, at least OSHYST sample times m
257 /* by before another is allowed to occur. */
258 } else if ((*hyst
) && i__
- *lasti
>= 10) {