| 193 | |
| 194 | template<bool stereo> |
| 195 | int 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 |
nothing calls this directly
no test coverage detected