Hi all, needing sfread~ with a signal inlet for varispeed and 4 point interpolation I reworked Günter Geigers object and renamed it to sfread4~ (hope you don't mind, Günter and thanks for the original code!).
I didn't test it for negative speeds (it might get screwed up using it), but it seems to work fine for positive speeds. I found a couple of weirdnesses in the original code which seemed to make it sound a little distorted for speeds != integer multiples. Therefore I reorganized the perform routine and datastructs a little. It seems to be fixed now, but use at your own risk. The varispeed signal inlet is the leftmost inlet (therefore the third inlet doesn't exist anymore). Note that sfread4~ will not produce any sound if the inlet isn't connected to anything as this means a speed value of 0. To make it play back at original speed, connect a [sig~ 1] to the leftmost inlet. I also attach the compiled binary for linux i386. -- Orm
/* (C) Guenter Geiger <[EMAIL PROTECTED]> */
/* */
/* changed 10 03 2007 by Orm Finnendahl */
/* Changes:
/* - added varispeed as (left) signal inlet */
/* - added 4 point interpolation and renamed sfread4~ */
#include <m_pd.h>
#include <stdio.h>
#include <string.h>
#ifndef NT
#include <unistd.h>
#include <sys/mman.h>
#else
#include <io.h>
#endif
#include <fcntl.h>
#include <sys/stat.h>
/* ------------------------ sfread4~ ----------------------------- */
#ifdef NT
#define BINREADMODE "rb"
#else
#define BINREADMODE "r"
#endif
static t_class *sfread4_class;
typedef struct _sfread4
{
t_object x_obj;
void* x_mapaddr;
int x_fd;
t_int x_play;
t_int x_channels;
t_int x_size;
t_int x_loop;
t_float x_offset;
t_float x_skip;
t_float x_debug;
float x_frac;
float x_inc;
t_canvas * x_canvas;
t_outlet *x_bangout;
} t_sfread4;
void sfread4_open(t_sfread4 *x,t_symbol *filename)
{
struct stat fstate;
char fname[MAXPDSTRING];
if (filename == &s_) {
post("sfread4: open without filename");
return;
}
canvas_makefilename(x->x_canvas, filename->s_name,
fname, MAXPDSTRING);
/* close the old file */
if (x->x_mapaddr) munmap(x->x_mapaddr,x->x_size);
if (x->x_fd >= 0) close(x->x_fd);
if ((x->x_fd = open(fname,O_RDONLY)) < 0)
{
error("can't open %s",fname);
x->x_play = 0;
x->x_mapaddr = NULL;
return;
}
/* get the size */
fstat(x->x_fd,&fstate);
x->x_size = fstate.st_size;
/* map the file into memory */
if (!(x->x_mapaddr = mmap(NULL,x->x_size,PROT_READ,MAP_PRIVATE,x->x_fd,0)))
{
error("can't mmap %s",fname);
return;
}
}
#define MAX_CHANS 4
static t_int *sfread4_perform(t_int *w)
{
t_sfread4* x = (t_sfread4*)(w[1]);
short* buf = x->x_mapaddr;
t_float *in1 = (t_float *)(w[2]);
x->x_debug=*in1;
int c = x->x_channels;
t_float offset = x->x_offset*c;
t_float speed = *in1++;
float frac = x->x_frac;
float inc = x->x_inc;
long aoff = x->x_offset;
/* post("startfrac-inc: %8.4f %8.4f", frac, inc); */
int i,n;
int end = x->x_size/sizeof(short) - 2;
t_float* out[MAX_CHANS];
for (i=0;i<c;i++)
out[i] = (t_float *)(w[3+i]);
n = (int)(w[3+c]);
/* loop */
if (offset > end)
offset = end;
if (offset + n*c*speed > end) { // playing forward end
if (!x->x_loop) {
x->x_play=0;
offset = x->x_skip*c;
}
}
if (offset + n*c*speed < 0) { // playing backwards end
if (!x->x_loop) {
x->x_play=0;
offset = end;
}
}
if (x->x_play && x->x_mapaddr) {
if (1) { /* different speed */
/* post ("start: aoff=%d", aoff); */
while (n--) {
for (i=0;i<c;i++) {
if (aoff <= c) {
*out[i]++ = (t_sample) *(buf+i)*3.052689e-05;
}
else
{
float as = *(buf+aoff+i - c);
float bs = *(buf+aoff+i);
float cs = *(buf+aoff+i+c);
float ds = *(buf+aoff+i+c+c);
float cminusb;
float tmp;
cminusb = cs-bs;
tmp = bs + frac * (
cminusb - 0.1666667f * (1.-frac) * (
(ds - as - 3.0f * cminusb) * frac +
(ds + 2.0f*as - 3.0f*bs)
)
);
*out[i]++ = tmp * 3.052689e-05;
}
}
inc = frac + speed;
aoff+= ((int) inc) * c;
frac = inc - (int)inc;
speed = *in1++;
if (aoff > end) {
if (x->x_loop) aoff = x->x_skip;
else break;
}
if (aoff < 0) {
if (x->x_loop) aoff = end;
else break;
}
}
/* Fill with zero in case of end */
n++;
while (n--)
for (i=0;i<c;i++)
*out[i]++ = 0;
offset = aoff;
}
}
else {
while (n--) {
for (i=0;i<c;i++)
*out[i]++ = 0.;
}
}
x->x_offset = (float) aoff; /* this should always be integer !! */
x->x_frac = frac;
x->x_inc = inc;
return (w+c+4);
}
static void sfread4_float(t_sfread4 *x, t_floatarg f)
{
int t = f;
if (t && x->x_mapaddr) {
x->x_play=1;
}
else {
x->x_play=0;
}
}
static void sfread4_loop(t_sfread4 *x, t_floatarg f)
{
x->x_loop = f;
}
static void sfread4_size(t_sfread4* x)
{
t_atom a;
SETFLOAT(&a,x->x_size*0.5/x->x_channels);
outlet_list(x->x_bangout, gensym("size"),1,&a);
}
static void sfread4_state(t_sfread4* x)
{
t_atom a;
SETFLOAT(&a,x->x_play);
outlet_list(x->x_bangout, gensym("state"),1,&a);
}
static void sfread4_bang(t_sfread4* x)
{
x->x_offset = x->x_skip*x->x_channels;
sfread4_float(x,1.0);
}
static void sfread4_dsp(t_sfread4 *x, t_signal **sp)
{
/* post("sfread4: dsp"); */
switch (x->x_channels) {
case 1:
dsp_add(sfread4_perform, 4, x, sp[0]->s_vec,
sp[1]->s_vec, sp[0]->s_n);
break;
case 2:
dsp_add(sfread4_perform, 5, x, sp[0]->s_vec,
sp[1]->s_vec,sp[2]->s_vec, sp[0]->s_n);
break;
case 4:
dsp_add(sfread4_perform, 6, x, sp[0]->s_vec,
sp[1]->s_vec,sp[2]->s_vec,
sp[3]->s_vec,sp[4]->s_vec,
sp[0]->s_n);
break;
}
}
static void *sfread4_new(t_floatarg chan,t_floatarg skip)
{
t_sfread4 *x = (t_sfread4 *)pd_new(sfread4_class);
t_int c = chan;
x->x_canvas = canvas_getcurrent();
if (c<1 || c > MAX_CHANS) c = 1;
floatinlet_new(&x->x_obj, &x->x_offset);
x->x_fd = -1;
x->x_mapaddr = NULL;
x->x_size = 0;
x->x_frac = 0;
x->x_inc = 1;
x->x_loop = 0;
x->x_channels = c;
x->x_mapaddr=NULL;
x->x_offset = skip;
x->x_skip = skip;
x->x_play = 0;
while (c--) {
outlet_new(&x->x_obj, gensym("signal"));
}
x->x_bangout = outlet_new(&x->x_obj, &s_float);
/* post("sfread4: x_channels = %d, x_speed = %f",x->x_channels,x->x_speed);*/
return (x);
}
void sfread4_tilde_setup(void)
{
/* sfread4 */
sfread4_class = class_new(gensym("sfread4~"), (t_newmethod)sfread4_new, 0,
sizeof(t_sfread4), 0,A_DEFFLOAT,A_DEFFLOAT,0);
class_addmethod(sfread4_class, nullfn, gensym("signal"), 0);
class_addmethod(sfread4_class, (t_method) sfread4_dsp, gensym("dsp"), 0);
class_addmethod(sfread4_class, (t_method) sfread4_open, gensym("open"), A_SYMBOL,A_NULL);
class_addmethod(sfread4_class, (t_method) sfread4_size, gensym("size"), 0);
class_addmethod(sfread4_class, (t_method) sfread4_state, gensym("state"), 0);
class_addfloat(sfread4_class, sfread4_float);
class_addbang(sfread4_class,sfread4_bang);
class_addmethod(sfread4_class,(t_method)sfread4_loop,gensym("loop"),A_FLOAT,A_NULL);
}
sfread4~.pd_linux
Description: Binary data
_______________________________________________ [email protected] mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
