aboutsummaryrefslogtreecommitdiff
path: root/engines/cine/sound_driver.h
blob: c6fc571f892d483bf53e670fb77ae47d53a26ce7 (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
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2006 The ScummVM project
 *
 * cinE Engine is (C) 2004-2005 by CinE Team
 *
 * 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 CINE_SOUNDDRIVER_H
#define CINE_SOUNDDRIVER_H

#include "sound/audiostream.h"
#include "sound/fmopl.h"
#include "sound/mixer.h"

namespace Cine {
	
class SoundDriver {
public:
	typedef void (*UpdateCallback)(void *);

	virtual ~SoundDriver() {}

	virtual void setupChannel(int channel, const byte *data, int instrument, int volume) = 0;
	virtual void setChannelFrequency(int channel, int frequency) = 0;
	virtual void stopChannel(int channel) = 0;
	virtual void playSound(const byte *data, int channel, int volume) = 0;
	virtual void stopSound() = 0;
	virtual const char *getInstrumentExtension() const = 0;
	
	void setUpdateCallback(UpdateCallback upCb, void *ref);
	void resetChannel(int channel);
	void findNote(int freq, int *note, int *oct) const;

protected:
	UpdateCallback _upCb;
	void *_upRef;

	static const int _noteTable[];
	static const int _noteTableCount;
};

struct AdlibRegisterSoundInstrument {
	uint16 vibrato;
	uint16 attackDecay;
	uint16 sustainRelease;
	uint16 feedbackStrength;
	uint16 keyScaling;
	uint16 outputLevel;
	uint16 freqMod;
};

struct AdlibSoundInstrument {
	byte mode;
	byte channel;
	AdlibRegisterSoundInstrument regMod;
	AdlibRegisterSoundInstrument regCar;
	byte waveSelectMod;
	byte waveSelectCar;
	byte amDepth;
};
	
class AdlibSoundDriver : public SoundDriver, Audio::AudioStream {
public:
	AdlibSoundDriver(Audio::Mixer *mixer);
	virtual ~AdlibSoundDriver();

	// SoundDriver interface
	virtual void setupChannel(int channel, const byte *data, int instrument, int volume);
	virtual void stopChannel(int channel);
	virtual void stopSound();

	// AudioStream interface
	virtual int readBuffer(int16 *buffer, const int numSamples);
	virtual bool isStereo() const { return false; }
	virtual bool endOfData() const { return false; }
	virtual int getRate() const { return _sampleRate; }

	void initCard();
	void update(int16 *buf, int len);
	void setupInstrument(const byte *data, int channel);
	void loadRegisterInstrument(const byte *data, AdlibRegisterSoundInstrument *reg);
	virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi) = 0;

protected:
	FM_OPL *_opl;
	int _sampleRate;
	Audio::Mixer *_mixer;
	Audio::SoundHandle _soundHandle;

	byte _vibrato;
	int _channelsVolumeTable[4];
	AdlibSoundInstrument _instrumentsTable[4];

	static const int _freqTable[];
	static const int _freqTableCount;
	static const int _operatorsTable[];
	static const int _operatorsTableCount;
	static const int _voiceOperatorsTable[];
	static const int _voiceOperatorsTableCount;
};

// Future Wars adlib driver
class AdlibSoundDriverINS : public AdlibSoundDriver {
public:
	AdlibSoundDriverINS(Audio::Mixer *mixer) : AdlibSoundDriver(mixer) {}
	virtual const char *getInstrumentExtension() const { return ".INS"; }
	virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi);
	virtual void setChannelFrequency(int channel, int frequency);
	virtual void playSound(const byte *data, int channel, int volume);
};

// Operation Stealth adlib driver
class AdlibSoundDriverADL : public AdlibSoundDriver {
public:
	AdlibSoundDriverADL(Audio::Mixer *mixer) : AdlibSoundDriver(mixer) {}
	virtual const char *getInstrumentExtension() const { return ".ADL"; }
	virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi);
	virtual void setChannelFrequency(int channel, int frequency);
	virtual void playSound(const byte *data, int channel, int volume);
};

extern SoundDriver *g_soundDriver; // TEMP

} // End of namespace Cine

#endif /* CINE_SOUNDDRIVER_H_ */