Click here to Skip to main content
16,016,759 members
Articles / Programming Languages / C#
Article

C# MP3 Compressor

Rate me:
Please Sign up or sign in to vote.
4.74/5 (48 votes)
13 Jul 20044 min read 724.8K   17.4K   190   118
A C# MP3 compressor using "lame_enc.dll" from the LAME project.

Sample image

Introduction

The first question to my previous article (C Sharp Ripper) was about how to rip directly to MP3 format. Then I looked for some MP3 compressor done for .NET framework and I couldn't find the exact solution, so I decided to write one. The solution was to use the LAME MP3 encoder, specifically to wrap in C# the functions of lame_enc.dll. See this website for technical and copyright information regarding the LAME project.

In this work, there is code from the article: A low level audio player in C# by Ianier Munoz.

Background

While it is true that the LAME encoder is written in C and all source code is available, one could think of compiling these source files in managed C++ to obtain a managed compressor. However, an easier way to achieve that goal is to use the LAME compressor through the functions exposed by the lame_enc.dll. This DLL exports a few functions and it is relatively easy to use.

One problem to mention about the use of the DLL is that in the current version, it is not possible to compress two streams at the same time. The compressor I describe in this article (Mp3Writer) is a class derived from AudioWriter, which is a binary writer that can be used as a base of writers for different audio streams (different audio formatters, compressors, etc.). AudioWriter receives audio data in PCM format, then the data is compressed and written to the resulting stream, or just written without modifications using a specific format (WAV format, for instance, as in the WaveWriter class).

Using the code

AudioWriter and other base and tools classes are in a library named yeti.mmedia. All other classes related to the MP3 compressor are in a library yeti.mp3. Within this library, I included all the translation of structures, constants, and functions needed to use lame_enc.dll. The following code shows the simplest way to use the MP3 compressor with the default configuration:

C#
...
using WaveLib;
using Yeti.MMedia; 
using Yeti.MMedia.Mp3;
..
WaveStream InStr = new WaveStream("SomeFile.wav");
try
{
  Mp3Writer writer = new Mp3Writer(new FileStream("SomeFile.mp3", 
                                      FileMode.Create), InStr.Format);
  try
  {
    byte[] buff = new byte[writer.OptimalBufferSize];
    int read = 0;
    while ( (read = InStr.Read(buff, 0, buff.Length)) > 0 )
    {
      writer.Write(buff, 0, read);
    }
  }
  finally
  {
    writer.Close();
  }
}
finally
{
  InStr.Close();
}

First, a WaveStream is created to read the uncompressed audio data from a WAV file, then a Mp3Writer is created. The Mp3Writer constructor is called passing as the first parameter the stream where to write the resulting MP3 stream (in this case, a FileStream), and as second parameter the WaveFormat that specifies the format of the input data. The input stream is read until the end and all the data is written to the writer, which converts it to MP3 format and saves the result to the output stream.

There are two other overloads of the Mp3Writer constructor: one that accepts a BE_CONFIG instance, which is a structure translated from LAME that describes how the stream must be compressed (bit rate, compression method, quality, etc.). The other overload accepts a Mp3WriterConfig instance, which wraps BE_CONFIG and it is serializable, so it can be used to persist the compressor configuration using serialization. Another important class is EditMp3Writer, which is a custom control that can be included in a form or dialog to configure the parameters of the compressor, as shown in the sample code.

Another example of using the writer could be an improved version of the ripper described in my article C Sharp Ripper to rip directly to MP3 format. In the file Form1.cs, inside the handler of the "Save as.." button, there is the line:

C#
m_Writer = new WaveWriter(WaveFile, Format);

which may be changed to:

C#
m_Writer = new Mp3Writer(WaveFile, Format);

The rest of the code remains without change and, of course, if you need more control on the compressor parameters then you should add extra code to use BE_CONFIG and/or Mp3WriterConfig.

Conclusion

As shown here, the use of this compressor is relatively easy. When more control about the compression process is required, then a deeper knowledge about the meaning and use of all fields of each LAME structure is mandatory. It is also important to note that if you use this code in any product, you should observe the LAME product licensing details.

Any use of this product does not convey a license under the relevant intellectual property of Thomson and/or Fraunhofer Gesellschaft nor imply any right to use this product in any finished end user or ready-to-use final product. An independent license for such use is required. For details, please visit http://www.mp3licensing.com.

You can find a first version of a Widows Media Audio (WMA) compressor in my article, Windows Media Audio Compressor. A better compressor and a translation of the Windows Media Format SDK could be found in my article, C Sharp Windows Media Format SDK translation.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalif do you have sample source with mfc, give me source please! Pin
HoiN\ kyung-joon30-Oct-07 3:54
HoiN\ kyung-joon30-Oct-07 3:54 
GeneralCompiling using .NET 2005 Pin
Life as a Coder5-Aug-07 23:19
Life as a Coder5-Aug-07 23:19 
GeneralRe: Compiling using .NET 2005 Pin
Juraj Borza26-Aug-07 20:05
Juraj Borza26-Aug-07 20:05 
GeneralRe: Compiling using .NET 2005 Pin
cdebel18-Jan-08 15:03
cdebel18-Jan-08 15:03 
GeneralLame_encDll.beInitStream failed with the error code 4294967295 when using VBR Pin
Fink Christoph13-Apr-07 10:28
Fink Christoph13-Apr-07 10:28 
GeneralRe: Lame_encDll.beInitStream failed with the error code 4294967295 when using VBR Pin
trylon10-Sep-07 1:34
trylon10-Sep-07 1:34 
GeneralRe: Lame_encDll.beInitStream failed with the error code 4294967295 when using VBR Pin
bkaratte17-Nov-10 4:27
bkaratte17-Nov-10 4:27 
GeneralRe: Lame_encDll.beInitStream failed with the error code 4294967295 when using VBR Pin
siddhe12-Apr-13 13:00
siddhe12-Apr-13 13:00 
I was having the exact same error, guess just like anyone attempting VBR off the box changing some param.

The solution I found is related to structure:
struct LHV1
within Lame.cs at yety.mp3 project.

Specifically related to the filling of param
dwVbrAbr_bps
along with the rest of params.

Whether you intended it or not, it is filled with some value at the config dialog. That would mean that you want to force average bitrate for VBR, overwritting the rest of the VBR params; well, having that param set along with the rest seemed to cause the failure for me. Since I did not intend to use VbrAbr, I set it to zero for lame dll to obviate it as I wanted. That did the trick for me.

Another thing that's not set by default is the
Quote:
format.LHV1.bWriteVBRHeader
, I kind of like the mp3 to have the VBR header being set, so I set it to true.

the full spec of the struct LHV1 may be found here:
http://www.fi.muni.cz/~qruzicka/Smid/man.htm[^]

or else I'll just replicate it below just in case it gets lost:


Quote:
The LHV1 BE_CONFIG - structure (recommended)

These are the members of the LHV1 BE_CONFIG structure, you need to fill in before you call beInitStream():
dwConfig Specifies what kind of output you want. Since only MP3 currently is supported you must set this to BE_CONFIG_LAME

format.LHV1.dwStructVersion Indicates the version number of the structure, current version number is 1
format.LHV1.dwStructSize Specifies the size of the BE_CONFIG structure (currently 331 bytes)

format.LHV1.dwSampleRate Samplerate in Hz for MP3 file. This can be set to either:
32000, 44100 or 48000 for MPEG-I
16000, 22050 or 24000 for MPEG-I
8000, 11025 or 12000 for MPEG-II.5
format.LHV1.dwReSampleRate Specifies to which sample rate the input stream has to be resampled, if set to 0, the encoder will decide which ReSample rate to use
format.LHV1.nMode Stereomode for MP3 file. This can be either BE_MP3_MODE_STEREO, BE_MP3_MODE_JSTEREO, BE_MP3_MODE_DUALCHANNEL or BE_MP3_MODE_MONO.
format.LHV1.dwBitrate For CBR, this specifies the actual bitrate, for VBR, it specifies the minimum bitrate
Allowed bitrates are: 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256 and 320.for MPEG-I
Allowed bitrates are: 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144 and 160.for MPEG-II
format.LHV1.dwMaxBitrate For CBR this setting is ignored, when using VBR, it specifies the maximum bitrate
format.LHV1.nPreset The quality option can be set to one of the following presets:
NOPRESET,PHONE,SW,AM,FM,VOICE,RADIO,TAPE,HIFI,CD,STUDIO as defined in the LAME_QUALTIY_PRESET. Keep in mind that the presets can overwrite some of the other settings, since it is called right before the encoder is initialized


format.LHV1.bCopyright If this is set to TRUE the Copyright bit in the MP3 stream will be set.
format.LHV1.bCRC Set this to TRUE in order to enable CRC-checksum in the bitstream.
format.LHV1.bOriginal If this is set to TRUE the Original bit in the MP3 stream will be set.
format.LHV1.bPrivate If this is set to TRUE the Private bit in the MP3 stream will be set.

format.LHV1.bWriteVBRHeader Sepecifes if the a XING VBR header should be written or not. When this option is enabled, you have to call the beWriteVBRHeader function when encoding has been completed
format.LHV1.bEnableVBR Specifies if VBR encoding option shall be used or not, possible values are TRUE/FALSE
format.LHV1.nVBRQuality Quality option if VBR is enabled (0=highest quality, 9 is lowest quality)
format.LHV1.dwVbrAbr_bps If the Average Bit Rate is specified, the lame encoder ignores the nVBRQuality settings

format.LHV1.bNoBitRes Disables the bit-resorvoir and disables the insertion of padded frames

format.mp3.btReserved For future use, set all elements to zero

GeneralErrors after conversion to VS 2005 solution Pin
hswear321-Feb-07 15:53
hswear321-Feb-07 15:53 
QuestionPermission Pin
acosano10-Jan-07 4:33
acosano10-Jan-07 4:33 
GeneralWell done Pin
martin.susil14-Nov-06 10:09
martin.susil14-Nov-06 10:09 
GeneralBE_CONFIG arguments Pin
dabneyr27-Jul-06 22:19
dabneyr27-Jul-06 22:19 
GeneralGreat stuff! Pin
IPC20006-Jun-06 3:39
IPC20006-Jun-06 3:39 
GeneralMP3 Reader! Pin
Marc Schneider3-May-06 0:34
Marc Schneider3-May-06 0:34 
GeneralProblems extending Structure in C# Pin
Mark Johnson13-Mar-06 22:23
Mark Johnson13-Mar-06 22:23 
GeneralChange samplerate Pin
robertpnl27-Feb-06 8:16
robertpnl27-Feb-06 8:16 
AnswerRe: Change samplerate Pin
Idael Cardoso10-Mar-06 6:52
Idael Cardoso10-Mar-06 6:52 
QuestionRe: Change samplerate Pin
see7a3-Feb-07 8:26
see7a3-Feb-07 8:26 
GeneralC Sharp MP3 Compressor on pocket pc Pin
mattmematty9-Oct-05 11:18
mattmematty9-Oct-05 11:18 
GeneralRe: C Sharp MP3 Compressor on pocket pc Pin
Idael Cardoso28-Nov-05 10:20
Idael Cardoso28-Nov-05 10:20 
GeneralResampling Pin
18-Aug-05 8:19
suss18-Aug-05 8:19 
GeneralRe: Resampling Pin
Idael Cardoso4-Sep-05 0:05
Idael Cardoso4-Sep-05 0:05 
GeneralID3 tags Pin
Ed Brey31-Jul-05 1:52
Ed Brey31-Jul-05 1:52 
GeneralRe: ID3 tags Pin
Idael Cardoso7-Aug-05 6:22
Idael Cardoso7-Aug-05 6:22 
GeneralDecode 8 bits sample Pin
srenzi12-Apr-05 4:20
srenzi12-Apr-05 4:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.