Exemple #1
0
        public void Add(Sf2Zone z)
        {
            /**
             * If the generator operator is a Range Generator, the generator values are NOT ADDED to
             * those in the instrument level, rather they serve as an intersection filter to those key number or
             * velocity ranges in the instrument that is used in the preset zone.
             */
            if (noteLo < z.noteLo)
            {
                noteLo = z.noteLo;
            }
            if (z.noteHi < noteHi)
            {
                noteHi = z.noteHi;
            }
            if (velocityLo < z.velocityLo)
            {
                velocityLo = z.velocityLo;
            }
            if (z.velocityHi < velocityHi)
            {
                velocityHi = z.velocityHi;
            }

            for (int i = 0; i < z.gens.Length; i += 1)
            {
                if (z.gens[i].flag)
                {
                    gens[i].value += z.gens[i].value;
                    gens[i].flag   = true;
                }
            }
        }
Exemple #2
0
        public void Set(Sf2Zone z)
        {
            noteLo     = z.noteLo; noteHi = z.noteHi;
            velocityLo = z.velocityLo; velocityHi = z.velocityHi;

            for (int i = 0; i < z.gens.Length; i += 1)
            {
                if (z.gens[i].flag)
                {
                    gens[i].value = z.gens[i].value;
                    gens[i].flag  = true;
                }
            }
        }
Exemple #3
0
        public static Sf2Zone GetAppliedZone(Sf2Zone iGlobalZone, Sf2Zone iZone, Sf2Zone pGlobalZone, Sf2Zone pZone)
        {
            // short v1 = 0, v2 = 0, v3 = 0, v4 = 0;
            // if (iGlobalZone != null) v1 = iGlobalZone.gens[GeneratorType.sustainVolEnv].value;
            // v2 = iZone.gens[GeneratorType.sustainVolEnv].value;
            // if (pGlobalZone != null) v2 = pGlobalZone.gens[GeneratorType.sustainVolEnv].value;
            // v4 = pZone.gens[GeneratorType.sustainVolEnv].value;
            // Console.Log(v1, v2, v3, v4);

            var zone = new Sf2Zone();

            zone.Default();
            if (iGlobalZone != null)
            {
                zone.Set(iGlobalZone);
            }
            zone.Set(iZone);

            /**
             * SF 2.01 Page 65
             * A generator in a local preset zone that is identical to a generator in a global preset zone
             * supersedes or replaces that generator in the global preset zone. That generator then has its
             * effects added to the destination-summing node of all zones in the given instrument.
             */
            var zone2 = new Sf2Zone();

            if (pGlobalZone != null)
            {
                zone2.Set(pGlobalZone);
            }
            zone2.Set(pZone);

            zone.Add(zone2);
            zone.Clamp();
            return(zone);
        }
Exemple #4
0
            public void On(Sf2File.SampleHeader sample, Sf2Zone zone)
            {
                count = lastLfoCount = lastEnvCount = 0;
                // when (count & xxxMask) == 0, update xxx and xxx's dependents
                lfoMask = 0xff;
                envMask = 0xff;

                killed = false;

                var gs = zone.gens;

                // voice
                start       = sample.start;
                startOffset = (uint)((gs[GenType.startAddrsCoarseOffset].value << 15) + gs[GenType.startAddrsOffset].value);
                // start = (uint)(sample.start + (gs[GenType.startAddrsCoarseOffset].value << 15) + gs[GenType.startAddrsOffset].value);
                uint end       = (uint)(sample.end + (gs[GenType.endAddrsCoarseOffset].value << 15) + gs[GenType.endAddrsOffset].value);
                uint startloop = (uint)(sample.startloop + (gs[GenType.startloopAddrsCoarseOffset].value << 15) + gs[GenType.startloopAddrsOffset].value);
                uint endloop   = (uint)(sample.endloop + (gs[GenType.endloopAddrsCoarseOffset].value << 15) + gs[GenType.endloopAddrsOffset].value);

                duration     = end - start;
                loopEnd      = endloop - start;
                loopDuration = endloop - startloop;
                phase        = startOffset;
                // Console.Log(start, startOffset, end, startloop, endloop, duration, loopEnd, loopDuration);

                short root        = gs[GenType.overridingRootKey].value;           // MIDI ky#
                short scaleTuning = gs[GenType.scaleTuning].value;                 // cent/key

                if (root < 0)
                {
                    root = sample.originalKey;                            // root = -1 means not set
                }
                curStep = step = sample.sampleRate * table.sampleRateRecip
                                 * table.semi2Pitch[Table.Semi2PitchCenter + gs[GenType.coarseTune].value]
                                 * (float)Table.Cent2Pitch((note - root) * scaleTuning + sample.correction + gs[GenType.fineTune].value);
                mode        = gs[GenType.sampleModes].value;
                attenuation = (float)Table.Db2Gain(-gs[GenType.initialAttenuation].value * .1); // cB

                short pan     = gs[GenType.pan].value;                                          // 0.1%
                byte  bytePan = (byte)(64 + 127 * (pan * .001f));

                panLeft  = table.pan2Left[bytePan];
                panRight = table.pan2Right[bytePan];
                // Console.Log("\tpan", pan, panLeft, panRight);

                // filter
                short initialFilterFc = gs[GenType.initialFilterFc].value;                // cent
                short initialFilterQ  = gs[GenType.initialFilterQ].value;                 // cB

                filterFc  = (float)Table.AbsCent2Freq(initialFilterFc);
                filter.h1 = filter.h2 = 0;
                filter.Set(table, filterFc, (float)Table.Db2Gain(initialFilterQ * .1 - 3.01));
                // useFilter may be set by modLfo and/or modEnv if they set the fc, so just init whatsoever
                useFilter = initialFilterFc < 13500;

                // vibLfo
                vibLfoToPitch = gs[GenType.vibLfoToPitch].value;                  // cent fs
                if (vibLfoToPitch != 0)
                {
                    useVibLfo = true;
                    short delayVibLfo = gs[GenType.delayVibLfo].value;                    // timecent
                    short freqVibLfo  = gs[GenType.freqVibLfo].value;                     // cent
                    vibLfo.On(table, (float)Table.Timecent2Sec(delayVibLfo), (float)Table.AbsCent2Freq(freqVibLfo));
                }
                else
                {
                    useVibLfo = false;
                }

                // modLfo
                modLfoToPitch       = gs[GenType.modLfoToPitch].value;            // cent fs
                modLfoToFilterFc    = gs[GenType.modLfoToFilterFc].value;         // cent fs
                modLfoToVolume      = gs[GenType.modLfoToVolume].value;           // cB fs
                useModLfoToPitch    = modLfoToPitch != 0;
                useModLfoToFilterFc = modLfoToFilterFc != 0;
                useModLfoToVolume   = modLfoToVolume != 0;
                useModLfo           = useModLfoToPitch || useModLfoToFilterFc || useModLfoToVolume;
                if (useModLfo)
                {
                    // modLfo affects filter, so use filter
                    if (useModLfoToFilterFc)
                    {
                        useFilter = true;
                    }
                    short delayModLfo = gs[GenType.delayModLfo].value;                    // timecent
                    short freqModLfo  = gs[GenType.freqModLfo].value;                     // cent
                    modLfo.On(table, (float)Table.Timecent2Sec(delayModLfo), (float)Table.AbsCent2Freq(freqModLfo));
                }

                // volEnv
                short delayVolEnv   = gs[GenType.delayVolEnv].value;              // timecent
                short attackVolEnv  = gs[GenType.attackVolEnv].value;             // timecent
                short holdVolEnv    = gs[GenType.holdVolEnv].value;               // timecent
                short decayVolEnv   = gs[GenType.decayVolEnv].value;              // timecent
                short releaseVolEnv = gs[GenType.releaseVolEnv].value;            // timecent
                short sustainVolEnv = gs[GenType.sustainVolEnv].value;            // cB attn

                volEnv.On(table,
                          (float)Table.Timecent2Sec(delayVolEnv),
                          (float)Table.Timecent2Sec(attackVolEnv),
                          (float)Table.Timecent2Sec(holdVolEnv),
                          (float)Table.Timecent2Sec(decayVolEnv),
                          (float)Table.Timecent2Sec(releaseVolEnv),
                          (float)Table.Db2Gain(-(double)sustainVolEnv * .1));
                // Console.Log("\tv", id, "on volEnv", delayVolEnv, attackVolEnv, holdVolEnv, decayVolEnv, releaseVolEnv, sustainVolEnv, -(double)sustainVolEnv * .1, Table.Db2Gain(-(double)sustainVolEnv * .1));

                // modEnv
                modEnvToPitch       = gs[GenType.modEnvToPitch].value;            // cent fs
                modEnvToFilterFc    = gs[GenType.modEnvToFilterFc].value;         // cent fs
                useModEnvToPitch    = modEnvToPitch != 0;
                useModEnvToFilterFc = modEnvToFilterFc != 0;
                useModEnv           = useModEnvToPitch || useModEnvToFilterFc;
                if (useModEnv)
                {
                    // modEnv affects filter, so use filter
                    if (useModEnvToFilterFc)
                    {
                        useFilter = true;
                    }
                    short delayModEnv   = gs[GenType.delayModEnv].value;                  // timecent
                    short attackModEnv  = gs[GenType.attackModEnv].value;                 // timecent
                    short holdModEnv    = gs[GenType.holdModEnv].value;                   // timecent
                    short decayModEnv   = gs[GenType.decayModEnv].value;                  // timecent
                    short releaseModEnv = gs[GenType.releaseModEnv].value;                // timecent
                    short sustainModEnv = gs[GenType.sustainModEnv].value;                // cB attn
                    modEnv.On(table,
                              (float)Table.Timecent2Sec(delayModEnv),
                              (float)Table.Timecent2Sec(attackModEnv),
                              (float)Table.Timecent2Sec(holdModEnv),
                              (float)Table.Timecent2Sec(decayModEnv),
                              (float)Table.Timecent2Sec(releaseModEnv),
                              (float)Table.Db2Gain(-(double)sustainModEnv * .1));
                    // Console.Log("\tv", id, "on modEnv", delayModEnv, attackModEnv, holdModEnv, decayModEnv, releaseModEnv, sustainVolEnv);
                }

                // Console.Log("v", id, "on", note,
                //  "vibLfo", vibLfoToPitch,
                //  "modLfo", modLfoToPitch, modLfoToFilterFc, modLfoToVolume,
                //  "modEnv", modEnvToPitch, modEnvToFilterFc,
                //  "useVibLfo", useVibLfo, "useModLfo", useModLfo, "useModEnv", useModEnv, "useFilter", useFilter,
                //  "filter", filterFc, filter.q, sample.sampleName);
            }