1 /*
2 tabaudio.c:
3
4 Copyright (C) 2018 John ffitch
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 #include "csoundCore.h"
25 #include "interlocks.h"
26 //#include <pthread.h>
27 #include <sndfile.h>
28 #include "soundio.h"
29
30 typedef struct {
31 OPDS h;
32 MYFLT *kans;
33 MYFLT *itab;
34 STRINGDAT *file;
35 MYFLT *format;
36 MYFLT *beg;
37 MYFLT *end;
38 /* Local */
39 } TABAUDIO;
40
41 typedef struct {
42 OPDS h;
43 MYFLT *kans;
44 MYFLT *trig;
45 MYFLT *itab;
46 STRINGDAT *file;
47 MYFLT *format;
48 MYFLT *sync;
49 MYFLT *beg;
50 MYFLT *end;
51 /* Local */
52 } TABAUDIOK;
53
54 typedef struct {
55 CSOUND *csound;
56 MYFLT* t;
57 uint32_t size;
58 SNDFILE* ff;
59 MYFLT* ans;
60 void *thread;
61 OPDS *h;
62 } SAVE_THREAD;
63
64 static const int32_t format_table[51] = {
65 /* 0 - 9 */
66 (SF_FORMAT_FLOAT | SF_FORMAT_RAW), (SF_FORMAT_PCM_16 | SF_FORMAT_RAW),
67 SF_FORMAT_PCM_16, SF_FORMAT_ULAW, SF_FORMAT_PCM_16, SF_FORMAT_PCM_32,
68 SF_FORMAT_FLOAT, SF_FORMAT_PCM_U8, SF_FORMAT_PCM_24, SF_FORMAT_DOUBLE,
69 /* 10 - 19 */
70 SF_FORMAT_WAV, (SF_FORMAT_PCM_S8 | SF_FORMAT_WAV),
71 (SF_FORMAT_ALAW | SF_FORMAT_WAV), (SF_FORMAT_ULAW | SF_FORMAT_WAV),
72 (SF_FORMAT_PCM_16 | SF_FORMAT_WAV), (SF_FORMAT_PCM_32 | SF_FORMAT_WAV),
73 (SF_FORMAT_FLOAT | SF_FORMAT_WAV), (SF_FORMAT_PCM_U8 | SF_FORMAT_WAV),
74 (SF_FORMAT_PCM_24 | SF_FORMAT_WAV), (SF_FORMAT_DOUBLE | SF_FORMAT_WAV),
75 /* 20 - 29 */
76 SF_FORMAT_AIFF, (SF_FORMAT_PCM_S8 | SF_FORMAT_AIFF),
77 (SF_FORMAT_ALAW | SF_FORMAT_AIFF), (SF_FORMAT_ULAW | SF_FORMAT_AIFF),
78 (SF_FORMAT_PCM_16 | SF_FORMAT_AIFF), (SF_FORMAT_PCM_32 | SF_FORMAT_AIFF),
79 (SF_FORMAT_FLOAT | SF_FORMAT_AIFF), (SF_FORMAT_PCM_U8 | SF_FORMAT_AIFF),
80 (SF_FORMAT_PCM_24 | SF_FORMAT_AIFF), (SF_FORMAT_DOUBLE | SF_FORMAT_AIFF),
81 /* 30 - 39 */
82 SF_FORMAT_RAW, (SF_FORMAT_PCM_S8 | SF_FORMAT_RAW),
83 (SF_FORMAT_ALAW | SF_FORMAT_RAW), (SF_FORMAT_ULAW | SF_FORMAT_RAW),
84 (SF_FORMAT_PCM_16 | SF_FORMAT_RAW), (SF_FORMAT_PCM_32 | SF_FORMAT_RAW),
85 (SF_FORMAT_FLOAT | SF_FORMAT_RAW), (SF_FORMAT_PCM_U8 | SF_FORMAT_RAW),
86 (SF_FORMAT_PCM_24 | SF_FORMAT_RAW), (SF_FORMAT_DOUBLE | SF_FORMAT_RAW),
87 /* 40 - 49 */
88 SF_FORMAT_IRCAM, (SF_FORMAT_PCM_S8 | SF_FORMAT_IRCAM),
89 (SF_FORMAT_ALAW | SF_FORMAT_IRCAM), (SF_FORMAT_ULAW | SF_FORMAT_IRCAM),
90 (SF_FORMAT_PCM_16 | SF_FORMAT_IRCAM), (SF_FORMAT_PCM_32 | SF_FORMAT_IRCAM),
91 (SF_FORMAT_FLOAT | SF_FORMAT_IRCAM), (SF_FORMAT_PCM_U8 | SF_FORMAT_IRCAM),
92 (SF_FORMAT_PCM_24 | SF_FORMAT_IRCAM), (SF_FORMAT_DOUBLE | SF_FORMAT_IRCAM),
93 /* 50 */
94 (SF_FORMAT_OGG | SF_FORMAT_VORBIS)
95 };
96
write_tab(void * pp)97 static uintptr_t write_tab(void* pp)
98 {
99 SAVE_THREAD *p = (SAVE_THREAD*)pp;
100 MYFLT* t = p->t;
101 uint32_t size = p->size;
102 SNDFILE* ff = p->ff;
103 MYFLT* ans = p->ans;
104 CSOUND* csound = p->csound;
105 OPDS *h = p->h;
106 //free(pp);
107 //printf("t=%p size=%d ff=%p\n", t, size, ff);
108 if (sf_writef_MYFLT(ff, t, size) != size) {
109 sf_close(ff);
110 csound->PerfError(csound, h,
111 Str("tabaudio: failed to write data %d"),size);
112 *ans = -FL(1.0);
113 }
114 else *ans = FL(1.0);
115 sf_close(ff);
116 return 0;
117 }
118
on_reset_audio(CSOUND * csound,void * pp)119 int on_reset_audio(CSOUND *csound, void *pp)
120 {
121 SAVE_THREAD *p = (SAVE_THREAD *) pp;
122 csound->JoinThread(p->thread);
123 return 0;
124 }
125
tabaudiok(CSOUND * csound,TABAUDIOK * p)126 static int32_t tabaudiok(CSOUND *csound, TABAUDIOK *p)
127 {
128 if (*p->trig) {
129 FUNC *ftp;
130 MYFLT *t;
131 int32_t size, n;
132 SNDFILE *ff;
133 SF_INFO sfinfo;
134 int32_t format = MYFLT2LRND(*p->format);
135 int32_t skip = MYFLT2LRND(*p->beg);
136 int32_t end = MYFLT2LRND(*p->end);
137
138 if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->itab)) == NULL)) {
139 return csound->PerfError(csound, &(p->h), Str("tabaudio: No table %g"), *p->itab);
140 }
141 *p->kans = FL(0.0);
142 t = ftp->ftable + skip;
143 size = ftp->flenfrms;
144 if (end<=0) size -= skip;
145 else size = end - skip;
146 if (UNLIKELY(size<0 || size>ftp->flenfrms))
147 return csound->PerfError(csound, &(p->h), Str("ftudio: ilegal size"));
148 memset(&sfinfo, 0, sizeof(SF_INFO));
149 if (format >= 51)
150 sfinfo.format = SF_FORMAT_PCM_16 | SF_FORMAT_RAW;
151 else if (format < 0) {
152 sfinfo.format = FORMAT2SF(csound->oparms->outformat);
153 sfinfo.format |= TYPE2SF(csound->oparms->filetyp);
154 }
155 else sfinfo.format = format_table[format];
156 if (!SF2FORMAT(sfinfo.format))
157 sfinfo.format |= FORMAT2SF(csound->oparms->outformat);
158 if (!SF2TYPE(sfinfo.format))
159 sfinfo.format |= TYPE2SF(csound->oparms->filetyp);
160 sfinfo.samplerate = (int32_t) MYFLT2LRND(CS_ESR);
161 sfinfo.channels = ftp->nchanls;
162 ff = sf_open(p->file->data, SFM_WRITE, &sfinfo);
163 if (ff==NULL)
164 return csound->PerfError(csound, &(p->h),
165 Str("tabaudio: failed to open file %s"),
166 p->file->data);
167 if (*p->sync==FL(0.0)) { /* write in perf thread */
168 if ((n=sf_writef_MYFLT(ff, t, size)) != size) {
169 printf("%s\n", sf_strerror(ff));
170 sf_close(ff);
171 return csound->PerfError(csound, &(p->h),
172 Str("tabaudio: failed to write data %d %d"),
173 n,size);
174 }
175 sf_close(ff);
176 }
177 else { /* Use a helper thread */
178 SAVE_THREAD *q = (SAVE_THREAD*)csound->Malloc(csound, sizeof(SAVE_THREAD));
179 q->t = t;
180 q->size = size;
181 q->ff = ff;
182 q->ans = p->kans;
183 q->csound = csound;
184 q->h = &(p->h);
185 if ((q->thread = csound->CreateThread(write_tab, (void*)q))==NULL) {
186 OPDS * i = q->h;
187 free(q);
188 return csound->PerfError(csound, i,
189 Str("Error creating thread"));
190 }
191 csound->RegisterResetCallback(csound, (void*)q, on_reset_audio);
192 /* if (fork() == 0) { */
193 /* ff = sf_open(p->file->data, SFM_WRITE, &sfinfo); */
194 /* if (ff==NULL) { */
195 /* printf(Str("tabaudio: failed to open file %s"), p->file->data); */
196 /* exit(1); */
197 /* } */
198 /* if ((n=sf_writef_MYFLT(ff, t, size)) != size) { */
199 /* sf_close(ff); */
200 /* printf("%s %s", Str("tabaudio: failed to write data:"), */
201 /* sf_strerror(ff)); */
202 /* exit(1); */
203 /* } */
204 /* sf_close(ff); */
205 /* exit(0); */
206 /* } */
207 }
208 *p->kans = FL(1.0);
209 }
210 else *p->kans = FL(0.0);
211 return OK;
212 }
213
tabaudioi(CSOUND * csound,TABAUDIO * p)214 static int32_t tabaudioi(CSOUND *csound, TABAUDIO *p)
215 {
216 FUNC *ftp;
217 MYFLT *t;
218 int32_t size, n;
219 SNDFILE *ff;
220 SF_INFO sfinfo;
221 int32_t format = MYFLT2LRND(*p->format);
222 int32_t skip = MYFLT2LRND(*p->beg);
223 int32_t end = MYFLT2LRND(*p->end);
224
225 if (UNLIKELY((ftp = csound->FTnp2Find(csound, p->itab)) == NULL)) {
226 return csound->InitError(csound, Str("tabaudio: No table"));
227 }
228 *p->kans = FL(0.0);
229 t = ftp->ftable + skip;
230 size = ftp->flenfrms;
231 if (end<=0) size -= skip;
232 else size = end - skip;
233 if (UNLIKELY(size<0 || size>ftp->flenfrms))
234 return csound->InitError(csound, Str("ftudio: ilegal size"));
235 memset(&sfinfo, 0, sizeof(SF_INFO));
236 if (format >= 51)
237 sfinfo.format = SF_FORMAT_PCM_16 | SF_FORMAT_RAW;
238 else if (format < 0) {
239 sfinfo.format = FORMAT2SF(csound->oparms->outformat);
240 sfinfo.format |= TYPE2SF(csound->oparms->filetyp);
241 }
242 else sfinfo.format = format_table[format];
243 if (!SF2FORMAT(sfinfo.format))
244 sfinfo.format |= FORMAT2SF(csound->oparms->outformat);
245 if (!SF2TYPE(sfinfo.format))
246 sfinfo.format |= TYPE2SF(csound->oparms->filetyp);
247 sfinfo.samplerate = (int32_t) MYFLT2LRND(CS_ESR);
248 sfinfo.channels = ftp->nchanls;
249
250 ff = sf_open(p->file->data, SFM_WRITE, &sfinfo);
251 if (ff==NULL)
252 return csound->InitError(csound, Str("tabaudio: failed to open file %s"),
253 p->file->data);
254 if ((n=sf_writef_MYFLT(ff, t, size)) != size) {
255 printf("%s\n", sf_strerror(ff));
256 sf_close(ff);
257 return csound->InitError(csound, Str("tabaudio: failed to write data: %s"),
258 sf_strerror(ff));
259 }
260 *p->kans = FL(1.0);
261 sf_close(ff);
262 return OK;
263 }
264
265 #define S(x) sizeof(x)
266
267 static OENTRY tabaudio_localops[] =
268 {
269 { "ftaudio.i", S(TABAUDIO), TR, 1, "i", "iSioo", (SUBR)tabaudioi, NULL },
270 { "ftaudio.k", S(TABAUDIOK), TR, 2, "k", "kkSkpOO", NULL, (SUBR)tabaudiok },
271 };
272
273 LINKAGE_BUILTIN(tabaudio_localops)
274
275
276
277