Welcome to Pete Brown's 10rem.net

First time here? If you are a developer or are interested in Microsoft tools and technology, please consider subscribing to the latest posts.

You may also be interested in my blog archives, the articles section, or some of my lab projects such as the C64 emulator written in Silverlight.

(hide this)

Silverlight Synthesizer

Silverlight Synthesizer Thumbnail
I originally wrote the Silverlight Synthesizer as a sound test to figure out how to create sound in Silverlight, specifically for the Commodore 64 emulator. It evolved from there to become a testbed for multi-oscillator real-time sound generation using Silverlight 3+. The current version of the synthesizer targets Silverlight 4.

Synthesizer Information

Issues

  • My mixing algorithm is bad. If anyone knows the right algorithm for mixing multiple channels of sound, while keeping the same end volume regardless of how many channels are mixed (including times when some of the channels are silent) I'd love to know it. Please share!
  • Related to above, you can get distortion pretty quickly when you press more than a few notes
  • Fair bit of dead code - this is a test project :)

None of those are Silverlight issues - they're issues with my code.

One key thing that changed in Silverlight 3 RTW vs. the beta was the addition of the new MediaStreamSource AudioBufferLength property. It represents the number of milliseconds of sound to buffer before output. The minimum value is 15, but on most machines you won't be able to get close to that unless you have highly optimized sound generation code (doing wavetable lookups rather than real-time sawtooth waves, for example)

This value is highly machine dependent, so if you do anything serious with this code, you'll want to make that something the user can change to suit their own machine. To low a value and the sound will stutter, too high and the sound will have an audible delay.

The value is in the InitializeMediaStreamSource method of Synthesizer.MediaStreamSource.cs

AudioBufferLength = 30;

15 comments for “Silverlight Synthesizer”

  1. Attilasays:
    Hi,

    I don't understand fully what is your problem with mixing.
    It is expected if you mix (ie. add) signals, the result will be louder. If you try to mix a band, the sound is louder when all the members are playing.
    To get constant volume, you need to use compression, you can't do anything with mixing.
    http://en.wikipedia.org/wiki/Dynamic_range_compression

    I think you don't have to care about constant volume of the synth, it's fairly enough if the user has a master volume fader so s/he can adjust the loudness if it's too loud/silent.
    Anyway of course you can ease this with developing a compressor into the signal chain, before the master fader.
  2. Ryan Smythsays:
    Hello Pete,

    I don't know how you're handling the audio data, but you can attenuate the level in a channel to compensate for adding in. e.g. If you add 50% of the left channel to the right channel, you can compensate for the additional volume by reducing the level in the right by 50%.

    You can check it in most audio editors. For an easier check of the basics, you can use the trial of my software (Guitar & Drum Trainer at the URL above). Just load any song, then use the Channel Mixer to mix some left channel into the right, and then reduce the right channel by the same amount. When you make changes, watch the level meter (in the main window). When you raise the level in the left, you can start to see the signal top over 0 dB. When you roll back the right channel, you'll see the level meter return back to normal, peaking at 0 dB.

    That is only for 2 channels in stereo, but the general principle holds for adding in multiple channels. e.g. Adding in 10% of the left 2x is the same as adding in 20%. You're just adding more in.

    You can either use compression (as noted above), or just go with simple addition. However, you need to know the relative strength there of course. e.g. For a level of 100 with 3 channels at 100, divide by 3 and add.

    I haven't tried any audio in Silverlight, so I can't say much about how to do that there. However, it's a basic principle and it should work.

    Cheers,

    Ryan


  3. Sanjaysays:
    Hello Pete,

    I would like to know a can I use the source as mp3 and change the variable speed?
    Can you pls let me know you mail id so that I can mail you and explain you in details.

    Thanks
    Sanjay
  4. Petesays:
    @Sanjay

    That's doable, but I don't have any source code that would handle that. To speed it up, you'd essentially have to skip samples. However, I'm not sure if there are algorithms to average the samples before skipping or what.

    Pete
  5. Sanjaysays:
    Hi Pete,

    Would you be interested in a project which includes assisting me and my team in trying to implement variable speed playback in silverlight that works with mp3's? if you could give me your phone or email (you can email me directly) we can have a quick call and go over our project. i appreciate your time. txs

    Sanjay
  6. Sanjaysays:
    Hi Pete,

    I found the code of "tempo" effect from open source code at http://www.surina.net/soundtouch/index.html. "Tempo" effect will solve our requirement.
    It was written in C++, can you please guide us how to use C++ code in silverlight?

    I appreciate if you could help me.

    Thanks
    Sanjay
  7. Prakashsays:
    Hi Pete,

    I need following help from you,

    1) How to detect number of audio channels available in a media file, which is played in the MediaElement?
    2) How to change the Audio channel, show that the media file has to play with the selected Audio Channel?

    My Requirement:

    I need to get list of audio channels from the Media file which is currently playing in the MediaElement and show them to the user. When the user selects any audio channel, The MediaElement should play the file with the selected audio channel.
    I tried with MediaElement's AudioStreamCount and AudioStreamIndex property but while I change the AudioStreamIndex to 1, MediaElement is not playing with audio instead it’s plays the video in mute whereas if I set the AudioStreamIndex to 0, MediaElement plays the video with audio.

    I’m using Silverlight 4.

    Please help me in achieving the above requirement.

    Thanks in advance,
    Prakash.
  8. Yogeshsays:
    Hello Pete,

    That was a nice synth Silverlight app. However, I was wondering if there's anyway i could specify the volume in decibels for a custom WaveFileMediaSourceStream. And feed that to the MediaElement. So basically, I would want to be able to play 20 dBs as 20 dBs irrespective of the client's hardware. Is this possible? Or is there any other alternative apart from Silverlight?

    Thanks and best regards,
    Yogesh
  9. Petesays:
    @Yogesh

    Thanks.

    To change volume with this API, you'd have to scale the amplitude down on the samples using some multiplier. There's no way to force that, though, as the end user always has control over the volume, and that is applied across your entire sample set. You can't go above that value without clipping.

    Pete

Comment on this Page

Remember me