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 
29 namespace Audio {
30 
36 class Paula : public AudioStream {
37 public:
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);
103  bool isStereo() const { return _stereo; }
104  bool endOfData() const { return _end; }
105  int getRate() const { return _rate; }
106 
107 protected:
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 
222 private:
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: paula.h:65
int readBuffer(int16 *buffer, const int numSamples)
Definition: paula.h:108
Definition: paula.h:72
Definition: mutex.h:67
Definition: audiostream.h:50
int getRate() const
Definition: paula.h:105
bool isStereo() const
Definition: paula.h:103
Definition: paula.h:36
bool endOfData() const
Definition: paula.h:104
int32 frac_t
Definition: frac.h:52
Definition: system.h:38