private static int SquareFill(ToneChannel ch, short[] buffer, int index, int count) { if (ch.GenType != ch.GenTypePrev) { ch.FreqCountPrev = -1; ch.Noise.Sign = 1; ch.GenTypePrev = ch.GenType; } if (ch.FreqCount != ch.FreqCountPrev) { ch.Noise.Scale = (44100 / 2) * ch.FreqCount; ch.Noise.Count = ch.Noise.Scale; ch.FreqCountPrev = ch.FreqCount; } for (int i = index; i < (index + count); i++) { buffer[i] = (ch.Noise.Sign != 0) ? VolumeTable[ch.Attenuation] : (short)(0 - VolumeTable[ch.Attenuation]); // get next sample ch.Noise.Count -= Mult; while (ch.Noise.Count <= 0) { ch.Noise.Sign ^= 1; ch.Noise.Count += ch.Noise.Scale; } } return(count); }
private static int NoiseFill(ToneChannel ch, short[] buffer, int index, int count) { if (ch.GenType != ch.GenTypePrev) { ch.FreqCountPrev = -1; ch.GenTypePrev = ch.GenType; } if (ch.FreqCount != ch.FreqCountPrev) { ch.Noise.Scale = (44100 / 2) * ch.FreqCount; ch.Noise.Count = ch.Noise.Scale; ch.FreqCountPrev = ch.FreqCount; ch.Noise.Feedback = ch.GenType == GenerateWhite ? FeedbackWhiteNoise : FeedbackPeriodicNoise; // reset noise shifter ch.Noise.NoiseState = NoiseGeneratorStartPreset; ch.Noise.Sign = (int)(ch.Noise.NoiseState & 1); } for (int i = index; i < (index + count); i++) { buffer[i] = (ch.Noise.Sign != 0) ? VolumeTable[ch.Attenuation] : (short)(0 - VolumeTable[ch.Attenuation]); // get next sample ch.Noise.Count -= Mult; while (ch.Noise.Count <= 0) { if ((ch.Noise.NoiseState & 1) != 0) { ch.Noise.NoiseState ^= (uint)ch.Noise.Feedback; } ch.Noise.NoiseState >>= 1; ch.Noise.Sign = (int)(ch.Noise.NoiseState & 1); ch.Noise.Count += ch.Noise.Scale; } } return(count); }
int ISoundDriver.Open(int channel) { ToneChannel tc = new ToneChannel(); tc.Attenuation = 0xf; // silence tc.AgiChannel = channel; tc.FreqCount = 250; tc.FreqCountPrev = -1; tc.GenType = GenerateTone; tc.GenTypePrev = -1; tc.NoteCount = 0; tc.Avail = 1; this.channels.Add(tc); tc.Handle = this.pcmDriver.Open(this.TonePcmCallback, tc); if (tc.Handle == 0) { this.channels.Remove(tc); return(0); } return(tc.Handle); }
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); }