Compressing Wav file to MP3 | Compresser un fichier Wav en MP3 |
1. Introduction | Introduction |
First, I don't meant to give you informations about how to understand the mp3 algorithm. My goal is to explain how to use an already existing encoder with BCB. | Le but de cet article n'est pas d'expliquer le fonctionnement de l'algorithme de compression mp3 mais d'expliquer comment utiliser un encodeur existant avec BCB. |
2. Choosing the mp3 encoder | Choisir l'encodeur mp3 |
There
are tons of mp3 encoders. Some
of them are free others are not. Some are fast but produce an awful
result. Others are slow but with excellent result and give a high audio
quality. The ideal would be a free, reasonably fast encoder giving a
high audio quality, all at the same time. Enjoy! This pearl exists. But we have to look at it in the GNU world. There is a GNU project, called LAME, for Lame Ain't a Mp3 Encoder, under the GPL license. The official web site of the LAME project is http://www.mp3dev.org/mp3/ Moreover, as it is a GNU project, we have access to the source and there is a version compiled for Win32 in a DLL. Among all the other encoders, I want to quote two of them. The first, FRAUNHOFER, because it is a fast and excellent encoder : http://www.iis.fhg.de/ but it's not free though. The second because it's a very fast encoder but the audio result is awful. So don't use it except if you are looking for a fast encoder. It's the encoder from Xing Tech : http://www.xingtech.com/ Note : The Lame encoder has a limitation. The sample rate must be 32000, 44100 or 48000. |
Il existe des tas
de
codeur/décodeur mp3. Certains sont libres, d'autres pas.
Certains sont gratuits, d'autres payants. Certains sont rapides mais
donnent un résultat déplorable. D'autres sont lents mais
produisent un fichier mp3 de très bonne qualité sonore.
L'idéal serait de trouver un encodeur mp3 à la fois
gratuit, dont on disposerait des sources, qui serait suffisamment
rapide et dont le résultat sonore serait très bon. Et
bien, réjouissez-vous, cette perle rare existe. Il faut, comme
par hasard, aller la chercher dans la communauté du logiciel
libre. Il s'appelle LAME
(Lame Ain't a Mp3 Encoder), projet GNU sous license GPL : http://www.mp3dev.org/mp3/ Il existe une version compilée pour Win32 sous forme d'une DLL. Un autre excellent encoder est celui de FRAUNHOFER. Mais il n'est pas gratuit. Sa qualité n'en est pas moins excellente : http://www.iis.fhg.de/ Si vous cherchez un encodeur très rapide mais dont la qualité sonore du résultat est vraiment quelconque, tournez-vous vers Xing Tech : http://www.xingtech.com Note : L'encodeur Lame est limité au niveau des fréquences d'échantillonage. Seule les fréquences 32000,44100 et 48000 peuvent être utilisées. |
3. Some informations about the WAV format | Quelques informations sur le format WAV |
A
wav file is just a collection of
chunks. There is a format chunk wich contains all the informations
about the samples. For instance, the bitrate, the number of channels,
if it's stereo or mono... There is also a chunk containing the data. In
other words, this chunk contains all the samples. In front of the file,
there are 12 characters indicating that the file is a wav file. The two chunks given above must be present in the file. There could be other chunk but we just ignore them. They are not needed for our purpose. If you want to know more about wav file, take a look at http://www.wotsit.org/ for a complete description. The format chunk : |
Un
fichier wav se présente comme une collection de blocs. Le
premier contient 12 caractères et indique que nous sommes en
présence d'un fichier wav. Le bloc de format contient les
informations sur les échantillons (samples) contenus dans le
fichier. Par exemple, la fréquence d'échantillonnage,
mono ou stéréo, le nombre de bits par échantillon,
etc... Il y a également un bloc contenant les samples
eux-mêmes. C'est le bloc de données (data). Ces deux blocs
sont obligatoires. En plus de ceux-ci, il en existe tout un tas d'autres facultatifs. Je vous renvoie au site http://www.wotsit.org/ pour une description complète du format wav. Le bloc de format : |
struct FormatChunk
{ char chunkID[4]; long chunkSize; short wFormatTag; unsigned short wChannels; unsigned long dwSamplesPerSec; unsigned long dwAvgBytesPerSec; unsigned short wBlockAlign; unsigned short wBitsPerSample; // Note: there may be additional fields here, depending upon wFormatTag. }; |
Above,
you can see the struct
representing the format chunk. The chunkID is always "fmt " with an
ending space (4 characters). It's the identification of the chunk. All
other chunk have such an ID. The chunkSize parameter contains the
number of bytes of the chunk, the ID and chunkSize excluded. The format chunk must be the first chunk in the file. The data chunk : |
Vous
pouvez voir, ci-dessus, la structure représentant le bloc de
format. Le paramètre chunkID est l'identificateur de bloc (4
caractères). Dans le cas du bloc de format, il contient "fmt "
(notez l'espace à la fin). Le paramètre chunkSize
contient la taille du bloc, non-compris l'identificateur et le
paramètre contenant cette taille. Le bloc de format est le premier bloc que l'on rencontre dans le fichier wav Le bloc de données : |
struct Chunk
{ char chunkID[4]; long chunkSize; }; |
In the case of the data chunk, the chunkID contains "data". The chunkSize parameters contains the size of the raw data (samples). The data begins just after chunkSize. | Dans le cas du bloc de données, chunkID contient "data". Le paramètre chunkSize contient la taille du bloc de données proprement dites. Celles-ci commencent juste après chunkSize. |
So,
when we read a wav file, all we
have to do is :
- read the first 12 characters to check if it's a real wav
file. |
Donc,
ce que nous devons faire est :
- lire les 12 premiers caractères pour
déterminer si on est bien en présence d'un fichier wav. |
4. Importing the DLL | Importer la DLL |
The
DLL used for the encoding
is called lame_enc.dll. Unfortunately, this DLL was build with VC 6 from Microsoft. If we just create a lib file from the DLL and try to import the library in BCB, we'll get an 'Unresolved external error' at link time for each function we'll try to use. Due to the declaration type, BCB is expecting a function name with a leading underscore and the function names doesn't have such a leading underscore. To resolve this issue, we must, first, create a def file from our DLL. Open a console windows and type : |
La DLL utilisée pour l'encodage s'appelle lame_enc.dll. Malheureusement, cette DLL a été construite avec VC6 de Microsoft. Si nous créons un fichier .lib à partir de cette DLL et essayons de l'importer dans BCB, chaque fois que nous tenterons d'appeler une des fonctions de la DLL, nous aurons une erreur du type 'Unresolved external' au moment du link. Ceci est dû au fait que, à cause du type de déclaration des fonctions, BCB s'attend à un nom de fonction précédé d'un underscore. Pour résoudre ce problème, nous devons d'abord, créer un fichier .def à partir de la DLL. Ouvrez une fenêtre DOS et tapez : |
IMPDEF lame_enc.def lame_enc.dll
Open the lame_enc.def file with an editor (Notepad for instance) and modify it like this. This will create aliases for the functions : | Ouvrez le fichier lame_enc.def avec votre éditeur de texte préféré et modifiez-le comme ceci. Nous créons en fait des alias pour chaque fonction de la DLL. |
LIBRARY LAME_ENC.DLL
EXPORTS
_beCloseStream = beCloseStream
_beDeinitStream = beDeinitStream
_beEncodeChunk = beEncodeChunk
_beInitStream = beInitStream
_beVersion = beVersion
_beWriteVBRHeader = beWriteVBRHeader
beCloseStream
@4
beDeinitStream
@3
beEncodeChunk
@2
beInitStream
@1
beVersion
@5
beWriteVBRHeader
@6
Now, we can create the lib file from our def file. We'll import that lib file in our project. To create the lib file, type : | Maintenant, on peut créer le fichier .lib à partir du fichier .def modifié. C'est ce fichier .lib qui sera importé dans le projet. Pour cela, tapez : |
implib lame_enc.lib lame_enc.def
5. The code | Le code |
First,
you have to import the libary
in your project. Next, include the header file of the DLL into your
unit. In the DLL header file, you have to add extern "C" in front of
all exported function. Here is the header with the moifications (lame_enc.h) : |
Ajoutez
d'abord la librairie à votre projet. Ensuite, n'oubliez pas
d'inclure le fichier d'entête à votre unité. Dans
ce fichier d'entête, il faut ajouter extern "C" devant chaque
fonction exportée. Voici à quoi doit ressembler ce fichier d'entête (lame_enc.h) : |
/* bladedll.h |
As you can see in the header above, you have to add #define _BLADEDLL into your .cpp file before including the header. | Comme vous pouvez le voir dans l'entête de la DLL, vous devez ajouter #define _BLADEDLL avant l'inclusion du fichier dans votre .cpp. |
Below, you'll find the code of a little application which takes a wav file in input and encode the file to mp3. I don't give more explanations because the code is very straightforward and commented. It is not very elegant but it's just to show how to use the DLL. | Ci-dessous, vous trouverez le code d'une petite application qui reçoit en entrée un fichier .wav et l'encode en mp3. Je ne donne pas d'explications supplémentaires pour la simple raison que le code est trivial et documenté. |
Format.h //--------------------------------------------------------------------------- |
Unit1_H.h //--------------------------------------------------------------------------- |
Unit1.cpp //--------------------------------------------------------------------------- |
You can download the simple project above (BCB4). The zip file contains all you need to use the DLL : header file, DLL, help file : wav2mp3.zip | Vous pouvez télécharger le projet ci-dessus (BCB4). Le fichier .zip contient la DLL, les fichiers d'entête, un fichier d'aide au format doc et tout ce qui est nécessaire : wav2mp3.zip |