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
|
/* 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;
// TODO: class Channel should really be declared non-public, inside mixer.cpp
// However, right now Sound::updateMP3CD directly calls soundFinished. That
// should be changed, by adding proper API abstraction to SoundMixer for
// MP3/Vorbis "CD" playback.
class Channel {
protected:
SoundMixer *_mixer;
public:
bool _toBeDestroyed;
int _id;
Channel() : _mixer(0), _toBeDestroyed(false), _id(-1) {}
virtual void mix(int16 *data, uint len) = 0;
void destroy() {
_toBeDestroyed = true;
}
virtual void realDestroy() = 0;
virtual bool soundFinished();
};
class SoundMixer {
public:
typedef void PremixProc (void *param, int16 *data, uint len);
enum {
NUM_CHANNELS = 16
};
private:
static void onGenerateSamples(void *s, byte *samples, int len);
OSystem *_syst;
void *_mutex;
void *_premixParam;
PremixProc *_premixProc;
PlayingSoundHandle *_handles[NUM_CHANNELS];
public:
uint _outputRate;
int16 *_volumeTable;
int _musicVolume;
bool _paused;
Channel *_channels[NUM_CHANNELS];
public:
SoundMixer();
~SoundMixer();
// start playing a raw sound
enum {
// Do *NOT* change any of these flags without looking at the code in mixer.cpp
FLAG_UNSIGNED = 1 << 0, // unsigned samples
FLAG_STEREO = 1 << 1, // sound is in stereo
FLAG_16BITS = 1 << 2, // sound is 16 bits wide
FLAG_AUTOFREE = 1 << 3, // sound buffer is freed automagically at the end of playing
FLAG_REVERSE_STEREO = 1 << 4, // sound should be reverse stereo
FLAG_LOOP = 1 << 5 // loop the audio
};
int playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id = -1);
int playStream(void *sound, uint32 size, uint rate, byte flags, int32 buffer_size);
#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);
/** mix */
void mix(int16 * buf, uint len);
/** stop all currently playing sounds */
void stopAll();
/** stop playing a specific sound */
void stop(int index);
/** stop playing a specific sound */
void stopID(int id);
/** append to existing sound */
int append(int index, void * sound, uint32 size);
/** is any channel active? */
bool hasActiveChannel();
/** bind to the OSystem object => mixer will be
* invoked automatically when samples need
* to be generated */
bool bindToSystem(OSystem *syst);
/** set the volume, 0-256 */
void setVolume(int volume);
void setMusicVolume(int volume);
/** pause - unpause */
void pause(bool paused);
private:
int insertAt(PlayingSoundHandle *handle, int index, Channel *chan);
};
#endif
|