示例#1
0
        public bool IsGBInstrument()
        {
            if (Type == (int)M4AVoiceFlags.KeySplit || Type == (int)M4AVoiceFlags.Drum)
            {
                return(false);
            }
            M4AVoiceType vType = (M4AVoiceType)(Type & 0x7);

            return(vType >= M4AVoiceType.Square1 && vType <= M4AVoiceType.Noise);
        }
示例#2
0
        public Channel PlayNote(Track track, sbyte note, byte velocity, int duration)
        {
            int shift = note + track.KeyShift;

            note           = (sbyte)(shift.Clamp(0, 0x7F));
            track.PrevNote = note;

            if (!track.Ready)
            {
                return(null);
            }

            var          owner    = track.Index;
            WrappedVoice voice    = null;
            bool         fromDrum = false;

            try
            {
                voice = Song.VoiceTable.GetVoiceFromNote(track.Voice, note, out fromDrum);
            }
            catch
            {
                System.Console.WriteLine("Track {0} tried to play a bad note... Voice {1} Note {2}", owner, track.Voice, note);
                return(null);
            }

            var aNote = new Note {
                Duration = duration, Velocity = velocity, OriginalKey = note, Key = fromDrum ? voice.Voice.GetRootNote() : note
            };

            if (voice.Voice is M4AVoiceEntry m4a)
            {
                M4AVoiceType type = (M4AVoiceType)(m4a.Type & 0x7);
                switch (type)
                {
                case M4AVoiceType.Direct:
                    bool bFixed = (m4a.Type & (int)M4AVoiceFlags.Fixed) == (int)M4AVoiceFlags.Fixed;
                    return(SoundMixer.Instance.NewDSNote(owner, m4a.ADSR, aNote,
                                                         track.GetVolume(), track.GetPan(), track.GetPitch(),
                                                         bFixed, ((M4AWrappedDirect)voice).Sample.GetSample(), tracks));

                case M4AVoiceType.Square1:
                case M4AVoiceType.Square2:
                    return(SoundMixer.Instance.NewGBNote(owner, m4a.ADSR, aNote,
                                                         track.GetVolume(), track.GetPan(), track.GetPitch(),
                                                         type, m4a.SquarePattern));

                case M4AVoiceType.Wave:
                    return(SoundMixer.Instance.NewGBNote(owner, m4a.ADSR, aNote,
                                                         track.GetVolume(), track.GetPan(), track.GetPitch(),
                                                         type, m4a.Address - ROM.Pak));

                case M4AVoiceType.Noise:
                    return(SoundMixer.Instance.NewGBNote(owner, m4a.ADSR, aNote,
                                                         track.GetVolume(), track.GetPan(), track.GetPitch(),
                                                         type, m4a.NoisePattern));
                }
            }
            else if (voice.Voice is MLSSVoice mlssvoice)
            {
                MLSSVoiceEntry entry; bool bFixed = false; WrappedSample sample = null;
                try
                {
                    entry  = mlssvoice.GetEntryFromNote(note);
                    bFixed = entry.IsFixedFrequency == 0x80;
                    sample = ((MLSSVoiceTable)Song.VoiceTable).Samples[entry.Sample].GetSample();
                }
                catch
                {
                    System.Console.WriteLine("Track {0} tried to play a bad note... Voice {1} Note {2}", owner, track.Voice, note);
                    return(null);
                }
                if (sample != null)
                {
                    return(SoundMixer.Instance.NewDSNote(owner, new ADSR {
                        A = 0xFF, S = 0xFF
                    }, aNote,
                                                         track.GetVolume(), track.GetPan(), track.GetPitch(),
                                                         bFixed, sample, tracks));
                }
            }

            return(null);
        }
示例#3
0
        public GBChannel NewGBNote(byte owner, ADSR env, Note note, byte vol, sbyte pan, int pitch, M4AVoiceType type, object arg)
        {
            GBChannel nChn;

            switch (type)
            {
            case M4AVoiceType.Square1:
                nChn = sq1;
                if (nChn.State < ADSRState.Releasing && nChn.OwnerIdx < owner)
                {
                    return(null);
                }
                sq1.Init(owner, note, env, (SquarePattern)arg);
                break;

            case M4AVoiceType.Square2:
                nChn = sq2;
                if (nChn.State < ADSRState.Releasing && nChn.OwnerIdx < owner)
                {
                    return(null);
                }
                sq2.Init(owner, note, env, (SquarePattern)arg);
                break;

            case M4AVoiceType.Wave:
                nChn = wave;
                if (nChn.State < ADSRState.Releasing && nChn.OwnerIdx < owner)
                {
                    return(null);
                }
                wave.Init(owner, note, env, (int)arg);
                break;

            case M4AVoiceType.Noise:
                nChn = noise;
                if (nChn.State < ADSRState.Releasing && nChn.OwnerIdx < owner)
                {
                    return(null);
                }
                noise.Init(owner, note, env, (NoisePattern)arg);
                break;

            default: return(null);
            }
            nChn.SetVolume(vol, pan);
            nChn.SetPitch(pitch);
            return(nChn);
        }
示例#4
0
            void AddPSG(M4AVoiceEntry entry, byte low = 0, byte high = 0x7F)
            {
                int sample;

                M4AVoiceType type = (M4AVoiceType)(entry.Type & 0x7);

                if (type == M4AVoiceType.Square1 || type == M4AVoiceType.Square2)
                {
                    sample = (int)entry.SquarePattern;
                }
                else if (type == M4AVoiceType.Wave)
                {
                    sample = AddWave(entry.Address - ROM.Pak);
                }
                else if (type == M4AVoiceType.Noise)
                {
                    sample = (int)entry.NoisePattern + 4;
                }
                else
                {
                    return;
                }

                sf2.AddInstrumentBag();

                high = Math.Min((byte)0x7F, high);
                if (!(low == 0 && high == 0x7F))
                {
                    sf2.AddInstrumentGenerator(SF2Generator.KeyRange, new SF2GeneratorAmount {
                        LowByte = low, HighByte = high
                    });
                }

                // ADSR
                if (entry.ADSR.A != 0)
                {
                    // Compute attack time - the sound engine is called 60 times per second
                    // and adds "attack" to envelope every time the engine is called
                    double att_time = entry.ADSR.A / 5d;
                    double att      = 1200 * Math.Log(att_time, 2);
                    sf2.AddInstrumentGenerator(SF2Generator.AttackVolEnv, new SF2GeneratorAmount {
                        Amount = (short)att
                    });
                }
                if (entry.ADSR.S != 15)
                {
                    double sus;
                    // Compute attenuation in cB if sustain is non-zero
                    if (entry.ADSR.S != 0)
                    {
                        sus = 100 * Math.Log(15d / entry.ADSR.S);
                    }
                    // Special case where attenuation is infinite -> use max value
                    else
                    {
                        sus = 1000;
                    }

                    sf2.AddInstrumentGenerator(SF2Generator.SustainVolEnv, new SF2GeneratorAmount {
                        Amount = (short)sus
                    });

                    double dec_time = entry.ADSR.D / 5d;
                    double dec      = 1200 * Math.Log(dec_time + 1, 2);
                    sf2.AddInstrumentGenerator(SF2Generator.DecayVolEnv, new SF2GeneratorAmount {
                        Amount = (short)dec
                    });
                }
                if (entry.ADSR.R != 0)
                {
                    double rel_time = entry.ADSR.R / 5d;
                    double rel      = 1200 * Math.Log(rel_time, 2);
                    sf2.AddInstrumentGenerator(SF2Generator.ReleaseVolEnv, new SF2GeneratorAmount {
                        Amount = (short)rel
                    });
                }

                if (type == M4AVoiceType.Noise && entry.Panpot != 0)
                {
                    sf2.AddInstrumentGenerator(SF2Generator.Pan, new SF2GeneratorAmount {
                        Amount = (short)((entry.Panpot - 0xC0) * (500d / 0x80))
                    });
                }
                sf2.AddInstrumentGenerator(SF2Generator.SampleModes, new SF2GeneratorAmount {
                    Amount = 1
                });
                sf2.AddInstrumentGenerator(SF2Generator.SampleID, new SF2GeneratorAmount {
                    Amount = (short)sample
                });
            }