summaryrefslogtreecommitdiff
path: root/src/libs/sound/mixer/mixer.h
blob: 71e78780564c89383fb0e9cdc637fa4b5e56f6fd (plain)
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/* Mixer for low-level sound output drivers
 */

#ifndef LIBS_SOUND_MIXER_MIXER_H_
#define LIBS_SOUND_MIXER_MIXER_H_

#include "config.h"
#include "types.h"
#include "endian_uqm.h"

/**
 * The interface heavily influenced by OpenAL
 * to the point where you should use OpenAL's
 * documentation when programming the mixer.
 * (some source properties are not supported)
 *
 * EXCEPTION: You may not queue the same buffer
 * on more than one source
 */

#ifdef WORDS_BIGENDIAN
#	define MIX_IS_BIG_ENDIAN   true
#	define MIX_WANT_BIG_ENDIAN true
#else
#	define MIX_IS_BIG_ENDIAN   false
#	define MIX_WANT_BIG_ENDIAN false
#endif

/**
 * Mixer errors (see OpenAL errors)
 */
enum
{
	MIX_NO_ERROR = 0,
	MIX_INVALID_NAME = 0xA001U,
	MIX_INVALID_ENUM = 0xA002U,
	MIX_INVALID_VALUE = 0xA003U,
	MIX_INVALID_OPERATION = 0xA004U,
	MIX_OUT_OF_MEMORY = 0xA005U,

	MIX_DRIVER_FAILURE = 0xA101U
};

/**
 * Source properties (see OpenAL)
 */
typedef enum
{
	MIX_POSITION = 0x1004,
	MIX_LOOPING = 0x1007,
	MIX_BUFFER = 0x1009,
	MIX_GAIN = 0x100A,
	MIX_SOURCE_STATE = 0x1010,

	MIX_BUFFERS_QUEUED = 0x1015,
	MIX_BUFFERS_PROCESSED = 0x1016

} mixer_SourceProp;

/**
 * Source state information
 */
typedef enum
{
	MIX_INITIAL = 0,
	MIX_STOPPED,
	MIX_PLAYING,
	MIX_PAUSED,

} mixer_SourceState;

/** 
 * Sound buffer properties
 */
typedef enum
{
	MIX_FREQUENCY = 0x2001,
	MIX_BITS = 0x2002,
	MIX_CHANNELS = 0x2003,
	MIX_SIZE = 0x2004,
	MIX_DATA = 0x2005

} mixer_BufferProp;

/**
 * Buffer states: semi-private
 */
typedef enum
{
	MIX_BUF_INITIAL = 0,
	MIX_BUF_FILLED,
	MIX_BUF_QUEUED,
	MIX_BUF_PLAYING,
	MIX_BUF_PROCESSED

} mixer_BufferState;

/** Sound buffers: format specifier.
 * bits 00..07: bytes per sample
 * bits 08..15: channels
 * bits 15..31: meaningless
 */
#define MIX_FORMAT_DUMMYID     0x00170000
#define MIX_FORMAT_BPC(f)      ((f) & 0xff)
#define MIX_FORMAT_CHANS(f)    (((f) >> 8) & 0xff)
#define MIX_FORMAT_BPC_MAX     2
#define MIX_FORMAT_CHANS_MAX   2
#define MIX_FORMAT_MAKE(b, c) \
		( MIX_FORMAT_DUMMYID | ((b) & 0xff) | (((c) & 0xff) << 8) )

#define MIX_FORMAT_SAMPSIZE(f) \
		( MIX_FORMAT_BPC(f) * MIX_FORMAT_CHANS(f) )

typedef enum
{
	MIX_FORMAT_MONO8 = MIX_FORMAT_MAKE (1, 1),
	MIX_FORMAT_STEREO8 = MIX_FORMAT_MAKE (1, 2),
	MIX_FORMAT_MONO16 = MIX_FORMAT_MAKE (2, 1),
	MIX_FORMAT_STEREO16 = MIX_FORMAT_MAKE (2, 2)

} mixer_Format;

typedef enum
{
	MIX_QUALITY_LOW = 0,
	MIX_QUALITY_MEDIUM,
	MIX_QUALITY_HIGH,
	MIX_QUALITY_DEFAULT = MIX_QUALITY_MEDIUM,
	MIX_QUALITY_COUNT

} mixer_Quality;

typedef enum
{
	MIX_NOFLAGS = 0,
	MIX_FAKE_DATA = 1
} mixer_Flags;

/*************************************************
 *  Interface Types
 */

typedef intptr_t mixer_Object;
typedef intptr_t mixer_IntVal;

typedef struct _mixer_Source mixer_Source;

typedef struct _mixer_Buffer
{
	uint32 magic;
	bool locked;
	mixer_BufferState state;
	uint8 *data;
	uint32 size;
	uint32 sampsize;
	uint32 high;
	uint32 low;
	float (* Resample) (mixer_Source *src, bool left);
	/* original buffer values for OpenAL compat */
	void* orgdata;
	uint32 orgfreq;
	uint32 orgsize;
	uint32 orgchannels;
	uint32 orgchansize;
	/* next buffer in chain */
	struct _mixer_Buffer *next;

} mixer_Buffer;

#define mixer_bufMagic 0x4258494DU /* MIXB in LSB */

struct _mixer_Source
{
	uint32 magic;
	bool locked;
	mixer_SourceState state;
	bool looping;
	float gain;
	uint32 cqueued;
	uint32 cprocessed;
	mixer_Buffer *firstqueued; /* first buf in the queue */
	mixer_Buffer *nextqueued;  /* next to play, or 0 */
	mixer_Buffer *prevqueued;  /* previously played */
	mixer_Buffer *lastqueued;  /* last in queue */
	uint32 pos; /* position in current buffer */
	uint32 count; /* fractional part of pos */

	float samplecache;

};

#define mixer_srcMagic 0x5358494DU /* MIXS in LSB */

/*************************************************
 *  General interface
 */
uint32 mixer_GetError (void);

bool mixer_Init (uint32 frequency, uint32 format, mixer_Quality quality,
		mixer_Flags flags);
void mixer_Uninit (void);
void mixer_MixChannels (void *userdata, uint8 *stream, sint32 len);
void mixer_MixFake (void *userdata, uint8 *stream, sint32 len);

/*************************************************
 *  Sources
 */
void mixer_GenSources (uint32 n, mixer_Object *psrcobj);
void mixer_DeleteSources (uint32 n, mixer_Object *psrcobj);
bool mixer_IsSource (mixer_Object srcobj);
void mixer_Sourcei (mixer_Object srcobj, mixer_SourceProp pname,
		mixer_IntVal value);
void mixer_Sourcef (mixer_Object srcobj, mixer_SourceProp pname,
		float value);
void mixer_Sourcefv (mixer_Object srcobj, mixer_SourceProp pname,
		float *value);
void mixer_GetSourcei (mixer_Object srcobj, mixer_SourceProp pname,
		mixer_IntVal *value);
void mixer_GetSourcef (mixer_Object srcobj, mixer_SourceProp pname,
		float *value);
void mixer_SourceRewind (mixer_Object srcobj);
void mixer_SourcePlay (mixer_Object srcobj);
void mixer_SourcePause (mixer_Object srcobj);
void mixer_SourceStop (mixer_Object srcobj);
void mixer_SourceQueueBuffers (mixer_Object srcobj, uint32 n,
		mixer_Object* pbufobj);
void mixer_SourceUnqueueBuffers (mixer_Object srcobj, uint32 n,
		mixer_Object* pbufobj);

/*************************************************
 *  Buffers
 */
void mixer_GenBuffers (uint32 n, mixer_Object *pbufobj);
void mixer_DeleteBuffers (uint32 n, mixer_Object *pbufobj);
bool mixer_IsBuffer (mixer_Object bufobj);
void mixer_GetBufferi (mixer_Object bufobj, mixer_BufferProp pname,
		mixer_IntVal *value);
void mixer_BufferData (mixer_Object bufobj, uint32 format, void* data,
		uint32 size, uint32 freq);


/* Make sure the prop-value type is of suitable size
 * it must be able to store both int and void*
 * Adapted from SDL
 * This will generate "negative subscript or subscript is too large"
 * error during compile, if the actual size of a type is wrong
 */
#define MIX_COMPILE_TIME_ASSERT(name, x) \
	typedef int mixer_dummy_##name [(x) * 2 - 1]

MIX_COMPILE_TIME_ASSERT (mixer_Object,
		sizeof(mixer_Object) >= sizeof(void*));
MIX_COMPILE_TIME_ASSERT (mixer_IntVal,
		sizeof(mixer_IntVal) >= sizeof(mixer_Object));

#undef MIX_COMPILE_TIME_ASSERT

#endif /* LIBS_SOUND_MIXER_MIXER_H_ */