Sources PureBasicConsultez toutes les sources

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

 
OuvrirSommaireSons, musiques

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
  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2008 Developpez 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.