MP3 grafisch darstellen

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Stuhli
Beiträge: 75
Registriert: 18.10.2004 10:05

MP3 grafisch darstellen

Beitrag von Stuhli »

Ich hätte mal ein Problem. Wie kann ich ein MP3 grafisch darstellen wie es auch zB der MP3-Cutter macht ? Geht sowas (einfach) ?
SYNTAX ERROR IN 30! TYPE MISMATCH
Benutzeravatar
captain_hesse
Beiträge: 138
Registriert: 17.05.2009 18:55
Computerausstattung: Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Wohnort: Saarland

Re: MP3 grafisch darstellen

Beitrag von captain_hesse »

Hallo
Ich hatte damit auch schon mal herum experimentiert und habs dann später so gemacht daß ich die MP3
mittels acmStreamConvert_() in eine Wave Datei umgewandelt habe, diese Daten brauchst du dann nur noch auslesen und sie dann mit dem 2DDrawing Befehl LineXY() auf den Bildschirm zu zeichnen.

Gruß
Armin
Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Benutzeravatar
dige
Beiträge: 1235
Registriert: 08.09.2004 08:53

Re: MP3 grafisch darstellen

Beitrag von dige »

Würde mich auch mal interessieren wie das geht. @captain_hesse: magst du ein lauffähiges Beispiel posten?
"Papa, ich laufe schneller - dann ist es nicht so weit."
Benutzeravatar
captain_hesse
Beiträge: 138
Registriert: 17.05.2009 18:55
Computerausstattung: Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Wohnort: Saarland

Re: MP3 grafisch darstellen

Beitrag von captain_hesse »

Ein lauffähiges Beispiel hatte ich gerade nicht griffbereit und habe daher auf die schnelle was programmiert also bitte erschlagt mich nicht wenn es nicht ganz perfekt ist, soll ja auch nur ein Wegweiser sein.
Das folgende Beispiel zeigt wie man eine *.wav Datei grafisch auf dem Bildschirm darstellt aber bitte beachten es geht nur mit Wave Dateien.

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)
Wie man eine MP3 in eine Wave Datei umwandelt muß ich erst nochmal nachschauen und dann auch ins Reine schreiben. Bitte lasst mir etwas Zeit, ich werde es in den nächsten Tagen hier posten.

Gruß Armin
Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Benutzeravatar
captain_hesse
Beiträge: 138
Registriert: 17.05.2009 18:55
Computerausstattung: Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Wohnort: Saarland

Re: MP3 grafisch darstellen

Beitrag von captain_hesse »

So ich habe in meinem Archiv da noch einen Code gefunden mit dem ich früher mal experimentiert habe. Allerdings habe ich das nicht selbst geschrieben sondern irgendwo im Forum gefunden und es dann an meine Bedürfnisse angepasst aber es funktioniert. Das einzige was man nach dem Konvertieren noch tun muss ist der Wave Datei einen Header zu verpassen das macht diese Programm nämlich nicht. Also viel Spaß damit :D

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()
Windows 7 Ultimate 64 Bit / AMD Phenom II 1090T, 6x3200 MHz / AMD HD-6850 / PureBasic 5.1 (x86) (x64)
Antworten