Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Wav aus dem Speicher abspielen.

 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
arduno



Anmeldungsdatum: 12.05.2011
Beiträge: 252

BeitragVerfasst am: 13.01.2014, 11:07    Titel: Wav aus dem Speicher abspielen. Antworten mit Zitat

Hallo, guten Tag.

Ich möchte unten aus dem Programm die Wav aus dem Speicher abspielen.
Der Befehl spielt aber nichts ab:
PlaySound(@wavdata(0), 0, SND_MEMORY Or SND_NODEFAULT)

Was muss ich da bitte ändern?

Danke.
Gruss
Code:

#Include Once "windows.bi"
#Include Once "savewave.bi"
#Include Once "win/mmsystem.bi"

ScreenRes 400,400
?"ok"

Dim text As String
Dim As Integer i,j,k,nsamples=3*44100
Dim As Short wavdata(3*2*44100)
Dim As uByte Ptr wavdataptr=Cast(uByte Ptr,@wavdata(0))

text="d:\freebasic\pebi-bas\daten\mywav.wav"

For i=0 To nsamples-1
    wavdata(i+i)=16000*sin(i*2*3.1416/44.1)
    wavdata(i+i+1)=16000*Sin(i*2*3.1416/44.1)
Next i

savewave(text,wavdataptr,nsamples*2*2)
?"done"

'PlaySound(text, 1, SND_NODEFAULT)

PlaySound(@wavdata(0), 0, SND_MEMORY Or SND_NODEFAULT)

Sleep
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
storky



Anmeldungsdatum: 06.01.2013
Beiträge: 68

BeitragVerfasst am: 13.01.2014, 11:54    Titel: Antworten mit Zitat

Hey,

soweit ich mich erinnern kann, möchte er im Speicher nicht nur die Samples, sondern auch einen Waveheader. Quasi so eine komplette Wave Datei. Ist ja auch klar, er muss ja wissen wieviele Bits pro Sample und warum.

https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
Ich hatte mir mal dazu einen Type davon gebaut.

Was mir bei dir übrigens völlig fehlt. Wie es scheint möchtest du 16 Bits per Sample benutzen. Das könnte nun entweder durch die Auflösung kommen, dann hättest du 16 Bit Mono oder Stereo wären 8 Bit. Die 44100 Hz müssen auch noch in den Header rein damitdie Geschwindigkeit stimmt. Der Rest im Header ist doppelt gemoppelt und lässt sich aus den 3 Dingen ableiten. Also Bits per Sample, Mono/Stereo und Samplerate.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
arduno



Anmeldungsdatum: 12.05.2011
Beiträge: 252

BeitragVerfasst am: 13.01.2014, 12:14    Titel: Antworten mit Zitat

Jup, danke.

Warum wird hier aber die vorher abgespeicherte Wav abgespielt?
PlaySound(text, 1, SND_NODEFAULT)
Ist das kein wav-Fileformat was da abgespeichert wurde?

Danke.
Gruss
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
storky



Anmeldungsdatum: 06.01.2013
Beiträge: 68

BeitragVerfasst am: 13.01.2014, 13:14    Titel: Antworten mit Zitat

Doch die Datei anscheinend schon. Musst du mal in der savewave.bi nachsehen was die macht. Das im Speicher ist keine Wave, sondern nur die Daten lächeln
Vielleicht kannst du die savewave.bi so umbauen, dass du der savewave Funktion einen Parameter übergeben kannst, der bewirkt, dass er den Pointer returnt.

Ich suche mal eben auch mein Projekt raus.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
arduno



Anmeldungsdatum: 12.05.2011
Beiträge: 252

BeitragVerfasst am: 13.01.2014, 13:36    Titel: Antworten mit Zitat

Danke.
Hier ist die savewave aus der bi, wie kann ich die bitte umlenken in den Speicher?
Code:

Sub savewave(ficwave As String,wavdata As UByte Ptr,wavdatasize As Integer, _
         wbits As Integer=16,wsamplerate As Integer=44100,wchannels As Integer=2)

Dim  As integer   hOut,wnsamples
Dim  As _PCM_FILE_HDR wavehdr

  hOut=Freefile()
  Open ficwave for binary access write as #hOut

  wavehdr.ChunkDataSize=0
  wavehdr.ChunkRIFF     = _RIFF
  wavehdr.ChunkRIFFSize = sizeof(_PCM_FILE_HDR)-8
  wavehdr.ChunkID       = _WAVE
  wavehdr.Chunkfmt      = _fmt
  wavehdr.ChunkfmtSize  = 16
  wavehdr.wFormatTag    = 1
  wavehdr.nChannels     = wChannels
  wavehdr.nRate         = wsamplerate
  wavehdr.nBytesPerSec  = (wBits\8)*wsamplerate*wChannels
  wavehdr.Framesize     = (wBits\8)*wChannels
  wavehdr.nBits         = wBits
  wavehdr.Chunkdata     = _data
  put #hOut,,wavehdr

  wnsamples=wavdatasize\wavehdr.Framesize
  wavehdr.ChunkRIFFSize+=wnsamples*wavehdr.Framesize
  wavehdr.ChunkdataSize+=wnsamples*wavehdr.Framesize
  put #hOut,,wavdata[0],wnsamples*wavehdr.Framesize


  seek hOut,1
  put #hOut,,wavehdr

  Close #hOut
End Sub

Gruss
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
storky



Anmeldungsdatum: 06.01.2013
Beiträge: 68

BeitragVerfasst am: 13.01.2014, 13:54    Titel: Antworten mit Zitat

Hier mal mein Projekt. Der Hauptteil zum kontrollieren ist eigentlich nur:
Code:
Dim As UShort wdata(5000)
For i As UInteger = 0 To 5000
   wdata(i) = CInt(Rnd()* 165535)
Next

Dim As String w = genWave(1, 44100, 16, 5000, @wdata(0))

playWave(w)


Daten generieren, genWave aufrufen (Parameter müssen stimmen, sonst kommt er in nicht allocierten Speicher) und dann mit playWave kannst du abspielen. Die savewave.bi sehe ich mir mal eben an.


Code:
#Include Once "windows.bi"
#Include Once "win/mmsystem.bi"


Type header
   As   UInteger    ChunkID
   As UInteger    ChunkSize       
   As UInteger    wFormat
   As UInteger    Subchunk1ID
   As UInteger    Subchunk1Size
   As UShort       AudioFormat
   As UShort       NumChannels
   As UInteger    SampleRate
   As UInteger    ByteRate
   As UShort       BlockAlign
   As UShort       BitsPerSample
   As UInteger    Subchunk2ID
   As UInteger    Subchunk2Size
   Declare Constructor(NumChannels As UShort, SampleRate As UInteger, BitsPerSample As UShort, NumSamples As UInteger)
End Type

Type lFbString
   As Any Ptr    sDat
   As UInteger sLen
   As UInteger sMem
End Type

Declare Function genWave(NumChannels As UShort, SampleRate As UInteger, BitsPerSample As UShort, NumSamples As UInteger, wdata As Any Ptr) As String
Declare Sub playWave(wave As String)
Declare Sub saveWave(file As String, wave As String)

Constructor header(NumChannels As UShort, SampleRate As UInteger, BitsPerSample As UShort, NumSamples As UInteger)
   With This
      .ChunkID       = &h46464952         'RIFF
      .ChunkSize      = 0
      .wFormat       = &h45564157         'Wave
      .Subchunk1ID    = &h20746D66         'fmt
      .Subchunk1Size = 16                  'PCM
      .AudioFormat   = 1                  'PCM
      .NumChannels   = NumChannels
      .SampleRate      = SampleRate
      .ByteRate      = SampleRate * NumChannels * (BitsPerSample /8)
      .BlockAlign      = NumChannels * (BitsPerSample /8)
      .BitsPerSample   = BitsPerSample
      .Subchunk2ID   = &h61746164         'data
      .Subchunk2Size   = NumSamples * NumChannels * (BitsPerSample /8)
   End With
End Constructor


Function genWave(NumChannels As UShort, SampleRate As UInteger, BitsPerSample As UShort, NumSamples As UInteger, wdata As Any ptr) As String
   
   Dim As String Ptr cWave, cWaveData
   Dim As UInteger waveSize = NumChannels * (BitsPerSample / 8) * NumSamples
   
   Dim As lFbString wave, WaveData
   Dim As lFbString Ptr wavePtr, WaveDataPtr
   
   Dim WaveHeadType As header = header(NumChannels, SampleRate, BitsPerSample, NumSamples)

   WaveHeadType.ChunkSize = waveSize + SizeOf(header) - 8

   wavePtr = @wave
   wavePtr->sDat = @WaveHeadType
   wavePtr->sLen = SizeOf(header)
   wavePtr->sMem = SizeOf(header)
   cWave = wavePtr
   
   WaveDataPtr = @WaveData
   WaveDataPtr->sDat = wdata
   WaveDataPtr->sLen = waveSize
   WaveDataPtr->sMem = waveSize
   cWaveData = WaveDataPtr
   
   Return *cWave & *cWaveData
   
End Function

Sub playWave(wave As String)
   PlaySound(*(Cast(UInteger Ptr, @wave)), 0, SND_MEMORY Or SND_NODEFAULT)
End Sub

Sub saveWave(file As String, wave As String)
   Open file For Binary Access write As #1
   Put #1, 1, wave
   Close #1
End Sub


Dim As UShort wdata(5000)
For i As UInteger = 0 To 4999
   wdata(i) = CInt(Rnd()* 165535)
Next

Dim As String w = genWave(1, 44100, 16, 5000, @wdata(0))

Print "press key to play..."
Sleep
playWave(w)

Print "press key to save as 'test.wav'..."
Sleep
saveWave("test.wav", w)

Print "Ready."

Sleep
end


Zuletzt bearbeitet von storky am 13.01.2014, 14:48, insgesamt 2-mal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
storky



Anmeldungsdatum: 06.01.2013
Beiträge: 68

BeitragVerfasst am: 13.01.2014, 14:07    Titel: Antworten mit Zitat

Achso und ich weiß auch nicht wie du auf wavedata(i+i) oder (i+i+i) kommst, so groß ist der Array nicht.

Code:
Dim As UShort wdata(15000)
For i As UInteger = 0 To 14999
   wdata(i)=16000*sin(i*2*3.1416/44.1)
Next

Dim As String w = genWave(1, 44100, 16, 15000, @wdata(0))
playWave(w)


So kannst du die Sinusfunktion abspielen falls du meinen Code benutzen magst. Länge des Sounds ist Samplesize/Samplerate. In dem Fall 16Bit mono sind bei 30000 Bytes (15000 Shorts) genau 15000 Samples. Geteielt durch Rate 44100 kommt man auf 0,34 Sekunden Spielzeit.


Edit:

zu der savewave Funktion. Du musst wavehdr gefolgt von wavdata[0] hintereinander im Speicher haben und von diesem den Pointer returnen.

Quasi so... ganz am Ende der Sub (Funktion draus machen).

Code:
#inlcude "crt/string.bi" 'für memcpy
dim as any ptr wavePtr = allocate(sizeof(_PCM_FILE_HDR) + wavdatasize)
memcpy wavePtr, @wavehdr,  sizeof(_PCM_FILE_HDR)
memcpy wavePtr + sizeof(sizeof(_PCM_FILE_HDR)), wavdata, wavdatasize

return wavePtr


Den wavePtr solltest du dann direkt abspielen können. Ist aber alles ungetestet, da die savewave.bi anscheinend nicht komplett war. Also Achtung, ich mache immer Faselfehler zwinkern

Edit: Ich habe in meinem Code einen Fehler behoben. Im Fall du nutzt den, dann

Code:
      .ByteRate      = SampleRate * NumChannels * (BitsPerSample /8)
      .BlockAlign      = NumChannels * (BitsPerSample /8)
      .BitsPerSample   = BitsPerSample
      .Subchunk2ID   = &h61746164         'data
      .Subchunk2Size   = NumSamples * NumChannels * (BitsPerSample /8)


So abändern, die Klammern sind wichtig mit den Augen rollen soll eigentlich die Bits in Bytes umrechnen und nicht alles 8 mal kleiner machen.


Zuletzt bearbeitet von storky am 13.01.2014, 14:55, insgesamt 2-mal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
arduno



Anmeldungsdatum: 12.05.2011
Beiträge: 252

BeitragVerfasst am: 13.01.2014, 14:51    Titel: Antworten mit Zitat

Jup, danke.
Funktioniert wunderbar.

Ich wusste nicht, das es soviel Code ist.

Danke.
Gruss
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
storky



Anmeldungsdatum: 06.01.2013
Beiträge: 68

BeitragVerfasst am: 13.01.2014, 15:03    Titel: Antworten mit Zitat

Geht eigentlich auch kleiner. Wenn das Format feststeht, könnte man z.B einen Header in allocierten Speicher schreiben, dahinter einen Typepointer setzen, Daten reinschreiben (Drauf achten, dass der Speicher groß genug ist) und im Header alles was mit der Länge zu tun hat umcasten. Also Chunksize, bla...

Aber usability zwinkern

Mag nochmal anmerken, hab in meinem Code was geändert... nicht, dass du den nimmst und es übersehen hast lächeln
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.

 Impressum :: Datenschutz