# Sources PureBasicConsultez toutes les sources

Nombre d'auteurs : 41, nombre de sources : 88, dernière mise à jour : 13 août 2011

Sommaire→Sons, musiques

- Comment encoder un fichier wav dans le format mp3 ?

Version hors-ligne
Comment encoder un fichier wav dans le format mp3 ?

Ce code permet d'encoder des fichiers wav dans le format mp3.

Sélectionnez

    ;this is a minimal set of source coded needed to make use of the l3codecp.acm ACM filter driver
    ;that is installed along with windows media player 10
    ;
    ;Copyright (C) 2005  Thomson, Inc.
    ;
    ;Original source : http://www.all4mp3.com/Software4.aspx
    ;
    ;This library is free software; you can redistribute it and/or
    ;modify it under the terms of the GNU Lesser General Public
    ;License as published by the Free Software Foundation; either
    ;version 2.1 of the License, or (at your option) any later version.
    ;
    ;This library is distributed in the hope that it will be useful,
    ;but WITHOUT ANY WARRANTY; without even the implied warranty of
    ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    ;Lesser General Public License for more details.
    ;
    ;You should have received a copy of the GNU Lesser General Public
    ;License along with this library; if not, write to the Free Software
    ;Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    ;here's a msdn page that has lots of good acm related info and code
    ;http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dnarmulmed/html/msdn_codec.asp

    ;If you find that you are unable to get this to work for bitrates higher than 56k, then it may be that there
    ;are some registry settings that are causing acm drivers to pick up the old restricted filter and not the new one
    ;installed along with windows media player 10
    ;
    ;this one should be l3codecp.acm, but if it is l3codeca.acm then it is the 56k limited driver
    ;[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32]
    ;"msacm.l3acm"="l3codecp.acm"
    ;
    ;this one may not be necessary, but may just be cosmetic
    ;[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\drivers.desc]
    ;"l3codecp.acm"="Fraunhofer IIS MPEG Layer-3 Codec (professional)"

    ;PureBasic port by Rescator

    #MPEGLAYER3_ID_MPEG=1
    #WAVE_FORMAT_MPEGLAYER3=$0055
    #MPEGLAYER3_WFX_EXTRA_BYTES=12
    #ACM_FORMATSUGGESTF_WFORMATTAG=$00010000
    #ACM_STREAMSIZEF_SOURCE=$00000000
    #ACM_STREAMCONVERTF_BLOCKALIGN=$00000004
    #ACM_STREAMCONVERTF_END=$00000020

    Structure MPEGLAYER3WAVEFORMAT
     wfx.WAVEFORMATEX
     wID.w
     fdwFlags.l
     nBlockSize.w
     nFramesPerBlock.w
     nCodecDelay.w
    EndStructure

    Structure ACMSTREAMHEADER
     cbStruct.l
     fdwStatus.l
     dwUser.l
     pbSrc.l
     cbSrcLength.l
     cbSrcLengthUsed.l
     dwSrcUser.l
     pbDst.l
     cbDstLength.l
     cbDstLengthUsed.l
     dwDstUser.l
     dwReservedDriver.l[10]
    EndStructure

    Structure ACMVERSION
     build.w
     rev.b
     ver.b
    EndStructure

    OpenConsole()

    Enumeration
     #infile
     #outfile
    EndEnumeration

    nb_read.l=0
    leftover.l=0
    wfxSrc.WAVEFORMATEX
    MP3wfxDst.MPEGLAYER3WAVEFORMAT
    dwACMVer.l=0
    has.l=#Null
    ash.ACMSTREAMHEADER

    total_bytes.l=0
    ;these buffer sizes are hard coded here, you need to pick appropriate ones
    cbSrcBuf.l=1152*2*2*4
    cbDstBuf.l
    *pSrcBuf=AllocateMemory(cbSrcBuf)
    *pDstBuf=AllocateMemory(cbSrcBuf)

    ;Get and display the ACM version.
    dwACMVer = acmGetVersion_();
    *acmver.ACMVERSION=@dwACMVer
    Print("ACM v"+StrU(*acmver\ver,#PB_Byte)+"."+StrU(*acmver\rev,#PB_Byte))
    If *acmver\build=0
     PrintN(" Retail")
    Else
     PrintN(" build "+StrU(*acmver\build,#PB_Word))
    EndIf

    ;set the source structure  we need to know ahead of time what the sample rate,
    ;bits per sample, number of channels and bit rate numbers are
    wfxSrc\wFormatTag=#WAVE_FORMAT_PCM
    wfxSrc\nSamplesPerSec=44100
    wfxSrc\nBlockAlign=4
    wfxSrc\nAvgBytesPerSec=wfxSrc\nSamplesPerSec*wfxSrc\nBlockAlign
    wfxSrc\nChannels=2
    wfxSrc\wBitsPerSample=16
    wfxSrc\cbSize=0

    ;set the destination structure
    ;in this example we'll say it is going to be an mp3 with 2 channels, 44100hz sample
    ;rate and 128k bitrate
    MP3wfxDst\wID=#MPEGLAYER3_ID_MPEG
    MP3wfxDst\wfx\wFormatTag=#WAVE_FORMAT_MPEGLAYER3
    MP3wfxDst\wfx\nChannels=2
    MP3wfxDst\wfx\nSamplesPerSec=44100
    MP3wfxDst\wfx\wBitsPerSample=0
    MP3wfxDst\wfx\nAvgBytesPerSec=320000/8
    MP3wfxDst\wfx\cbSize=#MPEGLAYER3_WFX_EXTRA_BYTES
    MP3wfxDst\wfx\nBlockAlign=1

    ;now let the driver try and find the best match for us
    res=acmFormatSuggest_(#Null,@MP3wfxDst,@wfxSrc,SizeOf(WAVEFORMATEX),#ACM_FORMATSUGGESTF_WFORMATTAG)
    If res<>#S_OK
       PrintN("error "+StrU(res,#PB_Long))
     ;do something here about the failure
       Goto quit
    EndIf

    ;now try to open the input and output streams
    res=acmStreamOpen_(@has,#Null,@wfxSrc,@MP3wfxDst,#Null,0,0,ACM_STREAMOPENF_NONREALTIME)
    If res<>#S_OK
       PrintN("error "+StrU(res,#PB_Long))
     ;do something here about the failure
       Goto quit
    EndIf

    ;now let the driver decide how big the destination buffer should be based
    ;on the parameters of both input and output wfx
    res=acmStreamSize_(has,cbSrcBuf,@cbDstBuf,#ACM_STREAMSIZEF_SOURCE)
    If res<>#S_OK
       PrintN("error "+StrU(res,#PB_Long))
     ;do something here about the failure
       Goto quit
    EndIf

    ;this would likely be a better place to allocate both the input and output buffers
    ;instead of the fixed size [0xffff] used at the top

    ;now set up the header to get ready to convert
    ash\cbStruct=SizeOf(ACMSTREAMHEADER)
    ash\pbSrc=*pSrcBuf
    ash\cbSrcLength=cbSrcBuf
    ash\pbDst=*pDstBuf
    ash\cbDstLength=cbDstBuf
    res=acmStreamPrepareHeader_(has,@ash,0)

    If res<>#S_OK
       PrintN("error "+StrU(res,#PB_Long))
     ;do something here about the failure
       Goto quit
    EndIf

    ;open up the input pcm file
    res=ReadFile(#infile,"source.wav")
    If res=0
       PrintN("cannot open input file")
     ;do something here about the failure
       Goto quit
    EndIf

    ;open up the output mp3 file
    res=CreateFile(#outfile,"dest.mp3")
    If res=0
       PrintN("Cannot open outfile")
     ;do something here about the failure
       Goto quit
    EndIf

    ;here's a hack to skip over the usual 44 bytes in the wav header
    ;UseFile(#infile)
    FileSeek(#infile,44)

    ash\cbDstLengthUsed=0
    ash\cbSrcLengthUsed=0
    leftover=0
    total_bytes=0
    ;keep looping until we break or the eof is found on the input file
    While Eof(#infile)=0
       nb_read=0
       If leftover<cbSrcBuf
          ;read some bytes from the file
    ;  UseFile(#infile)
          nb_read=ReadData(#infile,*pSrcBuf+leftover,cbSrcBuf-leftover)
          If nb_read=0
             PrintN("cannot read bytes from input")
       ;do something here about the failure
             Goto quit
      EndIf
          total_bytes+nb_read
     EndIf

       ;adjust the size of the input buffer based on leftover amount and newly read data
       ash\cbSrcLength=leftover+nb_read

       ;loop this section for a stream convert
       ;The acmStreamConvert function converts data in a source buffer into
       ;the destination format, writing the converted data into the destination buffer.
       If nb_read>=0
          res=acmStreamConvert_(has,@ash,#ACM_STREAMCONVERTF_BLOCKALIGN)
       Else
          res=acmStreamConvert_(has,@ash,#ACM_STREAMCONVERTF_BLOCKALIGN|#ACM_STREAMCONVERTF_END)
       EndIf
     If res<>#S_OK
        PrintN("error "+StrU(res,#PB_Long))
      ;do something here about the failure
        Goto quit
     EndIf

       PrintN("compressed total: "+StrU(total_bytes,#PB_Long)+" mp3: "+StrU(ash\cbDstLengthUsed,#PB_Long)+" pcm: "+StrU(ash\cbSrcLengthUsed,#PB_Long))
       leftover=ash\cbSrcLength-ash\cbSrcLengthUsed
       ;move to the start of the input buffer any of the unused pcm data
       CopyMemory(*pSrcBuf+ash\cbSrcLengthUsed,*pSrcBuf,leftover)
    ; UseFile(#outfile)
       WriteData(#outfile,*pDstBuf,ash\cbDstLengthUsed)
    Wend
    ;now flush out any data from the queue
    PrintN("")
    PrintN("flushing decoder")
    ash\cbDstLengthUsed=1
    ash\cbSrcLength=0
    ;keep looping through the streamconverts until the input and output buffers are flushed
    ;UseFile(#outfile)
    While ash\cbDstLengthUsed>0
       ;The acmStreamConvert function converts data in a source buffer into
       ;the destination format, writing the converted data into the destination buffer.
       res=acmStreamConvert_(has,@ash,#ACM_STREAMCONVERTF_BLOCKALIGN|#ACM_STREAMCONVERTF_END)
     If res<>#S_OK
        PrintN("error "+StrU(res,#PB_Long))
      ;do something here about the failure
        Goto quit
     EndIf
     If ash\cbDstLengthUsed>0
      PrintN("compressed "+StrU(ash\cbDstLengthUsed,#PB_Long)+" bytes from "+StrU(ash\cbSrcLengthUsed,#PB_Long))
        WriteData(#outfile,*pDstBuf,ash\cbDstLengthUsed)
     EndIf
    Wend

    ;first make sure the input and output buffer sizes are
    ;the same as when the buffer was prepared
    ash\cbSrcLength=cbSrcBuf
    ash\cbDstLength=cbDstBuf
    ;unprepare the header before closing the stream
    res=acmStreamUnprepareHeader_(has,@ash,0)
    If res<>#S_OK
       PrintN("error "+StrU(res,#PB_Long))
     ;do something here about the failure
       Goto quit
    EndIf

    ;The acmStreamClose function closes a conversion stream.
    res=acmStreamClose_(has,0)
    If res<>#S_OK
       PrintN("error "+StrU(res,#PB_Long))
     ;do something here about the failure
       Goto quit
    EndIf

    quit:
    Input()
    CloseConsole()

    ;these are some of the more common error codes that come back from acm
    ;ACMERR_BUSY The stream header specified in pash is currently in use and cannot be reused.
    ;ACMERR_UNPREPARED The stream header specified in pash is currently not prepared by the acmStreamPrepareHeader function.
    ;MMSYSERR_INVALFLAG At least one flag is invalid.
    ;MMSYSERR_INVALHANDLE The specified handle is invalid.
    ;MMSYSERR_INVALPARAM At least one parameter is invalid.

Créé le 7 septembre 2009 par Rescator
Version hors-ligne

Les sources présentés sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre cette page de présentation de ces sources constitue une œuvre intellectuelle protégée par les droits d'auteurs. Copyright ©2008 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.