Sources PureBasic
Sources PureBasicConsultez toutes les sources
Nombre d'auteurs : 41, nombre de sources : 88, dernière mise à jour : 13 août 2011
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