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
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (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, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 /*
24  * The low-pass filter code is based on UAE's audio filter code
25  * found in audio.c. UAE is licensed under the terms of the GPLv2.
26  *
27  * audio.c in UAE states the following:
28  * Copyright 1995, 1996, 1997 Bernd Schmidt
29  * Copyright 1996 Marcus Sundberg
30  * Copyright 1996 Manfred Thole
31  * Copyright 2006 Toni Wilen
32  */
33 
34 #include <math.h>
35 
36 #include "common/scummsys.h"
37 
38 #include "audio/mixer.h"
39 #include "audio/mods/paula.h"
40 #include "audio/null.h"
41 
42 namespace Audio {
43 
Paula(bool stereo,int rate,uint interruptFreq,FilterMode filterMode,int periodScaleDivisor)44 Paula::Paula(bool stereo, int rate, uint interruptFreq, FilterMode filterMode, int periodScaleDivisor) :
45 		_stereo(stereo), _rate(rate), _periodScale((double)kPalPaulaClock / (rate * periodScaleDivisor)), _intFreq(interruptFreq), _mutex(g_system->getMixer()->mutex()) {
46 
47 	_filterState.mode      = filterMode;
48 	_filterState.ledFilter = false;
49 	filterResetState();
50 
51 	_filterState.a0[0] = filterCalculateA0(rate,  6200);
52 	_filterState.a0[1] = filterCalculateA0(rate, 20000);
53 	_filterState.a0[2] = filterCalculateA0(rate,  7000);
54 
55 	clearVoices();
56 	_voice[0].panning = 191;
57 	_voice[1].panning = 63;
58 	_voice[2].panning = 63;
59 	_voice[3].panning = 191;
60 
61 	if (_intFreq == 0)
62 		_intFreq = _rate;
63 
64 	_curInt = 0;
65 	_timerBase = 1;
66 	_playing = false;
67 	_end = true;
68 }
69 
~Paula()70 Paula::~Paula() {
71 }
72 
clearVoice(byte voice)73 void Paula::clearVoice(byte voice) {
74 	assert(voice < NUM_VOICES);
75 
76 	_voice[voice].data = 0;
77 	_voice[voice].dataRepeat = 0;
78 	_voice[voice].length = 0;
79 	_voice[voice].lengthRepeat = 0;
80 	_voice[voice].period = 0;
81 	_voice[voice].volume = 0;
82 	_voice[voice].offset = Offset(0);
83 	_voice[voice].dmaCount = 0;
84 }
85 
readBuffer(int16 * buffer,const int numSamples)86 int Paula::readBuffer(int16 *buffer, const int numSamples) {
87 	Common::StackLock lock(_mutex);
88 
89 	memset(buffer, 0, numSamples * 2);
90 	if (!_playing) {
91 		return numSamples;
92 	}
93 
94 	if (_stereo)
95 		return readBufferIntern<true>(buffer, numSamples);
96 	else
97 		return readBufferIntern<false>(buffer, numSamples);
98 }
99 
100 /* Denormals are very small floating point numbers that force FPUs into slow
101  * mode. All lowpass filters using floats are suspectible to denormals unless
102  * a small offset is added to avoid very small floating point numbers.
103  */
104 #define DENORMAL_OFFSET (1E-10)
105 
106 /* Based on UAE.
107  * Original comment in UAE:
108  *
109  * Amiga has two separate filtering circuits per channel, a static RC filter
110  * on A500 and the LED filter. This code emulates both.
111  *
112  * The Amiga filtering circuitry depends on Amiga model. Older Amigas seem
113  * to have a 6 dB/oct RC filter with cutoff frequency such that the -6 dB
114  * point for filter is reached at 6 kHz, while newer Amigas have no filtering.
115  *
116  * The LED filter is complicated, and we are modelling it with a pair of
117  * RC filters, the other providing a highboost. The LED starts to cut
118  * into signal somewhere around 5-6 kHz, and there's some kind of highboost
119  * in effect above 12 kHz. Better measurements are required.
120  *
121  * The current filtering should be accurate to 2 dB with the filter on,
122  * and to 1 dB with the filter off.
123  */
filter(int32 input,Paula::FilterState & state,int voice)124 inline int32 filter(int32 input, Paula::FilterState &state, int voice) {
125 	float normalOutput, ledOutput;
126 
127 	switch (state.mode) {
128 	case Paula::kFilterModeA500:
129 		state.rc[voice][0] = state.a0[0] * input + (1 - state.a0[0]) * state.rc[voice][0] + DENORMAL_OFFSET;
130 		state.rc[voice][1] = state.a0[1] * state.rc[voice][0] + (1-state.a0[1]) * state.rc[voice][1];
131 		normalOutput = state.rc[voice][1];
132 
133 		state.rc[voice][2] = state.a0[2] * normalOutput        + (1 - state.a0[2]) * state.rc[voice][2];
134 		state.rc[voice][3] = state.a0[2] * state.rc[voice][2]  + (1 - state.a0[2]) * state.rc[voice][3];
135 		state.rc[voice][4] = state.a0[2] * state.rc[voice][3]  + (1 - state.a0[2]) * state.rc[voice][4];
136 
137 		ledOutput = state.rc[voice][4];
138 		break;
139 
140 	case Paula::kFilterModeA1200:
141 		normalOutput = input;
142 
143 		state.rc[voice][1] = state.a0[2] * normalOutput        + (1 - state.a0[2]) * state.rc[voice][1] + DENORMAL_OFFSET;
144 		state.rc[voice][2] = state.a0[2] * state.rc[voice][1]  + (1 - state.a0[2]) * state.rc[voice][2];
145 		state.rc[voice][3] = state.a0[2] * state.rc[voice][2]  + (1 - state.a0[2]) * state.rc[voice][3];
146 
147 		ledOutput = state.rc[voice][3];
148 		break;
149 
150 	case Paula::kFilterModeNone:
151 	default:
152 		return input;
153 
154 	}
155 
156 	return CLIP<int32>(state.ledFilter ? ledOutput : normalOutput, -32768, 32767);
157 }
158 
159 template<bool stereo>
mixBuffer(int16 * & buf,const int8 * data,Paula::Offset & offset,frac_t rate,int neededSamples,uint bufSize,byte volume,byte panning,Paula::FilterState & filterState,int voice)160 inline int mixBuffer(int16 *&buf, const int8 *data, Paula::Offset &offset, frac_t rate, int neededSamples, uint bufSize, byte volume, byte panning, Paula::FilterState &filterState, int voice) {
161 	int samples;
162 	for (samples = 0; samples < neededSamples && offset.int_off < bufSize; ++samples) {
163 		const int32 tmp = filter(((int32) data[offset.int_off]) * volume, filterState, voice);
164 		if (stereo) {
165 			*buf++ += (tmp * (255 - panning)) >> 7;
166 			*buf++ += (tmp * (panning)) >> 7;
167 		} else
168 			*buf++ += tmp;
169 
170 		// Step to next source sample
171 		offset.rem_off += rate;
172 		if (offset.rem_off >= (frac_t)FRAC_ONE) {
173 			offset.int_off += fracToInt(offset.rem_off);
174 			offset.rem_off &= FRAC_LO_MASK;
175 		}
176 	}
177 
178 	return samples;
179 }
180 
181 template<bool stereo>
readBufferIntern(int16 * buffer,const int numSamples)182 int Paula::readBufferIntern(int16 *buffer, const int numSamples) {
183 	int samples = stereo ? numSamples / 2 : numSamples;
184 	while (samples > 0) {
185 
186 		// Handle 'interrupts'. This gives subclasses the chance to adjust the channel data
187 		// (e.g. insert new samples, do pitch bending, whatever).
188 		if (_curInt == 0) {
189 			_curInt = _intFreq;
190 			interrupt();
191 		}
192 
193 		// Compute how many samples to generate: at most the requested number of samples,
194 		// of course, but we may stop earlier when an 'interrupt' is expected.
195 		const uint nSamples = MIN((uint)samples, _curInt);
196 
197 		// Loop over the four channels of the emulated Paula chip
198 		for (int voice = 0; voice < NUM_VOICES; voice++) {
199 			// No data, or paused -> skip channel
200 			if (!_voice[voice].data || (_voice[voice].period <= 0))
201 				continue;
202 
203 			// The Paula chip apparently run at 7.0937892 MHz in the PAL
204 			// version and at 7.1590905 MHz in the NTSC version. We divide this
205 			// by the requested the requested output sampling rate _rate
206 			// (typically 44.1 kHz or 22.05 kHz) obtaining the value _periodScale.
207 			// This is then divided by the "period" of the channel we are
208 			// processing, to obtain the correct output 'rate'.
209 			frac_t rate = doubleToFrac(_periodScale / _voice[voice].period);
210 			// Cap the volume
211 			_voice[voice].volume = MIN((byte) 0x40, _voice[voice].volume);
212 
213 
214 			Channel &ch = _voice[voice];
215 			int16 *p = buffer;
216 			int neededSamples = nSamples;
217 
218 			// NOTE: A Protracker (or other module format) player might actually
219 			// push the offset past the sample length in its interrupt(), in which
220 			// case the first mixBuffer() call should not mix anything, and the loop
221 			// should be triggered.
222 			// Thus, doing an assert(ch.offset.int_off < ch.length) here is wrong.
223 			// An example where this happens is a certain Protracker module played
224 			// by the OS/2 version of Hopkins FBI.
225 
226 			// Mix the generated samples into the output buffer
227 			neededSamples -= mixBuffer<stereo>(p, ch.data, ch.offset, rate, neededSamples, ch.length, ch.volume, ch.panning, _filterState, voice);
228 
229 			// Wrap around if necessary
230 			if (ch.offset.int_off >= ch.length) {
231 				// Important: Wrap around the offset *before* updating the voice length.
232 				// Otherwise, if length != lengthRepeat we would wrap incorrectly.
233 				// Note: If offset >= 2*len ever occurs, the following would be wrong;
234 				// instead of subtracting, we then should compute the modulus using "%=".
235 				// Since that requires a division and is slow, and shouldn't be necessary
236 				// in practice anyway, we only use subtraction.
237 				ch.offset.int_off -= ch.length;
238 				ch.dmaCount++;
239 
240 				ch.data = ch.dataRepeat;
241 				ch.length = ch.lengthRepeat;
242 			}
243 
244 			// If we have not yet generated enough samples, and looping is active: loop!
245 			if (neededSamples > 0 && ch.length > 2) {
246 				// Repeat as long as necessary.
247 				while (neededSamples > 0) {
248 					// Mix the generated samples into the output buffer
249 					neededSamples -= mixBuffer<stereo>(p, ch.data, ch.offset, rate, neededSamples, ch.length, ch.volume, ch.panning, _filterState, voice);
250 
251 					if (ch.offset.int_off >= ch.length) {
252 						// Wrap around. See also the note above.
253 						ch.offset.int_off -= ch.length;
254 						ch.dmaCount++;
255 					}
256 				}
257 			}
258 
259 		}
260 		buffer += stereo ? nSamples * 2 : nSamples;
261 		_curInt -= nSamples;
262 		samples -= nSamples;
263 	}
264 	return numSamples;
265 }
266 
filterResetState()267 void Paula::filterResetState() {
268 	for (int i = 0; i < NUM_VOICES; i++)
269 		for (int j = 0; j < 5; j++)
270 			_filterState.rc[i][j] = 0.0f;
271 }
272 
273 /* Based on UAE.
274  * Original comment in UAE:
275  *
276  * This computes the 1st order low-pass filter term b0.
277  * The a1 term is 1.0 - b0. The center frequency marks the -3 dB point.
278  */
filterCalculateA0(int rate,int cutoff)279 float Paula::filterCalculateA0(int rate, int cutoff) {
280 	float omega;
281 	/* The BLT correction formula below blows up if the cutoff is above nyquist. */
282 	if (cutoff >= rate / 2)
283 		return 1.0;
284 
285 	omega = 2 * M_PI * cutoff / rate;
286 	/* Compensate for the bilinear transformation. This allows us to specify the
287 	 * stop frequency more exactly, but the filter becomes less steep further
288 	 * from stopband. */
289 	omega = tan(omega / 2) * 2;
290 	return 1 / (1 + 1 / omega);
291 }
292 
293 } // End of namespace Audio
294 
295 
296 //	Plugin interface
297 //	(This can only create a null driver since apple II gs support seeems not to be implemented
298 //  and also is not part of the midi driver architecture. But we need the plugin for the options
299 //  menu in the launcher and for MidiDriver::detectDevice() which is more or less used by all engines.)
300 
301 class AmigaMusicPlugin : public NullMusicPlugin {
302 public:
getName() const303 	const char *getName() const {
304 		return _s("Amiga Audio emulator");
305 	}
306 
getId() const307 	const char *getId() const {
308 		return "amiga";
309 	}
310 
311 	MusicDevices getDevices() const;
312 };
313 
getDevices() const314 MusicDevices AmigaMusicPlugin::getDevices() const {
315 	MusicDevices devices;
316 	devices.push_back(MusicDevice(this, "", MT_AMIGA));
317 	return devices;
318 }
319 
320 //#if PLUGIN_ENABLED_DYNAMIC(AMIGA)
321 	//REGISTER_PLUGIN_DYNAMIC(AMIGA, PLUGIN_TYPE_MUSIC, AmigaMusicPlugin);
322 //#else
323 	REGISTER_PLUGIN_STATIC(AMIGA, PLUGIN_TYPE_MUSIC, AmigaMusicPlugin);
324 //#endif
325