1 /*
2 pvadd.c:
3
4 Copyright (C) 1998 Richard Karpen
5
6 This file is part of Csound.
7
8 The Csound Library is free software; you can redistribute it
9 and/or modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 Csound is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with Csound; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 02110-1301 USA
22 */
23
24 /******************************************/
25 /* The applications in this file were */
26 /* designed and coded by Richard Karpen */
27 /* University of Washington, Seattle 1998 */
28 /******************************************/
29 /* PVADD.C */
30
31 #include "pvoc.h"
32 #include <math.h>
33
34 static int32_t pvx_loadfile(CSOUND *csound, const char *fname, PVADD *p);
35
36 /* This is used in pvadd instead of the Fetch() from dsputil.c */
FetchInForAdd(float * inp,MYFLT * buf,int32 fsize,MYFLT pos,int32_t binoffset,int32_t maxbin,int32_t binincr)37 void FetchInForAdd(float *inp, MYFLT *buf, int32 fsize,
38 MYFLT pos, int32_t binoffset, int32_t maxbin, int32_t binincr)
39 {
40 int32 j;
41 float *frame0, *frame1;
42 int32 base;
43 MYFLT frac;
44
45 base = (int32)pos;
46 frac = pos - (MYFLT)base;
47 /* & how close to get to next */
48 frame0 = inp + ((int32)fsize+2L)*base;
49 frame1 = frame0 + ((int32)fsize+2L);
50 if (frac != FL(0.0)) {
51 for (j = binoffset; j < maxbin; j+=binincr) {
52 buf[2L*j] = frame0[2L*j] + frac*(frame1[2L*j]-frame0[2L*j]);
53 buf[2L*j+1L] = frame0[2L*j+1L]
54 + frac*(frame1[2L*j+1L]-frame0[2L*j+1L]);
55 }
56 }
57 else {
58 for (j = binoffset; j < maxbin; j+=binincr) {
59 buf[2L*j] = frame0[2L*j];
60 buf[2L*j+1] = frame0[2L*j+1L];
61 }
62 }
63 }
64
pvaddset_(CSOUND * csound,PVADD * p,int32_t stringname)65 int32_t pvaddset_(CSOUND *csound, PVADD *p, int32_t stringname)
66 {
67 int32_t ibins;
68 char pvfilnam[MAXNAME];
69 int32_t size;
70 FUNC *ftp = NULL, *AmpGateFunc = NULL;
71 int32 memsize;
72
73 if (*p->ifn > FL(0.0))
74 if (UNLIKELY((ftp = csound->FTFind(csound, p->ifn)) == NULL))
75 return NOTOK;
76 p->ftp = ftp;
77
78 if (*p->igatefun > FL(0.0))
79 if (UNLIKELY((AmpGateFunc = csound->FTnp2Finde(csound, p->igatefun)) == NULL))
80 return NOTOK;
81 p->AmpGateFunc = AmpGateFunc;
82
83 if (stringname==0){
84 if (csound->ISSTRCOD(*p->ifilno))
85 strNcpy(pvfilnam,get_arg_string(csound, *p->ifilno), MAXNAME-1);
86 else csound->strarg2name(csound, pvfilnam, p->ifilno, "pvoc.",0);
87 }
88 else strNcpy(pvfilnam, ((STRINGDAT *)p->ifilno)->data, MAXNAME-1);
89
90 if (UNLIKELY(pvx_loadfile(csound, pvfilnam, p) != OK))
91 return NOTOK;
92
93 memsize = (int32) (MAXBINS + PVFFTSIZE + PVFFTSIZE);
94 if (*p->imode == 1 || *p->imode == 2) {
95 int32 n= (int32) ((p->frSiz + 2L) * (p->maxFr + 2L));
96 #ifdef USE_DOUBLE
97 n = (n + 1L) * (int32) sizeof(float) / (int32) sizeof(double);
98 #endif
99 memsize += n;
100 }
101
102 if (p->auxch.auxp == NULL || memsize != p->mems) {
103 MYFLT *fltp;
104 csound->AuxAlloc(csound, (memsize * sizeof(MYFLT)), &p->auxch);
105 fltp = (MYFLT *) p->auxch.auxp;
106 p->oscphase = fltp;
107 fltp += MAXBINS;
108 p->buf = fltp;
109 if (*p->imode == 1 || *p->imode == 2) {
110 fltp += PVFFTSIZE * 2;
111 p->pvcopy = (float*) ((void*) fltp);
112 }
113 }
114 p->mems = memsize;
115
116 size = pvfrsiz(p);
117 p->prFlg = 1; /* true */
118
119 if (*p->igatefun > 0)
120 p->PvMaxAmp = PvocMaxAmp(p->frPtr, size, p->maxFr);
121
122 if (*p->imode == 1 || *p->imode == 2) {
123 SpectralExtract(p->frPtr, p->pvcopy, size, p->maxFr,
124 (int32_t) *p->imode, *p->ifreqlim);
125 p->frPtr = (float*) p->pvcopy;
126 }
127
128 memset(p->oscphase, 0, MAXBINS*sizeof(MYFLT));
129
130 ibins = (*p->ibins <= FL(0.0) ? (size / 2) : (int32_t) *p->ibins);
131 p->maxbin = ibins + (int32_t) *p->ibinoffset;
132 p->maxbin = (p->maxbin > (size / 2) ? (size / 2) : p->maxbin);
133
134 return OK;
135 }
136
pvadd(CSOUND * csound,PVADD * p)137 int32_t pvadd(CSOUND *csound, PVADD *p)
138 {
139 MYFLT *ar, *ftab;
140 MYFLT frIndx;
141 int32_t size = pvfrsiz(p);
142 int32_t i, binincr = (int32_t) *p->ibinincr;
143 uint32_t offset = p->h.insdshead->ksmps_offset;
144 uint32_t early = p->h.insdshead->ksmps_no_end;
145 uint32_t n, nsmps = CS_KSMPS;
146 MYFLT amp, frq, v1, fract, *oscphase;
147 int32 phase, incr;
148 FUNC *ftp;
149 int32 lobits;
150
151 if (UNLIKELY(p->auxch.auxp == NULL)) goto err1;
152 ftp = p->ftp;
153 if (UNLIKELY((frIndx = *p->ktimpnt * p->frPrtim) < 0)) goto err2;
154
155 if (frIndx > p->maxFr) { /* not past last one */
156 frIndx = (MYFLT) p->maxFr;
157 if (p->prFlg) {
158 p->prFlg = 0; /* false */
159 csound->Warning(csound, Str("PVADD ktimpnt truncated to last frame"));
160 }
161 }
162 FetchInForAdd(p->frPtr, p->buf, size, frIndx,
163 (int32_t) *p->ibinoffset, p->maxbin, binincr);
164
165 if (*p->igatefun > 0)
166 PvAmpGate(p->buf, p->maxbin*2, p->AmpGateFunc, p->PvMaxAmp);
167
168 ar = p->rslt;
169 memset(ar, 0, nsmps*sizeof(MYFLT));
170 if (UNLIKELY(early)) nsmps -= early;
171 oscphase = p->oscphase;
172 for (i = (int32_t) *p->ibinoffset; i < p->maxbin; i += binincr) {
173 lobits = ftp->lobits;
174 phase = (int32) *oscphase;
175 frq = p->buf[i * 2 + 1] * *p->kfmod;
176 if (p->buf[i * 2 + 1] == FL(0.0) || frq >= CS_ESR * FL(0.5)) {
177 incr = 0; /* Hope then does not matter */
178 amp = FL(0.0);
179 }
180 else {
181 MYFLT tmp = frq * csound->sicvt;
182 incr = (int32) MYFLT2LONG(tmp);
183 amp = p->buf[i * 2];
184 }
185 for (n=offset;n<nsmps;n++) {
186 fract = PFRAC(phase);
187 ftab = ftp->ftable + (phase >> lobits);
188 v1 = *ftab++;
189 ar[n] += (v1 + (*ftab - v1) * fract) * amp;
190 phase += incr;
191 phase &= PHMASK;
192 }
193 *oscphase = (MYFLT) phase;
194 oscphase++;
195 }
196 return OK;
197 err1:
198 return csound->PerfError(csound, &(p->h), Str("pvadd: not initialised"));
199 err2:
200 return csound->PerfError(csound, &(p->h), Str("PVADD timpnt < 0"));
201 }
202
pvaddset(CSOUND * csound,PVADD * p)203 int32_t pvaddset(CSOUND *csound, PVADD *p){
204 return pvaddset_(csound, p, 0);
205 }
206
pvaddset_S(CSOUND * csound,PVADD * p)207 int32_t pvaddset_S(CSOUND *csound, PVADD *p){
208 return pvaddset_(csound, p, 1);
209 }
210
211
pvx_loadfile(CSOUND * csound,const char * fname,PVADD * p)212 static int32_t pvx_loadfile(CSOUND *csound, const char *fname, PVADD *p)
213 {
214 PVOCEX_MEMFILE pp;
215
216 if (UNLIKELY(csound->PVOCEX_LoadFile(csound, fname, &pp) != 0)) {
217 return csound->InitError(csound, Str("PVADD cannot load %s"), fname);
218 }
219 /* fft size must be <= PVFRAMSIZE (=8192) for Csound */
220 if (UNLIKELY(pp.fftsize > PVFRAMSIZE)) {
221 return csound->InitError(csound, Str("pvoc-ex file %s: "
222 "FFT size %d too large for Csound"),
223 fname, (int32_t
224 ) pp.fftsize);
225 }
226 if (UNLIKELY(pp.fftsize < 128)) {
227 return csound->InitError(csound, Str("PV frame %d seems too small in %s"),
228 pp.fftsize, fname);
229 }
230 /* have to reject m/c files for now, until opcodes upgraded */
231 if (UNLIKELY(pp.chans > 1)) {
232 return csound->InitError(csound, Str("pvoc-ex file %s is not mono"), fname);
233 }
234 /* ignore the window spec until we can use it! */
235 p->frSiz = pp.fftsize;
236 p->frPtr = (float*) pp.data;
237 p->maxFr = pp.nframes - 1;
238 p->asr = pp.srate;
239 /* factor by which to mult expand phase diffs (ratio of samp spacings) */
240 p->frPrtim = CS_ESR / (MYFLT) pp.overlap;
241 return OK;
242 }
243
244