2 Samples gleichzeitig via PlaySound() ausgeben
2 Samples gleichzeitig via PlaySound() ausgeben
Hallo,
gibt es irgendeine Möglichkeit 2 Samples (wav) gleichzeitig mittels PlaySound() auszugeben?
Wenn es so aufgerufen wird, dann entsteht da immer eine leichte Verzögerung:
PlaySound(0)
PlaySound(1)
Danke für alle Tipps!
Delle
gibt es irgendeine Möglichkeit 2 Samples (wav) gleichzeitig mittels PlaySound() auszugeben?
Wenn es so aufgerufen wird, dann entsteht da immer eine leichte Verzögerung:
PlaySound(0)
PlaySound(1)
Danke für alle Tipps!
Delle
PB 6.21 | Win 11
Re: 2 Samples gleichzeitig via PlaySound() ausgeben
Vllt könnte ein Thread helfen.
Indem du beide PlaySounds in einzelne Threads steckst welche du dann "kurz" nacheinander ausführst.
Deises Kurz sollte kurz genug sein.
Indem du beide PlaySounds in einzelne Threads steckst welche du dann "kurz" nacheinander ausführst.
Deises Kurz sollte kurz genug sein.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Re: 2 Samples gleichzeitig via PlaySound() ausgeben
Hallo,
wenn du wirklich willst, das die beiden Audio Dateien gleichzeitig abgespielt werden, musst du sie zu einer neuen zusammen mixen, dies wäre aber um einiges komplizierter, da dies nicht mit den Standardbefehlen geht. Einfacher wäre es wenn du die Dateien sowieso immer zusammen wiedergeben willst und einfach ein Programm wie Audacity nutzt und eine wav Datei erstellt wo beide hereingemixt sind.
mfg,
Dark
wenn du wirklich willst, das die beiden Audio Dateien gleichzeitig abgespielt werden, musst du sie zu einer neuen zusammen mixen, dies wäre aber um einiges komplizierter, da dies nicht mit den Standardbefehlen geht. Einfacher wäre es wenn du die Dateien sowieso immer zusammen wiedergeben willst und einfach ein Programm wie Audacity nutzt und eine wav Datei erstellt wo beide hereingemixt sind.
mfg,
Dark
Mein Blog: http://fds-team.de/cms/
Re: 2 Samples gleichzeitig via PlaySound() ausgeben
Dark darum geht es ja: Zusammenmixen aber eben ohne viel Aufwand. Audacity fällt da komplett weg.
Ich könnte höchstens die Verzögerung in ms messen und dann einen 2. Thread entsprechend später starten lassen oder sowas...
Je schneller die Kiste, desto synchroner läuft es ja auch ab... allerdings eben nicht 1:1
Ich könnte höchstens die Verzögerung in ms messen und dann einen 2. Thread entsprechend später starten lassen oder sowas...
Je schneller die Kiste, desto synchroner läuft es ja auch ab... allerdings eben nicht 1:1
PB 6.21 | Win 11
Re: 2 Samples gleichzeitig via PlaySound() ausgeben
Hallo,Delle hat geschrieben:Dark darum geht es ja: Zusammenmixen aber eben ohne viel Aufwand. Audacity fällt da komplett weg.
Ich könnte höchstens die Verzögerung in ms messen und dann einen 2. Thread entsprechend später starten lassen oder sowas...
Je schneller die Kiste, desto synchroner läuft es ja auch ab... allerdings eben nicht 1:1
irgendetwas verzögert zu starten, so das es genau gleichzeitig abspielt, ist nachezu unmöglich. Gehen wir davon aus du hast WAV daten mit 48kHz also 48.000 verschiedene Samples pro Sekunde(!), dann wäre der Abstand zwischen einem Sample und dem anderen ~0,021 Millisekunden. Das heißt du müsstest schon im Microsekunden Bereich arbeiten, damit es nicht schon um ein Sample verzögert ist.
Es gibt zwei verschiedene Möglichkeiten Audio Daten zu mixen:
- Die 100% korrekte Methode ist die Samples per Fast Fourrier Transformationen in ihre Frequenzen zu zerlegen, zusammenzurechnen und den Vorgang rückgängig zu machen.
- Die für diesen Fall wesentlich praktikablere Lösung ist es beide Wave Dateien in den Speicher zu laden und dann folgendes zu machen:
Wave Header der beiden Dateien lesen um Informationen über die WaveDateien zu bekommen. Dann Speicher für eine dritte Wave Datei allocaten und deren Header in den Ram schreiben.
Code: Alles auswählen
For i = 0 to SampleCount - 1
Sample1.i = PeekW(*Wave1+i*2) ;bei 16 bit Wave Oder PeekL(*Wave1+i*4) bei 32 Bit Wave
Sample2.i = PeekW(*Wave2+i*2) ;bei 16 bit Wave Oder PeekL(*Wave1+i*4) bei 32 Bit Wave
PokeW(*Wave3+i*2, (Sample1+Sample2)/2 ) ;Beide Samples addieren und durch zwei Teilen (Bei 32 bit erst beides teilen und dann addieren, da es sonst zu einem Integer Overflow kommt und dann auch wieder PokeL(...)
next
Nur musst du aufpassen, das Wave Dateien riesig sein können und dann wäre es sinvoller, lieber direkt aus den beiden Wave Dateien zu lesen und nur den Sound zu mixen, der auch gleich Wiedergegeben wird, was wiederum nur funktioniert wenn du eine Librarieverwendest bei dem du einen Sound stream verwendest.
Es gibt also keine einfache gute Möglichkeit. Wenn dir das speicher Problem egal ist, geht diese Methode zumindestens.
mfg,
DarkPlayer
Mein Blog: http://fds-team.de/cms/
Re: 2 Samples gleichzeitig via PlaySound() ausgeben
Naja geh mal davon aus, dass es kurze "Samples" sind und alle die gleiche Frequenz/Bitrate haben und mono sind.
Ich hab schon mit den RIFF-Headern rumhantiert und wollte 2 wavs zusammenmischen lassen, allerdings ist das auch wieder nicht so einfach wie es aussieht
Deswegen kam mir die Idee es einfach gleichzeitig abzuspielen und aufzunehmen.
Die Verzögerung ist leider bei mir nicht im "Microbereich", sondern eher im ms-Bereich... man hört also auch deutlich das ein Sample von beiden etwas zeitversetzt ist.
Wenn man jetzt mit 2 präparierten "Testsamples" eine Aufnahme macht und dann mit Audacity die Verzögerung in ms rausmarkiert, dann könnte es klappen...
Also den einen Sample in Thread 1 packen und X ms später abspielen lassen und den anderen in Thread 2 einfach "danach".
Also in etwa so bei gemessenen 250 ms Zeitverzögerung:
Wobei größtenteils das Aufnahmeprogramm auch noch für Verzögerungen sorgt 
Ich hab schon mit den RIFF-Headern rumhantiert und wollte 2 wavs zusammenmischen lassen, allerdings ist das auch wieder nicht so einfach wie es aussieht
Deswegen kam mir die Idee es einfach gleichzeitig abzuspielen und aufzunehmen.
Die Verzögerung ist leider bei mir nicht im "Microbereich", sondern eher im ms-Bereich... man hört also auch deutlich das ein Sample von beiden etwas zeitversetzt ist.
Wenn man jetzt mit 2 präparierten "Testsamples" eine Aufnahme macht und dann mit Audacity die Verzögerung in ms rausmarkiert, dann könnte es klappen...
Also den einen Sample in Thread 1 packen und X ms später abspielen lassen und den anderen in Thread 2 einfach "danach".
Also in etwa so bei gemessenen 250 ms Zeitverzögerung:
Code: Alles auswählen
Procedure Play1(wert)
Delay(wert)
PlaySound(1)
EndProcedure
Procedure Play2(wert)
Delay(wert)
PlaySound(2)
EndProcedure
CreateThread(@Play1,250)
CreateThread(@Play2,0)PB 6.21 | Win 11
Re: 2 Samples gleichzeitig via PlaySound() ausgeben
Hallo,
habe mal schnell nen Code geschrieben um zwei Audio Dateien zu mixen und als Ergebnis ein Sound Handle zu bekommen:
Volume1 und Volume2 zwei müssen hierbei zwischen 0 und 1 liegen (1 = Volle Lautstärke)
Beispiel:
mfg,
DarkPlayer
habe mal schnell nen Code geschrieben um zwei Audio Dateien zu mixen und als Ergebnis ein Sound Handle zu bekommen:
Code: Alles auswählen
Structure WaveFile
chunkID .s{4}
chunkSize.l
riffType.s{4}
FormatHeader.s{4}
FormatLength.l
wFormatTag.w
wChannels.w
dwSamplesPerSec.l
dwAvgBytesPerSec.l
wBlockAlign.w
wBitsPerSample.w
DataHeader.s{4}
DataLen.l
EndStructure
Procedure MixSound(FileName1.s, FileName2.s, Volume1.f, Volume2.f)
Protected Result.i = #False
Protected Size1.i = FileSize(FileName1)
Protected Size2.i = FileSize(FileName2)
If Size1 And Size2
Protected File1.i = OpenFile(#PB_Any, FileName1)
If File1
Protected File2.i = OpenFile(#PB_Any, FileName2)
If File2
*Wave1.WaveFile = AllocateMemory(Size1)
If *Wave1
*Wave2.WaveFile = AllocateMemory(Size2)
If *Wave2
If Size1 > Size2
*Wave3.WaveFile = AllocateMemory(Size1)
Else
*Wave3.WaveFile = AllocateMemory(Size2)
EndIf
If *Wave3
ReadData(File1,*Wave1,Size1)
ReadData(File2,*Wave2,Size2)
If *Wave1\dwSamplesPerSec = *Wave2\dwSamplesPerSec And *Wave1\wChannels = *Wave2\wChannels
If *Wave1\wBitsPerSample <> 8 And *Wave1\dwSamplesPerSec = *Wave2\dwSamplesPerSec
Protected BitPerSample.i = *Wave1\wBitsPerSample
Protected MaxSamples.i = *Wave1\DataLen / (BitPerSample / 8)
If *Wave2\DataLen / (BitPerSample / 8) > MaxSamples
MaxSamples = *Wave2\DataLen / (BitPerSample / 8)
EndIf
Protected i.i
Protected Sample1.i
Protected Sample2.i
If BitPerSample = 16
For i = 0 To MaxSamples - 1
If i < (*Wave1\DataLen / (BitPerSample / 8))
Sample1 = PeekW(*Wave1 + SizeOf(WaveFile) + i * 2) * Volume1
Else
Sample1 = 0
EndIf
If i < (*Wave2\DataLen / (BitPerSample / 8))
Sample2 = PeekW(*Wave2 + SizeOf(WaveFile) + i * 2) * Volume2
Else
Sample2 = 0
EndIf
PokeW(*Wave3 + SizeOf(WaveFile) + i * 2, (Sample1 + Sample2) /2)
Next
ElseIf BitPerSample = 32
For i = 0 To MaxSamples - 1
If i < (*Wave1\DataLen / (BitPerSample / 8))
Sample1 = PeekL(*Wave1 + SizeOf(WaveFile) + i * 4) * Volume1
Else
Sample1 = 0
EndIf
If i < (*Wave2\DataLen / (BitPerSample / 8))
Sample2 = PeekL(*Wave2 + SizeOf(WaveFile) + i * 4) * Volume2
Else
Sample2 = 0
EndIf
PokeL(*Wave3 + SizeOf(WaveFile) + i * 2, Sample1 / 2 + Sample2 / 2)
Next
EndIf
If *Wave1\DataLen > *Wave2\DataLen
CopyMemory(*Wave1, *Wave3, SizeOf(WaveFile))
Else
CopyMemory(*Wave2, *Wave3, SizeOf(WaveFile))
EndIf
Result = CatchSound(#PB_Any, *Wave3)
EndIf
EndIf
FreeMemory(*Wave3)
EndIf
FreeMemory(*Wave2)
EndIf
FreeMemory(*Wave1)
EndIf
CloseFile(File2)
EndIf
CloseFile(File1)
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Beispiel:
Code: Alles auswählen
InitSound()
Sound = MixSound("C:\datei1.wav", "C:\datei2.wav",1,1)
If Sound
PlaySound(Sound,0,100)
endif
DarkPlayer
Mein Blog: http://fds-team.de/cms/
Re: 2 Samples gleichzeitig via PlaySound() ausgeben
Hm... sieht auf den ersten Blick alles soweit logisch aus 
Spielt bei mir aber komischerweise immer nur einen Sound davon ab...
Beispiel:
Hab mal eine .rar-Datei gemacht mit der .pb und den 2 .wavs: http://ul.to/ci0bpi
Die 2 Sounds haben zwar nicht die gleiche Länge (wird ja aber in Deinem Code berücksichtigt), die Daten (Bitrate/KHz/Mono) sind aber gleich.
Manchmal gibt's auch einen "Ungültigen Speicherzugriff" (Lesefehler an Adresse ...)
Spielt bei mir aber komischerweise immer nur einen Sound davon ab...
Beispiel:
Code: Alles auswählen
InitSound()
Sound = MixSound("1.wav", "2.wav",1,1)
If Sound
PlaySound(Sound,0,100)
Delay(5000)
EndIfDie 2 Sounds haben zwar nicht die gleiche Länge (wird ja aber in Deinem Code berücksichtigt), die Daten (Bitrate/KHz/Mono) sind aber gleich.
Manchmal gibt's auch einen "Ungültigen Speicherzugriff" (Lesefehler an Adresse ...)
PB 6.21 | Win 11
Re: 2 Samples gleichzeitig via PlaySound() ausgeben
Hi,Delle hat geschrieben:Hm... sieht auf den ersten Blick alles soweit logisch aus
Spielt bei mir aber komischerweise immer nur einen Sound davon ab...
Beispiel:
Hab mal eine .rar-Datei gemacht mit der .pb und den 2 .wavs: http://ul.to/ci0bpiCode: Alles auswählen
InitSound() Sound = MixSound("1.wav", "2.wav",1,1) If Sound PlaySound(Sound,0,100) Delay(5000) EndIf
Die 2 Sounds haben zwar nicht die gleiche Länge (wird ja aber in Deinem Code berücksichtigt), die Daten (Bitrate/KHz/Mono) sind aber gleich.
Manchmal gibt's auch einen "Ungültigen Speicherzugriff" (Lesefehler an Adresse ...)
Das liegt daran, dass deine eine 1.wav scheinbar noch einen zusätzlichen Header beinhaltet, den ich hier nicht berücksichtige. Du müsstest wenn du wirklich alle Wave Dateien haben willst, ne bessere Routine schreiben um den Header einzulesen. Nach dem ich die datei erneut mit Audacity abgespeichert habe, war der extra header weg und der code hat funktioniert.
mfg,
DarkPlayer
Mein Blog: http://fds-team.de/cms/
Re: 2 Samples gleichzeitig via PlaySound() ausgeben
Gute Idee! Ich lass das "Headerentfernen" einfach per Batch in Audacity machen...
PB 6.21 | Win 11