~ubuntu-branches/ubuntu/precise/csound/precise

« back to all changes in this revision

Viewing changes to OOps/ugens2a.c

  • Committer: Package Import Robot
  • Author(s): Felipe Sateler
  • Date: 2012-04-19 09:26:46 UTC
  • mfrom: (3.2.19 sid)
  • Revision ID: package-import@ubuntu.com-20120419092646-96xbj1n6atuqosk2
Tags: 1:5.17.6~dfsg-1
* New upstream release
 - Do not build the wiimote opcodes (we need wiiuse).
* Add new API function to symbols file
* Disable lua opcodes, they were broken. Requires OpenMP to be enabled.
* Backport fixes from upstream:
  - Link dssi4cs with dl. Backport
  - Fix building of CsoundAC

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    ugens2a.c:
 
3
 
 
4
    Copyright (C) 2012 John ffitch
 
5
    Based in part on code from Vercoe and Whittle
 
6
 
 
7
    This file is part of Csound.
 
8
 
 
9
    The Csound Library is free software; you can redistribute it
 
10
    and/or modify it under the terms of the GNU Lesser General Public
 
11
    License as published by the Free Software Foundation; either
 
12
    version 2.1 of the License, or (at your option) any later version.
 
13
 
 
14
    Csound is distributed in the hope that it will be useful,
 
15
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
    GNU Lesser General Public License for more details.
 
18
 
 
19
    You should have received a copy of the GNU Lesser General Public
 
20
    License along with Csound; if not, write to the Free Software
 
21
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
22
    02111-1307 USA
 
23
*/
 
24
 
 
25
#include "csoundCore.h" /*                              UGENS2.C        */
 
26
#include "ugens2.h"
 
27
#include "ugrw1.h"
 
28
#include <math.h>
 
29
 
 
30
#define MYFLOOR(x) (x >= FL(0.0) ? (int32)x : (int32)((double)x - 0.99999999))
 
31
 
 
32
/*****************************************************************************/
 
33
 
 
34
/* Table read code - see TABLE data structure in ugens2.h.  */
 
35
 
 
36
/*************************************/
 
37
 
 
38
static int itblchk(CSOUND *csound, TABLE *p)
 
39
{
 
40
    if (UNLIKELY((p->ftp = csound->FTFind(csound, p->xfn)) == NULL))
 
41
      return csound->InitError(csound, Str("table does not exist"));
 
42
 
 
43
    /* Although TABLE has an integer variable for the table number
 
44
     * (p->pfn) we do not need to write it.  We know that the k
 
45
     * and a rate functions which will follow will not be
 
46
     * expecting a changed table number.
 
47
     *
 
48
     * p->pfn exists only for checking table number changes for
 
49
     * functions which are expecting a k rate table number.  */
 
50
 
 
51
    /* Set denormalisation factor to 1 or table length, depending
 
52
     * on the state of ixmode. */
 
53
    if (*p->ixmode)
 
54
      p->xbmul = p->ftp->flen;
 
55
    else
 
56
      p->xbmul = 1L;
 
57
 
 
58
    /* Multiply the ixoff value by the xbmul denormalisation
 
59
     * factor and then check it is between 0 and the table length.
 
60
     *
 
61
     * Bug fix: was p->offset * *p->ixoff */
 
62
 
 
63
    if (UNLIKELY((p->offset = p->xbmul * *p->ixoff) < FL(0.0) ||
 
64
                 p->offset > p->ftp->flen)) {
 
65
      return csound->InitError(csound, Str("Offset %f < 0 or > tablelength"),
 
66
                                       p->offset);
 
67
    }
 
68
 
 
69
    p->wrap   = (int)*p->iwrap;
 
70
    return OK;
 
71
}
 
72
 
 
73
int pktable(CSOUND *,TABLE*);
 
74
int pktabli(CSOUND *,TABLE*);
 
75
int pktabl3(CSOUND *,TABLE*);
 
76
 
 
77
int pitable(CSOUND *csound, TABLE *p)
 
78
{
 
79
    if (LIKELY(itblchk(csound,p)==OK)) return pktable(csound,p);
 
80
    return NOTOK;
 
81
}
 
82
 
 
83
int pitabli(CSOUND *csound, TABLE *p)
 
84
{
 
85
    if (LIKELY(itblchk(csound,p)==OK)) return pktabli(csound,p);
 
86
    return NOTOK;
 
87
}
 
88
 
 
89
int pitabl3(CSOUND *csound, TABLE *p)
 
90
{
 
91
    if (LIKELY(itblchk(csound,p)==OK)) return pktabl3(csound,p);
 
92
    return NOTOK;
 
93
}
 
94
 
 
95
/*---------------------------------------------------------------------------*/
 
96
 
 
97
/* Functions which read the table. */
 
98
 
 
99
int pktable(CSOUND *csound, TABLE   *p)
 
100
{
 
101
    FUNC        *ftp;
 
102
    int32        indx, length;
 
103
    MYFLT       ndx;
 
104
 
 
105
    ftp = p->ftp;
 
106
    if (UNLIKELY(ftp==NULL)) goto err1;            /* RWD fix */
 
107
    ndx = *p->xndx;
 
108
    length = ftp->flen;
 
109
    /* Multiply ndx by denormalisation factor, and add in the offset
 
110
     * - already denormalised - by tblchk().
 
111
     * xbmul = 1 or table length depending on state of ixmode.  */
 
112
 
 
113
    ndx = ( ndx * p->xbmul) + p->offset;
 
114
 
 
115
    /* ndx now includes the offset and is ready to address the table.
 
116
     *
 
117
     * The original code was:
 
118
     *  indx = (long) (ndx + p->offset);
 
119
     *
 
120
     * This is a problem, causes problems with negative numbers.
 
121
     *
 
122
     */
 
123
     indx = (int32) MYFLOOR((double)ndx);
 
124
 
 
125
    /* Now for "limit mode" - the "non-wrap" function, depending on
 
126
     * iwrap.
 
127
     *
 
128
     * The following section of code limits the final index to 0 and
 
129
     * the last location in the table.
 
130
     *
 
131
     * It is only used when wrap is OFF.  The wrapping is achieved by
 
132
     * code after this - when this code is not run.  */
 
133
    if (!p->wrap) {
 
134
      /* Previously this code limited the upper range of the indx to
 
135
       * the table length - for instance 8.  Then the result was ANDed
 
136
       * with a mask (for instance 7).
 
137
       *
 
138
       * This meant that when the input index was 8 or above, it got
 
139
       * reduced to 0.  What we want is for it to stick at the index
 
140
       * which reads the last value from the table - in this example
 
141
       * from location 7.
 
142
       *
 
143
       * So instead of limiting to the table length, we limit to
 
144
       * (table length - 1).  */
 
145
      if (UNLIKELY(indx > length - 1))
 
146
        indx = length - 1;
 
147
 
 
148
      /* Now limit negative values to zero.  */
 
149
      else if (UNLIKELY(indx < 0L))
 
150
        indx = 0L;
 
151
    }
 
152
    /* The following code used to use an AND with an integer like 0000 0111
 
153
     * to wrap the current index within the range of the table.  In
 
154
     * the original version, this code always ran, but with the new
 
155
     * (length - 1) code above, it would have no effect, so it is now
 
156
     * an else operation - running only when iwrap = 1.  This may save
 
157
     * half a usec or so.  */
 
158
    /* Now safe against non power-of-2 tables */
 
159
    else if (indx>=length) indx = indx % length;
 
160
    else if (indx<0) indx = length - (-indx)%length;
 
161
 
 
162
    /* Now find the address of the start of the table, add it to the
 
163
     * index, read the value from there and write it to the
 
164
     * destination.  */
 
165
    *p->rslt = *(ftp->ftable + indx);
 
166
    return OK;
 
167
 err1:
 
168
    return csound->PerfError(csound, Str("ptable(krate): not initialised"));
 
169
}
 
170
 
 
171
/* ptablefn()  */
 
172
 
 
173
int ptablefn(CSOUND *csound, TABLE *p)
 
174
{
 
175
    FUNC        *ftp;
 
176
    MYFLT       *rslt, *pxndx, *tab;
 
177
    int32       indx, length;
 
178
    int         n, nsmps=csound->ksmps;
 
179
    MYFLT       ndx, xbmul, offset;
 
180
    int         wrap = p->wrap;
 
181
 
 
182
    ftp = p->ftp;
 
183
    if (UNLIKELY(ftp==NULL)) goto err1;            /* RWD fix */
 
184
    rslt = p->rslt;
 
185
    length = ftp->flen;
 
186
    pxndx = p->xndx;
 
187
    xbmul = (MYFLT)p->xbmul;
 
188
    offset = p->offset;
 
189
    //mask = ftp->lenmask;
 
190
    tab = ftp->ftable;
 
191
    for (n=0; n<nsmps; n++) {
 
192
      /* Read in the next raw index and increment the pointer ready
 
193
       * for the next cycle.
 
194
       *
 
195
       * Then multiply the ndx by the denormalising factor and add in
 
196
       * the offset.  */
 
197
 
 
198
      ndx = (pxndx[n] * xbmul) + offset;
 
199
      indx = (int32) MYFLOOR((double)ndx);
 
200
 
 
201
      /* Limit = non-wrap.  Limits to 0 and (length - 1), or does the
 
202
       * wrap code.  See notes above in ktable().  */
 
203
      if (!wrap) {
 
204
        if (UNLIKELY(indx >= length))
 
205
          indx = length - 1;
 
206
        else if (UNLIKELY(indx < (int32)0))
 
207
          indx = (int32)0;
 
208
      }
 
209
      /* do the wrap code only if we are not doing the non-wrap code.  */
 
210
      else if (indx >= length) indx %= length;
 
211
      else if (indx < 0) indx = length - (-indx)%length;
 
212
      rslt[n] = tab[indx];
 
213
    }
 
214
    return OK;
 
215
 err1:
 
216
    return csound->PerfError(csound, Str("table: not initialised"));
 
217
}
 
218
 
 
219
/* pktabli() */
 
220
 
 
221
int pktabli(CSOUND *csound, TABLE   *p)
 
222
{
 
223
    FUNC        *ftp;
 
224
    int32       indx, length;
 
225
    MYFLT       v1, v2, fract, ndx;
 
226
 
 
227
    ftp = p->ftp;
 
228
    if (UNLIKELY(ftp==NULL)) goto err1;
 
229
    ndx = *p->xndx;
 
230
    length = ftp->flen;
 
231
    /* Multiply ndx by denormalisation factor.
 
232
     * xbmul is 1 or table length depending on state of ixmode.
 
233
     * Add in the offset, which has already been denormalised by
 
234
     * tblchk().  */
 
235
 
 
236
    ndx    = (ndx * p->xbmul) + p->offset;
 
237
    indx = (int32) MYFLOOR((double)ndx);
 
238
 
 
239
    /* We need to generate a fraction - How much above indx is ndx?
 
240
     * It will be between 0 and just below 1.0.  */
 
241
    fract = ndx - indx;
 
242
 
 
243
    if (!p->wrap) {
 
244
      if (UNLIKELY(ndx >= length)) {
 
245
        indx  = length - 1;
 
246
        fract = FL(1.0);
 
247
      }
 
248
      else if (UNLIKELY(ndx < 0)) {
 
249
        indx  = 0L;
 
250
        fract = FL(0.0);
 
251
      }
 
252
    }
 
253
    /* We are in wrap mode, so do the wrap function.  */
 
254
    else if (indx>=length) indx %= length;
 
255
    else if (indx<0) indx = length - (-indx)%length;
 
256
 
 
257
    /* Now read the value at indx and the one beyond */
 
258
    v1 = *(ftp->ftable + indx);
 
259
    indx++;
 
260
    if (indx>=length) indx -= length;
 
261
    v2 = *(ftp->ftable + indx);
 
262
    *p->rslt = v1 + (v2 - v1) * fract;
 
263
    return OK;
 
264
 err1:
 
265
    return csound->PerfError(csound, Str("ptablei(krate): not initialised"));
 
266
}
 
267
 
 
268
 
 
269
int pktabl3(CSOUND *csound, TABLE   *p)
 
270
{
 
271
    FUNC        *ftp;
 
272
    int32        indx, length;
 
273
    MYFLT       v1, v2, fract, ndx;
 
274
 
 
275
    ftp = p->ftp;
 
276
    if (UNLIKELY(ftp==NULL)) goto err1;
 
277
    ndx = *p->xndx;
 
278
    length = ftp->flen;
 
279
    /* Multiply ndx by denormalisation factor.
 
280
     * xbmul is 1 or table length depending on state of ixmode.
 
281
     * Add in the offset, which has already been denormalised by
 
282
     * tblchk().  */
 
283
 
 
284
    ndx    = (ndx * p->xbmul) + p->offset;
 
285
    indx = (int32) MYFLOOR((double)ndx);
 
286
 
 
287
    /* We need to generate a fraction - How much above indx is ndx?
 
288
     * It will be between 0 and just below 1.0.  */
 
289
    fract = ndx - indx;
 
290
 
 
291
    if (!p->wrap) {
 
292
      if (UNLIKELY(ndx >= length)) {
 
293
        indx  = length - 1;
 
294
        fract = FL(1.0);
 
295
      }
 
296
      else if (UNLIKELY(ndx < 0)) {
 
297
        indx  = 0L;
 
298
        fract = FL(0.0);
 
299
      }
 
300
    }
 
301
    /* We are in wrap mode, so do the wrap function.  */
 
302
    else if (indx>=length) indx %= length;
 
303
    else if (indx<0) indx = length - (-indx)%length;
 
304
 
 
305
    /* interpolate with cubic if we can, else linear */
 
306
    if (UNLIKELY(indx<1 || indx==length-2 || length <4)) {
 
307
      v1 = *(ftp->ftable + indx);
 
308
      v2 = *(ftp->ftable + indx + 1);
 
309
      *p->rslt = v1 + (v2 - v1) * fract;
 
310
    }
 
311
    else {
 
312
      MYFLT *tab = ftp->ftable;
 
313
      MYFLT ym1 = tab[indx-1], y0 = tab[indx];
 
314
      MYFLT y1 = tab[indx+1], y2 = tab[indx+2];
 
315
      MYFLT frsq = fract*fract;
 
316
      MYFLT frcu = frsq*ym1;
 
317
      MYFLT t1 = y2 + y0+y0+y0;
 
318
      *p->rslt = y0 + FL(0.5)*frcu
 
319
        + fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0))
 
320
        + frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0);
 
321
    }
 
322
    return OK;
 
323
 err1:
 
324
    return csound->PerfError(csound, Str("ptable3(krate): not initialised"));
 
325
}
 
326
 
 
327
int ptabli(CSOUND *csound, TABLE   *p)
 
328
{
 
329
    FUNC        *ftp;
 
330
    int32       indx, length;
 
331
    int         n, nsmps=csound->ksmps;
 
332
    MYFLT       *rslt, *pxndx, *tab;
 
333
    MYFLT       fract, v1, v2, ndx, xbmul, offset;
 
334
 
 
335
    ftp = p->ftp;
 
336
    if (UNLIKELY(ftp==NULL)) goto err1;
 
337
    rslt   = p->rslt;
 
338
    length = ftp->flen;
 
339
    pxndx  = p->xndx;
 
340
    xbmul  = (MYFLT)p->xbmul;
 
341
    offset = p->offset;
 
342
    //mask   = ftp->lenmask;
 
343
    tab    = ftp->ftable;
 
344
    /* As for ktabli() code to handle non wrap mode, and wrap mode.  */
 
345
    if (!p->wrap) {
 
346
      for (n=0; n<nsmps; n++) {
 
347
        /* Read in the next raw index and increment the pointer ready
 
348
         * for the next cycle.
 
349
         * Then multiply the ndx by the denormalising factor and add in
 
350
         * the offset.  */
 
351
        ndx = (pxndx[n] * xbmul) + offset;
 
352
        indx = (int32) ndx;
 
353
        if (UNLIKELY(ndx <= FL(0.0))) {
 
354
          rslt[n] = tab[0];
 
355
          continue;
 
356
        }
 
357
        if (UNLIKELY(indx >= length)) {
 
358
          rslt[n] = tab[length-1];
 
359
          continue;
 
360
        }
 
361
        /* We need to generate a fraction - How much above indx is ndx?
 
362
         * It will be between 0 and just below 1.0.  */
 
363
        fract = ndx - indx;
 
364
        /* As for ktabli(), read two values and interpolate between
 
365
         * them.  */
 
366
        v1 = tab[indx];
 
367
        indx++;
 
368
        if (indx>=length) indx = length-1;
 
369
        v2 = tab[indx];
 
370
        rslt[n] = v1 + (v2 - v1)*fract;
 
371
      }
 
372
    }
 
373
    else {                      /* wrap mode */
 
374
      for (n=0; n<nsmps; n++) {
 
375
        int j;
 
376
        /* Read in the next raw index and increment the pointer ready
 
377
         * for the next cycle.
 
378
         * Then multiply the ndx by the denormalising factor and add in
 
379
         * the offset.  */
 
380
        ndx = (pxndx[n] * xbmul) + offset;
 
381
        indx = (int32) MYFLOOR(ndx);
 
382
        /* We need to generate a fraction - How much above indx is ndx?
 
383
         * It will be between 0 and just below 1.0.  */
 
384
        fract = ndx - indx;
 
385
        if (indx >= length) indx %= length;
 
386
        else if (indx<0) indx = length-(-indx)%length;
 
387
        /* As for ktabli(), read two values and interpolate between
 
388
         * them.  */
 
389
        v1 = tab[indx];
 
390
        j = indx + 1;
 
391
        if (j >= length) j -= length;
 
392
        v2 = tab[j];
 
393
        rslt[n] = v1 + (v2 - v1)*fract;
 
394
      }
 
395
    }
 
396
    return OK;
 
397
 err1:
 
398
    return csound->PerfError(csound, Str("ptablei: not initialised"));
 
399
}
 
400
 
 
401
int ptabl3(CSOUND *csound, TABLE *p)     /* Like ptabli but cubic interpolation */
 
402
{
 
403
    FUNC        *ftp;
 
404
    int32       indx, length;
 
405
    int         n, nsmps=csound->ksmps;
 
406
    MYFLT       *rslt, *pxndx, *tab;
 
407
    MYFLT       fract, v1, v2, ndx, xbmul, offset;
 
408
    int         wrap = p->wrap;
 
409
 
 
410
    ftp = p->ftp;
 
411
    if (UNLIKELY(ftp==NULL)) goto err1;
 
412
    rslt = p->rslt;
 
413
    length = ftp->flen;
 
414
    pxndx = p->xndx;
 
415
    xbmul = (MYFLT)p->xbmul;
 
416
    offset = p->offset;
 
417
    tab = ftp->ftable;
 
418
    for (n=0; n<nsmps; n++) {
 
419
      /* Read in the next raw index and increment the pointer ready
 
420
       * for the next cycle.
 
421
       * Then multiply the ndx by the denormalising factor and add in
 
422
       * the offset.  */
 
423
 
 
424
      ndx = (pxndx[n] * xbmul) + offset;
 
425
      indx = (int32) MYFLOOR((double)ndx);
 
426
 
 
427
      /* We need to generate a fraction - How much above indx is ndx?
 
428
       * It will be between 0 and just below 1.0.  */
 
429
      fract = ndx - indx;
 
430
      /* As for pktabli() code to handle non wrap mode, and wrap mode.  */
 
431
      if (!wrap) {
 
432
        if (UNLIKELY(ndx >= length)) {
 
433
          indx  = length - 1;
 
434
          fract = FL(1.0);
 
435
        }
 
436
        else if (UNLIKELY(ndx < 0)) {
 
437
          indx  = 0L;
 
438
          fract = FL(0.0);
 
439
        }
 
440
      }
 
441
      else if (UNLIKELY(indx>=length)) indx %= length;
 
442
      else if (UNLIKELY(indx<0)) indx = length-(-indx)%length;
 
443
      /* interpolate with cubic if we can */
 
444
      if (UNLIKELY(indx <1 || indx == length-2 || length<4)) {
 
445
        /* Too short or at ends */
 
446
        v1 = tab[indx];
 
447
        v2 = tab[indx + 1];
 
448
        rslt[n] = v1 + (v2 - v1)*fract;
 
449
      }
 
450
      else {
 
451
        MYFLT ym1 = tab[indx-1], y0 = tab[indx];
 
452
        int j = (indx+1<length ? indx+1 : indx+1-length);
 
453
        int k = (indx+2<length ? indx+2 : indx+2-length);
 
454
        MYFLT y1 = tab[j], y2 = tab[k];
 
455
        MYFLT frsq = fract*fract;
 
456
        MYFLT frcu = frsq*ym1;
 
457
        MYFLT t1 = y2 + y0+y0+y0;
 
458
        rslt[n] = y0 + FL(0.5)*frcu +
 
459
          fract*(y1 - frcu/FL(6.0) - t1/FL(6.0) - ym1/FL(3.0)) +
 
460
          frsq*fract*(t1/FL(6.0) - FL(0.5)*y1) + frsq*(FL(0.5)* y1 - y0);
 
461
      }
 
462
    }
 
463
    return OK;
 
464
 err1:
 
465
    return csound->PerfError(csound, Str("ptable3: not initialised"));
 
466
}
 
467
 
 
468
extern int itblchkw(CSOUND *, TABLEW*);
 
469
int pktablew(CSOUND *, TABLEW*);
 
470
int pitablew(CSOUND *csound, TABLEW *p)
 
471
{
 
472
    if (LIKELY(itblchkw(csound, p) == OK))
 
473
      return pktablew(csound, p);
 
474
    return NOTOK;
 
475
}
 
476
 
 
477
/*---------------------------------------------------------------------------*/
 
478
 
 
479
/* pktablew is called with p pointing to the TABLEW data structure -
 
480
 * which contains the input arguments.  */
 
481
 
 
482
int pktablew(CSOUND *csound, TABLEW   *p)
 
483
{
 
484
/* Pointer to data structure for accessing the table we will be
 
485
 * writing to.
 
486
 */
 
487
    FUNC        *ftp;
 
488
    int32        indx, length;
 
489
    MYFLT       ndx;            /*  for calculating index of read.  */
 
490
    MYFLT       *ptab;          /* Where we will write */
 
491
 
 
492
    /*-----------------------------------*/
 
493
    /* Assume that TABLEW has been set up correctly.  */
 
494
 
 
495
    ftp    = p->ftp;
 
496
    ndx    = *p->xndx;
 
497
    length = ftp->flen;
 
498
    /* Multiply ndx by denormalisation factor.  and add in the
 
499
     * offset - already denormalised - by tblchkw().
 
500
     * xbmul = 1 or table length depending on state of ixmode.  */
 
501
 
 
502
    ndx = (ndx * p->xbmul) + p->offset;
 
503
 
 
504
    /* ndx now includes the offset and is ready to address the table.
 
505
     * However we have three modes to consider:
 
506
     * igwm = 0     Limit mode.
 
507
     *        1     Wrap mode.
 
508
     *        2     Guardpoint mode.
 
509
     */
 
510
    if (p->iwgm == 0) {
 
511
      /* Limit mode - when igmode = 0.
 
512
       *
 
513
       * Limit the final index to 0 and the last location in the table.
 
514
       */
 
515
      indx = (int32) MYFLOOR(ndx); /* Limit to (table length - 1) */
 
516
      if (UNLIKELY(indx > length - 1))
 
517
        indx = length - 1;      /* Limit the high values. */
 
518
      else if (UNLIKELY(indx < 0L)) indx = 0L; /* limit negative values to zero. */
 
519
    }
 
520
    /* Wrap and guard point mode.
 
521
     * In guard point mode only, add 0.5 to the index. */
 
522
    else {
 
523
      if (p->iwgm == 2) ndx += FL(0.5);
 
524
      indx = (int32) MYFLOOR(ndx);
 
525
 
 
526
      /* Both wrap and guard point mode.
 
527
       * The following code uses an AND with an integer like 0000 0111 to wrap
 
528
       * the current index within the range of the table. */
 
529
      if (UNLIKELY(indx>=length)) indx %= length;
 
530
      else if (UNLIKELY(indx<0)) indx = length-(-indx)%length;
 
531
    }
 
532
                                /* Calculate the address of where we
 
533
                                 * want to write to, from indx and the
 
534
                                 * starting address of the table.
 
535
                                 */
 
536
    ptab = ftp->ftable + indx;
 
537
    *ptab = *p->xsig;           /* Write the input value to the table. */
 
538
                                /* If this is guard point mode and we
 
539
                                 * have just written to location 0,
 
540
                                 * then also write to the guard point.
 
541
                                 */
 
542
    if ((p->iwgm == 2) && indx == 0) { /* Fix -- JPff 2000/1/5 */
 
543
      ptab += ftp->flen;
 
544
      *ptab = *p->xsig;
 
545
    }
 
546
    return OK;
 
547
}
 
548
 
 
549
/*---------------------------------------------------------------------------*/
 
550
 
 
551
/* tablew() is similar to ktablew()  above, except that it processes
 
552
 * two arrays of input values and indexes.  These arrays are ksmps long. */
 
553
int ptablew(CSOUND *csound, TABLEW *p)
 
554
{
 
555
    FUNC        *ftp;   /* Pointer to function table data structure. */
 
556
    MYFLT       *psig;  /* Array of input values to be written to table. */
 
557
    MYFLT       *pxndx; /* Array of input index values */
 
558
    MYFLT       *ptab;  /* Pointer to start of table we will write. */
 
559
    MYFLT       *pwrite;/* Pointer to location in table where we will write */
 
560
    int32        indx;   /* Used to read table. */
 
561
    int32        length; /* Length of table */
 
562
    int         liwgm;          /* Local copy of iwgm for speed */
 
563
    int         n, nsmps = csound->ksmps;
 
564
    MYFLT       ndx, xbmul, offset;
 
565
                                /*-----------------------------------*/
 
566
    /* Assume that TABLEW has been set up correctly. */
 
567
 
 
568
    ftp    = p->ftp;
 
569
    psig   = p->xsig;
 
570
    pxndx  = p->xndx;
 
571
    ptab   = ftp->ftable;
 
572
    length = ftp->flen;
 
573
    liwgm  = p->iwgm;
 
574
    xbmul  = (MYFLT)p->xbmul;
 
575
    offset = p->offset;
 
576
                /* Main loop - for the number of a samples in a k cycle. */
 
577
    for (n=0; n<nsmps; n++) {
 
578
      /* Read in the next raw index and increment the pointer ready for the
 
579
         next cycle.  Then multiply the ndx by the denormalising factor and
 
580
         add in the offset.  */
 
581
      ndx = (pxndx[n] * xbmul) + offset;
 
582
      if (liwgm == 0) {         /* Limit mode - when igmode = 0. */
 
583
        indx = (int32) MYFLOOR(ndx);
 
584
        if (UNLIKELY(indx > length - 1)) indx = length - 1;
 
585
        else if (UNLIKELY(indx < 0L)) indx = 0L;
 
586
      }
 
587
      else {
 
588
        if (liwgm == 2) ndx += FL(0.5);
 
589
        indx = (int32) MYFLOOR(ndx);
 
590
        /* Both wrap and guard point mode. */
 
591
        if (UNLIKELY(indx>=length)) indx %= length;
 
592
        else if (UNLIKELY(indx<0)) indx = length-(-indx)%length;
 
593
      }
 
594
      pwrite = ptab + indx;
 
595
      *pwrite = psig[n];
 
596
                                        /* If this is guard point mode and we
 
597
                                         * have just written to location 0,
 
598
                                         * then also write to the guard point.
 
599
                                         */
 
600
      if ((liwgm == 2) && indx == 0) {  /* Fix -- JPff 2000/1/5 */
 
601
                                        /* Note that since pwrite is a pointer
 
602
                                         * to a float, adding length to it
 
603
                                         * adds (4 * length) to its value since
 
604
                                         * the length of a float is 4 bytes.
 
605
                                         */
 
606
        pwrite += length;
 
607
                                        /* Decrement psig to make it point
 
608
                                         * to the same input value.
 
609
                                         * Write to guard point.
 
610
                                         */
 
611
        *pwrite = psig[n];
 
612
      }
 
613
    }
 
614
    return OK;
 
615
}