Hi,
aufgrund einer Nachfrage habe ich mal in meinen halbfertigen Asservaten gewühlt. Der Generator erstellt bisher nur Sinuswellen, die Parameter sollte man einstellen können, bzw. wissen, was man wozu braucht. Die WAV-Datei wird im Speicher abgespielt, kann aber auch als Datei abgelegt werden.
Naja, ich setz mich dran um den Code mal zu entwursteln und den Rest einzubauen^^
Spoiler anzeigen
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
;Das Script erstellt eine WAV-Datei im Speicher, spielt diese ab und speichert anschließend in eine Datei
[/autoit] [autoit][/autoit] [autoit];Opt("GUIOnEventMode", 1)
[/autoit] [autoit][/autoit] [autoit]Global Const $pi = 4 * ATan(1) ;pi=3,1415926....
Global $struct, $wavstruct, $sekunden, $samplingrate, $Channels, $samplefaktor
Global $freq_sliderold = 440, $volm_sliderold = 50
$gui = GUICreate("Wave Generator ", 450, 450, -1, -1)
;label
$freq_lbl = GUICtrlCreateLabel("Frequenz Hz", 16, 16, 64, 17)
$grph_lbl = GUICtrlCreateLabel("Wave Form", 16, 184, 59, 17)
$samp_lbl = GUICtrlCreateLabel("Sampling Bits/Sec", 16, 48, 90, 17)
$bits_lbl = GUICtrlCreateLabel("Bits per Sample", 16, 120, 90, 17)
$chan_lbl = GUICtrlCreateLabel("Channels", 16, 152, 48, 17)
$show_lbl = GUICtrlCreateLabel("Show Samples ", 16, 216, 77, 17)
$volm_lbl = GUICtrlCreateLabel("Volume", 16, 80, 39, 17)
;input
Global $freq_inp = GUICtrlCreateInput("440.0", 120, 16, 81, 21, $ES_NUMBER)
Global $volm_inp = GUICtrlCreateInput("50", 120, 80, 81, 21, $ES_NUMBER)
;combo
$bits_cbo = GUICtrlCreateCombo("", 120, 120, 81, 25)
GUICtrlSetData(-1, "8|16|24", "16")
$samp_cbo = GUICtrlCreateCombo("", 120, 48, 81, 21)
GUICtrlSetData(-1, "8000|11025|12000|16000|22050|24000|32000|44100|48000", "22050")
$chan_cbo = GUICtrlCreateCombo("", 120, 152, 81, 25)
GUICtrlSetData(-1, "1|2|4", "1")
$form_cbo = GUICtrlCreateCombo("", 120, 184, 81, 25)
GUICtrlSetData(-1, "Sinus|Dreieck|Rechteck", "Sinus")
;slider
$freq_sld = GUICtrlCreateSlider(216, 16, 217, 25)
GUICtrlSetLimit($freq_sld, 20000, 1)
GUICtrlSetData($freq_sld, 441)
$volm_sld = GUICtrlCreateSlider(216, 80, 217, 25)
GUICtrlSetData($volm_sld, 100, 50)
GUICtrlSetData($volm_sld, 50)
;button
$test_btn = GUICtrlCreateButton("Test Channels", 224, 152, 105, 25, $WS_GROUP)
$play_btn = GUICtrlCreateButton("Play Wave", 16, 400, 129, 25, $WS_GROUP)
$save_btn = GUICtrlCreateButton("Save Wave to File", 160, 400, 129, 25, $WS_GROUP)
$exit_btn = GUICtrlCreateButton("Exit", 304, 400, 129, 25, $WS_GROUP)
;graphic
$graphic_line = GUICtrlCreateGraphic(16, 235, 420, 150)
GUISetState(@SW_SHOW)
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]While Sleep(20)
$nMsg = GUIGetMsg(1)
Switch $nMsg[0]
Case $GUI_EVENT_CLOSE
Exit
Case $play_btn
If GUICtrlRead($play_btn) = "Stop playing" Then
GUICtrlSetData($play_btn, "Play Wave")
_playsound("") ;sound stoppen
Else
GUICtrlSetData($play_btn, "Stop playing")
_playwave(0) ;sound abspielen
EndIf
Case $GUI_EVENT_MOUSEMOVE
$mpos=GUIGetCursorInfo()
if $mpos[4]=$freq_sld and $mpos[2] then _freq_sld() ;nur wenn maus über slider und mausbutton down, dann neue frequenz holen
if $mpos[4]=$volm_sld and $mpos[2] then _volm_sld()
Case $save_btn
_playwave(1) ;sound speichern
EndSwitch
WEnd
Func _playwave($save = 0) ;bei save=1 datei speichern
[/autoit] [autoit][/autoit] [autoit]$sekunden = 5 ;so lange soll der ton inb der abgespeicherten Datei abgespielt werden
$samplingrate = GUICtrlRead($samp_cbo) ;abtastungen pro sekunde
$BitsPerSample = GUICtrlRead($bits_cbo);guictrlread( ;8,16,24 äquivalent die "Farbtiefe bei einem Bild",
$Channels = GUICtrlRead($chan_cbo) ;1,2,4, Kanäle, mono, stereo usw
$block = Int($Channels * $BitsPerSample / ;1
$bytes = $samplingrate * $block
$samplefaktor = $BitsPerSample / 8 ;lokale hilfsvariable
$filesize = $samplefaktor * $sekunden * $samplingrate * $Channels + 44 - 8
;struktur mit dem Header einer WAV-Datei erstellen
Local $struct = DllStructCreate("byte[" & $samplefaktor * $sekunden * $samplingrate * $Channels + 44 & "]") ;platz für unser sampling
Local $s = "char RIFF [4];" & _ ;RIFF
"uint FileSize;" & _ ;Dateigröße-8 Bytes
"char WAVE [4];" & _ ;WAVE
"char fmt [4];" & _ ;fmt Header Signatur
"uint fmt_len;" & _ ;länge restl. fmt
"word Format;" & _ ;Datenformat s. Tabelle z.B. Wikipedia 1=PCM
"word Channels;" & _ ;Anzahl Kanäle 1=MONO
"uint Samplerate;" & _ ;Abtastrate pro Sekunde (22050)
"uint Bytes;" & _ ;Abtastrate * Block (22050)
"word Block;" & _ ;Channels * BitsPerSample / 8 (1)
"word BitsPerSample;" & _ ;8, 16, oder 24 (8)
"char DATA [4];" & _ ;DATA Header Signatur
"uint Len;" ;Länge des folgenden Datenblocks
Switch $samplefaktor ;je nach einstellungen platz für die wav-Daten reservieren
Case 1
$s &= "byte WAVDATA[" & $sekunden * $samplefaktor * $samplingrate * $Channels & "]"
Case 2
$s &= "word WAVDATA[" & $sekunden * $samplefaktor * $samplingrate * $Channels & "]"
Case 4
$s &= "dword WAVDATA[" & $sekunden * $samplefaktor * $samplingrate * $Channels & "]"
EndSwitch
Local $wavstruct = DllStructCreate($s, DllStructGetPtr($struct)) ;struct "überlagern" damit alle Daten byteweise in eine Datei geschrieben werden können
[/autoit] [autoit][/autoit] [autoit];Unsere Daten für die Sinuswelle
$f = GUICtrlRead($freq_inp) ;frequenz in hertz
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $f = ' & $f & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
$w = 2 * $pi * $f ;omega=2*pi*f für Maschinenbauer gilt: OMEGA das weiß ich, Pi mal N durch dreißig!!! :o)
$Amplitude = (GUICtrlRead($volm_inp) * 1.81019) ^ $samplefaktor ;Lautstärke, bei 8 bit maximal 2^8, bei 16 bit maximal 2^16
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Amplitude = ' & $Amplitude & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
$i = 0 ;anzahl der geschriebenen bytes (funktionswerte)
If $save = 1 Then
$f = 1 / $sekunden ;falls gespeichert werden soll, anzahl Sekunden festlegen
Else
GUICtrlDelete($graphic_line) ;grafik kurven-linien löschen
GUICtrlSetColor($graphic_line, 0)
$graphic_line = GUICtrlCreateGraphic(16, 235, 420, 150) ;kurven-linien
GUICtrlSetGraphic(-1, $GUI_GR_MOVE, 0, 75)
GUICtrlSetGraphic($graphic_line, $GUI_GR_LINE, 420, 75)
GUICtrlSetColor($graphic_line, 0xFF0000)
GUICtrlSetBkColor($graphic_line, 0xFFFFFF)
GUICtrlSetGraphic($graphic_line, $GUI_GR_COLOR, 0xFF0000, 0xFFFFF0)
;GUICtrlSetGraphic($graphic_line, $GUI_GR_RECT, 0, 0, 20, 150)
EndIf
;hier gehts los, wir erstellen eine komplette sinuswelle, diese wird so lange wiederholt, bis die Abspieldauer in sekunden erreicht ist
For $t = 0 To 1 / $f Step 1 / $samplingrate ;samplingrate y(t)-Werte ()Amplituden) ermitteln
$i += 1 ;anzahl der samples
$yt = Int($Amplitude * Sin($w * $t)) ;unsere altbekannte formel
If $i < 210 Then ConsoleWrite($i & " " & $yt & @CRLF)
DllStructSetData($wavstruct, "WAVDATA", $yt, $i) ;schreiben von y(t) in die struct
If $save = 0 Then ;wenn speichern gewählt, keine welle zeichnen
GUICtrlSetGraphic($graphic_line, $GUI_GR_MOVE, Int(420 * $f * $t), 75) ;punkt auf x-achse
GUICtrlSetGraphic($graphic_line, $GUI_GR_LINE, Int($t * 420 * $f), Int(75 - ($yt / $Amplitude * 75 * GUICtrlRead($volm_inp) / 100))) ;linie zeichnen (hoehe y(t))
EndIf
If $Channels = 2 Then ;wenn 2 kanäle (stereo), dann das byte für den 2. Kanal hinzufügen
$i += 1
DllStructSetData($wavstruct, "WAVDATA", $yt, $i)
EndIf
Next
GUICtrlSetGraphic($graphic_line, $GUI_GR_REFRESH)
;jetzt werden die Daten in die struct geschrieben, es entsteht eine WAV-Datei im Speicher
DllStructSetData($wavstruct, "RIFF", "RIFF")
DllStructSetData($wavstruct, "FileSize", $filesize)
DllStructSetData($wavstruct, "WAVE", "WAVE")
DllStructSetData($wavstruct, "fmt", "fmt ")
DllStructSetData($wavstruct, "fmt_len", 16)
DllStructSetData($wavstruct, "Format", 1) ;PCM
DllStructSetData($wavstruct, "Channels", $Channels)
DllStructSetData($wavstruct, "Samplerate", $samplingrate)
DllStructSetData($wavstruct, "Bytes", $bytes) ;samplerate*block
DllStructSetData($wavstruct, "Block", $block)
DllStructSetData($wavstruct, "BitsPerSample", $BitsPerSample)
DllStructSetData($wavstruct, "DATA", "data")
DllStructSetData($wavstruct, "Len", ($samplingrate / $f * $Channels * $samplefaktor));hier wird NUR DIE LÄNGE DER ERSTEN SINUSWELLE eingetragen, um den Sound im speicher abzuspielen
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : ($samplingrate / $f * $Channels * $samplefaktor) = ' & ($samplingrate / $f * $Channels * $samplefaktor) & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
;~ $data = ""
;~ For $i = 1 To 14 ;anzeigen des WAV-Headers
;~ $data &= DllStructGetData($wavstruct, $i) & @CRLF
;~ Next
;MsgBox(0, "Daten WAV-Header", StringLeft($data, 100))
If $save = 0 Then
_playsound("") ;aktuellen sound beenden
_Playsound(DllStructGetPtr($wavstruct), 1) ;abspielen des sounds aus dem speicher, Ton wird immer wiederholt
Else
$sdat = DllStructGetData($struct, 1) ;struktur in eine Datei schreiben
$wavdata = StringLeft(BinaryToString($sdat), $sekunden * $samplingrate * $Channels * $samplefaktor + 44)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $wavdata = ' & StringLen($wavdata) & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
$wav = FileOpen("test1.wav", 18)
$bindata = FileWrite($wav, $wavdata)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $bindata = ' & $bindata & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
FileClose($wav)
ShellExecute("test1.wav") ;wavedatei abspielen
EndIf
;Msgbox(0,"Ton mit Frequenz "&$f&" Hz","Spieldauer "&$sekunden&" Sekunden",$sekunden)
EndFunc ;==>_playwave
Func _freq_sld()
If GUICtrlRead($freq_sld) = $freq_sliderold Then Return
$freq_sliderold = GUICtrlRead($freq_sld)
GUICtrlSetData($freq_inp, GUICtrlRead($freq_sld))
If GUICtrlRead($play_btn) = "Stop playing" Then _playwave()
EndFunc ;==>_freq_sld
Func _volm_sld()
If GUICtrlRead($volm_sld) = $volm_sliderold Then Return
$volm_sliderold = GUICtrlRead($freq_sld)
GUICtrlSetData($volm_inp, GUICtrlRead($volm_sld))
If GUICtrlRead($play_btn) = "Stop playing" Then _playwave()
EndFunc ;==>_volm_sld
Func _PlaySound($sSoundFile, $mem = 0) ;mem=1 spielt sound aus dem speicher, dann muss $sSoundfile der pointer zum anfang der struct sein
Local Const $SND_ALIAS = 0x10000
Local Const $SND_ALIAS_ID = 0x110000
Local Const $SND_APPLICATION = 0x80
Local Const $SND_ASYNC = 0x1
Local Const $SND_FILENAME = 0x20000
Local Const $SND_LOOP = 0x8
Local Const $SND_MEMORY = 0x4
Local Const $SND_NODEFAULT = 0x2
Local Const $SND_NOSTOP = 0x10
Local Const $SND_NOWAIT = 0x2000
Local Const $SND_PURGE = 0x40
Local Const $SND_RESOURCE = 0x40004
Local Const $SND_SYNC = 0x0
If $sSoundFile = "" Then
DllCall('winmm.dll', 'int', 'PlaySoundA', 'ptr', 0, 'int', 0, 'int', 0)
Return
EndIf
If $mem = 1 Then
$a = DllCall('winmm.dll', 'int', 'PlaySoundA', 'ptr', $sSoundFile, 'int', 0, 'int', BitOR(4, 1, 8))
Else
$a = DllCall('winmm.dll', 'int', 'PlaySoundA', 'str', $sSoundFile, 'int', 0, 'int', BitOR(1, 2, 0x10))
EndIf
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $a = ' & $a[0] & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
EndFunc ;==>_PlaySound