1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or
5  *  (at your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *  GNU General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15  */
16 
17 /* Mixer for low-level sound output drivers
18  */
19 
20 #ifndef LIBS_SOUND_MIXER_MIXER_H_
21 #define LIBS_SOUND_MIXER_MIXER_H_
22 
23 #include "config.h"
24 #include "types.h"
25 #include "endian_uqm.h"
26 
27 /**
28  * The interface heavily influenced by OpenAL
29  * to the point where you should use OpenAL's
30  * documentation when programming the mixer.
31  * (some source properties are not supported)
32  *
33  * EXCEPTION: You may not queue the same buffer
34  * on more than one source
35  */
36 
37 #ifdef WORDS_BIGENDIAN
38 #	define MIX_IS_BIG_ENDIAN   true
39 #	define MIX_WANT_BIG_ENDIAN true
40 #else
41 #	define MIX_IS_BIG_ENDIAN   false
42 #	define MIX_WANT_BIG_ENDIAN false
43 #endif
44 
45 /**
46  * Mixer errors (see OpenAL errors)
47  */
48 enum
49 {
50 	MIX_NO_ERROR = 0,
51 	MIX_INVALID_NAME = 0xA001U,
52 	MIX_INVALID_ENUM = 0xA002U,
53 	MIX_INVALID_VALUE = 0xA003U,
54 	MIX_INVALID_OPERATION = 0xA004U,
55 	MIX_OUT_OF_MEMORY = 0xA005U,
56 
57 	MIX_DRIVER_FAILURE = 0xA101U
58 };
59 
60 /**
61  * Source properties (see OpenAL)
62  */
63 typedef enum
64 {
65 	MIX_POSITION = 0x1004,
66 	MIX_LOOPING = 0x1007,
67 	MIX_BUFFER = 0x1009,
68 	MIX_GAIN = 0x100A,
69 	MIX_SOURCE_STATE = 0x1010,
70 
71 	MIX_BUFFERS_QUEUED = 0x1015,
72 	MIX_BUFFERS_PROCESSED = 0x1016
73 
74 } mixer_SourceProp;
75 
76 /**
77  * Source state information
78  */
79 typedef enum
80 {
81 	MIX_INITIAL = 0,
82 	MIX_STOPPED,
83 	MIX_PLAYING,
84 	MIX_PAUSED,
85 
86 } mixer_SourceState;
87 
88 /**
89  * Sound buffer properties
90  */
91 typedef enum
92 {
93 	MIX_FREQUENCY = 0x2001,
94 	MIX_BITS = 0x2002,
95 	MIX_CHANNELS = 0x2003,
96 	MIX_SIZE = 0x2004,
97 	MIX_DATA = 0x2005
98 
99 } mixer_BufferProp;
100 
101 /**
102  * Buffer states: semi-private
103  */
104 typedef enum
105 {
106 	MIX_BUF_INITIAL = 0,
107 	MIX_BUF_FILLED,
108 	MIX_BUF_QUEUED,
109 	MIX_BUF_PLAYING,
110 	MIX_BUF_PROCESSED
111 
112 } mixer_BufferState;
113 
114 /** Sound buffers: format specifier.
115  * bits 00..07: bytes per sample
116  * bits 08..15: channels
117  * bits 15..31: meaningless
118  */
119 #define MIX_FORMAT_DUMMYID     0x00170000
120 #define MIX_FORMAT_BPC(f)      ((f) & 0xff)
121 #define MIX_FORMAT_CHANS(f)    (((f) >> 8) & 0xff)
122 #define MIX_FORMAT_BPC_MAX     2
123 #define MIX_FORMAT_CHANS_MAX   2
124 #define MIX_FORMAT_MAKE(b, c) \
125 		( MIX_FORMAT_DUMMYID | ((b) & 0xff) | (((c) & 0xff) << 8) )
126 
127 #define MIX_FORMAT_SAMPSIZE(f) \
128 		( MIX_FORMAT_BPC(f) * MIX_FORMAT_CHANS(f) )
129 
130 typedef enum
131 {
132 	MIX_FORMAT_MONO8 = MIX_FORMAT_MAKE (1, 1),
133 	MIX_FORMAT_STEREO8 = MIX_FORMAT_MAKE (1, 2),
134 	MIX_FORMAT_MONO16 = MIX_FORMAT_MAKE (2, 1),
135 	MIX_FORMAT_STEREO16 = MIX_FORMAT_MAKE (2, 2)
136 
137 } mixer_Format;
138 
139 typedef enum
140 {
141 	MIX_QUALITY_LOW = 0,
142 	MIX_QUALITY_MEDIUM,
143 	MIX_QUALITY_HIGH,
144 	MIX_QUALITY_DEFAULT = MIX_QUALITY_MEDIUM,
145 	MIX_QUALITY_COUNT
146 
147 } mixer_Quality;
148 
149 typedef enum
150 {
151 	MIX_NOFLAGS = 0,
152 	MIX_FAKE_DATA = 1
153 } mixer_Flags;
154 
155 /*************************************************
156  *  Interface Types
157  */
158 
159 typedef intptr_t mixer_Object;
160 typedef intptr_t mixer_IntVal;
161 
162 typedef struct _mixer_Source mixer_Source;
163 
164 typedef struct _mixer_Buffer
165 {
166 	uint32 magic;
167 	bool locked;
168 	mixer_BufferState state;
169 	uint8 *data;
170 	uint32 size;
171 	uint32 sampsize;
172 	uint32 high;
173 	uint32 low;
174 	float (* Resample) (mixer_Source *src, bool left);
175 	/* original buffer values for OpenAL compat */
176 	void* orgdata;
177 	uint32 orgfreq;
178 	uint32 orgsize;
179 	uint32 orgchannels;
180 	uint32 orgchansize;
181 	/* next buffer in chain */
182 	struct _mixer_Buffer *next;
183 
184 } mixer_Buffer;
185 
186 #define mixer_bufMagic 0x4258494DU /* MIXB in LSB */
187 
188 struct _mixer_Source
189 {
190 	uint32 magic;
191 	bool locked;
192 	mixer_SourceState state;
193 	bool looping;
194 	float gain;
195 	uint32 cqueued;
196 	uint32 cprocessed;
197 	mixer_Buffer *firstqueued; /* first buf in the queue */
198 	mixer_Buffer *nextqueued;  /* next to play, or 0 */
199 	mixer_Buffer *prevqueued;  /* previously played */
200 	mixer_Buffer *lastqueued;  /* last in queue */
201 	uint32 pos; /* position in current buffer */
202 	uint32 count; /* fractional part of pos */
203 
204 	float samplecache;
205 
206 };
207 
208 #define mixer_srcMagic 0x5358494DU /* MIXS in LSB */
209 
210 /*************************************************
211  *  General interface
212  */
213 uint32 mixer_GetError (void);
214 
215 bool mixer_Init (uint32 frequency, uint32 format, mixer_Quality quality,
216 		mixer_Flags flags);
217 void mixer_Uninit (void);
218 void mixer_MixChannels (void *userdata, uint8 *stream, sint32 len);
219 void mixer_MixFake (void *userdata, uint8 *stream, sint32 len);
220 
221 /*************************************************
222  *  Sources
223  */
224 void mixer_GenSources (uint32 n, mixer_Object *psrcobj);
225 void mixer_DeleteSources (uint32 n, mixer_Object *psrcobj);
226 bool mixer_IsSource (mixer_Object srcobj);
227 void mixer_Sourcei (mixer_Object srcobj, mixer_SourceProp pname,
228 		mixer_IntVal value);
229 void mixer_Sourcef (mixer_Object srcobj, mixer_SourceProp pname,
230 		float value);
231 void mixer_Sourcefv (mixer_Object srcobj, mixer_SourceProp pname,
232 		float *value);
233 void mixer_GetSourcei (mixer_Object srcobj, mixer_SourceProp pname,
234 		mixer_IntVal *value);
235 void mixer_GetSourcef (mixer_Object srcobj, mixer_SourceProp pname,
236 		float *value);
237 void mixer_SourceRewind (mixer_Object srcobj);
238 void mixer_SourcePlay (mixer_Object srcobj);
239 void mixer_SourcePause (mixer_Object srcobj);
240 void mixer_SourceStop (mixer_Object srcobj);
241 void mixer_SourceQueueBuffers (mixer_Object srcobj, uint32 n,
242 		mixer_Object* pbufobj);
243 void mixer_SourceUnqueueBuffers (mixer_Object srcobj, uint32 n,
244 		mixer_Object* pbufobj);
245 
246 /*************************************************
247  *  Buffers
248  */
249 void mixer_GenBuffers (uint32 n, mixer_Object *pbufobj);
250 void mixer_DeleteBuffers (uint32 n, mixer_Object *pbufobj);
251 bool mixer_IsBuffer (mixer_Object bufobj);
252 void mixer_GetBufferi (mixer_Object bufobj, mixer_BufferProp pname,
253 		mixer_IntVal *value);
254 void mixer_BufferData (mixer_Object bufobj, uint32 format, void* data,
255 		uint32 size, uint32 freq);
256 
257 
258 /* Make sure the prop-value type is of suitable size
259  * it must be able to store both int and void*
260  * Adapted from SDL
261  * This will generate "negative subscript or subscript is too large"
262  * error during compile, if the actual size of a type is wrong
263  */
264 #define MIX_COMPILE_TIME_ASSERT(name, x) \
265 	typedef int mixer_dummy_##name [(x) * 2 - 1]
266 
267 MIX_COMPILE_TIME_ASSERT (mixer_Object,
268 		sizeof(mixer_Object) >= sizeof(void*));
269 MIX_COMPILE_TIME_ASSERT (mixer_IntVal,
270 		sizeof(mixer_IntVal) >= sizeof(mixer_Object));
271 
272 #undef MIX_COMPILE_TIME_ASSERT
273 
274 #endif /* LIBS_SOUND_MIXER_MIXER_H_ */
275