wav: prettify wav_read_fmt() function
[sox.git] / lpc10 / onset.c
blob8215ed3e10dcfbd247ba70076ed1fdb93a4d152d
1 /*
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
6 * argument.
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
12 * Initial revision
17 /* -- translated by f2c (version 19951025).
18 You must link the resulting object file with the libraries:
19 -lf2c -lm (in that order)
22 #include "f2c.h"
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
37 * argument.
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
43 * Initial revision
44 * */
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 */
78 /* of speech. */
81 /* Input: */
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 */
87 /* Input/Output: */
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 */
107 real *n;
108 real *d__;
109 real *l2buf;
110 real *l2sum1;
111 integer *l2ptr1;
112 integer *l2ptr2;
113 logical *hyst;
115 /* System generated locals */
116 integer pebuf_offset, i__1;
117 real r__1;
119 /* Builtin functions */
120 double r_sign(real *, real *);
122 /* Local variables */
123 integer i__;
124 integer *lasti;
125 real l2sum2;
126 real *fpc;
128 /* Arguments */
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 */
140 /* Local state */
141 /* Variables */
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. */
177 n = &(st->n);
178 d__ = &(st->d__);
179 fpc = &(st->fpc);
180 l2buf = &(st->l2buf[0]);
181 l2sum1 = &(st->l2sum1);
182 l2ptr1 = &(st->l2ptr1);
183 l2ptr2 = &(st->l2ptr2);
184 lasti = &(st->lasti);
185 hyst = &(st->hyst);
187 /* Parameter adjustments */
188 if (osbuf) {
189 --osbuf;
191 if (pebuf) {
192 pebuf_offset = *sbufl;
193 pebuf -= pebuf_offset;
196 /* Function Body */
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". */
201 if (*hyst) {
202 *lasti -= *lframe;
204 i__1 = *sbufh;
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;
212 if ((*d__) != 0.f) {
213 if (abs(*n) > (*d__)) {
214 *fpc = r_sign(&c_b2, n);
215 } else {
216 *fpc = (*n) / (*d__);
219 /* Filter FPC */
220 /* In order to allow L2SUM1 not to be saved from one invocation
221 of */
222 /* this subroutine to the next, one could change the sequence of
224 /* assignments below, up to the IF statement, to the following.
225 In */
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) {
246 if (! (*hyst)) {
247 /* Ignore if buffer full */
248 if (*osptr <= *oslen) {
249 osbuf[*osptr] = i__ - 9;
250 ++(*osptr);
252 *hyst = TRUE_;
254 *lasti = i__;
255 /* After one onset detection, at least OSHYST sample times m
256 ust go */
257 /* by before another is allowed to occur. */
258 } else if ((*hyst) && i__ - *lasti >= 10) {
259 *hyst = FALSE_;
262 return 0;
263 } /* onset_ */