void IMuseDigital::callback() { Common::StackLock lock(_mutex, "IMuseDigital::callback()"); for (int l = 0; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) { Track *track = _track[l]; if (track->used) { // Ignore tracks which are about to finish. Also, if it did finish in the meantime, // mark it as unused. if (!track->stream) { if (!_mixer->isSoundHandleActive(track->mixChanHandle)) memset(track, 0, sizeof(Track)); continue; } if (_pause) return; if (track->volFadeUsed) { if (track->volFadeStep < 0) { if (track->vol > track->volFadeDest) { track->vol += track->volFadeStep; if (track->vol < track->volFadeDest) { track->vol = track->volFadeDest; track->volFadeUsed = false; } if (track->vol == 0) { // Fade out complete -> remove this track flushTrack(track); continue; } } } else if (track->volFadeStep > 0) { if (track->vol < track->volFadeDest) { track->vol += track->volFadeStep; if (track->vol > track->volFadeDest) { track->vol = track->volFadeDest; track->volFadeUsed = false; } } } debug(5, "Fade: sound(%d), Vol(%d)", track->soundId, track->vol / 1000); } if (!track->souStreamUsed) { assert(track->stream); byte *tmpSndBufferPtr = NULL; int32 curFeedSize = 0; if (track->curRegion == -1) { switchToNextRegion(track); if (!track->stream) // Seems we reached the end of the stream continue; } int bits = _sound->getBits(track->soundDesc); int channels = _sound->getChannels(track->soundDesc); int32 feedSize = track->feedSize / _callbackFps; if (track->stream->endOfData()) { feedSize *= 2; } if ((bits == 12) || (bits == 16)) { if (channels == 1) feedSize &= ~1; if (channels == 2) feedSize &= ~3; } else if (bits == 8) { if (channels == 2) feedSize &= ~1; } else { warning("IMuseDigita::callback: Unexpected sample width, %d bits", bits); continue; } if (feedSize == 0) continue; do { if (bits == 12) { byte *tmpPtr = NULL; feedSize += track->dataMod12Bit; int tmpFeedSize12Bits = (feedSize * 3) / 4; int tmpLength12Bits = (tmpFeedSize12Bits / 3) * 4; track->dataMod12Bit = feedSize - tmpLength12Bits; int32 tmpOffset = (track->regionOffset * 3) / 4; int tmpFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpPtr, tmpOffset, tmpFeedSize12Bits); curFeedSize = BundleCodecs::decode12BitsSample(tmpPtr, &tmpSndBufferPtr, tmpFeedSize); free(tmpPtr); } else if (bits == 16) { curFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize); if (channels == 1) { curFeedSize &= ~1; } if (channels == 2) { curFeedSize &= ~3; } } else if (bits == 8) { curFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize); if (_radioChatterSFX && track->soundId == 10000) { if (curFeedSize > feedSize) curFeedSize = feedSize; byte *buf = (byte *)malloc(curFeedSize); int index = 0; int count = curFeedSize - 4; byte *ptr_1 = tmpSndBufferPtr; byte *ptr_2 = tmpSndBufferPtr + 4; int value = ptr_1[0] - 0x80; value += ptr_1[1] - 0x80; value += ptr_1[2] - 0x80; value += ptr_1[3] - 0x80; do { int t = *ptr_1++; int v = t - (value / 4); value = *ptr_2++ - 0x80 + (value - t + 0x80); buf[index++] = v * 2 + 0x80; } while (--count); buf[curFeedSize - 1] = 0x80; buf[curFeedSize - 2] = 0x80; buf[curFeedSize - 3] = 0x80; buf[curFeedSize - 4] = 0x80; free(tmpSndBufferPtr); tmpSndBufferPtr = buf; } if (channels == 2) { curFeedSize &= ~1; } } if (curFeedSize > feedSize) curFeedSize = feedSize; if (_mixer->isReady()) { track->stream->queueBuffer(tmpSndBufferPtr, curFeedSize, DisposeAfterUse::YES, makeMixerFlags(track)); track->regionOffset += curFeedSize; } else free(tmpSndBufferPtr); if (_sound->isEndOfRegion(track->soundDesc, track->curRegion)) { switchToNextRegion(track); if (!track->stream) // Seems we reached the end of the stream break; } feedSize -= curFeedSize; assert(feedSize >= 0); } while (feedSize != 0); } if (_mixer->isReady()) { _mixer->setChannelVolume(track->mixChanHandle, track->getVol()); _mixer->setChannelBalance(track->mixChanHandle, track->getPan()); } } } }
void Imuse::callback() { Common::StackLock lock(_mutex); for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) { Track *track = _track[l]; if (track->used) { // Ignore tracks which are about to finish. Also, if it did finish in the meantime, // mark it as unused. if (!track->stream) { if (!track->soundDesc || !g_system->getMixer()->isSoundHandleActive(track->handle)) memset(track, 0, sizeof(Track)); continue; } if (_pause) return; if (track->volFadeUsed) { if (track->volFadeStep < 0) { if (track->vol > track->volFadeDest) { track->vol += track->volFadeStep; //warning("fade: %d", track->vol); if (track->vol < track->volFadeDest) { track->vol = track->volFadeDest; track->volFadeUsed = false; } if (track->vol == 0) { // Fade out complete -> remove this track flushTrack(track); continue; } } } else if (track->volFadeStep > 0) { if (track->vol < track->volFadeDest) { track->vol += track->volFadeStep; //warning("fade: %d", track->vol); if (track->vol > track->volFadeDest) { track->vol = track->volFadeDest; track->volFadeUsed = false; } } } } if (track->panFadeUsed) { if (track->panFadeStep < 0) { if (track->pan > track->panFadeDest) { track->pan += track->panFadeStep; if (track->pan < track->panFadeDest) { track->pan = track->panFadeDest; track->panFadeUsed = false; } } } else if (track->panFadeStep > 0) { if (track->pan < track->panFadeDest) { track->pan += track->panFadeStep; if (track->pan > track->panFadeDest) { track->pan = track->panFadeDest; track->panFadeUsed = false; } } } } assert(track->stream); byte *data = NULL; int32 result = 0; if (track->curRegion == -1) { switchToNextRegion(track); if (!track->stream) // Seems we reached the end of the stream continue; } int channels = _sound->getChannels(track->soundDesc); int32 mixer_size = track->feedSize / _callbackFps; if (track->stream->endOfData()) { mixer_size *= 2; } if (channels == 1) mixer_size &= ~1; if (channels == 2) mixer_size &= ~3; if (mixer_size == 0) continue; do { result = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &data, track->regionOffset, mixer_size); if (channels == 1) { result &= ~1; } if (channels == 2) { result &= ~3; } if (result > mixer_size) result = mixer_size; if (g_system->getMixer()->isReady()) { track->stream->queueBuffer(data, result, DisposeAfterUse::YES, makeMixerFlags(track->mixerFlags)); track->regionOffset += result; } else delete[] data; if (_sound->isEndOfRegion(track->soundDesc, track->curRegion)) { switchToNextRegion(track); if (!track->stream) break; } mixer_size -= result; assert(mixer_size >= 0); } while (mixer_size); if (g_system->getMixer()->isReady()) { g_system->getMixer()->setChannelVolume(track->handle, track->getVol()); g_system->getMixer()->setChannelBalance(track->handle, track->getPan()); } } } }