예제 #1
0
void Sprite::setScale(frac_t scale) {
	assert(scale != 0);

	_scale        = scale;
	// Is there a better way to do that? :/
	_scaleInverse = doubleToFrac(1.0 / fracToDouble(scale));
}
예제 #2
0
uint32 SoundGen2GS::mixSound() {
	int i, b;

	memset(_sndBuffer, 0, BUFFER_SIZE << 1);

	if (!_playing || _playingSound == -1)
		return BUFFER_SIZE;

	// Handle Apple IIGS sound mixing here
	// TODO: Implement playing both waves in an oscillator
	// TODO: Implement swap-mode in an oscillator
	for (uint midiChan = 0; midiChan < _midiChannels.size(); midiChan++) {
		for (uint gsChan = 0; gsChan < _midiChannels[midiChan]._gsChannels.size(); gsChan++) {
			IIgsChannelInfo &channel = _midiChannels[midiChan]._gsChannels[gsChan];
			if (channel.playing()) { // Only mix in actively playing channels
				// Frequency multiplier was 1076.0 based on tests made with MESS 0.117.
				// Tests made with KEGS32 averaged the multiplier to around 1045.
				// So this is a guess but maybe it's 1046.5... i.e. C6's frequency?
				double hertz = C6_FREQ * pow(SEMITONE, fracToDouble(channel.note));
				channel.posAdd = doubleToFrac(hertz / getRate());
				channel.vol = doubleToFrac(fracToDouble(channel.envVol) * fracToDouble(channel.chanVol) / 127.0);
				double tempVol = fracToDouble(channel.vol)/127.0;
				for (i = 0; i < IIGS_BUFFER_SIZE; i++) {
					b = channel.relocatedSample[fracToInt(channel.pos)];
					// TODO: Find out what volume/amplification setting is loud enough
					//       but still doesn't clip when playing many channels on it.
					_sndBuffer[i] += (int16) (b * tempVol * 256/4);
					channel.pos += channel.posAdd;

					if (channel.pos >= intToFrac(channel.size)) {
						if (channel.loop) {
							// Don't divide by zero on zero length samples
							channel.pos %= intToFrac(channel.size + (channel.size == 0));
							// Probably we should loop the envelope too
							channel.envSeg = 0;
							channel.envVol = channel.startEnvVol;
						} else {
							channel.pos = channel.chanVol = 0;
							channel.end = true;
							break;
						}
					}
				}

				if (channel.envSeg < ENVELOPE_SEGMENT_COUNT) {
					const IIgsEnvelopeSegment &seg = channel.ins->env.seg[channel.envSeg];
					// I currently assume enveloping works with the same speed as the MIDI
					// (i.e. with 1/60ths of a second ticks).
					// TODO: Check if enveloping really works with the same speed as MIDI
					frac_t envVolDelta = doubleToFrac(seg.inc/256.0);
					if (intToFrac(seg.bp) >= channel.envVol) {
						channel.envVol += envVolDelta;
						if (channel.envVol >= intToFrac(seg.bp)) {
							channel.envVol = intToFrac(seg.bp);
							channel.envSeg += 1;
						}
					} else {
						channel.envVol -= envVolDelta;
						if (channel.envVol <= intToFrac(seg.bp)) {
							channel.envVol = intToFrac(seg.bp);
							channel.envSeg += 1;
						}
					}
				}
			}
		}
	}

	removeStoppedSounds();

	return IIGS_BUFFER_SIZE;
}