public Synthesizer(int sampleRate, int audioChannels, int bufferSize, int bufferCount, int polyphony)
        {
            const int MinSampleRate = 8000;
            const int MaxSampleRate = 96000;

            //Setup synth parameters
            if (sampleRate < MinSampleRate || sampleRate > MaxSampleRate)
            {
                throw new ArgumentException("Invalid paramater: (sampleRate) Valid ranges are " + MinSampleRate + " to " + MaxSampleRate, "sampleRate");
            }
            this.sampleRate = sampleRate;
            if (audioChannels < 1 || audioChannels > 2)
            {
                throw new ArgumentException("Invalid paramater: (audioChannels) Valid ranges are " + 1 + " to " + 2, "audioChannels");
            }
            this.audioChannels    = audioChannels;
            this.microBufferSize  = SynthHelper.Clamp(bufferSize, (int)(MinBufferSize * sampleRate), (int)(MaxBufferSize * sampleRate));
            this.microBufferSize  = (int)Math.Ceiling(this.microBufferSize / (double)DefaultBlockSize) * DefaultBlockSize; //ensure multiple of block size
            this.microBufferCount = Math.Max(1, bufferCount);
            sampleBuffer          = new float[microBufferSize * microBufferCount * audioChannels];
            littleEndian          = true;
            //Setup Controllers
            synthChannels = new SynthParameters[DefaultChannelCount];
            for (int x = 0; x < synthChannels.Length; x++)
            {
                synthChannels[x] = new SynthParameters(this);
            }
            //Create synth voices
            voiceManager = new VoiceManager(SynthHelper.Clamp(polyphony, MinPolyphony, MaxPolyphony));
            //Create midi containers
            midiEventQueue  = new Queue <MidiMessage>();
            midiEventCounts = new int[this.microBufferCount];
            layerList       = new Patch[15];
        }
 public void Configure(int channel, int note, int velocity, Patch patch, SynthParameters synthParams)
 {
     voiceparams.Reset();
     voiceparams.channel = channel;
     voiceparams.note = note;
     voiceparams.velocity = velocity;
     voiceparams.synthParams = synthParams;
     this.patch = patch;
 }
Exemple #3
0
 public void Configure(int channel, int note, int velocity, Patch patch, SynthParameters synthParams)
 {
     voiceparams.Reset();
     voiceparams.channel     = channel;
     voiceparams.note        = note;
     voiceparams.velocity    = velocity;
     voiceparams.synthParams = synthParams;
     this.patch = patch;
 }
 public Patch GetProgram(int channel)
 {
     if (bank != null)
     {
         SynthParameters sChannel = synthChannels[channel];
         Patch           inst     = bank.GetPatch(sChannel.bankSelect, sChannel.program);
         if (inst != null)
         {
             return(inst);
         }
     }
     return(null);
 }
 public string GetProgramName(int channel)
 {
     if (bank != null)
     {
         SynthParameters sChannel = synthChannels[channel];
         Patch           inst     = bank.GetPatch(sChannel.bankSelect, sChannel.program);
         if (inst != null)
         {
             return(inst.Name);
         }
     }
     return("Null");
 }
 public Synthesizer(int sampleRate, int audioChannels, int bufferSize, int bufferCount, int polyphony)
 {
     const int MinSampleRate = 8000;
     const int MaxSampleRate = 96000;
     //Setup synth parameters
     if (sampleRate < MinSampleRate || sampleRate > MaxSampleRate)
         throw new ArgumentException("Invalid paramater: (sampleRate) Valid ranges are " + MinSampleRate + " to " + MaxSampleRate, "sampleRate");
     this.sampleRate = sampleRate;
     if (audioChannels < 1 || audioChannels > 2)
         throw new ArgumentException("Invalid paramater: (audioChannels) Valid ranges are " + 1 + " to " + 2, "audioChannels");
     this.audioChannels = audioChannels;
     this.microBufferSize = SynthHelper.Clamp(bufferSize, (int)(MinBufferSize * sampleRate), (int)(MaxBufferSize * sampleRate));
     this.microBufferSize = (int)Math.Ceiling(this.microBufferSize / (double)DefaultBlockSize) * DefaultBlockSize; //ensure multiple of block size
     this.microBufferCount = Math.Max(1, bufferCount);
     sampleBuffer = new float[microBufferSize * microBufferCount * audioChannels];
     littleEndian = true;
     //Setup Controllers
     synthChannels = new SynthParameters[DefaultChannelCount];
     for (int x = 0; x < synthChannels.Length; x++)
         synthChannels[x] = new SynthParameters(this);            
     //Create synth voices
     voiceManager = new VoiceManager(SynthHelper.Clamp(polyphony, MinPolyphony, MaxPolyphony));
     //Create midi containers
     midiEventQueue = new Queue<MidiMessage>();
     midiEventCounts = new int[this.microBufferCount];
     layerList = new Patch[15]; 
 }
        /// <summary>
        /// Starts a voice with the given key and velocity.
        /// </summary>
        /// <param name="channel">The midi channel this voice is on.</param>
        /// <param name="note">The key the voice will play in.</param>
        /// <param name="velocity">The volume of the voice.</param>
        public void NoteOn(int channel, int note, int velocity)
        {
            // Get the correct instrument depending if it is a drum or not
            SynthParameters sChan = synthChannels[channel];
            Patch           inst  = bank.GetPatch(sChan.bankSelect, sChan.program);

            if (inst == null)
            {
                return;
            }
            // A NoteOn can trigger multiple voices via layers
            int layerCount;

            if (inst is MultiPatch)
            {
                layerCount = ((MultiPatch)inst).FindPatches(channel, note, velocity, layerList);
            }
            else
            {
                layerCount   = 1;
                layerList[0] = inst;
            }
            // If a key with the same note value exists, stop it
            if (voiceManager.registry[channel, note] != null)
            {
                VoiceManager.VoiceNode node = voiceManager.registry[channel, note];
                while (node != null)
                {
                    node.Value.Stop();
                    node = node.Next;
                }
                voiceManager.RemoveFromRegistry(channel, note);
            }
            // Check exclusive groups
            for (int x = 0; x < layerCount; x++)
            {
                bool notseen = true;
                for (int i = x - 1; i >= 0; i--)
                {
                    if (layerList[x].ExclusiveGroupTarget == layerList[i].ExclusiveGroupTarget)
                    {
                        notseen = false;
                        break;
                    }
                }
                if (layerList[x].ExclusiveGroupTarget != 0 && notseen)
                {
                    LinkedListNode <Voice> node = voiceManager.activeVoices.First;
                    while (node != null)
                    {
                        if (layerList[x].ExclusiveGroupTarget == node.Value.Patch.ExclusiveGroup)
                        {
                            node.Value.Stop();
                            voiceManager.RemoveFromRegistry(node.Value);
                        }
                        node = node.Next;
                    }
                }
            }
            // Assign a voice to each layer
            for (int x = 0; x < layerCount; x++)
            {
                Voice voice = voiceManager.GetFreeVoice();
                if (voice == null)// out of voices and skipping is enabled
                {
                    break;
                }
                voice.Configure(channel, note, velocity, layerList[x], synthChannels[channel]);
                voiceManager.AddToRegistry(voice);
                voiceManager.activeVoices.AddLast(voice);
                voice.Start();
            }
            // Clear layer list
            for (int x = 0; x < layerCount; x++)
            {
                layerList[x] = null;
            }
        }