diff options
Diffstat (limited to 'apps/plugins/pdbox/PDa/intern/sfwrite~.c')
-rw-r--r-- | apps/plugins/pdbox/PDa/intern/sfwrite~.c | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/intern/sfwrite~.c b/apps/plugins/pdbox/PDa/intern/sfwrite~.c new file mode 100644 index 0000000000..dd3bfc4a09 --- /dev/null +++ b/apps/plugins/pdbox/PDa/intern/sfwrite~.c | |||
@@ -0,0 +1,480 @@ | |||
1 | |||
2 | #include <unistd.h> | ||
3 | #include <fcntl.h> | ||
4 | #include <errno.h> | ||
5 | #include <stdio.h> | ||
6 | #include <string.h> | ||
7 | #include <unistd.h> | ||
8 | #include <sys/mman.h> | ||
9 | #include <sys/stat.h> | ||
10 | |||
11 | #include <m_pd.h> | ||
12 | #include <m_fixed.h> | ||
13 | #include "g_canvas.h" | ||
14 | |||
15 | |||
16 | #define BLOCKTIME 10 | ||
17 | |||
18 | #define MAX_CHANS 4 | ||
19 | |||
20 | #include "sformat.h" | ||
21 | |||
22 | static t_class *sfwrite_class; | ||
23 | |||
24 | typedef struct _sfwrite | ||
25 | { | ||
26 | t_object x_obj; | ||
27 | t_symbol* filename; | ||
28 | int x_file; | ||
29 | |||
30 | t_int rec; | ||
31 | t_int x_channels; | ||
32 | uint32 size; | ||
33 | t_glist * x_glist; | ||
34 | t_int x_blocked; | ||
35 | t_int x_blockwarn; | ||
36 | } t_sfwrite; | ||
37 | |||
38 | |||
39 | static void sfwrite_wave_setup(t_sfwrite* x,t_wave* w) | ||
40 | { | ||
41 | |||
42 | strncpy(w->w_fileid,"RIFF",4); /* chunk id 'RIFF' */ | ||
43 | w->w_chunksize = x->size + sizeof(t_wave) -8; /* chunk size */ | ||
44 | strncpy(w->w_waveid,"WAVE",4); /* wave chunk id 'WAVE' */ | ||
45 | strncpy(w->w_fmtid,"fmt ",4); /* format chunk id 'fmt '*/ | ||
46 | w->w_fmtchunksize = 16; /* format chunk size */ | ||
47 | w->w_fmttag = 1; /* format tag, 1 for PCM */ | ||
48 | w->w_nchannels = x->x_channels; /* number of channels */ | ||
49 | w->w_samplespersec = 44100; /* sample rate in hz */ | ||
50 | w->w_navgbytespersec = 44100*x->x_channels*2; /* average bytes per second */ | ||
51 | w->w_nblockalign = 4; /* number of bytes per sample */ | ||
52 | w->w_nbitspersample = 16; /* number of bits in a sample */ | ||
53 | strncpy(w->w_datachunkid,"data",4); /* data chunk id 'data'*/ | ||
54 | w->w_datachunksize = x->size; /* length of data chunk */ | ||
55 | } | ||
56 | |||
57 | |||
58 | |||
59 | static void sfwrite_close(t_sfwrite *x) | ||
60 | { | ||
61 | if (x->x_file > 0) { | ||
62 | t_wave w; | ||
63 | sfwrite_wave_setup(x,&w); | ||
64 | lseek(x->x_file,0,SEEK_SET); | ||
65 | write(x->x_file,&w,sizeof(w)); | ||
66 | close(x->x_file); | ||
67 | } | ||
68 | x->x_file = -1; | ||
69 | } | ||
70 | |||
71 | |||
72 | static void sfwrite_open(t_sfwrite *x,t_symbol *filename) | ||
73 | { | ||
74 | char fname[MAXPDSTRING]; | ||
75 | |||
76 | if (filename == &s_) { | ||
77 | post("sfwrite: open without filename"); | ||
78 | return; | ||
79 | } | ||
80 | |||
81 | canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name, | ||
82 | fname, MAXPDSTRING); | ||
83 | |||
84 | x->x_blocked = 0; | ||
85 | x->filename = filename; | ||
86 | post("sfwrite: filename = %s",x->filename->s_name); | ||
87 | |||
88 | sfwrite_close(x); | ||
89 | |||
90 | if ((x->x_file = open(fname,O_RDWR | O_CREAT,0664)) < 0) | ||
91 | { | ||
92 | error("can't create %s",fname); | ||
93 | return; | ||
94 | } | ||
95 | |||
96 | /* skip the header */ | ||
97 | |||
98 | lseek(x->x_file,sizeof(t_wave),SEEK_SET); | ||
99 | x->size = 0; | ||
100 | |||
101 | |||
102 | } | ||
103 | |||
104 | static void sfwrite_block(t_sfwrite *x, t_floatarg f) | ||
105 | { | ||
106 | x->x_blockwarn = f; | ||
107 | } | ||
108 | |||
109 | |||
110 | static void sfwrite_float(t_sfwrite *x, t_floatarg f) | ||
111 | { | ||
112 | int t = f; | ||
113 | if (t) { | ||
114 | post("sfwrite: start", f); | ||
115 | x->rec=1; | ||
116 | } | ||
117 | else { | ||
118 | post("sfwrite: stop", f); | ||
119 | x->rec=0; | ||
120 | } | ||
121 | |||
122 | } | ||
123 | |||
124 | |||
125 | static short out[4*64]; | ||
126 | |||
127 | static t_int *sfwrite_perform(t_int *w) | ||
128 | { | ||
129 | t_sfwrite* x = (t_sfwrite*)(w[1]); | ||
130 | t_sample * in[4]; | ||
131 | int c = x->x_channels; | ||
132 | int i,num,n; | ||
133 | short* tout = out; | ||
134 | int ret; | ||
135 | int timebefore,timeafter; | ||
136 | double late; | ||
137 | |||
138 | for (i=0;i < c;i++) { | ||
139 | in[i] = (t_sample *)(w[2+i]); | ||
140 | } | ||
141 | |||
142 | n = num = (int)(w[2+c]); | ||
143 | |||
144 | /* loop */ | ||
145 | |||
146 | if (x->rec && x->x_file) { | ||
147 | |||
148 | while (n--) { | ||
149 | for (i=0;i<c;i++) { | ||
150 | *tout++ = (*(in[i])++)>>(fix1-16); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | timebefore = sys_getrealtime(); | ||
155 | if ((ret =write(x->x_file,out,sizeof(short)*num*c)) < (signed int)sizeof(short)*num*c) { | ||
156 | post("sfwrite: short write %d",ret); | ||
157 | |||
158 | } | ||
159 | timeafter = sys_getrealtime(); | ||
160 | late = timeafter - timebefore; | ||
161 | |||
162 | #if 0 | ||
163 | /* OK, we let only 10 ms block here */ | ||
164 | if (late > BLOCKTIME && x->x_blockwarn) { | ||
165 | post("sfwrite blocked %f ms",late*1000); | ||
166 | x->x_blocked++; | ||
167 | if (x->x_blocked > x->x_blockwarn) { | ||
168 | x->rec = 0; | ||
169 | post("maximum blockcount %d reached, recording stopped (set blockcount with \"block <num>\"",x->x_blockwarn); | ||
170 | } | ||
171 | } | ||
172 | #endif | ||
173 | x->size +=64*x->x_channels*sizeof(short) ; | ||
174 | } | ||
175 | |||
176 | return (w+3+c); | ||
177 | } | ||
178 | |||
179 | |||
180 | |||
181 | static void sfwrite_dsp(t_sfwrite *x, t_signal **sp) | ||
182 | { | ||
183 | switch (x->x_channels) { | ||
184 | case 1: | ||
185 | dsp_add(sfwrite_perform, 3, x, sp[0]->s_vec, | ||
186 | sp[0]->s_n); | ||
187 | break; | ||
188 | case 2: | ||
189 | dsp_add(sfwrite_perform, 4, x, sp[0]->s_vec, | ||
190 | sp[1]->s_vec, sp[0]->s_n); | ||
191 | break; | ||
192 | case 4: | ||
193 | dsp_add(sfwrite_perform, 6, x, sp[0]->s_vec, | ||
194 | sp[1]->s_vec, | ||
195 | sp[2]->s_vec, | ||
196 | sp[3]->s_vec, | ||
197 | sp[0]->s_n); | ||
198 | break; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | static void sfwrite_free(t_sfwrite* x) | ||
203 | { | ||
204 | sfwrite_close(x); | ||
205 | } | ||
206 | |||
207 | |||
208 | static void *sfwrite_new(t_floatarg chan) | ||
209 | { | ||
210 | t_sfwrite *x = (t_sfwrite *)pd_new(sfwrite_class); | ||
211 | t_int c = chan; | ||
212 | |||
213 | if (c<1 || c > MAX_CHANS) c = 1; | ||
214 | |||
215 | x->x_glist = (t_glist*) canvas_getcurrent(); | ||
216 | x->x_channels = c--; | ||
217 | x->x_file=0; | ||
218 | x->rec = 0; | ||
219 | x->size = 0; | ||
220 | x->x_blocked = 0; | ||
221 | x->x_blockwarn = 10; | ||
222 | while (c--) { | ||
223 | inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); | ||
224 | } | ||
225 | |||
226 | |||
227 | return (x); | ||
228 | } | ||
229 | |||
230 | void sfwrite_tilde_setup(void) | ||
231 | { | ||
232 | sfwrite_class = class_new(gensym("sfwrite~"), (t_newmethod)sfwrite_new, (t_method)sfwrite_free, | ||
233 | sizeof(t_sfwrite), 0,A_DEFFLOAT,0); | ||
234 | class_addmethod(sfwrite_class,nullfn,gensym("signal"), 0); | ||
235 | class_addmethod(sfwrite_class, (t_method) sfwrite_dsp, gensym("dsp"), 0); | ||
236 | class_addmethod(sfwrite_class, (t_method) sfwrite_open, gensym("open"), A_SYMBOL,A_NULL); | ||
237 | class_addmethod(sfwrite_class, (t_method) sfwrite_close, gensym("close"), 0); | ||
238 | class_addmethod(sfwrite_class, (t_method)sfwrite_block,gensym("block"),A_DEFFLOAT,0); | ||
239 | class_addfloat(sfwrite_class, sfwrite_float); | ||
240 | } | ||
241 | |||
242 | #include <unistd.h> | ||
243 | #include <fcntl.h> | ||
244 | #include <errno.h> | ||
245 | #include <stdio.h> | ||
246 | #include <string.h> | ||
247 | #include <unistd.h> | ||
248 | #include <sys/mman.h> | ||
249 | #include <sys/stat.h> | ||
250 | |||
251 | #include <m_pd.h> | ||
252 | #include <m_fixed.h> | ||
253 | #include "g_canvas.h" | ||
254 | |||
255 | |||
256 | #define BLOCKTIME 10 | ||
257 | |||
258 | #define MAX_CHANS 4 | ||
259 | |||
260 | #include "sformat.h" | ||
261 | |||
262 | static t_class *sfwrite_class; | ||
263 | |||
264 | typedef struct _sfwrite | ||
265 | { | ||
266 | t_object x_obj; | ||
267 | t_symbol* filename; | ||
268 | int x_file; | ||
269 | |||
270 | t_int rec; | ||
271 | t_int x_channels; | ||
272 | uint32 size; | ||
273 | t_glist * x_glist; | ||
274 | t_int x_blocked; | ||
275 | t_int x_blockwarn; | ||
276 | } t_sfwrite; | ||
277 | |||
278 | |||
279 | static void sfwrite_wave_setup(t_sfwrite* x,t_wave* w) | ||
280 | { | ||
281 | |||
282 | strncpy(w->w_fileid,"RIFF",4); /* chunk id 'RIFF' */ | ||
283 | w->w_chunksize = x->size + sizeof(t_wave) -8; /* chunk size */ | ||
284 | strncpy(w->w_waveid,"WAVE",4); /* wave chunk id 'WAVE' */ | ||
285 | strncpy(w->w_fmtid,"fmt ",4); /* format chunk id 'fmt '*/ | ||
286 | w->w_fmtchunksize = 16; /* format chunk size */ | ||
287 | w->w_fmttag = 1; /* format tag, 1 for PCM */ | ||
288 | w->w_nchannels = x->x_channels; /* number of channels */ | ||
289 | w->w_samplespersec = 44100; /* sample rate in hz */ | ||
290 | w->w_navgbytespersec = 44100*x->x_channels*2; /* average bytes per second */ | ||
291 | w->w_nblockalign = 4; /* number of bytes per sample */ | ||
292 | w->w_nbitspersample = 16; /* number of bits in a sample */ | ||
293 | strncpy(w->w_datachunkid,"data",4); /* data chunk id 'data'*/ | ||
294 | w->w_datachunksize = x->size; /* length of data chunk */ | ||
295 | } | ||
296 | |||
297 | |||
298 | |||
299 | static void sfwrite_close(t_sfwrite *x) | ||
300 | { | ||
301 | if (x->x_file > 0) { | ||
302 | t_wave w; | ||
303 | sfwrite_wave_setup(x,&w); | ||
304 | lseek(x->x_file,0,SEEK_SET); | ||
305 | write(x->x_file,&w,sizeof(w)); | ||
306 | close(x->x_file); | ||
307 | } | ||
308 | x->x_file = -1; | ||
309 | } | ||
310 | |||
311 | |||
312 | static void sfwrite_open(t_sfwrite *x,t_symbol *filename) | ||
313 | { | ||
314 | char fname[MAXPDSTRING]; | ||
315 | |||
316 | if (filename == &s_) { | ||
317 | post("sfwrite: open without filename"); | ||
318 | return; | ||
319 | } | ||
320 | |||
321 | canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name, | ||
322 | fname, MAXPDSTRING); | ||
323 | |||
324 | x->x_blocked = 0; | ||
325 | x->filename = filename; | ||
326 | post("sfwrite: filename = %s",x->filename->s_name); | ||
327 | |||
328 | sfwrite_close(x); | ||
329 | |||
330 | if ((x->x_file = open(fname,O_RDWR | O_CREAT,0664)) < 0) | ||
331 | { | ||
332 | error("can't create %s",fname); | ||
333 | return; | ||
334 | } | ||
335 | |||
336 | /* skip the header */ | ||
337 | |||
338 | lseek(x->x_file,sizeof(t_wave),SEEK_SET); | ||
339 | x->size = 0; | ||
340 | |||
341 | |||
342 | } | ||
343 | |||
344 | static void sfwrite_block(t_sfwrite *x, t_floatarg f) | ||
345 | { | ||
346 | x->x_blockwarn = f; | ||
347 | } | ||
348 | |||
349 | |||
350 | static void sfwrite_float(t_sfwrite *x, t_floatarg f) | ||
351 | { | ||
352 | int t = f; | ||
353 | if (t) { | ||
354 | post("sfwrite: start", f); | ||
355 | x->rec=1; | ||
356 | } | ||
357 | else { | ||
358 | post("sfwrite: stop", f); | ||
359 | x->rec=0; | ||
360 | } | ||
361 | |||
362 | } | ||
363 | |||
364 | |||
365 | static short out[4*64]; | ||
366 | |||
367 | static t_int *sfwrite_perform(t_int *w) | ||
368 | { | ||
369 | t_sfwrite* x = (t_sfwrite*)(w[1]); | ||
370 | t_sample * in[4]; | ||
371 | int c = x->x_channels; | ||
372 | int i,num,n; | ||
373 | short* tout = out; | ||
374 | int ret; | ||
375 | int timebefore,timeafter; | ||
376 | double late; | ||
377 | |||
378 | for (i=0;i < c;i++) { | ||
379 | in[i] = (t_sample *)(w[2+i]); | ||
380 | } | ||
381 | |||
382 | n = num = (int)(w[2+c]); | ||
383 | |||
384 | /* loop */ | ||
385 | |||
386 | if (x->rec && x->x_file) { | ||
387 | |||
388 | while (n--) { | ||
389 | for (i=0;i<c;i++) { | ||
390 | *tout++ = (*(in[i])++)>>(fix1-16); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | timebefore = sys_getrealtime(); | ||
395 | if ((ret =write(x->x_file,out,sizeof(short)*num*c)) < (signed int)sizeof(short)*num*c) { | ||
396 | post("sfwrite: short write %d",ret); | ||
397 | |||
398 | } | ||
399 | timeafter = sys_getrealtime(); | ||
400 | late = timeafter - timebefore; | ||
401 | |||
402 | #if 0 | ||
403 | /* OK, we let only 10 ms block here */ | ||
404 | if (late > BLOCKTIME && x->x_blockwarn) { | ||
405 | post("sfwrite blocked %f ms",late*1000); | ||
406 | x->x_blocked++; | ||
407 | if (x->x_blocked > x->x_blockwarn) { | ||
408 | x->rec = 0; | ||
409 | post("maximum blockcount %d reached, recording stopped (set blockcount with \"block <num>\"",x->x_blockwarn); | ||
410 | } | ||
411 | } | ||
412 | #endif | ||
413 | x->size +=64*x->x_channels*sizeof(short) ; | ||
414 | } | ||
415 | |||
416 | return (w+3+c); | ||
417 | } | ||
418 | |||
419 | |||
420 | |||
421 | static void sfwrite_dsp(t_sfwrite *x, t_signal **sp) | ||
422 | { | ||
423 | switch (x->x_channels) { | ||
424 | case 1: | ||
425 | dsp_add(sfwrite_perform, 3, x, sp[0]->s_vec, | ||
426 | sp[0]->s_n); | ||
427 | break; | ||
428 | case 2: | ||
429 | dsp_add(sfwrite_perform, 4, x, sp[0]->s_vec, | ||
430 | sp[1]->s_vec, sp[0]->s_n); | ||
431 | break; | ||
432 | case 4: | ||
433 | dsp_add(sfwrite_perform, 6, x, sp[0]->s_vec, | ||
434 | sp[1]->s_vec, | ||
435 | sp[2]->s_vec, | ||
436 | sp[3]->s_vec, | ||
437 | sp[0]->s_n); | ||
438 | break; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | static void sfwrite_free(t_sfwrite* x) | ||
443 | { | ||
444 | sfwrite_close(x); | ||
445 | } | ||
446 | |||
447 | |||
448 | static void *sfwrite_new(t_floatarg chan) | ||
449 | { | ||
450 | t_sfwrite *x = (t_sfwrite *)pd_new(sfwrite_class); | ||
451 | t_int c = chan; | ||
452 | |||
453 | if (c<1 || c > MAX_CHANS) c = 1; | ||
454 | |||
455 | x->x_glist = (t_glist*) canvas_getcurrent(); | ||
456 | x->x_channels = c--; | ||
457 | x->x_file=0; | ||
458 | x->rec = 0; | ||
459 | x->size = 0; | ||
460 | x->x_blocked = 0; | ||
461 | x->x_blockwarn = 10; | ||
462 | while (c--) { | ||
463 | inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); | ||
464 | } | ||
465 | |||
466 | |||
467 | return (x); | ||
468 | } | ||
469 | |||
470 | void sfwrite_tilde_setup(void) | ||
471 | { | ||
472 | sfwrite_class = class_new(gensym("sfwrite~"), (t_newmethod)sfwrite_new, (t_method)sfwrite_free, | ||
473 | sizeof(t_sfwrite), 0,A_DEFFLOAT,0); | ||
474 | class_addmethod(sfwrite_class,nullfn,gensym("signal"), 0); | ||
475 | class_addmethod(sfwrite_class, (t_method) sfwrite_dsp, gensym("dsp"), 0); | ||
476 | class_addmethod(sfwrite_class, (t_method) sfwrite_open, gensym("open"), A_SYMBOL,A_NULL); | ||
477 | class_addmethod(sfwrite_class, (t_method) sfwrite_close, gensym("close"), 0); | ||
478 | class_addmethod(sfwrite_class, (t_method)sfwrite_block,gensym("block"),A_DEFFLOAT,0); | ||
479 | class_addfloat(sfwrite_class, sfwrite_float); | ||
480 | } | ||