예제 #1
0
    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);
    }
예제 #2
0
    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);
    }
예제 #3
0
        int ISoundPcmDriver.Open(AudioCallback callback, ToneChannel tc)
        {
            (this as ISoundPcmDriver).Lock();

            Sdl2SoundChannel channel = new Sdl2SoundChannel();

            channel.Handle = this.CreateHandle();
            if (channel.Handle == 0)
            {
                return(0);
            }

            channel.Callback    = callback;
            channel.ToneChannel = tc;
            channel.Available   = 1;

            this.channels.Add(channel);

            (this as ISoundPcmDriver).Unlock();

            return(channel.Handle);
        }
예제 #4
0
    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);
    }
예제 #5
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);
    }