aboutsummaryrefslogtreecommitdiff
path: root/sound/mixer.h
blob: 6c7e8edf97db58ba5984d0be4dcb6a37505f4c53 (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
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001  Ludvig Strigeus
 * Copyright (C) 2001-2003 The ScummVM project
 *
 * 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.
 *
 * $Header$
 *
 */

#ifndef MIXER_H
#define MIXER_H

#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#ifdef USE_MAD
#include <mad.h>
#endif
#ifdef USE_VORBIS
#include <vorbis/vorbisfile.h>
#endif
#include "stdafx.h"
#include "common/scummsys.h"
#include "common/system.h"


typedef uint32 PlayingSoundHandle;

class Channel;
class File;

class SoundMixer {
	friend class Channel;
public:
	typedef void PremixProc (void *param, int16 *data, uint len);

	enum {
		NUM_CHANNELS = 16
	};

	enum {
		// Do *NOT* change any of these flags without looking at the code in mixer.cpp
		FLAG_UNSIGNED = 1 << 0,         // unsigned samples (default: signed)
		FLAG_STEREO = 1 << 1,           // sound is in stereo (default: mono)
		FLAG_16BITS = 1 << 2,           // sound is 16 bits wide (default: 8bit)
		FLAG_AUTOFREE = 1 << 3,         // sound buffer is freed automagically at the end of playing
		FLAG_REVERSE_STEREO = 1 << 4,   // reverse the left and right stereo channel
		FLAG_LOOP = 1 << 5              // loop the audio
	};

private:
	OSystem *_syst;
	OSystem::MutexRef _mutex;

	void *_premixParam;
	PremixProc *_premixProc;

	uint _outputRate;

	int _globalVolume;
	int _musicVolume;

	bool _paused;

	Channel *_channels[NUM_CHANNELS];

public:
	SoundMixer();
	~SoundMixer();

	// start playing a raw sound
	int playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id = -1);
#ifdef USE_MAD
	int playMP3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags);
	int playMP3CDTrack(PlayingSoundHandle *handle, File *file, mad_timer_t duration);
#endif
#ifdef USE_VORBIS
	int playVorbis(PlayingSoundHandle *handle, OggVorbis_File *ov_file, int duration, bool is_cd_track);
#endif

	/** Premix procedure, useful when using fmopl adlib */
	void setupPremix(void * param, PremixProc * proc);

	/** stop all currently playing sounds */
	void stopAll();

	/** stop playing the given channel */
	void stop(int channel);

	/** stop playing the sound with given ID  */
	void stopID(int id);

	/** stop playing the channel for the given handle */
	void stopHandle(PlayingSoundHandle handle);

	/** Start a new stream. */
	int newStream(void *sound, uint32 size, uint rate, byte flags, uint32 buffer_size);

	/** Append to an existing stream. */
	void appendStream(int index, void *sound, uint32 size);

	/** Mark a stream as finished - it will play all its remaining data, then stop. */
	void endStream(int index);

	/** Check whether any SFX channel is active.*/
	bool hasActiveSFXChannel();
	
	/** Check whether the specified channel is active. */
	bool isChannelActive(int index);

	/** Check whether the specified channel is in use. */
	bool isChannelUsed(int index);

	/** bind to the OSystem object => mixer will be
	 * invoked automatically when samples need
	 * to be generated */
	bool bindToSystem(OSystem *syst);

	/** pause - unpause */
	void pause(bool paused);

	/** set the global volume, 0-256 */
	void setVolume(int volume);
	
	/** query the global volume, 0-256 */
	int getVolume() const { return _globalVolume; }

	/** set the music volume, 0-256 */
	void setMusicVolume(int volume);
	
	/** query the music volume, 0-256 */
	int getMusicVolume() const { return _musicVolume; }
	
	/** query the output rate in kHz */
	uint getOutputRate() const { return _outputRate; }

private:
	int insertChannel(PlayingSoundHandle *handle, Channel *chan);

	/** mix */
	void mix(int16 * buf, uint len);

	static void mixCallback(void *s, byte *samples, int len);
};

#endif