internal int FillChannel(int channel, Tone tone) { if (!this.State.Flags[Flags.SoundOn]) { return(-1); } SoundChannel soundChannel = this.soundChannels[channel]; if (soundChannel.Avail == 0) { return(-1); } byte[] soundData = soundChannel.Data; while (soundChannel.Duration == 0 && soundChannel.Duration != 0xffff) { int offset = soundChannel.DataIndex; if (offset >= (soundData.Length - 2)) { soundChannel.Duration = 0xffff; break; } soundChannel.Duration = (soundData[offset + 1] * 0x100) + soundData[offset]; if (soundChannel.Duration != 0 && soundChannel.Duration != 0xffff) { // Only tone channels dissolve if (channel != 3 && this.Preferences.SoundDissolve != 0) { soundChannel.DissolveCount = 0; } // Volume soundChannel.Attenuation = soundData[offset + 4] & 0x0f; // Frequency if (channel < 3) { soundChannel.FreqCount = (ushort)(soundData[offset + 2] & 0x3f); soundChannel.FreqCount <<= 4; soundChannel.FreqCount |= (byte)(soundData[offset + 3] & 0x0f); soundChannel.GenType = PcmSoundDriver.GenerateTone; } else { byte noiseType = (byte)(soundData[offset + 3] & 0x04); soundChannel.GenType = noiseType != 0 ? PcmSoundDriver.GenerateWhite : PcmSoundDriver.GeneratePeriod; int noiseFreq = (byte)(soundData[offset + 3] & 0x03); switch (noiseFreq) { case 0: soundChannel.FreqCount = 32; break; case 1: soundChannel.FreqCount = 64; break; case 2: soundChannel.FreqCount = 128; break; case 3: soundChannel.FreqCount = this.soundChannels[2].FreqCount * 2; break; } } } soundChannel.DataIndex += 5; } if (soundChannel.Duration != 0xffff) { tone.FrequencyCount = soundChannel.FreqCount; tone.Attenuation = this.CalculateVolume(soundChannel); tone.Type = soundChannel.GenType; soundChannel.Duration--; } else { soundChannel.Avail = 0; soundChannel.Attenuation = 0x0f; // silent soundChannel.AttenuationCopy = 0x0f; return(-1); } return(0); }
private int TonePcmCallback(ToneChannel ch, short[] buffer, int count) { int result = -1; int index = 0; while (count > 0) { if (ch.NoteCount <= 0) { // Get new tone data Tone tone = new Tone(); tone.FrequencyCount = 0; tone.Attenuation = 0x0f; tone.Type = GenerateTone; if (ch.Avail != 0 && this.interpreter.SoundManager.FillChannel(ch.AgiChannel, tone) == 0) { ch.Attenuation = tone.Attenuation; ch.FreqCount = tone.FrequencyCount; ch.GenType = tone.Type; // setup counters 'n stuff // 44100 samples per sec.. tone changes 60 times per sec ch.NoteCount = 44100 / 60; result = 0; } else { ch.GenType = GenerateSilence; ch.NoteCount = count; ch.Avail = 0; } } // Write nothing if (ch.FreqCount == 0 || ch.Attenuation == 0x0f) { ch.GenType = GenerateSilence; } // Find which is smaller, the buffer or the note count int fillSize = ch.NoteCount < count ? ch.NoteCount : count; switch (ch.GenType) { case GenerateTone: fillSize = PcmSoundDriver.SquareFill(ch, buffer, index, fillSize); break; case GeneratePeriod: case GenerateWhite: fillSize = PcmSoundDriver.NoiseFill(ch, buffer, index, fillSize); break; case GenerateSilence: default: fillSize = PcmSoundDriver.SilenceFill(buffer, index, fillSize); break; } ch.NoteCount -= fillSize; count -= fillSize; index += fillSize; } return(result); }