  | 
					
						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, 10: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, 10: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, 11: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, 12: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, 12: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, 12: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, 13:48, insgesamt 2-mal bearbeitet | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		storky
 
  
  Anmeldungsdatum: 06.01.2013 Beiträge: 68
 
  | 
		
			
				 Verfasst am: 13.01.2014, 13: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, 13:55, insgesamt 2-mal bearbeitet | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		arduno
 
 
  Anmeldungsdatum: 12.05.2011 Beiträge: 252
 
  | 
		
			
				 Verfasst am: 13.01.2014, 13: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, 14: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.
  | 
   
 
     |