コード例 #1
0
        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);
        }
コード例 #2
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);
        }