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)); }
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; }