1 /*
2  * Copyright (C) 2002 - David W. Durham
3  *
4  * This file is part of ReZound, an audio editing application.
5  *
6  * ReZound is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published
8  * by the Free Software Foundation; either version 2 of the License,
9  * or (at your option) any later version.
10  *
11  * ReZound is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
19  */
20 
21 #ifndef __CSound_defs_H__
22 #define __CSound_defs_H__
23 
24 #include "../../config/common.h"
25 
26 class CSound;
27 
28 #include <stdint.h>
29 
30 	// ??? rename to something more specific to audio, PCM, or rezound
31 	// create a MAX_LENGTH that I check for in the methods... I've made it, but I don't think I use it yet much
32 	// right now I made this lower only because I haven't made the frontend dialogs not show unnecessary check boxes and such...so the dialogs were huge even when many channels were not in use
33 	// if this is changed, also consider the array size of gJACKOutputPortNames and gJACKInputPortNames in settings.h/cpp (although it should be big enough)
34 #define MAX_CHANNELS 8
35 
36 
37 
38 /*
39  * audio size specifications
40  *
41  *    sample_pos_t should always be unsigned since I use this assumption and never check for < 0 in the code
42  *    sample_fpos_t should be floating point, but big enough to hold all values of sample_pos_t
43  */
44 #ifdef ENABLE_LARGEFILE
45 
46 	// 64 bit
47 	typedef int64_t 	sample_pos_t;	// integer sample position
48 	typedef long double 	sample_fpos_t;	// floating-point sample position
49 
50 	#define MAX_LENGTH (0x7fffffffffffffffLL-(1024LL*1024LL))
51 
52 	#include <math.h>
53 	extern "C" {
54 		long double logl(long double);
55 		long double expl(long double);
56 	}
57 	#define sample_fpos_floor(a)	(floorl(a))
58 	#define sample_fpos_ceil(a)	(ceill(a))
59 	#define sample_fpos_round(a)	(nearbyintl(a))
60 	#define sample_fpos_log(a)	(logl(a))
61 	#define sample_fpos_exp(a)	(expl(a))
62 	#define sample_fpos_fabs(a)	(fabsl(a))
63 	#define sample_fpos_sin(a)	(sinl(a))
64 	#define sample_fpos_pow(a,b)	(powl(a,b))
65 
66 #else
67 
68 	// 32 bit
69 	typedef int32_t 	sample_pos_t;	// integer sample count
70 	typedef double		sample_fpos_t;	// floating-point sample count
71 
72 	#define MAX_LENGTH (0x7fffffff-(1024*1024))
73 
74 	#include <math.h>
75 	#define sample_fpos_floor(a)	(floor(a))
76 	#define sample_fpos_ceil(a)	(ceil(a))
77 	#define sample_fpos_round(a)	(nearbyint(a))
78 	#define sample_fpos_log(a)	(log(a))
79 	#define sample_fpos_exp(a)	(exp(a))
80 	#define sample_fpos_fabs(a)	(fabs(a))
81 	#define sample_fpos_sin(a)	(sin(a))
82 	#define sample_fpos_pow(a,b)	(pow(a,b))
83 
84 #endif
85 
86 static const sample_pos_t NIL_SAMPLE_POS=~((sample_pos_t)0);
87 
88 
89 // audio type specifications
90 #if defined(SAMPLE_TYPE_S16) // 16 bit PCM
91 
92 	#define MAX_SAMPLE ((sample_t)32767)
93 	#define MIN_SAMPLE ((sample_t)-MAX_SAMPLE) // these should stay symetric so I don't have to handle the possibility of them being off center in the frontend rendering
94 	typedef int16_t sample_t;
95 	typedef int_fast32_t mix_sample_t; // this needs to hold at least a value of MAX_SAMPLE squared
96 
97 	static mix_sample_t _SSS;
98 	#define ClipSample(s) ((sample_t)(_SSS=((mix_sample_t)(s)), _SSS>MAX_SAMPLE ? MAX_SAMPLE : ( _SSS<MIN_SAMPLE ? MIN_SAMPLE : _SSS ) ) )
99 
100 #elif defined(SAMPLE_TYPE_FLOAT) // 32 bit floating point PCM
101 	#define MAX_SAMPLE (1.0f)
102 	#define MIN_SAMPLE (-MAX_SAMPLE) // these should stay symetric so I don't have to handle the possibility of them being off center in the frontend rendering
103 	typedef float sample_t;
104 	typedef float mix_sample_t;
105 
106 	// empty implementation so that samples are not truncated until playback
107 	#define ClipSample(s) (s)
108 
109 #else
110 	#error no SAMPLE_TYPE_xxx defined -- was supposed to be defined from the configure script
111 #endif
112 
113 
114 
115 /***************************/
116 /* sample type conversions */
117 /***************************/
118 
119 struct int24_t // int24_t -> unsigned char[3]
120 {
121 	uint8_t data[3];
122 
123 	enum {			// indexes into data[] for the low, middle and high bytes
124 #ifdef WORDS_BIGENDIAN
125 		lo=2,
126 		mid=1,
127 		hi=0
128 #else
129 		lo=0,
130 		mid=1,
131 		hi=2
132 #endif
133 	};
134 
setint24_t135 	inline void set(const int_fast32_t v)
136 	{
137 		data[lo]=v&0xff;
138 		data[mid]=(v>>8)&0xff;
139 		data[hi]=(v>>16)&0xff;
140 	}
141 
getint24_t142 	inline int32_t get() const
143 	{
144 		if(data[hi]&0x80) // sign extension
145 			return (int_fast32_t)data[lo] | ((int_fast32_t)data[mid]<<8) | ((int_fast32_t)data[hi]<<16) | (0xff<<24);
146 		else
147 			return (int_fast32_t)data[lo] | ((int_fast32_t)data[mid]<<8) | ((int_fast32_t)data[hi]<<16);
148 	}
149 }
150 #ifdef __GNUC__
151 	__attribute__ ((packed))
152 #endif
153 ;
154 
155 #include <math.h>
156 
157 // It is necessary to call this template function with the template arguments because the
158 // compiler cannot infer the specialization to used since not all the template parameters
159 // types are used in the function's parameter list.
160 //
161 // ??? Some of the implementation may one day need conditional expressions to handle the
162 // possibility that the negative range is one sample value larger than the positive range
163 	/* just going to have to get a linker error now with gcc>=3.4 */
164 template<typename from_sample_t,typename to_sample_t> static inline const to_sample_t convert_sample(const register from_sample_t sample) ;//{ sample_type_conversion_for_this_combination_unimplemented; }
165 
166 // int8_t -> ...
167 	// int8_t -> int8_t
168 	template<> STATIC_TPL inline const int8_t convert_sample<int8_t,int8_t>(const register int8_t sample) { return sample; }
169 
170 	// int8_t -> int16_t
171 	template<> STATIC_TPL inline const int16_t convert_sample<int8_t,int16_t>(const register int8_t sample) { return sample*256; }
172 
173 	// int8_t -> int24_t
174 	//template<> static inline const int24_t convert_sample<int8_t,int24_t>(const register int8_t sample) { }
175 
176 	// int8_t -> int32_t
177 	//template<> static inline const int32_t convert_sample<int8_t,int32_t>(const register int8_t sample) { }
178 
179 	// int8_t -> float
180 	template<> STATIC_TPL inline const float convert_sample<int8_t,float>(const register int8_t sample) { return ((float)sample)/127.0f; }
181 
182 	// int8_t -> double
183 	//template<> static inline const double convert_sample<int8_t,double>(const register int8_t sample) { }
184 
185 
186 // int16_t -> ...
187 	// int16_t -> int8_t
188 	template<> STATIC_TPL inline const int8_t convert_sample<int16_t,int8_t>(const register int16_t sample) { return sample/256; }
189 
190 	// int16_t -> int16_t
191 	template<> STATIC_TPL inline const int16_t convert_sample<int16_t,int16_t>(const register int16_t sample) { return sample; }
192 
193 	// int16_t -> int24_t
194 	template<> STATIC_TPL inline const int24_t convert_sample<int16_t,int24_t>(const register int16_t sample) { int24_t r; r.set(sample*256); return r; }
195 
196 	// int16_t -> int32_t
197 	template<> STATIC_TPL inline const int32_t convert_sample<int16_t,int32_t>(const register int16_t sample) { return sample*65536; }
198 
199 	// int16_t -> float
200 	template<> STATIC_TPL inline const float convert_sample<int16_t,float>(const register int16_t sample) { return (float)sample/32767.0f; }
201 
202 	// int16_t -> double
203 	template<> STATIC_TPL inline const double convert_sample<int16_t,double>(const register int16_t sample) { return (double)sample/32767.0; }
204 
205 
206 // int24_t -> ...
207 	// int24_t -> int8_t
208 	//template<> static inline const int8_t convert_sample<int24_t,int8_t>(const int24_t sample) { }
209 
210 	// int24_t -> int16_t
211 	template<> STATIC_TPL inline const int16_t convert_sample<int24_t,int16_t>(const int24_t sample) { return sample.get()>>8; }
212 
213 	// int24_t -> int24_t
214 	template<> STATIC_TPL inline const int24_t convert_sample<int24_t,int24_t>(const int24_t sample) { return sample; }
215 
216 	// int24_t -> int32_t
217 	//template<> static inline const int32_t convert_sample<int24_t,int32_t>(const int24_t sample) { }
218 
219 	// int24_t -> float
220 	template<> STATIC_TPL inline const float convert_sample<int24_t,float>(const int24_t sample) { return sample.get()/8388607.0f; }
221 
222 	// int24_t -> double
223 	//template<> static inline const double convert_sample<int24_t,double>(const int24_t sample) { }
224 
225 
226 // int32_t -> ...
227 	// int32_t -> int8_t
228 	//template<> static inline const int8_t convert_sample<int32_t,int8_t>(const register int32_t sample) { }
229 
230 	// int32_t -> int16_t
231 	template<> STATIC_TPL inline const int16_t convert_sample<int32_t,int16_t>(const register int32_t sample) { return sample/65536; }
232 
233 	// int32_t -> int24_t
234 	//template<> static inline const int24_t convert_sample<int32_t,int24_t>(const register int32_t sample) { }
235 
236 	// int32_t -> int32_t
237 	template<> STATIC_TPL inline const int32_t convert_sample<int32_t,int32_t>(const register int32_t sample) { return sample; }
238 
239 	// int32_t -> float
240 	template<> STATIC_TPL inline const float convert_sample<int32_t,float>(const register int32_t sample) { return ((double)sample)/2147483647.0; }
241 
242 	// int32_t -> double
243 	//template<> static inline const double  convert_sample<int32_t,double >(const register int32_t sample) { }
244 
245 
246 // float -> ...
247 	// float -> int8_t
248 	template<> STATIC_TPL inline const int8_t convert_sample<float,int8_t>(const register float sample) { return (int8_t)floorf((sample>1.0f ? 1.0f : (sample<-1.0f ? -1.0f : sample))*127.0f); }
249 
250 	// float -> int16_t
251 	template<> STATIC_TPL inline const int16_t convert_sample<float,int16_t>(const register float sample) { return (int16_t)floorf((sample>1.0f ? 1.0f : (sample<-1.0f ? -1.0f : sample))*32767.0f); }
252 
253 	// float -> int24_t
254 	template<> STATIC_TPL inline const int24_t convert_sample<float,int24_t>(const register float sample) { int24_t r; r.set((int_fast32_t)floorf((sample>1.0f ? 1.0f : (sample<-1.0f ? -1.0f : sample))*8388607.0f)); return r; }
255 
256 	// float -> int32_t
257 	template<> STATIC_TPL inline const int32_t convert_sample<float,int32_t>(const register float sample) { return (int32_t) floor((double)(sample>1.0f ? 1.0f : (sample<-1.0f ? -1.0f : sample)) * 2147483647.0); }
258 
259 	// float -> float
260 	template<> STATIC_TPL inline const float convert_sample<float,float>(const register float sample) { return sample; }
261 
262 	// float -> double
263 	template<> STATIC_TPL inline const double convert_sample<float,double>(const register float sample) { return (double)sample; }
264 
265 
266 // double -> ...
267 	// double -> int8_t
268 	//template<> static inline const int8_t convert_sample<double,int8_t>(const register double sample) { }
269 
270 	// double -> int16_t
271 	template<> STATIC_TPL inline const int16_t convert_sample<double,int16_t>(const register double sample) { return (int16_t)floor((sample>1.0 ? 1.0 : (sample<-1.0 ? -1.0 : sample))*32767.0); }
272 
273 	// double -> int24_t
274 	//template<> static inline const int24_t convert_sample<double,int24_t>(const register double sample) { }
275 
276 	// double -> int32_t
277 	//template<> static inline const int32_t convert_sample<double,int32_t>(const register double sample) { }
278 
279 	// double -> float
280 	template<> STATIC_TPL inline const float convert_sample<double,float>(const register double sample) { return (float)sample; }
281 
282 	// double -> double
283 	template<> STATIC_TPL inline const double convert_sample<double,double>(const register double sample) { return sample; }
284 
285 
286 
287 
288 
289 
290 
291 // used in CSound::mixSound()
292 enum MixMethods
293 {
294     mmOverwrite,
295     mmAdd,
296     mmSubtract,
297     mmMultiply,
298     mmAverage
299 };
300 
301 // used in CSound::mixSound()
302 enum SourceFitTypes
303 {
304 	sftNone,
305 	sftChangeRate,
306 	sftChangeTempo
307 };
308 
309 // used in .rez files
310 enum AudioEncodingTypes
311 {
312 	// let 0 be invalid
313 	aetPCMSigned16BitInteger=1,
314 	aetPCM32BitFloat=2,
315 	aetPCMSigned8BitInteger=3,
316 	aetPCMSigned24BitInteger=4,
317 	aetPCMSigned32BitInteger=5
318 };
319 
320 enum Endians
321 {
322 	eLittleEndian=0,
323 	eBigEndian=1
324 };
325 
326 
327 #endif
328