summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/intern/sfwrite~.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/intern/sfwrite~.c')
-rw-r--r--apps/plugins/pdbox/PDa/intern/sfwrite~.c480
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
22static t_class *sfwrite_class;
23
24typedef 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
39static 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
59static 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
72static 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
104static void sfwrite_block(t_sfwrite *x, t_floatarg f)
105{
106 x->x_blockwarn = f;
107}
108
109
110static 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
125static short out[4*64];
126
127static 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
181static 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
202static void sfwrite_free(t_sfwrite* x)
203{
204 sfwrite_close(x);
205}
206
207
208static 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
230void 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
262static t_class *sfwrite_class;
263
264typedef 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
279static 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
299static 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
312static 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
344static void sfwrite_block(t_sfwrite *x, t_floatarg f)
345{
346 x->x_blockwarn = f;
347}
348
349
350static 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
365static short out[4*64];
366
367static 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
421static 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
442static void sfwrite_free(t_sfwrite* x)
443{
444 sfwrite_close(x);
445}
446
447
448static 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
470void 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}