예제 #1
0
        public void EnvToSecs(bool sustainIsGain)
        {
            // EG times need to be converted from timecents to seconds.
            // Pin very short EG segments.  Timecents don't get to zero, and our EG is
            // happier with zero values.
            Delay   = (Delay < -11950.0f ? 0.0f : SynthHelper.Timecents2Secs(Delay));
            Attack  = (Attack < -11950.0f ? 0.0f : SynthHelper.Timecents2Secs(Attack));
            Release = (Release < -11950.0f ? 0.0f : SynthHelper.Timecents2Secs(Release));

            // If we have dynamic hold or decay times depending on key number we need
            // to keep the values in timecents so we can calculate it during startNote
            if (KeynumToHold == 0)
            {
                Hold = (Hold < -11950.0f ? 0.0f : SynthHelper.Timecents2Secs(Hold));
            }

            if (KeynumToDecay == 0)
            {
                Decay = (Decay < -11950.0f ? 0.0f : SynthHelper.Timecents2Secs(Decay));
            }

            if (Sustain < 0.0f)
            {
                Sustain = 0.0f;
            }
            else if (sustainIsGain)
            {
                Sustain = SynthHelper.DecibelsToGain(-Sustain / 10.0f);
            }
            else
            {
                Sustain = 1.0f - (Sustain / 1000.0f);
            }
        }
예제 #2
0
 private void LoadFilter(Sf2Region region)
 {
     fltr = new FilterDescriptor();
     fltr.FilterMethod = FilterTypeEnum.BiquadLowpass;
     fltr.CutOff       = (float)SynthHelper.KeyToFrequency(region.Generators[(int)GeneratorEnum.InitialFilterCutoffFrequency] / 100.0, 69);
     fltr.Resonance    = (float)SynthHelper.DBtoLinear(region.Generators[(int)GeneratorEnum.InitialFilterQ] / 10.0);
 }
예제 #3
0
        public override bool Start(VoiceParameters voiceparams)
        {
            //calculate velocity
            float fVel = voiceparams.velocity / 127f;

            //setup generator
            voiceparams.generatorParams[0].QuickSetup(voiceparams.generators[0]);
            //setup envelopes
            voiceparams.envelopes[0].QuickSetup(voiceparams.synth.SampleRate, fVel, this.EnvelopeInfo[0]);
            voiceparams.envelopes[1].QuickSetup(voiceparams.synth.SampleRate, fVel, this.EnvelopeInfo[1]);
            voiceparams.envelopes[2].QuickSetup(voiceparams.synth.SampleRate, fVel, this.EnvelopeInfo[2]);
            //setup lfos
            voiceparams.lfos[0].QuickSetup(voiceparams.synth.SampleRate, LfoInfo[0]);
            voiceparams.lfos[1].QuickSetup(voiceparams.synth.SampleRate, LfoInfo[1]);
            voiceparams.lfos[2].QuickSetup(voiceparams.synth.SampleRate, LfoInfo[2]);
            //setup filter
            voiceparams.filters[0].QuickSetup(voiceparams.synth.SampleRate, voiceparams.note, fVel, this.FilterInfo[0]);
            if (!voiceparams.filters[0].Enabled)
            {//disable filter components if necessary
                voiceparams.envelopes[1].Depth = 0f;
                voiceparams.lfos[1].Depth      = 0f;
            }
            //setup sfz params
            voiceparams.pitchOffset = (voiceparams.note - voiceparams.generators[0].RootKey) * voiceparams.generators[0].KeyTrack + (int)(fVel * voiceparams.generators[0].VelocityTrack) + voiceparams.generators[0].Tune;
            float dBVel = -20.0f * (float)Math.Log10(16129.0 / (voiceparams.velocity * voiceparams.velocity));

            voiceparams.volOffset = (float)SynthHelper.DBtoLinear((voiceparams.note - ampRootKey) * ampKeyTrack + dBVel * ampVelTrack + sfzVolume) * voiceparams.synth.MixGain;
            //check if we have finished before we have begun
            return(voiceparams.generatorParams[0].currentState != GeneratorStateEnum.Finished && voiceparams.envelopes[2].CurrentState != EnvelopeStateEnum.None);
        }
예제 #4
0
 private void clampArray(double[] array)
 {
     for (int x = 0; x < array.Length; x++)
     {
         array[x] = SynthHelper.Clamp(array[x], 0.0, 1.0);
     }
 }
예제 #5
0
        public override float getSampleAtTime(int note, int channel, int synthSampleRate, ref double time)
        {
            double freq  = SynthHelper.NoteToFrequency(note);
            double delta = (1.0 / freq); //Position in wave form in 2PI * (time* frequency)

            if (time >= delta)           //Waveform repeates at 1.0 / freq
            {
                time = time % delta;
            }
            switch (type)
            {
            case SynthHelper.WaveFormType.Sine:
                return(SynthHelper.Sine(freq, time) * SynthHelper.DEFAULT_AMPLITUDE);

            case SynthHelper.WaveFormType.Sawtooth:
                return(SynthHelper.Sawtooth(freq, time) * SynthHelper.DEFAULT_AMPLITUDE);

            case SynthHelper.WaveFormType.Square:
                return(SynthHelper.Square(freq, time) * SynthHelper.DEFAULT_AMPLITUDE);

            case SynthHelper.WaveFormType.Triangle:
                return(SynthHelper.Triangle(freq, time) * SynthHelper.DEFAULT_AMPLITUDE);

            case SynthHelper.WaveFormType.WhiteNoise:
                return(SynthHelper.WhiteNoise(note, time) * SynthHelper.DEFAULT_AMPLITUDE);

            default:
                return(0.0f);
            }
        }
예제 #6
0
 public void Load(Sf2Region region, AssetManager assets)
 {
     this.exGroup        = region.Generators[(int)GeneratorEnum.ExclusiveClass];
     this.exTarget       = exGroup;
     iniFilterFc         = region.Generators[(int)GeneratorEnum.InitialFilterCutoffFrequency];
     filterQ             = SynthHelper.DBtoLinear(region.Generators[(int)GeneratorEnum.InitialFilterQ] / 10.0);
     initialAttn         = -region.Generators[(int)GeneratorEnum.InitialAttenuation] / 10f;
     keyOverride         = region.Generators[(int)GeneratorEnum.KeyNumber];
     velOverride         = region.Generators[(int)GeneratorEnum.Velocity];
     keynumToModEnvHold  = region.Generators[(int)GeneratorEnum.KeyNumberToModulationEnvelopeHold];
     keynumToModEnvDecay = region.Generators[(int)GeneratorEnum.KeyNumberToModulationEnvelopeDecay];
     keynumToVolEnvHold  = region.Generators[(int)GeneratorEnum.KeyNumberToVolumeEnvelopeHold];
     keynumToVolEnvDecay = region.Generators[(int)GeneratorEnum.KeyNumberToVolumeEnvelopeDecay];
     pan              = new PanComponent(region.Generators[(int)GeneratorEnum.Pan] / 500f, PanFormulaEnum.Neg3dBCenter);
     modLfoToPitch    = region.Generators[(int)GeneratorEnum.ModulationLFOToPitch];
     vibLfoToPitch    = region.Generators[(int)GeneratorEnum.VibratoLFOToPitch];
     modEnvToPitch    = region.Generators[(int)GeneratorEnum.ModulationEnvelopeToPitch];
     modLfoToFilterFc = region.Generators[(int)GeneratorEnum.ModulationLFOToFilterCutoffFrequency];
     modEnvToFilterFc = region.Generators[(int)GeneratorEnum.ModulationEnvelopeToFilterCutoffFrequency];
     modLfoToVolume   = region.Generators[(int)GeneratorEnum.ModulationLFOToVolume] / 10f;
     LoadGen(region, assets);
     LoadEnvelopes(region);
     LoadLfos(region);
     LoadFilter(region);
 }
예제 #7
0
        public void SetValue(float value, PanFormulaEnum formula)
        {
            value = SynthHelper.ClampF(value, -1, 1);
            double dvalue;

            switch (formula)
            {
            case PanFormulaEnum.Neg3dBCenter:
                dvalue = SynthConstants.HalfPi * (value + 1) / 2.0;
                Left   = (float)Math.Cos(dvalue);
                Right  = (float)Math.Sin(dvalue);
                break;

            case PanFormulaEnum.Neg6dBCenter:
                Left  = (float)(.5 + value * -.5);
                Right = (float)(.5 + value * .5);
                break;

            case PanFormulaEnum.ZeroCenter:
                dvalue = SynthConstants.HalfPi * (value + 1.0) / 2.0;
                Left   = (float)(Math.Cos(dvalue) / SynthConstants.InverseSqrtOfTwo);
                Right  = (float)(Math.Sin(dvalue) / SynthConstants.InverseSqrtOfTwo);
                break;

            default:
                throw new Exception("Invalid pan law selected.");
            }
        }
예제 #8
0
        public override bool Start(VoiceParameters voiceparams)
        {
            int note = keyOverride > -1 ? keyOverride : voiceparams.note;
            int vel  = velOverride > -1 ? velOverride : voiceparams.velocity;

            //setup generator
            voiceparams.generatorParams[0].QuickSetup(voiceparams.generators[0]);
            //setup envelopes
            voiceparams.envelopes[0].QuickSetup(voiceparams.synth.SampleRate, note, keynumToModEnvHold, keynumToModEnvDecay, 1, this.EnvelopeInfo[0]);
            float susMod = (float)SynthHelper.DBtoLinear(-sustainVolEnv);

            if (susMod <= 1e-5f)
            {
                susMod = 0;
            }
            voiceparams.envelopes[1].QuickSetup(voiceparams.synth.SampleRate, note, keynumToVolEnvHold, keynumToVolEnvDecay, susMod, this.EnvelopeInfo[1]);
            //setup filter
            //if (filterQ == 1 && modLfoToFilterFc + modEnvToFilterFc + iniFilterFc > 14000)
            voiceparams.filters[0].Disable();
            //else
            //    voiceparams.filters[0].QuickSetup(44100, note, 1f, this.FilterInfo[0]);
            //setup lfos
            voiceparams.lfos[0].QuickSetup(voiceparams.synth.SampleRate, LfoInfo[0]);
            voiceparams.lfos[1].QuickSetup(voiceparams.synth.SampleRate, LfoInfo[1]);
            //calculate base volume and pitch
            voiceparams.pitchOffset = (note - voiceparams.generators[0].RootKey) * voiceparams.generators[0].KeyTrack + voiceparams.generators[0].Tune;
            voiceparams.volOffset   = -20.0f * (float)Math.Log10(16129.0 / (vel * vel)) + -initialAttn;
            //check if we have finished before we have begun
            return(voiceparams.generatorParams[0].currentState != GeneratorStateEnum.Finished && voiceparams.envelopes[1].CurrentState != EnvelopeStateEnum.None);
        }
예제 #9
0
        private void loadProgramFile(string file)
        {
            //StreamReader reader = new StreamReader(File.Open(file, FileMode.Open));
            StreamReader reader = new StreamReader(Application.GetResourceStream(new Uri(file, UriKind.Relative)).Stream);

            if (!reader.ReadLine().Trim().ToUpper().Equals("[FM INSTRUMENT]"))
            {
                reader.Close();
                throw new InvalidDataException("Invalid Program file: Incorrect Header!");
            }
            string[] args = reader.ReadLine().Split(new string[] { "|" }, StringSplitOptions.None);
            if (args.Length < 4)
            {
                reader.Close();
                throw new InvalidDataException("Invalid Program file: Parameters are missing");
            }
            this.baseWaveType = SynthHelper.getTypeFromString(args[0]);
            this.modWaveType  = SynthHelper.getTypeFromString(args[1]);
            this.mfreq        = getOpsAndValues(args[2], true);
            this.mamp         = getOpsAndValues(args[3], false);
            args = reader.ReadLine().Split(new string[] { "|" }, StringSplitOptions.None);
            if (args.Length < 3)
            {
                reader.Close();
                throw new InvalidDataException("Invalid Program file: Parameters are missing");
            }
            if (int.Parse(args[0]) == 0)
            {
                looping = true;
            }
            start_time = double.Parse(args[1]);
            end_time   = double.Parse(args[2]);
            args       = reader.ReadLine().Split(new string[] { "|" }, StringSplitOptions.None);
            if (args.Length < 3)
            {
                reader.Close();
                throw new InvalidDataException("Invalid Program file: Parameters are missing");
            }
            switch (args[0].ToLower().Trim())
            {
            case "fadein":
                env = Envelope.CreateBasicFadeIn(double.Parse(args[2]));
                break;

            case "fadeout":
                env = Envelope.CreateBasicFadeOut(double.Parse(args[2]));
                break;

            case "fadein&out":
                double p = double.Parse(args[2]) / 2.0;
                env = Envelope.CreateBasicFadeInAndOut(p, p);
                break;

            default:
                env = Envelope.CreateBasicConstant();
                break;
            }
            env.Peak = double.Parse(args[1]);
            reader.Close();
        }
예제 #10
0
        public override float getSampleAtTime(int note, int channel, int synthSampleRate, ref double time)
        {
            double freq = SynthHelper.NoteToFrequency(note);

            if (freq * time > 1.0)
            {
                time = 0.0;
            }
            switch (type)
            {
            case SynthHelper.WaveFormType.Sine:
                return(SynthHelper.Sine(freq, time) * SynthHelper.DEFAULT_AMPLITUDE);

            case SynthHelper.WaveFormType.Sawtooth:
                return(SynthHelper.Sawtooth(freq, time) * SynthHelper.DEFAULT_AMPLITUDE);

            case SynthHelper.WaveFormType.Square:
                return(SynthHelper.Square(freq, time) * SynthHelper.DEFAULT_AMPLITUDE);

            case SynthHelper.WaveFormType.Triangle:
                return(SynthHelper.Triangle(freq, time) * SynthHelper.DEFAULT_AMPLITUDE);

            case SynthHelper.WaveFormType.WhiteNoise:
                return(SynthHelper.WhiteNoise(note, time) * SynthHelper.DEFAULT_AMPLITUDE);

            default:
                return(0.0f);
            }
        }
예제 #11
0
        private void loadProgramFile(string file)
        {
            StreamReader reader = new StreamReader(PlatformHelper.StreamLoad(file));

            if (!reader.ReadLine().Trim().ToUpper().Equals("[FM INSTRUMENT]"))
            {
                reader.Close();
                throw new Exception("Invalid Program file: Incorrect Header!");
            }
            string[] args = reader.ReadLine().Split(new string[] { "|" }, StringSplitOptions.None);
            if (args.Length < 4)
            {
                reader.Close();
                throw new Exception("Invalid Program file: Parameters are missing");
            }
            this.baseWaveType = SynthHelper.getTypeFromString(args[0]);
            this.modWaveType  = SynthHelper.getTypeFromString(args[1]);
            this.mfreq        = (ModulatorFrequencyFunction)getOpsAndValues(args[2], true);
            this.mamp         = (ModulatorAmplitudeFunction)getOpsAndValues(args[3], false);
            args = reader.ReadLine().Split(new string[] { "|" }, StringSplitOptions.None);
            if (args.Length < 3)
            {
                reader.Close();
                throw new Exception("Invalid Program file: Parameters are missing");
            }
            if (int.Parse(args[0]) == 0)
            {
                looping = true;
            }
            start_time = double.Parse(args[1]);
            end_time   = double.Parse(args[2]);
            args       = reader.ReadLine().Split(new string[] { "|" }, StringSplitOptions.None);
            if (args.Length < 3)
            {
                reader.Close();
                throw new Exception("Invalid Program file: Parameters are missing");
            }
            switch (args[0].ToLower().Trim())
            {
            case "fadein":
                env = Envelope.CreateBasicFadeIn(double.Parse(args[2]));
                break;

            case "fadeout":
                env = Envelope.CreateBasicFadeOut(double.Parse(args[2]));
                break;

            case "fadein&out":
                double p = double.Parse(args[2]) / 2.0;
                env = Envelope.CreateBasicFadeInAndOut(p, p);
                break;

            default:
                env = Envelope.CreateBasicConstant();
                break;
            }
            env.Peak = double.Parse(args[1]);
            reader.Close();
        }
예제 #12
0
        public override void Process(VoiceParameters voiceparams, int startIndex, int endIndex, bool isMuted)
        {
            //--Base pitch calculation
            var basePitchFrequency = SynthHelper.CentsToPitch(voiceparams.SynthParams.CurrentPitch) * gen.Frequency;
            var pitchWithBend      = basePitchFrequency * SynthHelper.CentsToPitch(voiceparams.PitchOffset);
            var basePitch          = pitchWithBend / voiceparams.SynthParams.Synth.SampleRate;

            float baseVolume = isMuted ? 0 : voiceparams.SynthParams.Synth.MasterVolume * voiceparams.SynthParams.CurrentVolume * SynthConstants.DefaultMixGain * voiceparams.SynthParams.MixVolume;

            //--Main Loop
            for (int x = startIndex; x < endIndex; x += SynthConstants.DefaultBlockSize * SynthConstants.AudioChannels)
            {
                voiceparams.Envelopes[0].Increment(SynthConstants.DefaultBlockSize);
                voiceparams.Envelopes[1].Increment(SynthConstants.DefaultBlockSize);
                voiceparams.Lfos[0].Increment(SynthConstants.DefaultBlockSize);
                voiceparams.Lfos[1].Increment(SynthConstants.DefaultBlockSize);
                //--Calculate pitch and get next block of samples
                gen.GetValues(voiceparams.GeneratorParams[0], voiceparams.BlockBuffer, basePitch *
                              SynthHelper.CentsToPitch((int)(voiceparams.Envelopes[0].Value * modEnvToPitch +
                                                             voiceparams.Lfos[0].Value * modLfoToPitch + voiceparams.Lfos[1].Value * vibLfoToPitch)));
                //--Filter
                if (voiceparams.Filters[0].Enabled)
                {
                    double centsFc = voiceparams.PData[0].Int1 + voiceparams.Lfos[0].Value * modLfoToFilterFc + voiceparams.Envelopes[0].Value * modEnvToFilterFc;
                    if (centsFc > 13500)
                    {
                        centsFc = 13500;
                    }
                    voiceparams.Filters[0].CutOff = SynthHelper.KeyToFrequency(centsFc / 100.0, 69);
                    if (voiceparams.Filters[0].CoeffNeedsUpdating)
                    {
                        voiceparams.Filters[0].ApplyFilterInterp(voiceparams.BlockBuffer, voiceparams.SynthParams.Synth.SampleRate);
                    }
                    else
                    {
                        voiceparams.Filters[0].ApplyFilter(voiceparams.BlockBuffer);
                    }
                }
                //--Volume calculation
                float volume = (float)SynthHelper.DBtoLinear(voiceparams.VolOffset + voiceparams.Envelopes[1].Value + voiceparams.Lfos[0].Value * modLfoToVolume) * baseVolume;

                //--Mix block based on number of channels
                if (SynthConstants.AudioChannels == 2)
                {
                    voiceparams.MixMonoToStereoInterp(x, volume * pan.Left * voiceparams.SynthParams.CurrentPan.Left, volume * pan.Right * voiceparams.SynthParams.CurrentPan.Right);
                }
                else
                {
                    voiceparams.MixMonoToMonoInterp(x, volume);
                }
                //--Check and end early if necessary
                if ((voiceparams.Envelopes[1].CurrentStage > EnvelopeState.Hold && volume <= SynthConstants.NonAudible) || voiceparams.GeneratorParams[0].CurrentState == GeneratorState.Finished)
                {
                    voiceparams.State = VoiceStateEnum.Stopped;
                    return;
                }
            }
        }
예제 #13
0
 /*change time stretch parameters*/
 public void Configure(double timeScale, double sequenceSec, double overlapSec, double windowSec, int sampleRate)
 {
     time_scale    = SynthHelper.Clamp(timeScale, 0.0, 2.0);
     sequence_size = (int)SynthHelper.SamplesFromTime(sampleRate, sequenceSec);
     overlap_size  = (int)SynthHelper.SamplesFromTime(sampleRate, overlapSec);
     seek_window   = (int)SynthHelper.SamplesFromTime(sampleRate, windowSec);
     flat_duration = sequence_size - 2 * overlap_size;
     flat_duration = sequence_size - 2 * overlap_size;
     sequence_skip = (int)((sequence_size - overlap_size) * time_scale);
 }
예제 #14
0
 private void LoadSfzFilters(SfzRegion region)
 {
     FilterDescriptions    = new FilterDescriptor[1];
     FilterDescriptions[0] = new FilterDescriptor();
     FilterDescriptions[0].FilterMethod = region.filterType;
     FilterDescriptions[0].CutOff       = region.cutOff;
     FilterDescriptions[0].KeyTrack     = region.filterKeyTrack;
     FilterDescriptions[0].Resonance    = (float)SynthHelper.DBtoLinear(region.resonance);
     FilterDescriptions[0].RootKey      = region.filterKeyCenter;
     FilterDescriptions[0].VelTrack     = region.filterVelTrack;
 }
예제 #15
0
파일: Echo.cs 프로젝트: zzbin6210/BlockFun
 //--Public Methods
 /// <summary>
 /// A simple echo effect.
 /// </summary>
 /// <param name="synth">A constructed synthesizer instance.</param>
 /// <param name="delaytime">Echo delay in seconds.</param>
 /// <param name="decay">Controls the volume of the echo.</param>
 public Echo(StreamSynthesizer synth, float delaytime, float decay)
     : base()
 {
     if (delaytime <= 0.0f)
     {
         throw new ArgumentException("delay time must be positive non-zero for echo effect.");
     }
     this.decay         = SynthHelper.Clamp(decay, 0.0f, 1.0f);
     this.EffectBuffer  = new float[synth.Channels, SynthHelper.getSampleFromTime(synth.SampleRate, delaytime)];
     channels           = this.EffectBuffer.GetLength(0);
     secondarybufferlen = this.EffectBuffer.GetLength(1);
 }
예제 #16
0
        public override void Process(VoiceParameters voiceparams, int startIndex, int endIndex)
        {
            //--Base pitch calculation
            double basePitch = SynthHelper.CentsToPitch(voiceparams.pitchOffset + voiceparams.synth.totalPitch[voiceparams.channel])
                               * voiceparams.generators[0].Frequency / voiceparams.synth.SampleRate;

            //--Base volume calculation
            //float baseVolume = voiceparams.volOffset * voiceparams.synth.totalVolume[voiceparams.channel];
            //--Main Loop
            for (int x = startIndex; x < endIndex; x += Synthesizer.DefaultBlockSize * voiceparams.synth.AudioChannels)
            {
                voiceparams.envelopes[0].Increment(Synthesizer.DefaultBlockSize);
                voiceparams.envelopes[1].Increment(Synthesizer.DefaultBlockSize);
                voiceparams.lfos[0].Increment(Synthesizer.DefaultBlockSize);
                voiceparams.lfos[1].Increment(Synthesizer.DefaultBlockSize);

                //--Calculate pitch and get next block of samples
                voiceparams.generators[0].GetValues(voiceparams.generatorParams[0], voiceparams.blockBuffer, basePitch *
                                                    SynthHelper.CentsToPitch((int)(voiceparams.envelopes[0].Value * modEnvToPitch +
                                                                                   voiceparams.lfos[0].Value * modLfoToPitch + voiceparams.lfos[1].Value * vibLfoToPitch)));
                //--Filter
                if (voiceparams.filters[0].Enabled)
                {
                    double centsFc = iniFilterFc + voiceparams.lfos[0].Value * modLfoToFilterFc + voiceparams.envelopes[0].Value * modEnvToFilterFc;
                    if (centsFc > 13500)
                    {
                        centsFc = 13500;
                    }
                    voiceparams.filters[0].UpdateCoefficients(SynthHelper.KeyToFrequency(centsFc / 100.0, 69) / voiceparams.synth.SampleRate, filterQ);
                    voiceparams.filters[0].ApplyFilter(voiceparams.blockBuffer);
                }
                //--Volume calculation
                float volume = (float)SynthHelper.DBtoLinear(voiceparams.volOffset + voiceparams.lfos[0].Value * modLfoToVolume) * voiceparams.envelopes[1].Value * voiceparams.synth.totalVolume[voiceparams.channel] * voiceparams.synth.MixGain;
                //--Mix block based on number of channels
                if (voiceparams.synth.AudioChannels == 2)
                {
                    SynthHelper.MixMonoToStereoInterpolation(x,
                                                             volume * pan.Left * voiceparams.synth.panPositions[voiceparams.channel].Left,
                                                             volume * pan.Right * voiceparams.synth.panPositions[voiceparams.channel].Right,
                                                             voiceparams);
                }
                else
                {
                    SynthHelper.MixMonoToMonoInterpolation(x, volume, voiceparams);
                }
                //--Check and end early if necessary
                if ((voiceparams.envelopes[1].CurrentState > EnvelopeStateEnum.Hold && volume <= Synthesizer.NonAudible) || voiceparams.generatorParams[0].currentState == GeneratorStateEnum.Finished)
                {
                    voiceparams.state = VoiceStateEnum.Stopped;
                    return;
                }
            }
        }
예제 #17
0
 public override void enforceSampleRate(int sampleRate)
 {
     if (sampleRate != this.SampleRate)
     {
         //Proper calculation of voice states
         _attack         = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_ATTACK);
         _release        = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_RELEASE);
         _decay          = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_DECAY);
         _hold           = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_HOLD);
         this.SampleRate = sampleRate;
     }
 }
예제 #18
0
 protected PcmData(int bits, byte[] pcmData, bool isDataInLittleEndianFormat)
 {
     BytesPerSample = (byte)(bits / 8);
     //if (pcmData.Length % BytesPerSample != 0)
     //    throw new Exception("Invalid PCM format. The PCM data was an invalid size.");
     Data   = pcmData;
     Length = Data.Length / BytesPerSample;
     if (!isDataInLittleEndianFormat)
     {
         SynthHelper.SwapEndianess(Data, bits);
     }
 }
예제 #19
0
        public void CalcPitchRatio(float pitchShift, float outSampleRate)
        {
            var note          = PlayingKey + Region.Transpose + Region.Tune / 100.0;
            var adjustedPitch = Region.PitchKeyCenter + (note - Region.PitchKeyCenter) * (Region.PitchKeyTrack / 100.0);

            if (pitchShift != 0)
            {
                adjustedPitch += pitchShift;
            }
            PitchInputTimecents = adjustedPitch * 100.0;
            PitchOutputFactor   = Region.SampleRate / (SynthHelper.Timecents2Secs(Region.PitchKeyCenter * 100.0) * outSampleRate);
        }
예제 #20
0
 private void updateTimeControls(int current, int max)
 {
     max     = (int)SynthHelper.TimeFromSamples(Properties.Settings.Default.SampleRate, max);
     current = (int)SynthHelper.TimeFromSamples(Properties.Settings.Default.SampleRate, current);
     current = Math.Min(max, current);
     if (trackBar1.Maximum != max)
     {
         trackBar1.Maximum       = max;
         trackBar1.TickFrequency = Math.Max(1, trackBar1.Maximum / 20);
     }
     trackBar1.Value = current;
     label1.Text     = new TimeSpan(0, 0, current).ToString(@"mm\:ss") + "/" + new TimeSpan(0, 0, max).ToString(@"mm\:ss");
 }
예제 #21
0
 //--Public Methods
 public FMInstrument(string fmProgramFile, int sampleRate)
     : base()
 {
     this.SampleRate = sampleRate;
     //Proper calculation of voice states
     _attack  = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_ATTACK);
     _release = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_RELEASE);
     _decay   = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_DECAY);
     _hold    = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_HOLD);
     //open fm program file
     loadProgramFile(fmProgramFile);
     //set base attribute name
     base.Name = System.IO.Path.GetFileNameWithoutExtension(fmProgramFile);
 }
예제 #22
0
 private void CheckValidParameters()
 {
     //limit cutoff
     if (CutOff <= 0)
     {
         FilterMethod = FilterTypeEnum.None;
     }
     if (RootKey < 0 || RootKey > 127)
     {
         RootKey = 60;
     }
     KeyTrack = SynthHelper.Clamp(KeyTrack, (short)0, (short)1200);
     VelTrack = SynthHelper.Clamp(VelTrack, (short)-9600, (short)9600);
 }
예제 #23
0
 //--Public Methods
 public AnalogInstrument(SynthHelper.WaveFormType waveformtype, int sampleRate)
     : base()
 {
     //set type
     this.type       = waveformtype;
     this.SampleRate = sampleRate;
     //Proper calculation of voice states
     _attack  = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_ATTACK);
     _release = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_RELEASE);
     _decay   = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_DECAY);
     _hold    = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_HOLD);
     //set base attribute name
     base.Name = waveformtype.ToString();
 }
예제 #24
0
 private void CheckValidParameters()
 {
     //release must be with min and max
     ReleaseTime = SynthHelper.Clamp(ReleaseTime, 0.001f, 2.0f);
     //positive only checks
     DelayTime    = Math.Max(DelayTime, 0f);
     AttackTime   = Math.Max(AttackTime, 0f);
     HoldTime     = Math.Max(HoldTime, 0f);
     DecayTime    = Math.Max(DecayTime, 0f);
     SustainTime  = Math.Max(SustainTime, 0);
     ReleaseTime  = Math.Max(ReleaseTime, 0f);
     SustainLevel = Math.Max(SustainLevel, 0f);
     PeakLevel    = Math.Max(PeakLevel, 0f);
     StartLevel   = SynthHelper.Clamp(StartLevel, 0, PeakLevel);
 }
예제 #25
0
 private void LoadSfzLfos(SfzRegion region)
 {
     LfoDescriptions              = new LfoDescriptor[3];
     LfoDescriptions[0]           = new LfoDescriptor();
     LfoDescriptions[0].DelayTime = region.pitchLfoDelay; //make sure pitch lfo is enabled for midi mod event
     LfoDescriptions[0].Frequency = region.pitchLfoFrequency > 0 ? region.pitchLfoFrequency : (float)Synthesizer.DefaultLfoFrequency;
     LfoDescriptions[0].Depth     = region.pitchLfoDepth;
     LfoDescriptions[1]           = new LfoDescriptor();
     LfoDescriptions[1].DelayTime = region.filterLfoDelay;
     LfoDescriptions[1].Frequency = region.filterLfoFrequency;
     LfoDescriptions[1].Depth     = region.filterLfoDepth;
     LfoDescriptions[2]           = new LfoDescriptor();
     LfoDescriptions[2].DelayTime = region.ampLfoDelay;
     LfoDescriptions[2].Frequency = region.ampLfoFrequency;
     LfoDescriptions[2].Depth     = (float)SynthHelper.DBtoLinear(region.ampLfoDepth);
 }
예제 #26
0
        public override void Process(VoiceParameters voiceparams, int startIndex, int endIndex)
        {
            //--Base pitch calculation
            double basePitch = SynthHelper.CentsToPitch(voiceparams.pitchOffset + voiceparams.synthParams.currentPitch)
                               * gen.Period * gen.Frequency / voiceparams.synthParams.synth.SampleRate;
            //--Base volume calculation
            float baseVolume = voiceparams.volOffset * voiceparams.synthParams.currentVolume;

            //--Main Loop
            for (int x = startIndex; x < endIndex; x += Synthesizer.DefaultBlockSize * voiceparams.synthParams.synth.AudioChannels)
            {
                //--Volume Envelope
                voiceparams.envelopes[0].Increment(Synthesizer.DefaultBlockSize);
                //--Lfo pitch modulation
                double pitchMod;
                if (voiceparams.synthParams.modRange.Combined != 0)
                {
                    voiceparams.lfos[0].Increment(Synthesizer.DefaultBlockSize);
                    pitchMod = SynthHelper.CentsToPitch((int)(voiceparams.lfos[0].Value * voiceparams.synthParams.currentMod));
                }
                else
                {
                    pitchMod = 1;
                }
                //--Get next block of samples
                gen.GetValues(voiceparams.generatorParams[0], voiceparams.blockBuffer, basePitch * pitchMod);
                //--Mix block based on number of channels
                float volume = baseVolume * voiceparams.envelopes[0].Value;
                if (voiceparams.synthParams.synth.AudioChannels == 2)
                {
                    voiceparams.MixMonoToStereoInterp(x,
                                                      volume * voiceparams.synthParams.currentPan.Left,
                                                      volume * voiceparams.synthParams.currentPan.Right);
                }
                else
                {
                    voiceparams.MixMonoToMonoInterp(x, volume);
                }
                //--Check and end early if necessary
                if (voiceparams.envelopes[0].CurrentState == EnvelopeStateEnum.None || voiceparams.generatorParams[0].currentState == GeneratorStateEnum.Finished)
                {
                    voiceparams.state = VoiceStateEnum.Stopped;
                    return;
                }
            }
        }
예제 #27
0
 //--Public Methods
 public FMInstrument(string fmProgramFile, int sampleRate)
     : base()
 {
     this.SampleRate = sampleRate;
     //Proper calculation of voice states
     _attack  = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_ATTACK);
     _release = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_RELEASE);
     _decay   = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_DECAY);
     _hold    = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_HOLD);
     //open fm program file
     loadProgramFile(fmProgramFile);
     //set base attribute name
     //base.Name = System.IO.Path.GetFileNameWithoutExtension(fmProgramFile);
     System.Diagnostics.Debug.WriteLine(fmProgramFile.LastIndexOf("/"));
     System.Diagnostics.Debug.WriteLine(fmProgramFile.Length);
     base.Name = fmProgramFile.Substring(fmProgramFile.LastIndexOf("/"), fmProgramFile.Length - fmProgramFile.LastIndexOf("/"));
 }
예제 #28
0
        private static SampleArray CreateExponentialTable(int size, float coeff)
        {
            coeff = SynthHelper.ClampF(coeff, .001f, .9f);
            var graph = new SampleArray(size);
            var val   = 0.0;

            for (int x = 0; x < size; x++)
            {
                graph[x] = (float)val;
                val     += coeff * ((1 / 0.63) - val);
            }
            for (int x = 0; x < size; x++)
            {
                graph[x] = graph[x] / graph[graph.Length - 1];
            }
            return(graph);
        }
예제 #29
0
        public static float[] CreateExponentialTable(int size, double coeff)
        {
            coeff = SynthHelper.Clamp(coeff, .001, .9);
            float[] graph = new float[size];
            double  val   = 0;

            for (int x = 0; x < graph.Length; x++)
            {
                graph[x] = (float)val;
                val     += coeff * ((1 / 0.63) - val);
            }
            for (int x = 0; x < graph.Length; x++)
            {
                graph[x] = graph[x] / graph[graph.Length - 1];
            }
            return(graph);
        }
예제 #30
0
 public void QuickSetup(int sampleRate, int note, float velocity, FilterDescriptor filterInfo)
 {
     coeffUpdateRequired = false;
     cutOff     = filterInfo.CutOff;
     resonance  = filterInfo.Resonance;
     filterType = filterInfo.FilterMethod;
     a1         = 0; a2 = 0; b1 = 0; b2 = 0;
     m1         = 0f; m2 = 0f; m3 = 0f;
     if (cutOff <= 0 || resonance <= 0)
     {
         filterType = FilterTypeEnum.None;
     }
     if (filterType != FilterTypeEnum.None)
     {
         cutOff *= SynthHelper.CentsToPitch((note - filterInfo.RootKey) * filterInfo.KeyTrack + (int)(velocity * filterInfo.VelTrack));
         UpdateCoeff(sampleRate);
     }
 }