1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
/* Copyright (c) 2002-2003 krzYszcz and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
/* When bit-shifting 32-bit values, gcc (intel?) bashes the second operand
modulo 32. In msp x << 32 gives 0, x >> 32 gives a propagated sign bit
(as expected). Mimicking that is clumsy. LATER consider making the calcs
more generic (use long long values?) */
#include "m_pd.h"
#include "common/loud.h"
#include "sickle/sic.h"
#ifdef KRZYSZCZ
//#define BITSHIFT_DEBUG
#endif
typedef struct _bitshift
{
t_sic x_sic;
int x_convert1;
int x_lshift;
int x_rshift;
int x_lover;
} t_bitshift;
static t_class *bitshift_class;
static t_int *bitshift_perform(t_int *w)
{
t_bitshift *x = (t_bitshift *)(w[1]);
int nblock = (int)(w[2]);
t_float *in = (t_float *)(w[3]);
t_float *out = (t_float *)(w[4]);
/* LATER think about performance */
if (x->x_lshift)
{
unsigned int shift = x->x_lshift;
if (x->x_convert1) while (nblock--)
{
/* CHECKED */
t_int i = ((t_int)*in++ << shift);
*out++ = (t_float)i;
}
else while (nblock--)
{
/* CHECKED */
t_int i = (*(t_int *)(t_float *)in++ << shift);
*out++ = *(t_float *)&i;
}
}
else if (x->x_rshift)
{
unsigned int shift = x->x_rshift;
if (x->x_convert1) while (nblock--)
{
/* CHECKME */
t_int i = ((t_int)*in++ >> shift);
*out++ = (t_float)i;
}
else while (nblock--)
{
/* CHECKME */
t_int i = (*(t_int *)(t_float *)in++ >> shift);
*out++ = *(t_float *)&i;
}
}
else if (x->x_lover)
while (nblock--) *out++ = 0; /* CHECKED both modes */
else
while (nblock--) *out++ = *in++; /* CHECKED both modes */
return (w + 5);
}
static void bitshift_dsp(t_bitshift *x, t_signal **sp)
{
dsp_add(bitshift_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
}
static void bitshift_mode(t_bitshift *x, t_floatarg f)
{
int i = (int)f;
x->x_convert1 = (i > 0); /* CHECKED */
}
static void bitshift_shift(t_bitshift *x, t_floatarg f)
{
int i = (int)f;
int nbits = sizeof(t_int) * 8;
x->x_lshift = x->x_rshift = 0;
x->x_lover = 0;
if (i > 0)
{
#ifdef BITSHIFT_DEBUG
loudbug_post("%.8x << %d == %.8x, %.8x << %d == %.8x",
1, i, 1 << i, -1, i, -1 << i);
#endif
if (i < nbits)
x->x_lshift = i;
else
x->x_lover = 1;
}
else if (i < 0)
{
#ifdef BITSHIFT_DEBUG
loudbug_post("%.8x >> %d == %.8x, %.8x >> %d == %.8x",
0x7fffffff, -i, 0x7fffffff >> -i, -1, -i, -1 >> -i);
#endif
x->x_rshift = (i <= -nbits ? nbits - 1 : -i);
}
}
static void *bitshift_new(t_floatarg f1, t_floatarg f2)
{
t_bitshift *x = (t_bitshift *)pd_new(bitshift_class);
outlet_new((t_object *)x, &s_signal);
bitshift_shift(x, f1);
bitshift_mode(x, f2);
return (x);
}
void bitshift_tilde_setup(void)
{
bitshift_class = class_new(gensym("bitshift~"),
(t_newmethod)bitshift_new, 0,
sizeof(t_bitshift), 0,
A_DEFFLOAT, A_DEFFLOAT, 0);
sic_setup(bitshift_class, bitshift_dsp, SIC_FLOATTOSIGNAL);
class_addmethod(bitshift_class, (t_method)bitshift_mode,
gensym("mode"), A_FLOAT, 0);
class_addmethod(bitshift_class, (t_method)bitshift_shift,
gensym("shift"), A_FLOAT, 0);
}
|