MCPcopy Create free account
hub / github.com/OpenFodder/openfodder / readBufferIntern

Method readBufferIntern

Source/Amiga/paula.cpp:195–287  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

193
194template<bool stereo>
195int Paula::readBufferIntern(int16 *buffer, const int numSamples) {
196 int samples = stereo ? numSamples / 2 : numSamples;
197 while (samples > 0) {
198
199 // Handle 'interrupts'. This gives subclasses the chance to adjust the channel data
200 // (e.g. insert new samples, do pitch bending, whatever).
201 if (_curInt == 0) {
202 _curInt = _intFreq;
203 interrupt();
204 }
205
206 // Compute how many samples to generate: at most the requested number of samples,
207 // of course, but we may stop earlier when an 'interrupt' is expected.
208 const unsigned int nSamples = std::min((unsigned int)samples, _curInt);
209
210 // Loop over the four channels of the emulated Paula chip
211 for (int voice = 0; voice < NUM_VOICES; voice++) {
212 // No data, or paused -> skip channel
213 if (!_voice[voice].data || (_voice[voice].period <= 0))
214 continue;
215
216 // The Paula chip apparently run at 7.0937892 MHz in the PAL
217 // version and at 7.1590905 MHz in the NTSC version. We divide this
218 // by the requested the requested output sampling rate _rate
219 // (typically 44.1 kHz or 22.05 kHz) obtaining the value _periodScale.
220 // This is then divided by the "period" of the channel we are
221 // processing, to obtain the correct output 'rate'.
222 frac_t rate = doubleToFrac(_periodScale / _voice[voice].period);
223 // Cap the volume
224 _voice[voice].volume = std::min((uint8) volumeMax[voice], _voice[voice].volume);
225
226
227 Channel &ch = _voice[voice];
228 int16 *p = buffer;
229 int neededSamples = nSamples;
230
231 // NOTE: A Protracker (or other module format) player might actually
232 // push the offset past the sample length in its interrupt(), in which
233 // case the first mixBuffer() call should not mix anything, and the loop
234 // should be triggered.
235 // Thus, doing an assert(ch.offset.int_off < ch.length) here is wrong.
236 // An example where this happens is a certain Protracker module played
237 // by the OS/2 version of Hopkins FBI.
238
239 // Mix the generated samples into the output buffer
240 neededSamples -= mixBuffer<stereo>(p, ch.data, ch.offset, rate, neededSamples, ch.length, ch.volume, ch.panning, _filterState, voice);
241
242 // Wrap around if necessary
243 if (ch.offset.int_off >= ch.length) {
244 // Important: Wrap around the offset *before* updating the voice length.
245 // Otherwise, if length != lengthRepeat we would wrap incorrectly.
246 // Note: If offset >= 2*len ever occurs, the following would be wrong;
247 // instead of subtracting, we then should compute the modulus using "%=".
248 // Since that requires a division and is slow, and shouldn't be necessary
249 // in practice anyway, we only use subtraction.
250 ch.offset.int_off -= ch.length;
251 ch.dmaCount++;
252

Callers

nothing calls this directly

Calls 1

doubleToFracFunction · 0.85

Tested by

no test coverage detected