MP3 grafisch darstellen
Verfasst: 23.05.2014 15:11
Ich hätte mal ein Problem. Wie kann ich ein MP3 grafisch darstellen wie es auch zB der MP3-Cutter macht ? Geht sowas (einfach) ?
Code: Alles auswählen
InitSprite()
window=OpenWindow(#PB_Any,0,0,1024,600,"stream", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
wav_datei$ = OpenFileRequester(".wav Datei laden", "", "wav (*.wav) |*.wav|Alle Dateien (*.*) |*.*", 0)
If ReadFile( 0,wav_datei$ )
;wave header einlesen
riff$=""
For i=1 To 4
riff$+Chr(ReadCharacter(0))
Next
gr=ReadLong(0)
wave$=""
For i=1 To 4
wave$+Chr(ReadCharacter(0))
Next
fmt$=""
For i=1 To 4
fmt$+Chr(ReadCharacter(0))
Next
fmt_length=ReadLong(0)
format_tag=ReadWord(0)
channels=ReadWord(0)
sample_rate=ReadLong(0)
bytes_per_second=ReadLong(0)
block_align=ReadWord(0)
bits_per_sample=ReadWord(0)
dat$=""
For i=1 To 4
dat$+Chr(ReadCharacter(0))
Next
data_length=ReadLong(0)
;Audio daten einlesen
*buffer=AllocateMemory(data_length)
ReadData(0, *buffer, data_length)
Debug riff$
Debug "dateigröße = "+Str(gr)
Debug wave$
Debug fmt$
Debug Str(fmt_length)
Debug "format_tag ="+Str(format_tag)
Debug "channels ="+Str(channels)
Debug "sample_rate ="+Str(sample_rate)
Debug "bytes_per_second ="+Str(bytes_per_second)
Debug "block_align ="+Str(block_align)
Debug "bits_per_sample ="+Str(bits_per_sample)
Debug dat$
Debug "data_length ="+Str(data_length)
CloseFile(0)
EndIf
faktor_x=data_length/1024
faktor_y.d=200/32767
If faktor_x % 2 <> 0 ;faktor_x muß durch 2 teilbar sein
faktor_x+1
EndIf
OpenWindowedScreen(WindowID(window),0,0,1024,500,0,0,0, #PB_Screen_WaitSynchronization)
Repeat
event=WindowEvent()
ClearScreen(0)
StartDrawing(ScreenOutput())
x=0
x1=0
While x<data_length
y=PeekW(*buffer+x)
y*faktor_y
LineXY( x1,250,x1,250+y,RGB($ff,$ff,$ff) )
x+faktor_x
x1+1
Wend
LineXY( 0,250,1024,250,RGB($ff,$00,$00) )
StopDrawing()
FlipBuffers()
Until event=#PB_Event_CloseWindow
CloseScreen()
CloseWindow(window)
Code: Alles auswählen
#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
#ACM_STREAMOPENF_NONREALTIME = $00000004
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
cbSrcBuf.l = 50000000
cbDstBuf.l
;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
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
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 = 128 / 8*1024
MP3wfxDst\wfx\cbSize = #MPEGLAYER3_WFX_EXTRA_BYTES
MP3wfxDst\wfx\nBlockAlign = 1
MP3wfxDst\fdwFlags = 2
MP3wfxDst\nBlockSize = 522
MP3wfxDst\nFramesPerBlock = 1
MP3wfxDst\nCodecDelay = 1393
;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, @MP3wfxDst,@wfxSrc, #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
*pSrcBuf = AllocateMemory(cbSrcBuf)
*pDstBuf = AllocateMemory(cbDstBuf)
;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
Debug "ende"
Goto quit
EndIf
;open up the input file
res = ReadFile(#infile, "source.mp3")
If res = 0
PrintN("cannot open input file")
;do something here about the failure
Goto quit
EndIf
;open up the output file
res = CreateFile(#outfile, "dest.wav")
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
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
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)
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
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()