aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/sfx/sfx_pcm.h
blob: 89ccee04d9da2cb8c489213999aa38b3095120fc (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
/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL$
 * $Id$
 *
 */

#ifndef SCI_SFX_SFX_PCM_H
#define SCI_SFX_SFX_PCM_H

#include "sci/sfx/sfx_core.h"
#include "sci/sfx/sfx_time.h"

namespace Sci {

#define SFX_PCM_MONO 0
#define SFX_PCM_STEREO_LR 1 /* left sample, then right sample */
#define SFX_PCM_STEREO_RL 2 /* right sample, then left sample */

/* The following are used internally by the mixer */
#define SFX_PCM_FORMAT_LMASK 0x7
#define SFX_PCM_FORMAT_BE 0
#define SFX_PCM_FORMAT_LE 1
#define SFX_PCM_FORMAT_ENDIANNESS 1
#define SFX_PCM_FORMAT_8  0
#define SFX_PCM_FORMAT_16 2


/* Pick one of these formats (including the _NATIVE) ones for your PCM feed */
#define SFX_PCM_FORMAT_U8     (0x0080 | SFX_PCM_FORMAT_8)			/* Unsigned (bias 128) 8 bit format */
#define SFX_PCM_FORMAT_S8     (0x0000 | SFX_PCM_FORMAT_8)			/* Signed 8 bit format */
#define SFX_PCM_FORMAT_U16_LE (0x8000 | SFX_PCM_FORMAT_16 | SFX_PCM_FORMAT_LE)	/* Unsigned (bias 32768) 16 bit LE format */
#define SFX_PCM_FORMAT_S16_LE (0x0000 | SFX_PCM_FORMAT_16 | SFX_PCM_FORMAT_LE)	/* Signed 16 bit format, little endian */
#define SFX_PCM_FORMAT_U16_BE (0x8000 | SFX_PCM_FORMAT_16 | SFX_PCM_FORMAT_BE)	/* Unsigned (bias 32768) 16 bit BE format */
#define SFX_PCM_FORMAT_S16_BE (0x0000 | SFX_PCM_FORMAT_16 | SFX_PCM_FORMAT_BE)	/* Signed 16 bit format, big endian */

#ifdef SCUMM_BIG_ENDIAN
#  define SFX_PCM_FORMAT_U16_NATIVE SFX_PCM_FORMAT_U16_BE
#  define SFX_PCM_FORMAT_S16_NATIVE SFX_PCM_FORMAT_S16_BE
#else
#  define SFX_PCM_FORMAT_U16_NATIVE SFX_PCM_FORMAT_U16_LE
#  define SFX_PCM_FORMAT_S16_NATIVE SFX_PCM_FORMAT_S16_LE
#endif

#define SFX_PCM_FRAME_SIZE(conf) ((conf).stereo? 2 : 1) * (((conf).format & SFX_PCM_FORMAT_16)? 2 : 1)


struct sfx_pcm_config_t {
	int rate;   /* Sampling rate */
	int stereo; /* The stereo mode used (SFX_PCM_MONO or SFX_PCM_STEREO_*) */
	unsigned int format; /* Sample format (SFX_PCM_FORMAT_*) */
};

struct sfx_pcm_device_t {
	/* SFX devices are PCM players, i.e. output drivers for digitalised audio (sequences of audio samples).
	** Implementors are (in general) allowed to export specifics of these devices and let the mixer handle
	** endianness/signedness/bit size/mono-vs-stereo conversions.
	*/

	int (*init)(sfx_pcm_device_t *self);
	/* Initializes the device
	** Parameters: (sfx_pcm_device_t *) self: Self reference
	** Returns   : (int) SFX_OK on success, SFX_ERROR if the device could not be
	**                   opened
	** This should attempt to open the highest quality output allowed by any options
	** specified beforehand.
	*/

	int (*output)(sfx_pcm_device_t *self, byte *buf,
	              int count, sfx_timestamp_t *timestamp);
	/* Writes output to the device
	** Parameters: (sfx_pcm_device_t *) self: Self reference
	**             (byte *) buf: The buffer to write
	**             (int) count: Number of /frames/ that should be written
	**             (sfx_timestamp_t *) timestamp: Optional point in time
	**                                     for which the PCM data is scheduled
	** Returns   : (int) SFX_OK on success, SFX_ERROR on error
	** The size of the buffer allocated as 'buf' equals buf_size.
	** 'buf' is guaranteed not to be modified in between calls to 'output()'.
	** 'timestamp' is guaranteed to be used only in sequential order, but not
	** guaranteed to be used in all cases. It is guaranteed to be compaible with
	** the sample rate used by the device itself (i.e., the sfx_time.h functionality
	** is applicable)
	*/

	sfx_timestamp_t
	(*get_output_timestamp)(sfx_pcm_device_t *self);
	/* Determines the timestamp for 'output'
	** Parameters: (sfx_pcm_device_t *) self: Self reference
	** Returns   : (sfx_timestamp_t) A timestamp (with the device's conf.rate)
	**                               describing the point in time at which
	**                               the next frame passed to 'output'
	**                               will be played
	** This function is OPTIONAL and may be NULL, but it is recommended
	** that pcm device implementers attempt to really implement it.
	*/

	/* The following must be set after initialisation */
	sfx_pcm_config_t conf;
	int buf_size; /* Output buffer size, i.e. the number of frames (!)
		      ** that can be queued by this driver before calling
		      ** output() will block or fail, drained according
		      ** to conf.rate  */

};


#define PCM_FEED_TIMESTAMP 0	/* New timestamp available */
#define PCM_FEED_IDLE 1		/* No sound ATM, but new timestamp may be available later */
#define PCM_FEED_EMPTY 2	/* Feed is finished, can be destroyed */

struct sfx_pcm_feed_t {
	/* PCM feeds are sources of input for the PCM mixer. Their member functions
	** are invoked as callbacks on demand, to provide the mixer with input it
	** (in turn) passes on to PCM output devices.
	**   PCM feeds must explicitly register themselves with the mixer in order
	** to be considered.
	*/

	int (*poll)(sfx_pcm_feed_t *self, byte *dest, int size);
	/* Asks the PCM feed to write out the next stuff it would like to have written
	** Parameters: (sfx_pcm_feed_t *) self: Self reference
	**             (byte *) dest: The destination buffer to write to
	**             (int) size: The maximum number of _frames_ (not neccessarily bytes)
	**                         to write
	** Returns   : (int) The number of frames written
	** If the number of frames written is smaller than 'size', the PCM feed will
	** be queried for a new timestamp afterwards, or destroyed if no new timestamp
	** is available.
	*/

	void (*destroy)(sfx_pcm_feed_t *self);
	/* Asks the PCM feed to free all resources it occupies
	** Parameters: (sfx_pcm_feed_t *) self: Self reference
	** free(self) should be part of this function, if applicable.
	*/

	int
	(*get_timestamp)(sfx_pcm_feed_t *self, sfx_timestamp_t *timestamp);
	/* Determines the timestamp of the next frame-to-read
	** Returns   : (sfx_timestamp_t) timestamp: The timestamp of the next frame
	**             (int) PCM_FEED_*
	** This function is OPTIONAL and may be NULL
	*/

	void *internal; /* The private bits of a PCM feed. */

	sfx_pcm_config_t conf; /* The channel's setup */

	const char *debug_name; /* The channel name, for debugging */
	int debug_nr; /* A channel number relative to the channel name, for debugging
		      ** (print in hex)  */
	int frame_size; /* Frame size, computed by the mixer for the feed */

};

int sfx_pcm_available();
/* Determines whether a PCM device is available and has been initialised
** Returns   : (int) zero iff no PCM device is available
*/

} // End of namespace Sci

#endif // SCI_SFX_SFX_PCM_H