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; }
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; } }