C# – Rx and Permutation

Today I read an introduce to a guessing game which hosted on http://jotto.ciphertechs.com/. In this game the machine will generate a random 5-letters word and we try to guess the word through hints given that how many letters did we guess correctly. Who has less tries to guess a word is the better. Guessing the letters in that word is not difficult because each letter is unique. In my turn after some tries I found out 5 letters of that word which are ‘a’, ‘r’, ‘c’, ‘l’ and ‘e’. Now it’s more difficult because I must find out how these letters are arranged to make a meaningful word.

This leads to a task of calculating all permutations of 5 letters forming a word and then choose a meaninful one from this word list. It’s pretty simple to calculate permutation with C# and I think you can find out a ton of examples in internet out there. Therefore the topic of this blog does not discuss about how I calculate the permutation but I would like to introduce an extension which help me to solve this problem pretty fast. That is Reactive Extensions http://msdn.microsoft.com/en-us/devlabs/ee794896.

Rx is a library for composing asynchronous and event-based programs using observable collections.“. My colleague introduces me this extension. It’s very powerful but I am new to it. Therefore in this post I will not metion anything about asynchronous or event-based programs but I would like to illustrate a very small example using Interactive library of Rx to calculate permutation for my game. There’s are installation packages of Rx on the homepage but we can download its packages through Visual Studio.

1. Go to http://nuget.codeplex.com/releases and click on NuGet Package Manager to download Nuget. Click “I Agree”.
2. Open the “Download File” with “Microsoft Visual Studio Version Selector”

Open with Firefox

3. Click to “Install” Nuget add-on

Install Nuget

4. In Visual Studio, create a project to calculate the permutations of the 5 letters above. Then choose Tools –> Library Package Manager –> Add Library Package Reference… (Be sure that in Solution Explorere you are selecting a project. Otherwise there’s an error message telling that “Project” is not supported”.

Library Package Reference

5. Choose “Online” option, then enter “rx” on search box and choose to install Rx-Main and Rx-Interactiv

Rx Package install

6. After installing this package, new references will be inserted to your project such as System.Reactive, System.Observable and System.Interactive. In project folder there are also new folder “packages” which contains all neccessary files of Rx. It’s comfortable to use a package in a project because it will be automatically updated when new version comes. However it makes our project bigger and the library is not “really” for sharing to other projects because it’s put under a defined project folder.
Now insert a static class to add extended Permutation method to IEnumerable

public static class EnumerableExtension
{
	public static IEnumerable<IEnumerable<T>> Permutations<T>(this IEnumerable<T> source)
	{
		if (!source.Any())
			return EnumerableEx.Return(Enumerable.Empty<T>());
		else
			return from item in Permutations(source.Skip(1))
				   from i in Enumerable.Range(0, item.Count() + 1)
				   select item.Take(i).Concat(EnumerableEx.Return(source.First())).Concat(item.Skip(i));
	}
}

7. Enter some code for handling button “Calculate”. You can see that I give 5 letters as input and call Permuations function on “source” object to generate all possible cases. With help of Linq I put these permutations in a beautiful string to display on textbox.

private void btnCalculate_Click(object sender, RoutedEventArgs e)
{            
	IEnumerable<string> source = new List<string>{"a","r","c","l","e"};
	txtResult.Text = source.Permutations().Select(x => x.Aggregate((y, z) => y = y + z)).ToList().Aggregate((y, z) => y = y + " " + z);

}

8. And we have result of permutations for 5 letters about 120 cases.

Permutation

I found out the correct word is “clear” and you can find the complete source code at “Rx Permutation”

UPDATE 21.03.2012
If you don’t want to use Nuget to install Rx Extensions, you can download it directly with this link http://www.microsoft.com/download/en/details.aspx?id=28568 and install it as usual. After installing, you’ll have dlls in your reference list.

Rx Extensions

C# – MP3/WAV Converter with Lame/NAudio

Converting between music formats is common user activity when they want to play musics on many portable devices. As you know the current most popular format is being supported on many portable devices, is MP3. This audio encoding format uses a form of lossy data compression which reduces strongly the amount of data required for representing audio. However it keeps sound like a faithful reproduction of the original uncompressed audio for most listeners. The standard bitrate of a MP3 file ist about 128 kbits (11 times smaller than CD file from original source as stated in Wikipedia http://en.wikipedia.org/wiki/MP3).

Cause of demand above, in this blog post, I would like to demonstrate a small code snippet for converting between MP3/WAV so that we can write our own tools for converting to MP3 with some code lines instead of spending a lot of time for searching for a freeware, downloading and installing … In this example I’ll use two open source MP3 Encoders for demonstrating – LAME (http://lame.sourceforge.net/) and NAUDIO (http://naudio.codeplex.com/).

The package of LAME includes 2 files (lame.exe and lame_enc.dll coded by C++). You can write a C# Wrapper for the DLL and using it directly in your solution but I see that it takes so much time if I write a wrapper and use it directly in my solution because this DLL exports only some functions below which servicing only for stream encoding. That means I must take care of the task for conversion “How should the stream be converted?”, “How many bitrates should be used”…. and it turns to be not a simple code block anymore. It is also not worth to invent the wheel which is “lame.exe” in this case.

__declspec(dllexport) BE_ERR	beInitStream(PBE_CONFIG pbeConfig, PDWORD dwSamples, PDWORD dwBufferSize, PHBE_STREAM phbeStream);
__declspec(dllexport) BE_ERR	beEncodeChunk(HBE_STREAM hbeStream, DWORD nSamples, PSHORT pSamples, PBYTE pOutput, PDWORD pdwOutput);
__declspec(dllexport) BE_ERR	beEncodeChunkFloatS16NI(HBE_STREAM hbeStream, DWORD nSamples, PFLOAT buffer_l, PFLOAT buffer_r, PBYTE pOutput, PDWORD pdwOutput);
__declspec(dllexport) BE_ERR	beDeinitStream(HBE_STREAM hbeStream, PBYTE pOutput, PDWORD pdwOutput);
__declspec(dllexport) BE_ERR	beCloseStream(HBE_STREAM hbeStream);
__declspec(dllexport) VOID		beVersion(PBE_VERSION pbeVersion);
__declspec(dllexport) BE_ERR	beWriteVBRHeader(LPCSTR lpszFileName);
__declspec(dllexport) BE_ERR	beFlushNoGap(HBE_STREAM hbeStream, PBYTE pOutput, PDWORD pdwOutput);
__declspec(dllexport) BE_ERR	beWriteInfoTag( HBE_STREAM hbeStream, LPCSTR lpszFileName );

Therefore I decide to use the perfect programmed “lame.exe” for conversion.

 private static void LameWavToMp3(string wavFile, string outmp3File)
{
	ProcessStartInfo psi = new ProcessStartInfo();
	psi.FileName = @"..\..\Lame\lame.exe";
	psi.Arguments = "-V2 " + wavFile + " " + outmp3File;
	psi.WindowStyle = ProcessWindowStyle.Hidden;
	Process p = Process.Start(psi);
	p.WaitForExit();
}

private static void LameMp3ToWav(string mp3File, string outwavFile)
{
	ProcessStartInfo psi = new ProcessStartInfo();
	psi.FileName = @"..\..\Lame\lame.exe";
	psi.Arguments = mp3File + " " + outwavFile;
	psi.WindowStyle = ProcessWindowStyle.Hidden;
	Process p = Process.Start(psi);
	p.WaitForExit();
}

It works perfectly. For converting to MP3 I would like to choose V2 of MP3 which is recommended by LAME. In comparision to V3 I can not realize which is better but just use as recommendation.

One of alternatives to LAME for converting MP3 to WAV is NAUDIO. It is also an open-source library and written in C#. However it’s not a MP3 Encoder therefore it does not support converting from WAV to MP3. Using this library we just simply add a reference to it in solution and write a function as below to convert from MP3 to WAV

private static void NAudioMp3ToWav(string mp3File, string outwavFile)
{
	using (Mp3FileReader reader = new Mp3FileReader(mp3File))
	{
		using (WaveStream pcmStream = WaveFormatConversionStream.CreatePcmStream(reader))
		{
			WaveFileWriter.CreateWaveFile(outwavFile, pcmStream);
		}
	}
}

Bring all these 3 functions to test if they really work

static void Main(string[] args)
{
	Console.WriteLine("MP3/WAV CONVERTER");
	Console.WriteLine("Using LAME");
	Console.Write("     WAV TO MP3");
	LameWavToMp3(@"..\..\Sample\testcase.wav", @"..\..\Output\testcaselame.mp3");
	Console.WriteLine(" : Successfully");
	Console.Write("     MP3 TO WAV");
	LameMp3ToWav(@"..\..\Sample\testcase.mp3", @"..\..\Output\testcaselame.wav");
	Console.WriteLine(" : Successfully");
	Console.WriteLine("Using NAUDIO");
	Console.Write("     MP3 TO WAV");
	NAudioMp3ToWav(@"..\..\Sample\testcase.mp3", @"..\..\Output\testcasenaudio.wav");
	Console.WriteLine(" : Successfully");
	Console.WriteLine("Finished");
	Console.ReadLine();
}

The complete solution you can download MP3-WAV Converter with LAME/Audio.

UPDATE 20.08.2013
For converting file from Ogg to Wav, we can combine Nvorbis http://nvorbis.codeplex.com/ with NAudio to get a perfect result with following code

private static void NAudioOggToWav(string oggFile, string wavFile)
{
	using (var vorbis = new NVorbis.NAudioSupport.VorbisWaveReader(oggFile))
	{
		WaveFileWriter.CreateWaveFile(wavFile, vorbis);
	}
}