19 /* ------------------------ sfread~ ----------------------------- */
23 static t_class
*sfread_class
;
26 typedef struct _sfread
46 void sfread_open(t_sfread
*x
,t_symbol
*filename
)
51 char fname
[MAXPDSTRING
];
53 if (filename
== &s_
) {
54 post("sfread: open without filename");
58 canvas_makefilename(glist_getcanvas(x
->x_glist
), filename
->s_name
,
62 /* close the old file */
65 if (x
->x_mapaddr
) freebytes(x
->x_mapaddr
, x
->x_size
);
67 if (x
->x_mapaddr
) munmap(x
->x_mapaddr
,x
->x_size
);
69 if (x
->x_fd
>= 0) close(x
->x_fd
);
71 if ((x
->x_fd
= open(fname
,O_RDONLY
)) < 0)
73 error("can't open %s",fname
);
81 x
->x_size
= rb
->filesize(x
->x_fd
);
83 fstat(x
->x_fd
,&fstate
);
84 x
->x_size
= fstate
.st_size
;
87 /* map the file into memory */
90 x
->x_mapaddr
= getbytes(x
->x_size
);
93 error("can't mmap %s",fname
);
96 int r
= read(x
->x_fd
, x
->x_mapaddr
, x
->x_size
);
99 error("can't mmap %s",fname
);
103 if (!(x
->x_mapaddr
= mmap(NULL
,x
->x_size
,PROT_READ
,MAP_PRIVATE
,x
->x_fd
,0)))
105 error("can't mmap %s",fname
);
113 static t_int
*sfread_perform(t_int
*w
)
115 t_sfread
* x
= (t_sfread
*)(w
[1]);
116 short* buf
= x
->x_mapaddr
;
118 int c
= x
->x_channels
;
119 t_time pos
= x
->x_pos
;
120 t_sample speed
= x
->x_speed
;
121 t_time end
= itofix(x
->x_size
/sizeof(short)/c
);
123 t_sample
* out
[MAX_CHANS
];
126 out
[i
] = (t_sample
*)(w
[3+i
]);
134 if (pos
+ n
*speed
>= end
) { // playing forward end
142 if (pos
+ n
*speed
<= 0) { // playing backwards end
149 if (x
->x_play
&& x
->x_mapaddr
) {
150 t_time aoff
= fixtoi(pos
)*c
;
152 long frac
= (long long)((1<<fix1
)-1)&pos
;
155 t_sample bs
= *(buf
+aoff
+i
)<<(fix1
-16);
156 t_sample cs
= *(buf
+aoff
+i
+1)<<(fix1
-16);
157 *out
[i
]++ = bs
+ mult((cs
- bs
),frac
);
161 aoff
= fixtoi(pos
)*c
;
163 if (x
->x_loop
) pos
= x
->x_skip
;
166 if (aoff
< x
->x_skip
) {
167 if (x
->x_loop
) pos
= end
;
171 /* Fill with zero in case of end */
189 static void sfread_float(t_sfread
*x
, t_floatarg f
)
192 if (t
&& x
->x_mapaddr
) {
201 static void sfread_loop(t_sfread
*x
, t_floatarg f
)
208 static void sfread_size(t_sfread
* x
)
212 SETFLOAT(&a
,x
->x_size
*0.5/x
->x_channels
);
213 outlet_list(x
->x_bangout
, gensym("size"),1,&a
);
216 static void sfread_state(t_sfread
* x
)
220 SETFLOAT(&a
,x
->x_play
);
221 outlet_list(x
->x_bangout
, gensym("state"),1,&a
);
227 static void sfread_bang(t_sfread
* x
)
229 x
->x_pos
= x
->x_skip
;
234 static void sfread_dsp(t_sfread
*x
, t_signal
**sp
)
236 /* post("sfread: dsp"); */
237 switch (x
->x_channels
) {
239 dsp_add(sfread_perform
, 4, x
, sp
[0]->s_vec
,
240 sp
[1]->s_vec
, sp
[0]->s_n
);
243 dsp_add(sfread_perform
, 5, x
, sp
[0]->s_vec
,
244 sp
[1]->s_vec
,sp
[2]->s_vec
, sp
[0]->s_n
);
247 dsp_add(sfread_perform
, 6, x
, sp
[0]->s_vec
,
248 sp
[1]->s_vec
,sp
[2]->s_vec
,
249 sp
[3]->s_vec
,sp
[4]->s_vec
,
256 static void sfread_speed(t_sfread
* x
, t_floatarg f
)
258 x
->x_speed
= ftofix(f
);
261 static void sfread_offset(t_sfread
* x
, t_floatarg f
)
266 static void *sfread_new(t_floatarg chan
,t_floatarg skip
)
271 t_sfread
*x
= (t_sfread
*)pd_new(sfread_class
);
274 x
->x_glist
= (t_glist
*) canvas_getcurrent();
276 if (c
<1 || c
> MAX_CHANS
) c
= 1;
277 inlet_new(&x
->x_obj
, &x
->x_obj
.ob_pd
, &s_float
, gensym("ft1"));
278 inlet_new(&x
->x_obj
, &x
->x_obj
.ob_pd
, &s_float
, gensym("ft2"));
290 x
->x_speed
= ftofix(1.0);
294 outlet_new(&x
->x_obj
, gensym("signal"));
297 x
->x_bangout
= outlet_new(&x
->x_obj
, &s_float
);
302 void sfread_tilde_setup(void)
306 sfread_class
= class_new(gensym("sfread~"), (t_newmethod
)sfread_new
, 0,
307 sizeof(t_sfread
), 0,A_DEFFLOAT
,A_DEFFLOAT
,0);
308 class_addmethod(sfread_class
, nullfn
, gensym("signal"), 0);
309 class_addmethod(sfread_class
, (t_method
) sfread_dsp
, gensym("dsp"), 0);
310 class_addmethod(sfread_class
, (t_method
) sfread_open
, gensym("open"), A_SYMBOL
,A_NULL
);
311 class_addmethod(sfread_class
, (t_method
) sfread_size
, gensym("size"), 0);
312 class_addmethod(sfread_class
, (t_method
) sfread_offset
, gensym("ft1"), A_FLOAT
, A_NULL
);
313 class_addmethod(sfread_class
, (t_method
) sfread_speed
, gensym("ft2"), A_FLOAT
, A_NULL
);
314 class_addmethod(sfread_class
, (t_method
) sfread_state
, gensym("state"), 0);
315 class_addfloat(sfread_class
, sfread_float
);
316 class_addbang(sfread_class
,sfread_bang
);
317 class_addmethod(sfread_class
,(t_method
)sfread_loop
,gensym("loop"),A_FLOAT
,A_NULL
);