mike hodnick

Point your browser to www.hodnick.com for Mike's latest content.

Notice:

You are viewing Mike's old, archived site. For new content, navigate to hodnick.com

Latest From Twitter...

The Blog

I've been working on a fluent interface API for producing synthesized audio in Silverlight. Keith Dahlby originally suggested this idea to me, and as I've been testing my own complex signal chains in code I decided it was time to implement the idea. Setting up signal chains using a more conventional syntax was just getting too tedious.

I've been using Charles Petzold's Simple Sequencer as a base and have tweaked and modified the code to include support for frequency modulation, amplitude modulation, and panning.

To set up a simple signal chain with a mixer, here is what the code looks like:

StereoPcmStreamSource source = new StereoPcmStreamSource();

Mixer mixer =
   Oscillator.Create(440)
      .FrequencyModulate(150, 50000000)
      .AmplitudeModulate(77)
      .Pan(short.MinValue)
      .Attenuate(-6)
      .SendToMixer();

   Oscillator.Create(640)
      .FrequencyModulate(130, 51000000)
      .AmplitudeModulate(55)
      .Pan(short.MaxValue)
      .Attenuate(-6)
      .SendToMixer(mixer);

   Oscillator.Create(540)
      .FrequencyModulate(140, 53000000)
      .AmplitudeModulate(45)
      .Pan(short.MinValue)
      .Attenuate(-6)
      .SendToMixer(mixer);

   Oscillator.Create(740)
      .FrequencyModulate(160, 59000000)
      .AmplitudeModulate(41)
      .Pan(short.MaxValue)
      .Attenuate(-6)
      .SendToMixer(mixer);

source.Input = mixer;
this.media.SetSource(source);

The code above generates a "droning" sound with four oscillators under heavy and fast vibrato. Two oscillators are panned hard right and the other two are hard left.

The main idea is to make it easier to set up signal chains. Contrast the first oscillator setup code above with this conventional approach:

Mixer mixer = new Mixer();

Oscillator osc1 = new Oscillator();
osc1.Frequency = 440;
osc1.FrequencyModulator.Amplitude = 150;
osc1.FrequencyModulator.ModulationFrequency = 50000000;
osc1.AmplitudeModulator.ModulationFrequency = 77;
Panner pan = new Panner();
pan.Pan = short.MinValue;
pan.Input = osc1;
Attenuator attenuator = new Attenuator();
attenuator.Attenuation = -6;
attenuator.Input = pan;
mixer.Inputs.Add(attenuator);

Ouch.

The next step is to integrate the fluent interface with UI controls. What good is this code if you can't tweak the parameters on the screen?!

posted on Wednesday, November 04, 2009 8:18 AM |