In a Previous Post I provided a music transcoder program, which I called Recoder for no particularly good reason. This program was designed to simply take input files and convert them to .mp3, using the BASS.NET library.
That program was written as a Command-Line, console-driven application. Not the most user-friendly UI. At the time it made sense- I wanted MP3 files ASAP to stick on my MP3 player and figured that I may as well just grab my flac files and convert those- and since it was just for me at the time I went ahead and whipped up a quick BASS.NET based program to do the dirty work for me. It wasn’t until I was a good way into the task of programming it that I realized it would make an excellent topic to post about (which I proceeded to do).
In the closing of that previous article I mentioned the possibility of a future post documenting a Windows Version of that same program to some degree. This is that post.
Behold it in all it’s glory! Originally I aimed for a fully asynchronous program- but then realized that if I went that route the UI tracking progress would be both confusing and a pain in the butt to code, so I kept the more synchronous approach, though the code is still using Tasks. At the core of the program is the same Function present in the older console version described in the previously linked post:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public bool ConvertFile(String pSource, String pTarget) { InvokeBeginReencode(new ReencodeEventArgs(pSource, pTarget)); int hStream = Bass.BASS_StreamCreateFile(pSource, 0, 0, BASSFlag.BASS_DEFAULT); var l = new EncoderLAME(hStream); l.InputFile = null; //STDIN (recording) l.OutputFile = pTarget; l.LAME_Bitrate = (int) _BitRate; l.LAME_Mode = EncoderLAME.LAMEMode.Stereo; l.LAME_TargetSampleRate = (int) _SampleRate; l.LAME_Quality = EncoderLAME.LAMEQuality.Quality; BaseEncoder.EncodeFile(pSource, pTarget, l, EncodeFileProc, true, false); InvokeFinishReencode(new ReencodeEventArgs(pSource, pTarget)); return true; } |
Effectively it simply tells BASS to re-encode the file. EncodeFileProc is the function called during the re-encode; this method is basically responsible for updating the appropriate UI of the program. The “meat” of the program itself is primarily in the orchestration to get things to that point:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public ReencodeResults EncodeFolder(String SourceFolder, String TargetFolder, String[] ValidExtensions = null) { int Count = 0; long SourceBytes = 0; long TargetBytes = 0; if (ValidExtensions == null) ValidExtensions = InputExtensions; //loop through each file, and convert each one. if (!Directory.Exists(TargetFolder)) { Directory.CreateDirectory(TargetFolder); } var di = new DirectoryInfo(SourceFolder); foreach (FileInfo fi in di.GetFiles()) { if (ValidExtensions.Any(a => a.Equals(fi.Extension, StringComparison.OrdinalIgnoreCase))) { String sFilePart = Path.GetFileNameWithoutExtension(fi.FullName); String TargetFile = Path.Combine(TargetFolder, sFilePart + ".mp3"); //Console.WriteLine("Re-Encoding " + Path.GetFileNameWithoutExtension(fi.FullName)); //Console.WriteLine("Target:" + Path.GetFileNameWithoutExtension(TargetFile)); ConvertFile(fi.FullName, TargetFile); Count++; SourceBytes += fi.Length; TargetBytes += new FileInfo(TargetFile).Length; } } //now subfolders. foreach (DirectoryInfo subdir in di.GetDirectories()) { String TargetName = Path.Combine(TargetFolder, subdir.Name); ReencodeResults EncodeResults = EncodeFolder(subdir.FullName, TargetName, ValidExtensions); Count += EncodeResults.FileCount; SourceBytes += EncodeResults.OriginalBytes; TargetBytes += EncodeResults.TargetBytes; } return new ReencodeResults(Count, SourceBytes, TargetBytes); } |
The program also includes some useful functions that are used for similar ancillary purposes, such as recursively searching for files in a folder. The Full Source folder for This Windows version of Recoder can be found here.
Have something to say about this post? Comment!