ScummVM API documentation
paula.h
1/* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#ifndef AUDIO_MODS_PAULA_H
23#define AUDIO_MODS_PAULA_H
24
25#include "audio/audiostream.h"
26#include "common/frac.h"
27#include "common/mutex.h"
28
29namespace Audio {
30
36class Paula : public AudioStream {
37public:
38 static const int NUM_VOICES = 4;
39 // Default panning value for left channels.
40 static const int PANNING_LEFT = 63;
41 // Default panning value for right channels.
42 static const int PANNING_RIGHT = 191;
43 enum {
44 kPalSystemClock = 7093790,
45 kNtscSystemClock = 7159090,
46 kPalCiaClock = kPalSystemClock / 10,
47 kNtscCiaClock = kNtscSystemClock / 10,
48 kPalPaulaClock = kPalSystemClock / 2,
49 kNtscPaulaClock = kNtscSystemClock / 2
50 };
51
52 enum FilterMode {
53 kFilterModeNone = 0,
54 kFilterModeA500,
55 kFilterModeA1200,
56
57#if defined(__DS__)
58 kFilterModeDefault = kFilterModeNone
59#else
60 kFilterModeDefault = kFilterModeA1200
61#endif
62 };
63
64 /* TODO: Document this */
65 struct Offset {
66 uint int_off; // integral part of the offset
67 frac_t rem_off; // fractional part of the offset, at least 0 and less than 1
68
69 explicit Offset(int off = 0) : int_off(off), rem_off(0) {}
70 };
71
72 struct FilterState {
73 FilterMode mode;
74 bool ledFilter;
75
76 float a0[3];
77 float rc[NUM_VOICES][5];
78 };
79
80 Paula(bool stereo = false, int rate = 44100, uint interruptFreq = 0,
81 FilterMode filterMode = kFilterModeDefault, int periodScaleDivisor = 1);
82 ~Paula();
83
84 bool playing() const { return _playing; }
85 void setTimerBaseValue( uint32 ticksPerSecond ) { _timerBase = ticksPerSecond; }
86 uint32 getTimerBaseValue() { return _timerBase; }
87 void setSingleInterrupt(uint sampleDelay) { assert(sampleDelay < _intFreq); _curInt = sampleDelay; }
88 void setSingleInterruptUnscaled(uint timerDelay) {
89 setSingleInterrupt((uint)(((double)timerDelay * getRate()) / _timerBase));
90 }
91 void setInterruptFreq(uint sampleDelay) { _intFreq = sampleDelay; _curInt = 0; }
92 void setInterruptFreqUnscaled(uint timerDelay) {
93 setInterruptFreq((uint)(((double)timerDelay * getRate()) / _timerBase));
94 }
95 void clearVoice(byte voice);
96 void clearVoices() { for (int i = 0; i < NUM_VOICES; ++i) clearVoice(i); }
97 void startPlay() { filterResetState(); _playing = true; }
98 void stopPlay() { _playing = false; }
99 void pausePlay(bool pause) { _playing = !pause; }
100
101// AudioStream API
102 int readBuffer(int16 *buffer, const int numSamples) override;
103 bool isStereo() const override { return _stereo; }
104 bool endOfData() const override { return _end; }
105 int getRate() const override { return _rate; }
106
107protected:
108 struct Channel {
109 const int8 *data;
110 const int8 *dataRepeat;
111 uint32 length;
112 uint32 lengthRepeat;
113 int16 period;
114 byte volume;
115 Offset offset;
116 byte panning; // For stereo mixing: 0 = far left, 255 = far right
117 int dmaCount;
118 bool interrupt;
119 };
120
121 bool _end;
122 Common::Mutex &_mutex;
123
124 virtual void interrupt() = 0;
125
126 virtual void interruptChannel(byte channel) { }
127
128 void startPaula() {
129 _playing = true;
130 _end = false;
131 }
132
133 void stopPaula() {
134 _playing = false;
135 _end = true;
136 }
137
138 void setChannelPanning(byte channel, byte panning) {
139 assert(channel < NUM_VOICES);
140 _voice[channel].panning = panning;
141 }
142
143 void disableChannel(byte channel) {
144 assert(channel < NUM_VOICES);
145 _voice[channel].data = 0;
146 }
147
148 void enableChannel(byte channel) {
149 assert(channel < NUM_VOICES);
150 Channel &ch = _voice[channel];
151 ch.data = ch.dataRepeat;
152 ch.length = ch.lengthRepeat;
153 // actually first 2 bytes are dropped?
154 ch.offset = Offset(0);
155 // ch.period = ch.periodRepeat;
156 }
157
158 void setChannelInterrupt(byte channel, bool enable) {
159 assert(channel < NUM_VOICES);
160 _voice[channel].interrupt = enable;
161 }
162
163 void setChannelPeriod(byte channel, int16 period) {
164 assert(channel < NUM_VOICES);
165 _voice[channel].period = period;
166 }
167
168 void setChannelVolume(byte channel, byte volume) {
169 assert(channel < NUM_VOICES);
170 _voice[channel].volume = volume;
171 }
172
173 void setChannelSampleStart(byte channel, const int8 *data) {
174 assert(channel < NUM_VOICES);
175 _voice[channel].dataRepeat = data;
176 }
177
178 void setChannelSampleLen(byte channel, uint32 length) {
179 assert(channel < NUM_VOICES);
180 assert(length < 32768/2);
181 _voice[channel].lengthRepeat = 2 * length;
182 }
183
184 void setChannelData(uint8 channel, const int8 *data, const int8 *dataRepeat, uint32 length, uint32 lengthRepeat, int32 offset = 0) {
185 assert(channel < NUM_VOICES);
186
187 Channel &ch = _voice[channel];
188
189 ch.dataRepeat = data;
190 ch.lengthRepeat = length;
191 enableChannel(channel);
192 ch.offset = Offset(offset);
193
194 ch.dataRepeat = dataRepeat;
195 ch.lengthRepeat = lengthRepeat;
196 }
197
198 void setChannelOffset(byte channel, Offset offset) {
199 assert(channel < NUM_VOICES);
200 _voice[channel].offset = offset;
201 }
202
203 Offset getChannelOffset(byte channel) {
204 assert(channel < NUM_VOICES);
205 return _voice[channel].offset;
206 }
207
208 int getChannelDmaCount(byte channel) {
209 assert(channel < NUM_VOICES);
210 return _voice[channel].dmaCount;
211 }
212
213 void setChannelDmaCount(byte channel, int dmaVal = 0) {
214 assert(channel < NUM_VOICES);
215 _voice[channel].dmaCount = dmaVal;
216 }
217
218 void setAudioFilter(bool enable) {
219 _filterState.ledFilter = enable;
220 }
221
222private:
223 Channel _voice[NUM_VOICES];
224
225 const bool _stereo;
226 const int _rate;
227 const double _periodScale;
228 uint _intFreq;
229 uint _curInt;
230 uint32 _timerBase;
231 bool _playing;
232
233 FilterState _filterState;
234
235 template<bool stereo>
236 int readBufferIntern(int16 *buffer, const int numSamples);
237
238 void filterResetState();
239 float filterCalculateA0(int rate, int cutoff);
240};
241
242} // End of namespace Audio
243
244#endif
Definition: audiostream.h:50
Definition: paula.h:36
bool endOfData() const override
Definition: paula.h:104
bool isStereo() const override
Definition: paula.h:103
int readBuffer(int16 *buffer, const int numSamples) override
int getRate() const override
Definition: paula.h:105
Definition: mutex.h:67
int32 frac_t
Definition: frac.h:52
Definition: system.h:39
Definition: paula.h:108
Definition: paula.h:72
Definition: paula.h:65