FQ über normalen Lautsprecher

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Beitrag von Andreas_S »

Ertapt :oops:

habs nicht ausprobiert
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

ts-soft hat geschrieben:... weil dann würde Speicher für 10000 Sounds reserviert.
es ist so wie bei gadgets und sprites aber es wird nicht speicher für 10000 sounds reserviert,
sondern "nur" speicher für 10000 pointer zu möglichen sound-speichern. ;)

@PBprogger
komplette info:
elemente die man in PB einrichten kann, werden in einer liste von pointern geführt,
falls man sie mit nummern und nicht mit PB_Any einrichtet.
(gilt für fenster, gadgets, sprites, images, sounds, usw.)

diese liste braucht auch platz. wenn man also ein einziges element mit Nr. 9999 einrichtet,
wird eine liste für 10.000 elemente erstellt, auch wenn die anderen 9999 elemente nicht benutzt werden.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Code: Alles auswählen

 Structure PB_StructureSound
    Sound.l         ; DirectSound pointer
  EndStructure
Hast ja recht, wollte nur nicht nachsehen :wink:
Aber 39 KB sind doch auch was, in der grösse erstellen die freaks komplette
Spiele :mrgreen:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Beitrag von Andreas_S »

Ist der Code jetzt eigendlich nützlich? Ehrlich antworten!
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

PBprogger hat geschrieben:Ist der Code jetzt eigendlich nützlich? Ehrlich antworten!
Ich finds schon ganz geil aber bis jetzt hab ich noch keinen richtigen Nutzen davon (außer dem Lerneffekt). Was neben Sinus noch fehlt sind andere Grundformen wie Square, Triangle, Sawtooth und Noise. In Addition dazu noch eine Art einfaches Playback System für eigene "Songs". Somit wäre es ideal als "Engine" für Demos oder kleinere Spiele.

Ach ja, wie integriert man eigentlich einen Tunning Table? Ich meine wie wird definiert was eine ganze Note ist? Mit dem Code gibt man ja die Tonhöhe nicht mit der Samplerate sondern mit der Frequenz an. Also wäre doch eine Note jeweils +100 oder?

Ganz vergessen, habs noch mal überarbeitet:

Code: Alles auswählen

Structure WAVEFORMATEX
    wFormatTag.w
    nChannels.w
    nSamplesPerSec.l
    nAvgBytesPerSec.l
    nBlockAlign.w
    wBitsPerSample.w
EndStructure

Procedure CreateSound(SoundID,Frequency,Millisecs,Samplerate=44100,Bitrate=16,Channels=1)
	Protected avBytesPerSec = Channels * Bitrate/8 * Samplerate
	Protected Seconds.d = Millisecs/1000
	Protected wfmt.WAVEFORMATEX
	
	*sndData = AllocateMemory(avBytesPerSec * Seconds + 44)
	
	PokeL(*sndData + 00,$46464952)						; RIFF Header
	PokeL(*sndData + 04,avBytesPerSec * Seconds + 44)	; Remaining File Length
	PokeL(*sndData + 08,$45564157)						; WAVE Header	
	PokeL(*sndData + 12,$20746D66)						; FMT Header
	PokeL(*sndData + 16,SizeOf(WAVEFORMATEX))			; FMT Chunk Length
	
	wfmt\wFormatTag = #WAVE_FORMAT_PCM
	wfmt\nChannels = Channels
	wfmt\nSamplesPerSec = Samplerate
	wfmt\nAvgBytesPerSec = avBytesPerSec
	wfmt\nBlockAlign = avBytesPerSec / Samplerate
	wfmt\wBitsPerSample = Bitrate
	CopyMemory(wfmt,*sndData + 20,SizeOf(WAVEFORMATEX))
	
	PokeL(*sndData + 36,$61746164)						; DATA Header
	PokeL(*sndData + 40,avBytesPerSec * Seconds)		; DATA Chunk Length
	
	For ActTime=1 To Samplerate * Seconds
		For ActChannel=1 To Channels
			ActSampleVal = $7FFF * Sin(2 * #PI * Frequency * ActTime/Samplerate)			
			PokeW(*sndData + 44 + IncVal,ActSampleVal) : IncVal + 2						
		Next
	Next
	
	CatchSound(SoundID,*sndData) : FreeMemory(*sndData)
EndProcedure

InitSound()

CreateSound(0,1000,1000)
PlaySound(0)
Delay(1000)
Windows 10 Pro, 64-Bit / Outtakes | Derek
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

Hallo,

Das ganze gab es schonmal. http://www.purebasic.fr/german/viewtopi ... 9661#19661
Fluid Byte hat geschrieben:Somit wäre es ideal als "Engine" für Demos oder kleinere Spiele.
QBPlay lib. Wird anscheinend noch auf PB4 portiert.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Beitrag von Andreas_S »

@Fluid Byte

Erstmal Danke und ich hab da noch ein bischen was dazu gemacht. Ist so eine Art kleine Wave erstellung. Hat sicher ein paar Fehler aber hier die Proceduren:

Code: Alles auswählen

Global numWave
Global NewList numFQ()
Global NewList numMS()

Procedure CreateWave()
 *Mem=AllocateMemory(16)
 ProcedureReturn *Mem
EndProcedure

Procedure SetSamplerate(Wave,samplerate)
 *Mem=Wave
 PokeL(*Mem,samplerate)
EndProcedure

Procedure SetBitrate(Wave,bitrate)
 *Mem=Wave
 PokeW(*Mem+4,bitrate)
EndProcedure

Procedure SetChannels(Wave,channels)
 *Mem=Wave
 PokeW(*Mem+6,channels)
EndProcedure

Procedure SetMs(Wave,ms.q)
 *Mem=Wave
 PokeQ(*Mem+8,ms)
EndProcedure

Procedure AddFQ(Wave,fq,ms)
 *Mem=Wave
 AllMS=PeekL(*Mem+12)
 AddElement(numFQ())
 numFQ()=fq
 AddElement(numMS())
 numMS()=ms
 AllMS+ms
 PokeL(*Mem+12,AllMS)
EndProcedure

Procedure Pause(Wave,ms)
 *Mem=Wave
 AllMS=PeekL(*Mem+12)
 AddElement(numFQ())
 numFQ()=0
 AddElement(numMS())
 numMS()=ms
 AllMS+ms
 PokeL(*Mem+12,AllMS)
EndProcedure

Procedure SaveWave(Wave,FileName$)
 *Mem=Wave
 samplerate.l=PeekL(*Mem)
 bitrate.w=PeekW(*Mem+4)
 channels.w=PeekW(*Mem+6)
 secs.d=PeekQ(*Mem+8)/1000

 avBytesPerSec=channels*bitrate/8*samplerate

 file=CreateFile(#PB_Any,FileName$)
  WriteByte(file,Asc("R"))
  WriteByte(file,Asc("I"))
  WriteByte(file,Asc("F"))
  WriteByte(file,Asc("F"))

  WriteLong(file,avBytesPerSec*secs+44)

  WriteByte(file,Asc("W"))
  WriteByte(file,Asc("A"))
  WriteByte(file,Asc("V"))
  WriteByte(file,Asc("E"))

  WriteByte(file,Asc("f"))
  WriteByte(file,Asc("m"))
  WriteByte(file,Asc("t"))
  WriteByte(file,Asc(" "))

  WriteLong(file,16)

  WriteWord(file,1)
  WriteWord(file,channels)
  WriteLong(file,samplerate)
  WriteLong(file,channels*bitrate/8*samplerate)
  WriteWord(file,bitrate/8*channels)
  WriteWord(file,bitrate)

  WriteByte(file,Asc("d"))
  WriteByte(file,Asc("a"))
  WriteByte(file,Asc("t"))
  WriteByte(file,Asc("a"))

  WriteLong(file,avBytesPerSec*secs)

  actsamplevalue.w

  FirstElement(numMS())
   ForEach numFQ()
    fq=numFQ()
    ms=numMS()
    NextElement(numMS())
     If CountList(numFQ())=a
      Break
     EndIf
    a+1 

    For acttime=1 To samplerate*ms/1000
     For actchannel=1 To channels
      actsamplevalue=32767*Sin(2*#PI*fq*acttime/samplerate)
      WriteWord(file,actsamplevalue)
     Next
    Next
   Next
EndProcedure

Procedure WaveToBuffer(Wave)
 *Mem=Wave
 samplerate.l=PeekL(*Mem)
 bitrate.w=PeekW(*Mem+4)
 channels.w=PeekW(*Mem+6)
 secs.d=PeekQ(*Mem+8)/1000
  If PeekQ(*Mem+8)>PeekL(*Mem+12)
   ms=PeekQ(*Mem+8)-PeekL(*Mem+12)
   Pause(Wave,ms)
  EndIf
  If secs<PeekL(*Mem+12)/1000
   secs=PeekL(*Mem+12)/1000
  EndIf

 avBytesPerSec=channels*bitrate/8*samplerate

 *Mem1=AllocateMemory(avBytesPerSec*secs+44)

  PokeB(*Mem1+0,Asc("R"))
  PokeB(*Mem1+1,Asc("I"))
  PokeB(*Mem1+2,Asc("F"))
  PokeB(*Mem1+3,Asc("F"))

  PokeL(*Mem1+4,avBytesPerSec*secs+44)

  PokeB(*Mem1+8,Asc("W"))
  PokeB(*Mem1+9,Asc("A"))
  PokeB(*Mem1+10,Asc("V"))
  PokeB(*Mem1+11,Asc("E"))

  PokeB(*Mem1+12,Asc("f"))
  PokeB(*Mem1+13,Asc("m"))
  PokeB(*Mem1+14,Asc("t"))
  PokeB(*Mem1+15,Asc(" "))

  PokeL(*Mem1+16,16)

  PokeW(*Mem1+20,1)
  PokeW(*Mem1+22,channels)
  PokeL(*Mem1+24,samplerate)
  PokeL(*Mem1+28,channels*bitrate/8*samplerate)
  PokeW(*Mem1+32,bitrate/8*channels)
  PokeW(*Mem1+34,bitrate)

  PokeB(*Mem1+36,Asc("d"))
  PokeB(*Mem1+37,Asc("a"))
  PokeB(*Mem1+38,Asc("t"))
  PokeB(*Mem1+39,Asc("a"))

  PokeL(*Mem1+40,avBytesPerSec*secs)

 actsamplevalue.w

 FirstElement(numMS())
  ForEach numFQ()
   fq=numFQ()
   ms=numMS()
   NextElement(numMS())
    If CountList(numFQ())=a
     Break
    EndIf
   a+1 

   For acttime=1 To samplerate*ms/1000
    For actchannel=1 To channels
     actsamplevalue=32767*Sin(2*#PI*fq*acttime/samplerate)
     PokeW(*Mem1+44+k,actsamplevalue)
     k+2
    Next
   Next
  Next
 ProcedureReturn *Mem1
EndProcedure

Procedure InitDirectPlay()
 Global Int_=1
 result=InitSound()
 ProcedureReturn result
EndProcedure

Procedure CatchWaveBuffer(FreeSound,*WaveBuffer)
 k=CatchSound(FreeSound,*WaveBuffer)
  If k<>0
   result=1
  Else
   result=-1
  EndIf
 ProcedureReturn result
EndProcedure

Procedure PlayWave(FreeSound,Mode)
 PlaySound(FreeSound,Mode)
EndProcedure

Procedure StopWave(FreeSound,Channel=0)
 StopSound(FreeSound,Channel)
EndProcedure

Procedure BalanceWave(FreeSound,Balance,Channel=0)
 SoundPan(FreeSound,Balance,Channel)
EndProcedure

Procedure VolumeWave(FreeSound,Volume,Channel=0)
 SoundVolume(FreeSound,Volume,Channel)
EndProcedure

Procedure LoadWave(FreeSound,FileName$)
 LoadSound(FreeSound,FileName$)
EndProcedure

Procedure FreeWave(FreeSound)
 FreeSound(FreeSound)
EndProcedure

Procedure FrequencyWave(FreeSound,Frequency,Channel=0)
 SoundFrequency(FreeSound,Frequency,Channel)
EndProcedure
Kann dann zB. so verwendet werden:

Code: Alles auswählen

InitDirectPlay()

Wave=CreateWave()

SetSamplerate(Wave,44100)
SetBitrate(Wave,16)
SetChannels(Wave,2)
SetMs(Wave,2000)

AddFQ(Wave,1000,1000)
AddFQ(Wave,2000,1000)
Dann kann man es in einen Buffer speichern und abspielen oder in einen Wave seichern.

Buffer & Play:

Code: Alles auswählen

*Buffer=WaveToBuffer(Wave)

CatchWaveBuffer(0,*Buffer)
PlayWave(0)

Delay(2000)
To File:

Code: Alles auswählen

SaveWave(Wave,...)
Bitte Verzeichnis statt den Punkten eingeben und .wav nicht vergessen!

Was anderes als mit Sinus hab ich noch nicht gesehen oder probiert(hab auch keine Ahnung wie das funktioniert)[/code]

@DarkDragon

Progge ich eigendlich immer das gleiche wie andere???
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

QBPlay lib. Wird anscheinend noch auf PB4 portiert.
Froggerprogger ist für mich der Sound Gott! Bild

Es gibt "sogar" Effekte wie Arpeggio. Da lässt sich sicher noch einiges rausholen aus der Engine.

Danke für die Info! Bild

[EDIT]

@PBprogger
Ich glaub ich bin zu behämmert, es funzt irgendwie nicht.

Als Erstes habe Ich alle nötigen Prozeduren rüberkopiert und dann

Code: Alles auswählen

InitDirectPlay()

Wave=CreateWave()

SetSamplerate(Wave,44100)
SetBitrate(Wave,16)
SetChannels(Wave,2)
SetMs(Wave,2000)

AddFQ(Wave,1000,1000)
AddFQ(Wave,2000,1000)
eingefügt und danach

Code: Alles auswählen

*Buffer=WaveToBuffer(Wave)

CatchWaveBuffer(0,*Buffer)
PlayWave(0,0)

Delay(2000)
Bei PlayWave meckert PB und sagt das ein Parameter fehlt (Playmode). Hab Ich dann nachgetragen aber wenn man es dann kompliert bekomme Ich bei Zeile 132

Code: Alles auswählen

*Mem1=AllocateMemory(avBytesPerSec*secs+44)
einen Fehler das PB keinen Speicherblock von NULL anlegen kann.
[/EDIT]
Zuletzt geändert von Fluid Byte am 20.04.2007 20:31, insgesamt 1-mal geändert.
Windows 10 Pro, 64-Bit / Outtakes | Derek
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

@DarkDragon

Progge ich eigendlich immer das gleiche wie andere???
:lol: k.A. wollt dich nur drauf Hinweisen, nicht dass du denkst du wärst der komplett erste (Ist mit PB noch gut möglich der erste zu sein).
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Antworten