Home > Posts > HowTo: Compress speech audio using CSpeex codec at Silverlight apps

HowTo: Compress speech audio using CSpeex codec at Silverlight apps

Following up on my post on how to fix CSpeex (http://cspeex.codeplex.com) to compile at Silverlight 5 (see https://zoomicon.wordpress.com/2012/06/09/fix-compile-cspeex-audio-codec-at-silverlight-4-rc-and-silverlight-5/). 

Initially I thought it was not working correctly, but then I noticed I was running it on Terminal Server and didn’t have an audio device available. Running SLAudioDemo included in the CSpeex distribution (after doing the fix mentioned at my post above) seems to work fine on my local PC.

The SLAudioDemo demonstrates capturing audio into memory as a compressed CSpeex stream which it can decompress and save into a .WAV file that one can play say with Windows Media Player. The WAV is uncompressed, since SLAudioDemo compresses in memory (via StreamAudioSink) and decompresses to normal PCM WAV when you save (else it would be unplayable).

Obviously the Speex codec is useful for uploading (e.g. via HSS Interlink) compressed audio to a server (or to the other end at some voice chat app) and decompress there before playback (similarly the other way around).

At the server side if you want to do audio storage too, you could also keep an extra decoded copy of the compressed Speex audio data, recoded into WMA using automation of Microsoft Expression Encoder for example (see Microsoft Transform Manager, can do this in the background if you uncompress into a .WAV file at some incoming folder). That way you could serve that audio to your Silverlight client as Speex-encoded data file, but also to other users that use Windows Media Player to get the audio file from some URL etc. Could also encode to MP4/AAC or MP3 but there are licensing issues with those from what I know.

 

For the CSpeex encoder see StreamAudioSink.cs. Only 2 lines are needed in MainPage.xaml.cs of SLAudioDemo:

streamAudioSink = new StreamAudioSink();
streamAudioSink.CaptureSource = _captureSource;

after you 1st declare at the top level (must have this as a top-level field, else the garbage collector can get it)

private StreamAudioSink streamAudioSink;

 

Here’s the decoding code that saves the WAV (from MainPage.xaml.cs):

if (sfd.ShowDialog() == true)
{
  // User selected item. Only property we can get to is.
  using (Stream stream = sfd.OpenFile())
  {
    JSpeexDec decoder = new JSpeexDec();
    decoder.setDestFormat(JSpeexDec.FILE_FORMAT_WAVE);
    decoder.setStereo(true);
 
    Stream memStream = streamAudioSink.MemFile.InnerStream;
    memStream.Position = 0;
 
    decoder.decode(new RandomInputStream(memStream), 
new RandomOutputStream(stream)); stream.Close(); } }

 

Don’t get puzzled by the use of RandomInputStream / RandomOutputStream. These are from Java’s I/O package (java.io.*) that CSpeex has ported to .NET, since it’s in fact a port of JSpeex, a Java implementation of the Speex codec.

  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: