aboutsummaryrefslogtreecommitdiff
path: root/engines/gob/sound.h
blob: 0a574ef06ca5b9c7d7a32ca6c94da6199ae7251f (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
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004 Ivan Dubrov
 * Copyright (C) 2004-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL$
 * $Id$
 *
 */
#ifndef GOB_SOUND_H
#define GOB_SOUND_H

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

namespace Gob {

class Snd : public Audio::AudioStream {
public:
	struct SoundDesc {
		Audio::SoundHandle handle;
		char *data;
		uint32 size;
		int16 repCount;
		int16 timerTicks;
		int16 inClocks;
		int16 frequency;
		int16 flag;
		SoundDesc() : data(0), size(0), repCount(0), timerTicks(0),
					  inClocks(0), frequency(0), flag(0) {}
	};

	char _playingSound;

	Snd(GobEngine *vm);
	~Snd();

	void speakerOn(int16 frequency, int32 length);
	void speakerOff(void);
	void speakerOnUpdate(uint32 milis);
	SoundDesc *loadSoundData(const char *path);
	void stopSound(int16 fadeLength);
	void playSample(SoundDesc *sndDesc, int16 repCount, int16 frequency, int16 fadeLength = 0);
	void playComposition(int16 *composition, int16 freqVal, SoundDesc **sndDescs = 0,
			int8 *sndTypes = 0, int8 sndCount = 60);
	void stopComposition(void);
	void waitEndPlay(bool interruptible = false, bool stopComp = true);

	// This deletes sndDesc and stops playing the sample.
	// If freedata is set, it also delete[]s the sample data.
	void freeSoundDesc(SoundDesc *sndDesc, bool freedata=true);

	int readBuffer(int16 *buffer, const int numSamples);
	bool isStereo() const { return false; }
	bool endOfData() const { return _end; }
	bool endOfStream() const { return false; }
	int getRate() const { return _rate; }

protected:
	// TODO: This is a very primitive square wave generator. The only thing is
	//       has in common with the PC speaker is that it sounds terrible.
	// Note: The SCUMM code has a PC speaker implementations; maybe it could be
	//       refactored to be reusable by all engines. And DosBox also has code
	//       for emulating the PC speaker.
	class SquareWaveStream : public Audio::AudioStream {
	private:
		uint _rate;
		bool _beepForever;
		uint32 _periodLength;
		uint32 _periodSamples;
		uint32 _remainingSamples;
		uint32 _mixedSamples;
		int16 _sampleValue;

	public:
		SquareWaveStream();

		void playNote(int freq, int32 ms, uint rate);
		void update(uint32 milis);
		void stop(uint32 milis);

		int readBuffer(int16 *buffer, const int numSamples);

		bool isStereo() const	{ return false; }
		bool endOfData() const	{ return false; }
		bool endOfStream() const { return false; }
		int getRate() const	{ return _rate; }
	};

	SquareWaveStream _speakerStream;
	Audio::SoundHandle _speakerHandle;
	uint32 _speakerStartTimeKey;

	Audio::SoundHandle *_activeHandle;
	Audio::SoundHandle _compositionHandle;
	
	SoundDesc **_compositionSamples;
	int8 *_compositionSampleTypes;
	int8 _compositionSampleCount;
	int16 _composition[50];
	int8 _compositionPos;

	Audio::SoundHandle _handle;
	Common::Mutex _mutex;
	SoundDesc *_curSoundDesc;
	bool _end;
	int8 *_data;
	uint32 _length;
	uint32 _rate;
	int32 _freq;
	int32 _repCount;
	double _offset;
	double _ratio;

	double _frac;
	int16 _cur;
	int16 _last;

	bool _fade;
	double _fadeVol;
	double _fadeVolStep;
	uint8 _fadeLength;
	uint32 _fadeSamples;
	uint32 _curFadeSamples;

	GobEngine *_vm;

	void setSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency, int16 fadeLength);
	void checkEndSample(void);
	void nextCompositionPos(void);
};

}				// End of namespace Gob

#endif