miércoles, 27 de enero de 2010

Convertir un archivo WAV a MP3

La idea en este tutorial es como su titulo lo indica, convertir un archivo que esta en formato WAV, en un archivo con formato MP3. Una de las mejores soluciones para lograr este objetivo es usar la DLL de LAME.

¿Que es LAME?
LAME es un proyecto, que tiene como finalidad crear un compresor/descompresor de mp3/wav de gran calidad, que por cierto ya lo ha logrado, pero igualmente se le sigue agregando opciones.
LAME es un programa de libre distribución que es mantenido por una grana cantidad de personas.
LAME se lo puede encontrar como EXE (lame.exe) o como DLL (lame_enc.dll). En el caso del EXE podemos convertir archivos de un formato a otro, desde la linea de comandos, en cambio en la version DLL, la idea es que podemos hacer llamadas a esta desde nuestra aplicacion escrita en cualquier lenguaje, y asi crear una aplicacion totalmente grafica que utiliza LAME.
 
Todo el codigo fuente de LAME esta disponible para el que lo quiera bajar. El mismo se encuentra en lenguaje C, tambien podemos obtener información sobre que funciones tiene la dll, que estructuras usar, etc.. Pero si bien se dispone de esta informacion, cuando debemos "traducir" la estructuras desde "C" a otro lenguaje como VB .NET, C# o cualquier otro, puede provocar varios dolores de cabezas si no tenemos realmente claro que espera recibir la DLL, y que le estamos enviando. La página desde la cual se puede bajar el codigo, y obtener mas información es: http://www.lame.sourceforge.net/

Acerca de la implementación
Para llevar a cabo esta idea, vamos a crear una biblioteca de clases en C#, en la cual tendremos las funciones que necesitamos para trabajar desde nuestra aplicación. Aclaro que sólo implemente lo justo y necesario para esta aplicacion en particular, y de hecho hay una gran cantidad de funciones que expone lame_enc.dll que ni siquiera declare.
Por otro lado, vamos a crear una aplicación en VB .NET que utilice la biblioteca creada en C#, para asi lograr tener una aplicacion que convierta un archivo Wav en MP3.

A Trabajar
Vamos a crear varias clases, las cuales van a pertenecer al espacio de nombres "Sonido". Dentro del namespace "Sonido.MP3.LAME" tendremos todo lo referido a la comunicacion con la DLL de LAME, y en el namespace "Sonido.MP3" tendremos una clase llamada ConversorMP3 que es la que nos permitira convertir el archivo WAV en MP3, sin necesidad de conocer los detalles de LAME (Estructuras, funciones, tipos de datos, etc) del lado de nuestra aplicación.
Para no llenar la pagina de código, aqui sólo voy a mostrar como utilizar la biblioteca de clases desde la aplicación que queremos crear. En fin, basta de hablar y vamos a lo nuestro: El codigo.




Imports System.Runtime.InteropServices
Imports Sonido.MP3

Public
Class Form1

       
Inherits

System.Windows.Forms.Form


#
Region "
Código generado por el Diseñador de Windows Forms "


....
#End Region
        'Cargo los Bitrates posibles para los archivos MP3 que creemos


        Dim
ValoresCalidadPersonalizada()
As
LAME.BitRates =
{LAME.BitRates._8, _


                                                             
LAME.BitRates._16, _

                                                             LAME.BitRates._24,
_                                                              LAME.BitRates._32,
_

                                                           
  LAME.BitRates._40, _

                                                              LAME.BitRates._48,
_

                                                            
 LAME.BitRates._56, _

                                                              LAME.BitRates._64,
_

                                                             
LAME.BitRates._80, _

                                                              LAME.BitRates._96,
_

                                                              LAME.BitRates._112,
_

                                                              LAME.BitRates._128,
_

                                                              LAME.BitRates._144,
_

                                                              LAME.BitRates._160,
_

                                                              LAME.BitRates._192,
_

                                                              LAME.BitRates._224,
_

                                                              LAME.BitRates._256,
_

                                                              LAME.BitRates._320}

        'Cargo los valores que puedo utilizar cuando creo un archivo MP3 con Bitrate variable
        Dim
ValoresCalidadPersonalizadaVBR()
As
LAME.CalidadVBR
= {LAME.CalidadVBR._0, _

                                                                  
LAME.CalidadVBR._1, _

                                                                  
LAME.CalidadVBR._2, _

                                                                  
LAME.CalidadVBR._3, _

                                                                  
LAME.CalidadVBR._4, _

                                                                  
LAME.CalidadVBR._5, _

                                                                  
LAME.CalidadVBR._6, _

                                                                  
LAME.CalidadVBR._7, _

                                                                  
LAME.CalidadVBR._8, _

                                                                  
LAME.CalidadVBR._9}

        Private Sub
cmdConvertir_Click(
ByVal
sender
As System.Object,
ByVal e As System.EventArgs) Handles
cmdConvertir.Click
                'El archivo que se va a crear (MP3)
               
Dim
ArchMP3 As New IO.FileStream(txtMP3.Text,
IO.FileMode.Create)



                'El archivo que se va a abrir para convertir (WAV)
                Dim ArchAbrir As
New
IO.FileStream(txtWAV.Text, IO.FileMode.Open)

                'En esta variable se obtendra la cantidad de byte leidos desde el archivo WAV
                Dim Read As
Int32



                'Aqui guardo la informacion leida desde el archivo WAV
                Dim buff As
Byte()



                'Este objeto nos permitira convertir lo leido en WAV a MP3 y grabarlo en el archivo MP3
                Dim GrabadorMP3 As
ConversorMP3


                'Determino la configuracion que desea el usuario, para el archivo de salida (MP3)
                If optCalidadNormal.Checked = True Then



                       
GrabadorMP3 =
New ConversorMP3(ArchMP3,
LAME.Calidad.CalidadNormal)

               
ElseIf
optCalidadRegular.Checked = True Then

                        GrabadorMP3
=
New ConversorMP3(ArchMP3, LAME.Calidad.CalidadRegular)
                ElseIf optCalidadMuyBuena.Checked = True Then
                        GrabadorMP3
=
New ConversorMP3(ArchMP3,
LAME.Calidad.CalidadMuyBuena)

                ElseIf optCalidadPersonalizada.Checked = True Then


                        GrabadorMP3
=
New ConversorMP3(ArchMP3,
ValoresCalidadPersonalizada(tbCalidadPersonalizada.Value))



                ElseIf optCalidadPersonalizadaVBR.Checked = True Then


                        GrabadorMP3
=
New ConversorMP3(ArchMP3,
ValoresCalidadPersonalizadaVBR(tbCalidadPersonalizadaVBR.Value))



                End If

                'Redimensiono el buffer de lectura segun lo que el "GrabadorMP3" desea que le envie en cada llamada a convertir.
                ReDim buff(GrabadorMP3.TamañoDelBuffer - 1)

                'Inicializo las propiedades de la barra de progreso
                          With
pbProgresoDeLaCopia

                        
.Maximum = ArchAbrir.Length

                         .Value
= 0

                 End With


                    
'En los primeros 44 bytes se encuetra el encabezado del archivo (Esto no lo convierto a MP3)


                ArchAbrir.Seek(44,
IO.SeekOrigin.Begin)

                'Leo una porcion del archivo WAV

                Read
= ArchAbrir.Read(buff, 0, buff.Length)

                'Mientras no haya terminado de leer el archivo WAV, sigo "Leyendo WAV->Convirtiendo a MP3->Grabando en MP3"
                Do While (Read > 0)
                       
'Codifico lo leido del archivo WAV y lo grabo en el archivo MP3




                        GrabadorMP3.Write(buff,
0, Read)

                        'Leo una porcion del archivo WAV

                        Read
= ArchAbrir.Read(buff, 0, buff.Length)

                        'Actualizo la barra de prograso
                        pbProgresoDeLaCopia.Value
= pbProgresoDeLaCopia.Value + Read

                        'Atiendo otros mensajes, para que la aplicacion no parezca que se colgo

                        Application.DoEvents()

                Loop


                'Cierro todo
                GrabadorMP3.Close()

                ArchMP3.Close()

                ArchAbrir.Close()

                'Aviso que termine
                MsgBox("La
conversion ha finalizado", MsgBoxStyle.Information, "WAV TO MP3")

        End
Sub

        'AQUI VA EL RESTO DEL CODIGO QUE MANEJA CIERTOS ASPECTOS DE LA INTERFACE
End Class

Esta pequeña aplicación sólo es a modo de ejemplo, y presenta muy pocas validaciones, asi que debes mirar que lo que escribes en las cajas de texto sea correcto y que incluyan todo el path y la extension (Por ej: "c:\Prueba.wav" para el WAV y "c:\Musica\MP3\ArchConv.mp3"). En el caso del MP3 lo unico que debe existir es path, ya que el archivo se creara con el nombre que tu especifiques.

CUIDADO: Como dije antes no hay muchas validaciones, y si el archivo de destino existe se reemplazara sin preguntar, asi que cuidado ( ¡yo avise! ).

Conclusión
Podemos ver que para convertir el archivo WAV en MP3, lo unico que debemos hacer es ir leyendo el archivo WAV por trozos del tamaño que nos devuelve el objeto de la clase ConversorMP3, y luego enviar lo leido al mismo objeto, para que se encargue de codificarlo y grabarlo en MP3, hasta que se termine de leer el archivo WAV.
Un detalle importante es que antes de empezar a leer y enviar a convertir, debemos avanzar 44 bytes en el archivo WAV, ya que en esta zona se encuentra el encabezado del archivo, donde podemos obtener cierta informacion sobre el formato en el que esta
grabado el mismo. Si no tuvieramos esta precaucion, el archivo igualmente se convertiria en MP3, pero escuchariamos un pequeño ruido cuando arranca la cancion.

La clase ConversorMP3 tiene 3 sobrecargas, segun que tipo de conversion queremos. Tenemos la posibilidad de grabar en MP3 con 3 calidades predifinidas (Regular, Normal, Muy Buena), las cuales en realidad son a modo ilustrativo y de hecho podria haber muchas mas, ya que LAME soporta varias calidades predefinidas que yo no he implementado en este ejemplo. Por otro lado tenemos la posibilidad de especificar nosotros cual es el Bitrate que queremos para nuestro archivo MP3 y por ultimo tambien podemos decirle al conversor que queremos usar un Bitrate variable.
Para terminar, queria decir que aquí sólo se trata de brindar un introduccion a la utilización de lame_enc.dll y que aun queda mucho por investigar y aprender.
Hay muchos aspectos que no tienen que ver netamente con la programación sino que en realidad estan relacionados con ciertas cuestiones que tienen que ver con el sonido (Bitrates (Constantes y variables), Samplerate, Psicoacustica entre otros.

Justamente lo que yo queria lograr aqui, era birndar una forma simple de poder convertir en MP3 un archivo WAV, sin tener que conocer demasiado sobre el tema, por eso es que una de las opciones que brinda la clase ConversorMP3 es la de crear un archivo MP3 con calidad Normal, Regular o Muy buena, ya que creo que es mas entendible esto, que decir que la calidad es 112 Kbps, 128 Kbps o 192 Kbps, todos a 44100 Hz y en modo Joint Stereo. Para el quiere probar como influye el Bitrate en la calidad del sonido, que pruebe con un bitrate de 8 Kbps y luego con uno de 128 Kbps o superior, y notara que este un factor mas que importante en el resultado final.

No hay comentarios:

Publicar un comentario