public Sf2Synth(Sf2File file, Table table, int voiceCount) { this.file = file; this.table = table; masterGain = 1; this.voiceCount = voiceCount; voices = new Voice[voiceCount]; for (int i = 0; i < voiceCount; i += 1) { voices[i].Init(i, file.data, table); } #if MIDIF_DEBUG_VISUALIZER WaveVisualizer.Request(0, 1024); WaveVisualizer.Request(1, 1024); WaveVisualizer.Request(2, 1024); WaveVisualizer.Request(3, 1024); WaveVisualizer.Request(4, 1024); WaveVisualizer.Request(5, 1024); #endif Reset(); }
public void Process(float[] data) { for (int i = 0, length = data.Length; i < length; i += 2) { float left = 0; float right = 0; for (int j = firstActiveVoice; j != -1; j = voices[j].next) { float envelopeGain = voices[j].envelope.gain; voices[j].envelope.AdvanceTime(sampleRateRecip); float value = envelopeGain * (float)Math.Sin(voices[j].time * voices[j].freq * Table.Pi2); left += value * voices[j].gainLeft; right += value * voices[j].gainRight; voices[j].time += sampleRateRecip; } data[i] = left; data[i + 1] = right; #if MIDIF_DEBUG_VISUALIZER WaveVisualizer.Push(0, left); #endif } Panic(); }
public void Process(float[] buffer) { #if MIDIF_DEBUG_VISUALIZER WaveVisualizer.Clear(0); WaveVisualizer.Clear(1); WaveVisualizer.Clear(2); WaveVisualizer.Clear(3); WaveVisualizer.Clear(5); #endif try { for (int j = firstActiveVoice; j != -1; j = voices[j].next) { voices[j].Process(buffer); #if MIDIF_DEBUG_VISUALIZER WaveVisualizer.SetI(0, 0); WaveVisualizer.SetI(1, 0); WaveVisualizer.SetI(2, 0); WaveVisualizer.SetI(3, 0); WaveVisualizer.SetI(5, 0); #endif } } catch (System.Exception e) { UnityEngine.Debug.LogError(e); Reset(); return; } #if MIDIF_DEBUG_VISUALIZER for (int i = 0, length = buffer.Length; i < length; i += 2) { WaveVisualizer.Push(4, buffer[i]); } #endif // Panic(); }
public MidiSynth(Table table, float sampleRate, int voiceCount) { #if MIDIF_DEBUG_VISUALIZER WaveVisualizer.Request(0, 1024); #endif this.table = table; this.sampleRate = sampleRate; sampleRateRecip = 1f / sampleRate; masterGain = 1; envelopeConfig = new EnvelopeConfig(table, 120, .01f, 60, .1f, 100, .5f, 0, .01f); this.voiceCount = voiceCount; voices = new Voice[voiceCount]; for (int i = 0; i < voiceCount; i += 1) { voices[i].envelope = new Envelope(envelopeConfig); } Reset(); }
public void Process(float[] buffer) { float min = 0, max = 0; for (int i = 0, length = buffer.Length; i < length; i += 2) { // the first iteration will call update with count = 0 so that filter, lfos, envs can init bool lfoFlag = (count & lfoMask) == 0; bool envFlag = (count & envMask) == 0; // maybe more specific flags will be better? if (lfoFlag || envFlag) { Update(lfoFlag, envFlag); } count += 1; // simple interpolation float value; if (killed) { value = 0; } else { if (phase < 0) { UnityEngine.Debug.LogWarning("phase < 0"); Kill(); return; } uint uintPhase = (uint)phase; float ut = (float)(phase - uintPhase); value = data[start + uintPhase] * (1f - ut) + data[start + uintPhase + 1] * ut; // Console.Log(phase, uintPhase, ut); } // filter even when fc > 13500 (set fc = 13500 when that happens) so that filter is always ready if (useFilter) { value = filter.Process(value); } value = value * gain; if (value < min) { min = value; } if (value > max) { max = value; } buffer[i] += value * channelGainLeft * panLeft; buffer[i + 1] += value * channelGainRight * panRight; #if MIDIF_DEBUG_VISUALIZER WaveVisualizer.Inc(0, filter.h1 * attenuation); WaveVisualizer.Inc(1, filter.h2 * attenuation); WaveVisualizer.Inc(2, vibLfo.value * attenuation); WaveVisualizer.Inc(3, modLfo.value * attenuation); WaveVisualizer.Inc(5, data[start + (int)phase] * attenuation); #endif phase += curStep * channelPitch; switch (mode) { case Sf2File.SampleMode.contLoop: if (phase > loopEnd) { phase -= loopDuration; } break; case Sf2File.SampleMode.contLoopRelease: if (volEnv.stage == Envelope.StageRelease) { if (phase > duration) { Kill(); } } else { if (phase > loopEnd) { phase -= loopDuration; } } break; // case Sf2File.SampleMode.noLoop: default: if (phase > duration) { Kill(); } break; } } if (max - min > 3f) { UnityEngine.Debug.LogWarningFormat("max ({0:F2}) - min ({1:F2}) = ({2:F2})", max, min, max - min); Kill(); } }