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);
}
|