 |
Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
arduno
Anmeldungsdatum: 12.05.2011 Beiträge: 252
|
Verfasst am: 13.01.2014, 11:07 Titel: Wav aus dem Speicher abspielen. |
|
|
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 |
|
 |
storky

Anmeldungsdatum: 06.01.2013 Beiträge: 68
|
Verfasst am: 13.01.2014, 11:54 Titel: |
|
|
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 |
|
 |
arduno
Anmeldungsdatum: 12.05.2011 Beiträge: 252
|
Verfasst am: 13.01.2014, 12:14 Titel: |
|
|
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 |
|
 |
storky

Anmeldungsdatum: 06.01.2013 Beiträge: 68
|
Verfasst am: 13.01.2014, 13:14 Titel: |
|
|
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
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 |
|
 |
arduno
Anmeldungsdatum: 12.05.2011 Beiträge: 252
|
Verfasst am: 13.01.2014, 13:36 Titel: |
|
|
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 |
|
 |
storky

Anmeldungsdatum: 06.01.2013 Beiträge: 68
|
Verfasst am: 13.01.2014, 13:54 Titel: |
|
|
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 |
|
 |
storky

Anmeldungsdatum: 06.01.2013 Beiträge: 68
|
Verfasst am: 13.01.2014, 14:07 Titel: |
|
|
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
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 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 |
|
 |
arduno
Anmeldungsdatum: 12.05.2011 Beiträge: 252
|
Verfasst am: 13.01.2014, 14:51 Titel: |
|
|
Jup, danke.
Funktioniert wunderbar.
Ich wusste nicht, das es soviel Code ist.
Danke.
Gruss |
|
Nach oben |
|
 |
storky

Anmeldungsdatum: 06.01.2013 Beiträge: 68
|
Verfasst am: 13.01.2014, 15:03 Titel: |
|
|
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
Mag nochmal anmerken, hab in meinem Code was geändert... nicht, dass du den nimmst und es übersehen hast  |
|
Nach oben |
|
 |
|
|
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.
|
|