1 /*
2 * Schism Tracker - a cross-platform Impulse Tracker clone
3 * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4 * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5 * copyright (c) 2009 Storlek & Mrs. Brisby
6 * copyright (c) 2010-2012 Storlek
7 * URL: http://schismtracker.org/
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include <string.h>
25
26 #include "sndfile.h"
27
28 #include "cmixer.h"
29
30 #define OFSDECAYSHIFT 8
31 #define OFSDECAYMASK 0xFF
32
33
init_mix_buffer(int * buffer,unsigned int samples)34 void init_mix_buffer(int *buffer, unsigned int samples)
35 {
36 memset(buffer, 0, samples * sizeof(int));
37 }
38
39
stereo_fill(int * buffer,unsigned int samples,int * profs,int * plofs)40 void stereo_fill(int *buffer, unsigned int samples, int* profs, int *plofs)
41 {
42 int rofs = *profs;
43 int lofs = *plofs;
44
45 if (!rofs && !lofs) {
46 init_mix_buffer(buffer, samples * 2);
47 return;
48 }
49
50 for (unsigned int i = 0; i < samples; i++) {
51 int x_r = (rofs + (((-rofs) >> 31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
52 int x_l = (lofs + (((-lofs) >> 31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
53
54 rofs -= x_r;
55 lofs -= x_l;
56 buffer[i * 2 ] = x_r;
57 buffer[i * 2 + 1] = x_l;
58 }
59
60 *profs = rofs;
61 *plofs = lofs;
62 }
63
64
end_channel_ofs(song_voice_t * channel,int * buffer,unsigned int samples)65 void end_channel_ofs(song_voice_t *channel, int *buffer, unsigned int samples)
66 {
67 int rofs = channel->rofs;
68 int lofs = channel->lofs;
69
70 if (!rofs && !lofs)
71 return;
72
73 for (unsigned int i = 0; i < samples; i++) {
74 int x_r = (rofs + (((-rofs) >> 31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
75 int x_l = (lofs + (((-lofs) >> 31) & OFSDECAYMASK)) >> OFSDECAYSHIFT;
76
77 rofs -= x_r;
78 lofs -= x_l;
79 buffer[i * 2] += x_r;
80 buffer[i * 2 + 1] += x_l;
81 }
82
83 channel->rofs = rofs;
84 channel->lofs = lofs;
85 }
86
87
mono_from_stereo(int * mix_buf,unsigned int samples)88 void mono_from_stereo(int *mix_buf, unsigned int samples)
89 {
90 for (unsigned int j, i = 0; i < samples; i++) {
91 j = i << 1;
92 mix_buf[i] = (mix_buf[j] + mix_buf[j + 1]) >> 1;
93 }
94 }
95
96
97 static const float f2ic = (float) (1 << 28);
98 static const float i2fc = (float) (1.0 / (1 << 28));
99
100
stereo_mix_to_float(const int * src,float * out1,float * out2,unsigned int count)101 void stereo_mix_to_float(const int *src, float *out1, float *out2, unsigned int count)
102 {
103 for (unsigned int i = 0; i < count; i++) {
104 *out1++ = *src * i2fc;
105 src++;
106
107 *out2++ = *src * i2fc;
108 src++;
109 }
110 }
111
112
float_to_stereo_mix(const float * in1,const float * in2,int * out,unsigned int count)113 void float_to_stereo_mix(const float *in1, const float *in2, int *out, unsigned int count)
114 {
115 for (unsigned int i = 0; i < count; i++) {
116 *out++ = (int) (*in1 * f2ic);
117 *out++ = (int) (*in2 * f2ic);
118 in1++;
119 in2++;
120 }
121 }
122
123
mono_mix_to_float(const int * src,float * out,unsigned int count)124 void mono_mix_to_float(const int *src, float *out, unsigned int count)
125 {
126 for (unsigned int i = 0; i < count; i++) {
127 *out++ = *src * i2fc;
128 src++;
129 }
130 }
131
132
float_to_mono_mix(const float * in,int * out,unsigned int count)133 void float_to_mono_mix(const float *in, int *out, unsigned int count)
134 {
135 for (unsigned int i = 0; i < count; i++) {
136 *out++ = (int) (*in * f2ic);
137 in++;
138 }
139 }
140
141
142 // ----------------------------------------------------------------------------
143 // Clip and convert functions
144 // ----------------------------------------------------------------------------
145 // XXX mins/max were int[2]
146 //
147 // The original C version was written by Rani Assaf <rani@magic.metawire.com>
148
149
150 // Clip and convert to 8 bit. mins and maxs returned in 27bits: [MIXING_CLIPMIN..MIXING_CLIPMAX]. mins[0] left, mins[1] right.
clip_32_to_8(void * ptr,int * buffer,unsigned int samples,int * mins,int * maxs)151 unsigned int clip_32_to_8(void *ptr, int *buffer, unsigned int samples, int *mins, int *maxs)
152 {
153 unsigned char *p = (unsigned char *) ptr;
154
155 for (unsigned int i = 0; i < samples; i++) {
156 int n = buffer[i];
157
158 if (n < MIXING_CLIPMIN)
159 n = MIXING_CLIPMIN;
160 else if (n > MIXING_CLIPMAX)
161 n = MIXING_CLIPMAX;
162
163 if (n < mins[i & 1])
164 mins[i & 1] = n;
165 else if (n > maxs[i & 1])
166 maxs[i & 1] = n;
167
168 // 8-bit unsigned
169 p[i] = (n >> (24 - MIXING_ATTENUATION)) ^ 0x80;
170 }
171
172 return samples;
173 }
174
175
176 // Clip and convert to 16 bit. mins and maxs returned in 27bits: [MIXING_CLIPMIN..MIXING_CLIPMAX]. mins[0] left, mins[1] right.
clip_32_to_16(void * ptr,int * buffer,unsigned int samples,int * mins,int * maxs)177 unsigned int clip_32_to_16(void *ptr, int *buffer, unsigned int samples, int *mins, int *maxs)
178 {
179 signed short *p = (signed short *) ptr;
180
181 for (unsigned int i = 0; i < samples; i++) {
182 int n = buffer[i];
183
184 if (n < MIXING_CLIPMIN)
185 n = MIXING_CLIPMIN;
186 else if (n > MIXING_CLIPMAX)
187 n = MIXING_CLIPMAX;
188
189 if (n < mins[i & 1])
190 mins[i & 1] = n;
191 else if (n > maxs[i & 1])
192 maxs[i & 1] = n;
193
194 // 16-bit signed
195 p[i] = n >> (16 - MIXING_ATTENUATION);
196 }
197
198 return samples * 2;
199 }
200
201
202 // Clip and convert to 24 bit. mins and maxs returned in 27bits: [MIXING_CLIPMIN..MIXING_CLIPMAX]. mins[0] left, mins[1] right.
203 // Note, this is 24bit, not 24-in-32bits. The former is used in .wav. The latter is used in audio IO
clip_32_to_24(void * ptr,int * buffer,unsigned int samples,int * mins,int * maxs)204 unsigned int clip_32_to_24(void *ptr, int *buffer, unsigned int samples, int *mins, int *maxs)
205 {
206 /* the inventor of 24bit anything should be shot */
207 unsigned char *p = (unsigned char *) ptr;
208
209 for (unsigned int i = 0; i < samples; i++) {
210 int n = buffer[i];
211
212 if (n < MIXING_CLIPMIN)
213 n = MIXING_CLIPMIN;
214 else if (n > MIXING_CLIPMAX)
215 n = MIXING_CLIPMAX;
216
217 if (n < mins[i & 1])
218 mins[i & 1] = n;
219 else if (n > maxs[i & 1])
220 maxs[i & 1] = n;
221
222 // 24-bit signed
223 n = n >> (8 - MIXING_ATTENUATION);
224
225 /* err, assume same endian */
226 memcpy(p, &n, 3);
227 p += 3;
228 }
229
230 return samples * 3;
231 }
232
233
234 // Clip and convert to 32 bit(int). mins and maxs returned in 27bits: [MIXING_CLIPMIN..MIXING_CLIPMAX]. mins[0] left, mins[1] right.
clip_32_to_32(void * ptr,int * buffer,unsigned int samples,int * mins,int * maxs)235 unsigned int clip_32_to_32(void *ptr, int *buffer, unsigned int samples, int *mins, int *maxs)
236 {
237 signed int *p = (signed int *) ptr;
238
239 for (unsigned int i = 0; i < samples; i++) {
240 int n = buffer[i];
241
242 if (n < MIXING_CLIPMIN)
243 n = MIXING_CLIPMIN;
244 else if (n > MIXING_CLIPMAX)
245 n = MIXING_CLIPMAX;
246
247 if (n < mins[i & 1])
248 mins[i & 1] = n;
249 else if (n > maxs[i & 1])
250 maxs[i & 1] = n;
251
252 // 32-bit signed
253 p[i] = (n << MIXING_ATTENUATION);
254 }
255
256 return samples * 4;
257 }
258
259