public MainWindow() { InitializeComponent(); const int sampleRate = 44100; _voice = new ExampleVoiceWithFilter(sampleRate); _pcm = new MonoWaveStream(sampleRate, _voice); _timer.Interval = TimeSpan.FromMilliseconds(10); // this "stuff" should be in some class, perhaps the State itself. _timer.Tick += (s, e) => { // "push" into state _state.Attack = A1.Value / 10d; _state.Decay = D1.Value / 10d; _state.SustainLevel = (Amplitude)S1.Value; _state.Release = R1.Value / 10d; _state.WF1 = WF1.Text; _state.Volume1 = (Amplitude)Volume1.Value; _state.WF2 = WF2.Text; _state.Volume2 = (Amplitude)Volume2.Value; _state.Harmonic1 = Harmonic1.Value / 12d + Harmonic1Fine.Value; _state.Harmonic2 = Harmonic2.Value / 12d + Harmonic2Fine.Value; _state.PulseWidth = PW.Value; _state.LFO = LFO.Value; _state.IsLfoRoutedToHarmonic = ModHarmonic.IsChecked ?? false; _state.IsLfoRoutedToPulseWidth = ModPW.IsChecked ?? false; _state.IsLfoRingModulate = RingMod.IsChecked ?? false; _state.Delay = Delay.Value; _state.DelayFeedback = DelayFeedback.Value; _state.FilterFrequency = FilterFrequency.Value; _state.FilterResonance = FilterResonance.Value; }; _keyboard.KeyDown += MainWindow_KeyDown; _keyboard.KeyUp += MainWindow_KeyUp; var device = new WaveOutDevice(_pcm, sampleRate); // "pull" from state _voice.Attack = () => _state.Attack; _voice.Decay = () => _state.Decay; _voice.SustainLevel = () => _state.SustainLevel; _voice.Release = () => _state.Release; _voice.WaveForm = (t, f, w, p) => _state.WaveForm(t)(t, f, w, p); _voice.PulseWidth = (t, f) => _state.Modulate(_state.IsLfoRoutedToPulseWidth, t, _state.PulseWidth); _voice.FilterFrequency = (t) => _state.FilterFrequency; _voice.FilterResonance = (t) => _state.FilterResonance; device.Play(); _timer.Start(); }
static void Main(string[] args) { // TODO: review all the todo's // DONE - convert to 16 bit. jumping between signal scales of -1:1, 0:1 and 0:255 is very confusing. // you can always decimate back to 8bit at the end if you want // Phase issue when frequency changes - we get a click // tempo, duration should be able to be expressed as semi or quarter times // metronome // sync metronome to tempo, delay to tempo, etc, lfo to tempo // amplitude adding // parameter inputs // delay, filter, arp, envelope, etc all have parameters // delay, filter, etc - convert to a pipeline, add an on/off switch OUTPUT PHASES // filter - add high pass so we can have band and notch somehow? // arpeggiator! also pipelined, on/off... INPUT PHASE // LFO just waveform at low f, on/off INPUT PHASE // wavetable support for line in and samples, and our waveforms // waveforms/wavetable - get the c64 to spit them out as 0-255 values? won't work for pulsewidth...? // cleanup, stabilize and build the control surface // sequencer // midi support // etc etc const int sampleRate = 44100; var voice = new ExampleVoiceWithDelayAndFilter(sampleRate) { SustainDuration = () => 0.2, Release = () => 0.01, Attack = () => 0, Decay = () => 0, Delay = () => 0.5, DelayFeedback = () => 0.5, WaveForm = WaveForm.WaveForms.Triangle(), IsFilterEnabled = false, IsDelayEnabled = false, FilterFrequency = (t) => Pulsator(t, 1200, 600), FilterResonance = (t) => Pulsator(t, 12, 6), PulseWidth = (t, f) => Pulsator(t, 4 / 12, 1 / 12), }; var pcm = new MonoWaveStream(sampleRate, voice); var device = new Devices.WaveOutDevice(pcm, sampleRate); var isPlaying = true; device.Play(); var f = 440D; while (isPlaying) { voice.Frequency = () => f += 0.00001; if (!System.Console.KeyAvailable) { continue; } var key = System.Console.ReadKey().Key; if (key == ConsoleKey.Escape) { break; } voice.Frequency = ProcessKeyPress(key); //voice.WaveForm = Arpeggiator.Arpeggio(WaveForms.Triangle(), pcm.Time, Arpeggio.OnTheRun2); voice.TriggerOn(); } device.Stop(); }