예제 #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Note"/> class.
        /// </summary>
        /// <param name="audioBuffer">The audioBuffer to fill<see cref="List{float}"/></param>
        /// <param name="sampleRate">The sampleRate<see cref="int"/></param>
        /// <param name="oscillator">The oscillator reference<see cref="Oscillator"/></param>
        /// <param name="duration">The duration of the note<see cref="float"/></param>
        /// <param name="volume">The volume of the note<see cref="byte"/></param>
        /// <param name="waveform">The waveform of the note<see cref="byte"/></param>
        /// <param name="pitch">The pitch of the note<see cref="byte"/></param>
        /// <param name="pitchFrom">The pitch to start the note from<see cref="int"/></param>
        /// <param name="fadeIn">The fadeIn length<see cref="float"/></param>
        /// <param name="fadeOut">The fadeOut length<see cref="float"/></param>
        /// <param name="vibrato">If it should have a vibrato effect<see cref="bool"/></param>
        public Note(ref List <float> audioBuffer, int sampleRate, ref Oscillator oscillator, float duration, byte volume, byte waveform, byte pitch, int pitchFrom = -1, float fadeIn = 1, float fadeOut = 1, bool vibrato = false)
        {
            _audioBuffer = audioBuffer;

            _duration   = duration;
            _sampleRate = sampleRate;

            _fadeIn  = fadeIn * duration / 100.0f;
            _fadeOut = fadeOut * duration / 100.0f;

            _timePassed = 0.0f;
            _volume     = 1;

            isCustom      = waveform > 7;
            targetVolume  = volume / 7.0f;
            this.waveform = waveform;
            this.pitch    = pitch;

            if (pitchFrom == -1)
            {
                _pitchFrom = pitch;
            }
            else
            {
                _pitchFrom = pitchFrom;
            }

            _oscillator = oscillator;

            _vibrato = vibrato;
        }
예제 #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MusicPlayer"/> class.
        /// </summary>
        /// <param name="memory">The memory unit reference<see cref="MemoryUnit"/></param>
        /// <param name="audioBuffer">The audioBuffer reference<see cref="List{float}"/></param>
        /// <param name="sampleRate">The sampleRate for the music<see cref="int"/></param>
        public MusicPlayer(ref MemoryUnit memory, ref List <float> audioBuffer, int sampleRate)
        {
            sfxs = new Sfx[4] {
                null, null, null, null
            };
            isPlaying = false;
            _ram      = memory.ram;

            _audioBuffer = audioBuffer;
            _sampleRate  = sampleRate;

            _oscillator = new Oscillator(_sampleRate);

            patternData = new PatternData[64];
            for (int i = 0; i < patternData.Length; i += 1)
            {
                byte[] vals = { _ram[i * 4 + 0 + util.ADDR_SONG],
                                _ram[i * 4 + 1 + util.ADDR_SONG],
                                _ram[i * 4 + 2 + util.ADDR_SONG],
                                _ram[i * 4 + 3 + util.ADDR_SONG] };

                if ((vals[0] & 0x80) == 0x80)
                {
                    patternData[i].loopStart = true;
                }
                if ((vals[1] & 0x80) == 0x80)
                {
                    patternData[i].loopEnd = true;
                }
                if ((vals[2] & 0x80) == 0x80)
                {
                    patternData[i].shouldStop = true;
                }

                patternData[i].channels = new ChannelData[4];
                for (int j = 0; j < 4; j += 1)
                {
                    patternData[i].channels[j] = new ChannelData();
                    if ((vals[j] & 0b01000000) != 0)
                    {
                        patternData[i].channels[j].isSilent = true;
                    }
                    patternData[i].channels[j].sfxIndex = (byte)(vals[j] & 0b00111111);
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Sfx"/> class.
        /// </summary>
        /// <param name="_sfxData">The _sfxData to use<see cref="byte[]"/></param>
        /// <param name="_sfxIndex">The _sfxIndex that this sfx references to<see cref="int"/></param>
        /// <param name="audioBuffer">The audioBuffer to fill with data<see cref="List{float}"/></param>
        /// <param name="oscillator">The oscillator reference<see cref="Oscillator"/></param>
        /// <param name="sampleRate">The sampleRate<see cref="int"/></param>
        /// <param name="audioBufferIndex">The index to start filling the audio buffer<see cref="int"/></param>
        public Sfx(byte[] _sfxData, int _sfxIndex, ref List <float> audioBuffer, ref Oscillator oscillator, int sampleRate, int audioBufferIndex = 0)
        {
            notes        = new P8Note[32];
            _audioBuffer = audioBuffer;

            duration  = _sfxData[65] / 120.0f;
            startLoop = _sfxData[66];
            endLoop   = _sfxData[67];

            _sampleRate = sampleRate;
            sfxIndex    = _sfxIndex;

            _oscillator = oscillator;

            Console.WriteLine($"header {_sfxData[64]} {_sfxData[65]} {_sfxData[66]} {_sfxData[67]}");

            for (int i = 0; i < _sfxData.Length - 4; i += 2)
            {
                byte lo = _sfxData[i];
                byte hi = _sfxData[i + 1];

                notes[i / 2].pitch    = (byte)(lo & 0b00111111);
                notes[i / 2].waveform = (byte)(((lo & 0b11000000) >> 6) | ((hi & 0b1) << 2));
                notes[i / 2].volume   = (byte)((hi & 0b00001110) >> 1);
                notes[i / 2].effect   = (byte)((hi & 0b01110000) >> 4);
                notes[i / 2].isCustom = (byte)((hi & 0b10000000) >> 7) == 1;

                Console.WriteLine($"{i} {notes[i / 2].pitch} {notes[i / 2].waveform} {notes[i / 2].volume} {notes[i / 2].effect} {notes[i / 2].isCustom}");
            }

            oscillator  = new Oscillator(sampleRate);
            notesToPlay = new Queue <Note>();

            this.audioBufferIndex = audioBufferIndex;

            isActive = true;

            _fadeIn = 0.05f / duration;
        }
예제 #4
0
        /// <summary>
        /// play sfx n on channel (0..3) from note offset (0..31) for length notes
        /// n -1 to stop sound on that channel
        /// n -2 to release sound on that channel from looping
        /// Any music playing on the channel will be halted
        /// offset in number of notes(0..31)

        /// channel -1 (default) to automatically choose a channel that is not being used
        /// channel -2 to stop the sound from playing on any channel
        /// </summary>
        /// <param name="n">The sfx number<see cref="int"/></param>
        /// <param name="channel">The channel to play the sfx in<see cref="int?"/></param>
        /// <param name="offset">The offset note to start playing from<see cref="int?"/></param>
        /// <param name="length">The length of the sfx to play<see cref="int?"/></param>
        /// <returns>The <see cref="object"/></returns>
        public object Sfx(int n, int?channel = -1, int?offset = 0, int?length = 32)
        {
            switch (n)
            {
            case -1:
                if (channel == -1)
                {
                    StopAllChannels();
                    break;
                }

                if (channel < 0 || channel >= channelCount)
                {
                    break;
                }

                sfxChannels[channel.Value] = null;
                break;

            case -2:
                if (channel.Value < 0 || channel.Value >= channelCount)
                {
                    break;
                }

                if (sfxChannels[channel.Value] != null)
                {
                    sfxChannels[channel.Value].loop = false;
                }
                break;

            default:

                // If sound is already playing, stop it.
                int?index = FindSoundOnAChannel(n);
                if (index != null)
                {
                    sfxChannels[index.Value] = null;
                }

                if (channel == -1)
                {
                    channel = FindAvailableChannel();
                    if (channel == null)
                    {
                        break;
                    }
                }

                if (channel == -2)
                {
                    break;
                }

                byte[] _sfxData = new byte[68];
                Buffer.BlockCopy(_memory.ram, util.ADDR_SFX + 68 * n, _sfxData, 0, 68);

                Oscillator osc = new Oscillator(sampleRate);
                sfxChannels[channel.Value]             = new Sfx(_sfxData, n, ref audioBuffer, ref osc, sampleRate);
                sfxChannels[channel.Value].currentNote = offset.Value;
                sfxChannels[channel.Value].lastIndex   = offset.Value + length.Value - 1;
                sfxChannels[channel.Value].Start();
                break;
            }

            return(null);
        }