Aufnahme mit _BASS_Record

  • das "+" am Anfang bedeutet, daß der Input aktiv ist!
    bei nicht aktiven sollte ein "!" davorstehen

    Das ist komisch.
    Es sollte eigentlich nur 1 Input aktiv sein

    StereoMix ist ein Input, welcher alles aufnimmt was über den Output rauskommt
    Und da auch dieser aktiv ist wird wahrscheinlich hiermit der Sinus "aufgenommen"

    Probier mal mit _BASS_RecordSetInput alle zu deaktivieren und nur den gewünschten Input zu aktivieren
    in etwa so sollte das gehen:
    For $i=0 to 5
    _BASS_RecordSetInput($i, $BASS_INPUT_OFF)
    Next
    _BASS_RecordSetInput(1, $BASS_INPUT_ON)

  • Hallo Eukalyptus,

    ich habe Dein Script noch etwas angepasst:

    Spoiler anzeigen
    [autoit]

    #include "Bass.au3"
    #include "BassConstants.au3"

    [/autoit] [autoit][/autoit] [autoit]

    Global $File = "1kHz.wav"
    Local $aRecordInfo
    _BASS_STARTUP("BASS.dll") ;Open Bass.DLL.
    _BASS_Init(0, -1, 44100, 0, "") ;Initalize bass.
    _BASS_RecordInit(-1)

    [/autoit] [autoit][/autoit] [autoit]

    $aRecordInfo = _BASS_RecordGetInfo() ;Number of available input sources ([2])

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 to $aRecordInfo[2] ;Disable all input sources
    _BASS_RecordSetInput($i, $BASS_INPUT_OFF, -1)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 to $aRecordInfo[2]
    If StringLeft(_BASS_RecordGetInputName($i),4) = "Line" OR StringLeft(_BASS_RecordGetInputName($i),5) = "Haupt" OR StringLeft(_BASS_RecordGetInputName($i),6) = "Master" Then ExitLoop
    Next

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_RecordSetInput($i, $BASS_INPUT_ON, -1) ;Enable Line Input

    [/autoit] [autoit][/autoit] [autoit]

    $hRecord = _BASS_RecordStart(44100, 1, 0, "", 0)

    [/autoit] [autoit][/autoit] [autoit]

    $hMusic = _BASS_StreamCreateFile(False, $File, 0, 0, 0)
    _BASS_ChannelPlay($hMusic, 1)
    While _BASS_ChannelIsActive($hMusic) = $BASS_ACTIVE_PLAYING
    $iFreqOut = _GetFreq($hMusic)
    $iFreqIn = _GetFreq($hRecord)
    ToolTip("Frequenz Out: " & $iFreqOut & @LF & "Frequenz In: " & $iFreqIn & " / " & _BASS_RecordGetInputName($i))
    Sleep(100)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_Free()
    _BASS_RecordFree()

    [/autoit] [autoit][/autoit] [autoit]

    Func _GetFreq($hHandle)
    Local $TmpData = 0, $TmpNr = 0, $fft = 0
    Local $fftstruct = DllStructCreate("float[4096]")
    _BASS_ChannelGetData($hHandle, DllStructGetPtr($fftstruct), $BASS_DATA_FFT8192)
    For $i = 0 To 4095
    $TmpData = Round(DllStructGetData($fftstruct, 1, $i + 1) * 100)
    If $fft < $TmpData Then ;Bestimme den Ort des Maximalwerts der FFT Analyse
    $fft = $TmpData
    $TmpNr = $i + 1
    EndIf
    Next
    Return Round(22000 / 4096 * $TmpNr) ;Max 22kHz.
    EndFunc ;==>_GetFreq

    [/autoit]

    Es fragt nun auch noch die Anzahl der Inputs ab, deaktiviert alle und aktiviert dann den, der mit Line, Haupt oder Master anfängt.
    (Unter deutschem XP heisst es Line, unter deutschem Win7 Haupt...)

    Das Ganze funktioniert nun auf meinem deutschen XP.
    Da wir aber bald auf Win7 wechseln testete ich es auch dort. Und dort bekomme ich bei eingestecktem Kabel nur 5Hz.
    Bei ausgestecktem Kabel erhalte ich gar eine Fehlermeldung und das Programm stürzt ab.

    Any idea?

    Grüsse + DANKE!
    Veronesi

  • Windows 7 ( und auch Vista ) listen die Inputs anders auf als XP

    Bei Bass.dll unter XP ist jedes Device eine eigene Soundkarte, die mehrere Out/Inputs haben kann
    zb:
    Device 1 Realtek HD Audio Input
    - Input CD-Lautstärke
    - Input Mikrofon
    - Input Line-Lautstärke
    - Input Aux-Lautstärke
    - Input Stereomix

    Device 2...


    Unter WIn7 und Vista werden alle Out/Inputs als eigenes Device mit dem Input "Hauptinput" dargestellt
    zb:
    Device 1 Realtek CD-Lautstärke
    - Input Hauptinput

    Device 2 Realtek Mikrofon
    - Input Hauptinput

    Device 3 Realtek Line-In
    - Input Hauptinput

    usw...


    Zudem sind viele deaktiviert und müssen in der Systemsteuerung aktiviert werden (Audiogeräte - deaktivierte Geräte anzeigen)

    Probier mal meinen Recorder unter Win7 aus...

  • Ich muss morgen mal noch schauen, ob ich irgendwelche deaktivierten Geräte (Aufnahmegeräte) finde.

    Aber irgendwie stehe ich gerade etwas auf dem Schlauch (ist schon spät :) ). Welchen Recorder meinst Du genau? Sorry...

    Zudem: aufnehmen kann ich ja (sofern das Kabel eingesteckt ist). Aber ich messe die falsche Frequenz!

    Gruss
    Veronesi

  • Ok, ich habe nun alle (war nur 1) Audioaufnahmegerät unter Windows 7 aktiviert. Trotzdem messe ich bei der Frequenzanalyse im besten Fall 5Hz. (Vielleicht eine Schwankung des Netzes).
    Dann habe ich Deinen Recorder verwendet.

    Der funktioniert einwandfrei. Natürlich nur mit lokalen Admin-Rechten. Und er gibt beim "FileEncoding" einen Error aus, aber das File ist trotzdem da und tönt +/- nach einem 1kHz. Sinus!

    Bloss ist die Source von Deinem Recorder zu kompliziert für mich. Ich blick da momentan einfach nicht durch.
    Denn ich möchte das ja so einfach wie möglich (muss ja nicht zu genau sein) programmieren, damit ich dann auch irgendwann drauskomme! (Bin eigentlich kein Programmierer und bei AutoIt auch erst seit ca 2 Wochen...)

    Kannst Du mir nochmals einen Denkanstoss geben? Grundsätzlich möchte ich "bloss" auf dem Line-In Eingang kontrollieren ob +/- das reinkommt (Frequenz / Pegel) was auch rausgeht!
    Danke!
    Grüsse
    Veronesi

  • Nun wieder ein Script von mir:

    Spoiler anzeigen
    [autoit]

    #include <BassEnc.au3>
    #include "Bass.au3"
    #include "BassConstants.au3"

    [/autoit] [autoit][/autoit] [autoit]

    FileInstall("bass.dll",@ScriptDir & "\bass.dll")
    FileInstall("basscb.dll",@ScriptDir & "\basscb.dll")
    FileInstall("bassenc.dll",@ScriptDir & "\bassenc.dll")

    [/autoit] [autoit][/autoit] [autoit]

    Dim $File1 = @ScriptDir & "\1kHz.wav", $File2 = @ScriptDir & "\test.wav"
    Local $hMusic, $iFreq, $iFreq1, $iFreq2, $basscb_dll, $RecordDevice, $temp ,$hRecord, $EncHandle

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_STARTUP("BASS.dll") ;Open Bass.DLL.
    _BASS_Init(0, -1, 44100, 0, "") ;Initalize bass.
    _BASS_Encode_STARTUP("BassEnc.dll")
    $basscb_dll = DllOpen("BASSCB.dll")
    $RecordDevice = _BASS_RecordInit(-1)
    $temp = DllCall($basscb_dll, "dword", "RecordStart", "dword", 44100, "dword", 2, "dword", _makelong($BASS_SAMPLE_FX, 10))
    $hRecord = $temp[0]

    [/autoit] [autoit][/autoit] [autoit]

    $iFreq1 = Play($File1) ;Play 1kHz. testfile
    Record() ;Record
    $iFreq2 = Play($File2) ;Play recorded file

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(0,"Ausgabe","Ausgangsfrequenz: " & $iFreq1 & @lF & "Eingangsfrequenz: " & $iFreq2)

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_Free()
    _BASS_RecordFree()
    Exit ;=>Main

    [/autoit] [autoit][/autoit] [autoit]

    Func Play($File)
    $hMusic = _BASS_StreamCreateFile(False, $File, 0, 0, 0) ;Create Play Handle
    _BASS_ChannelPlay($hMusic, 1) ;Play File
    Sleep(100) ;Ignore silence at the beginning of file
    $iFreq = GetFreq($hMusic)
    Return $iFreq
    EndFunc ;=>Play

    [/autoit] [autoit][/autoit] [autoit]

    Func Record()
    $EncHandle = _BASS_Encode_Start($hRecord,$File2, $BASS_ENCODE_PCM)
    Sleep(1000)
    _BASS_Encode_Stop($hRecord)
    EndFunc ;=>Record

    [/autoit] [autoit][/autoit] [autoit]

    Func GetFreq($hHandle)
    Local $TmpData = 0, $TmpNr = 0, $fft = 0
    Local $fftstruct = DllStructCreate("float[4096]")
    _BASS_ChannelGetData($hHandle, DllStructGetPtr($fftstruct), $BASS_DATA_FFT8192)
    For $i = 0 To 4095
    $TmpData = Round(DllStructGetData($fftstruct, 1, $i + 1) * 100)
    If $fft < $TmpData Then ;Bestimme den Ort des Maximalwerts der FFT Analyse
    $fft = $TmpData
    $TmpNr = $i + 1
    EndIf
    Next
    Return Round(22000 / 4096 * $TmpNr) ;Max 22kHz.
    EndFunc ;=>GetFreq

    [/autoit]

    Es wird folgendes gemacht:
    1. Testfile wiedergeben und Frequenz messen.
    2. (Fast) gleichzeitig Testfile wieder aufnehmen
    3. Aufgenommenes File wiedergeben und Frequenz messen.

    Testergebnisse unter XP
    - Kabel von Line-In zu Line-Out eingesteckt: Out = 1004Hz / In = 1004Hz.
    - Kabel ausgesteckt (oder nur an einem Ein-/Ausgang): Out = 1004Hz. / In = 0Hz.
    => Funktioniert!

    Testergebnisse unter Win7
    - Kabel von Line-In zu Line-Out eingesteckt: Out = 1004Hz / In = 1004Hz.
    (Aber manchmal erkennt Win7 gar nicht, dass am Line-In was eingesteckt ist. Dann muss man den Stecker wieder rausziehen und langsam (!!) wieder einstecken. Dann gehts.
    - Kabel ganz ausgesteckt: Out = 0Hz. / In = 0Hz. (vermutlich weil der Line-Out auch ausgesteckt ist! Aber das kann man abfangen, Wenn Out = 0 dann.... Meldung: Kabel vergessen!)
    - Kabel NUR am Line-Out eingesteckt: Out = 1004Hz. / In = 1004Hz. (Fehler!)

    => Windows 7 macht einfach irgendwie zicken.....
    Gruss
    Veronesi

  • Probier doch mal dieses Script unter Win7 mit den verschiedenen Möglichkeiten (Kabel eingesteckt, ausgesteckt...)
    und poste wieder den Consolenoutput

    Spoiler anzeigen
    [autoit]

    #AutoIt3Wrapper_UseX64=n

    [/autoit] [autoit][/autoit] [autoit]

    #include "Bass.au3"
    #include "BassConstants.au3"

    [/autoit] [autoit][/autoit] [autoit]

    Global $File = "1kHz.wav"

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_STARTUP("BASS.dll") ;Open Bass.DLL.
    _BASS_Init(0, -1, 44100, 0, "") ;Initalize bass.
    _BASS_SetVolume(1)

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_RecordInit(-1)
    ConsoleWrite(@LF & "-Default Device: " & _BASS_RecordGetDevice() & @LF)
    _BASS_RecordFree()

    [/autoit] [autoit][/autoit] [autoit]

    $hMusic = _BASS_StreamCreateFile(False, $File, 0, 0, $BASS_SAMPLE_LOOP)
    _BASS_ChannelPlay($hMusic, 1)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    For $iDevice = 0 To 10
    $aInfo = _BASS_RecordGetDeviceInfo($iDevice)
    If @error Then ExitLoop
    _BASS_RecordInit($iDevice)
    For $iInput = 0 To 10
    $sName=_BASS_RecordGetInputName($iInput)
    If @error Then ExitLoop
    For $i=0 To 10
    _BASS_RecordSetInput($iInput, $BASS_INPUT_OFF,-1)
    Next
    _BASS_RecordSetInput($iInput, $BASS_INPUT_ON,1)
    $hRecord = _BASS_RecordStart(44100, 2, 0, "", 0)
    $nMax=0
    For $i=1 To 5
    $nLevel=_LoWord(_BASS_ChannelGetLevel($hRecord)) / 32768
    If $nLevel > $nMax Then $nMax = $nLevel
    Sleep(200)
    Next
    If $nMax > 0.1 Then
    ConsoleWrite("+" & $aInfo[0] & " " & $sName & ": Device " & $iDevice & " / Input " & $iInput & " / Level " & Round($nMax*100) & "%" & @LF)
    Else
    ConsoleWrite("!" & $aInfo[0] & " " & $sName & ": Device " & $iDevice & " / Input " & $iInput & " / Level " & Round($nMax*100) & "%" & @LF)
    EndIf
    _BASS_ChannelStop($hRecord)
    Next
    _BASS_RecordFree()
    Next

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite(@LF)

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_RecordFree()
    _BASS_Free()

    [/autoit]
  • So, nun konnte ich das endlich testen.
    Hier die Ergebnisse:

    Ganz ohne Kabel:
    -Default Device: 4294967295

    Kabel nur am Line-Out:
    -Default Device: 4294967295

    Kabel nur am Line-In:
    -Default Device: 0
    !Eingang (High Definition Audio- Hauptlautstärke: Device 0 / Input 0 / Level 1%

    Kabel in beide eingesteckt:
    -Default Device: 0
    +Eingang (High Definition Audio-Gerät) Hauptlautstärke: Device 0 / Input 0 / Level 100%

  • Schaut doch nicht so schlecht aus ;)

    Das sollte doch eigentlich so funktionieren:

    Spoiler anzeigen
    [autoit]

    #AutoIt3Wrapper_UseX64=n

    [/autoit] [autoit][/autoit] [autoit]

    #include "Bass.au3"
    #include "BassConstants.au3"

    [/autoit] [autoit][/autoit] [autoit]

    Global $File = "1kHz.wav"

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_STARTUP("BASS.dll") ;Open Bass.DLL.
    _BASS_Init(0, 2, 44100, 0, "") ;Initalize bass.
    If @error Then
    MsgBox(0,"ERROR","ERROR Audio Out")
    Exit
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_RecordInit(0)
    If @error Or _BASS_RecordGetDevice() > 10 Or _BASS_RecordGetDevice() < 0 Then
    MsgBox(0,"ERROR","ERROR Audio In")
    Exit
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_RecordSetInput(0, $BASS_INPUT_ON,-1)

    [/autoit] [autoit][/autoit] [autoit]

    $hRecord = _BASS_RecordStart(44100, 2, 0, "", 0)

    [/autoit] [autoit][/autoit] [autoit]

    $hMusic = _BASS_StreamCreateFile(False, $File, 0, 0, 0)
    _BASS_ChannelPlay($hMusic, 1)

    [/autoit] [autoit][/autoit] [autoit]

    While _BASS_ChannelIsActive($hMusic) = $BASS_ACTIVE_PLAYING
    $iFreqOut = _GetFreq($hMusic)
    $iFreqIn = _GetFreq($hRecord)
    ToolTip("Frequenz Out: " & $iFreqOut & @LF & "Frequenz In: " & $iFreqIn)
    Sleep(100)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_Free()
    _BASS_RecordFree()

    [/autoit] [autoit][/autoit] [autoit]

    Func _GetFreq($hHandle)
    Local $TmpData = 0, $TmpNr = 0, $fft = 0
    Local $fftstruct = DllStructCreate("float[4096]")
    _BASS_ChannelGetData($hHandle, DllStructGetPtr($fftstruct), $BASS_DATA_FFT8192)
    For $i = 0 To 4095
    $TmpData = Round(DllStructGetData($fftstruct, 1, $i + 1) * 100)
    If $TmpData > 0.2 And $fft < $TmpData Then ;Bestimme den Ort des Maximalwerts der FFT Analyse
    $fft = $TmpData
    $TmpNr = $i + 1
    EndIf
    Next
    Return Round(22000 / 4096 * $TmpNr) ;Max 22kHz.
    EndFunc ;==>_GetFreq

    [/autoit]
  • HEY EUKALYPTUS, Du bist genial! :rock:

    das Script scheint nun auf XP und Windows 7 zu laufen!
    Einzig die Zeile

    [autoit]

    _BASS_Init(0, 2, 44100, 0, "") ;Initalize bass.

    [/autoit]


    musste ich abändern. Aus der 2 eine 1 machen!

    Nun läuft es einwandfrei! 8)

    Nun muss ich das ganze natürlich noch ein klein wenig umbauen, damit es in mein gesamtes Skript passt. (Es muss eben noch mehr geprüft werden).
    Und statt MsgBox'es mache ich natürlich mit Return Fehlerauswertungen!

    Vielen herzlichen Dank!!
    Sobald ich das geschafft habe, werde ich das natürlich noch auf verschiedenen PCs mit verschiedenen Soundkarten testen!

    Beste Grüsse
    Veronesi

  • So, ich hoffe, ihr lest hier noch mit!

    Inzwischen habe ich aus dem Skript eine Funktion gemacht und in mein ganzes Projekt eingefügt.
    Die Funktion sieht so aus:

    Spoiler anzeigen
    [autoit]

    #include "Include\Bass.au3"
    #include "Include\BassConstants.au3"
    #include "Include\BassEnc.au3"

    [/autoit] [autoit][/autoit] [autoit]

    Dim $File = @TempDir & "\1kHz.wav"

    [/autoit] [autoit][/autoit] [autoit]

    CheckAudio(50)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func CheckAudio($Tolerance) ;Check for Audio
    Local $hRecord, $hMusic, $iFreqOut, $iFreqIn, $TimerAudio

    [/autoit] [autoit][/autoit] [autoit]

    ;~ GUICtrlSetBkColor($CheckBoxNr,$LightGray)
    ;~ IESetText($Text, $LightGreen, $Size)

    [/autoit] [autoit][/autoit] [autoit]

    FileInstall("Include\1kHz.wav",@TempDir & "\1kHz.wav",1)
    FileInstall("Include\bass.dll",@TempDir & "\bass.dll",1)
    FileInstall("Include\basscb.dll",@TempDir & "\basscb.dll",1)
    FileInstall("Include\bassenc.dll",@TempDir & "\bassenc.dll",1)

    _BASS_STARTUP(@TempDir & "\BASS.dll") ;Open Bass.DLL.
    _BASS_Init(0, 1, 44100, 0, "") ;Initalize bass.
    If @error Then
    ;~ MsgBox(0,"ERROR","ERROR Audio Out")
    ;~ GUICtrlSetBkColor($CheckBoxNr,$LightRed) ;Set color for Checkbox Background
    ;~ GUICtrlSetState($CheckBoxNr,1) ;Set Checkbox checked
    Return 0
    EndIf

    _BASS_RecordInit(0)
    If @error Or _BASS_RecordGetDevice() > 10 Or _BASS_RecordGetDevice() < 0 Then
    ;~ MsgBox(0,"ERROR","ERROR Audio In")
    ;~ GUICtrlSetBkColor($CheckBoxNr,$LightRed) ;Set color for Checkbox Background
    ;~ GUICtrlSetState($CheckBoxNr,1) ;Set Checkbox checked
    Return 0
    EndIf

    _BASS_RecordSetInput(0, $BASS_INPUT_ON,-1)

    $hRecord = _BASS_RecordStart(44100, 2, 0)

    $hMusic = _BASS_StreamCreateFile(False, $File, 0, 0, 0) ;Set handle for 1kHz. Music File

    _BASS_ChannelPlay($hMusic, 1) ;Play 1kHz. Music-File
    $TimerAudio = TimerInit()

    [/autoit] [autoit][/autoit] [autoit]

    While _BASS_ChannelIsActive($hMusic) = $BASS_ACTIVE_PLAYING ;While playing get frequency of Line-Out and Line-In
    $iFreqOut = GetFreq($hMusic)
    $iFreqIn = GetFreq($hRecord)
    ;~ ToolTip("Frequenz Out: " & $iFreqOut & @LF & "Frequenz In: " & $iFreqIn)
    If TimerDiff($TimerAudio) > 1500 Then ExitLoop
    Sleep(50)
    WEnd
    ToolTip(@error)
    Sleep(5000)

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_Free()
    _BASS_RecordFree()

    If $iFreqOut + $Tolerance > $iFreqIn AND $iFreqOut - $Tolerance < $iFreqIn AND $iFreqOut < 1100 and $iFreqOut > 900 Then ;If both frequencies are +/- the same and the Output frequency is +/- 1kHz. then it's OK!
    ;~ MsgBox(0,"Erfolg","Signal wurde erfolgreich empfangen!" & @LF & "Ausgangsfrequenz: " & $iFreq1 & @lF & "Eingangsfrequenz: " & $iFreq2)
    ;~ GUICtrlSetBkColor($CheckBoxNr,$GUIBackgroundColor) ;Set color for Checkbox Background
    ;~ GUICtrlSetColor($CheckBoxNr,$LightGreen) ;Set color for Checkbox Text
    ;~ GUICtrlSetState($CheckBoxNr,1) ;Set Checkbox checked
    Return 1
    ElseIf $iFreqOut > 1100 OR $iFreqOut < 900 Then
    ;~ MsgBox(0,"Fehler","Fehler! Vermutlich wurde das Kabel nicht korrekt am Line-Out Anschluss angeschlossen" & $ifreq1 & $ifreq2)
    ;~ GUICtrlSetBkColor($CheckBoxNr,$LightRed) ;Set color for Checkbox Background
    ;~ GUICtrlSetState($CheckBoxNr,1) ;Set Checkbox checked
    Return -1
    Else
    ;~ MsgBox(0,"Fehler","Fehler! Vielleicht wurde das Kabel nicht korrekt am Line-In Anschluss angeschlossen, oder das Produkt hat einen defekt!")
    ;~ GUICtrlSetBkColor($CheckBoxNr,$LightRed) ;Set color for Checkbox Background
    ;~ GUICtrlSetState($CheckBoxNr,1) ;Set Checkbox checked
    Return 0
    EndIf
    EndFunc ;=> CheckAudio

    [/autoit] [autoit][/autoit] [autoit]

    Func GetFreq($hHandle)
    Local $TmpData = 0, $TmpNr = 0, $fft = 0
    Local $fftstruct = DllStructCreate("float[4096]")
    _BASS_ChannelGetData($hHandle, DllStructGetPtr($fftstruct), $BASS_DATA_FFT8192)
    For $i = 0 To 4095
    $TmpData = Round(DllStructGetData($fftstruct, 1, $i + 1) * 100)
    If $TmpData > 0.2 And $fft < $TmpData Then ;Bestimme den Ort des Maximalwerts der FFT Analyse
    $fft = $TmpData
    $TmpNr = $i + 1
    EndIf
    Next
    Return Round(22000 / 4096 * $TmpNr) ;Max 22kHz.
    EndFunc ;=> GetFreq

    [/autoit]

    Man beachte die Line mit dem ToolTip(@error) und danach die Sleep(5000). Irgendwo vom _BASS_ChannelPlay(....) bis zu der erwähnten Zeile passiert ein Fehler.
    Zwar wird alles ausgeführt, doch wenn ich das ganze Programm dann beende, dann bekomme ich einen Exit Code: -1073741819. (Fehlermeldung: autoit.de/wcf/attachment/9060/)
    Dies sei ein Hard-Crash. Doch wie bringe ich den weg? Denn mit diesem Fehler ist mein ganzes Programm ziemlich wertlos und unprofessionell!
    Ich verwende die aktuellste AutoIT Version 3.3.6.1

    Leider kann ich das meistens nur reproduzieren, wenn ich den Code-Schnippsel im meinem ganzen Programm verwende! Doch das ist zu gross um von Euch analysiert zu werden....
    Gibt es generelle Anregungen?

    Vielen Dank für Eure Anregungen!
    Gruss
    Veronesi

    PS: Includes: autoit.de/wcf/attachment/9061/

  • Nun konnte ich den Fehler etwas weiter eingrenzen:

    Er tritt nur auf, wenn ich in meinem "grossen" Programm folgendes aktiviere:

    [autoit]

    AdlibRegister("GetMousePosition",500) ;Create Interrupt for GUI Moving

    [/autoit]

    Dieser Befehl überprüft, auf welchem Bildschirm die Maus ist und verschiebt das GUI automatisch auf den richtigen Monitor.
    Hier die Funktionen dahinter:

    Func GetMousePosition()

    Spoiler anzeigen
    [autoit]

    Func GetMousePosition() ;Interrupt Timer: Check Mouse Position and moves the GUI to this screen
    Local $aTmp[32], $ResX, $ResY, $PosX, $PosY, $Tmp

    $Tmp = _GetMouseInfo()
    If $Tmp <> $MouseScreenNumber Then
    $MouseScreenNumber = $Tmp
    $aTmp = _GetMonitorInfo()
    $ResX = $aTmp[$Tmp][0]
    $ResY = $aTmp[$Tmp][1]
    $PosX = $aTmp[$Tmp][2]
    $PosY = $aTmp[$Tmp][3]
    $aTmp = WinGetPos($hGUI)

    WinMove($hGUI,"",$PosX + ($ResX/2) - ($aTmp[2]/2),$PosY + ($ResY/2) - ($aTmp[3]/2),$aTmp[2],$aTmp[3],2)
    EndIf
    EndFunc ;=> GetMousePosition

    [/autoit]

    Func _GetMouseInfo()

    Spoiler anzeigen
    [autoit]

    #include-once
    #include "Func_GetMonitorInfo.au3"
    Func _GetMouseInfo()
    ;Returns the screen number on which the actual mouse cursor is
    ;Call: _GetMouseInfo()

    Local $aTmp[32][32], $MousePos, $NrOfScreens, $i
    $MousePos = MouseGetPos()
    $aTmp = _GetMonitorInfo()
    $NrOfScreens = $aTmp[0][0]
    For $i = 1 To $NrOfScreens
    If $MousePos[0] >= $aTmp[$i][2] AND ($MousePos[0] <= $aTmp[$i][2] + $aTmp[$i][0]) AND $MousePos[1] >= $aTmp[$i][3] AND ($MousePos[1] <= $aTmp[$i][3] + $aTmp[$i][1]) Then Return $i
    ;Checks on which Screen the Mousecursor is
    Next
    EndFunc

    [/autoit]

    Func _GetMonitorInfo()

    Spoiler anzeigen
    [autoit]

    #include-once

    [/autoit] [autoit][/autoit] [autoit]

    Func _GetMonitorInfo()
    ;Returns some informations about your screens
    ;Call: _GetMonitorInfo()
    ;Return: Array With
    ;[0][0] Nr of Monitors
    ;[1][0] X Resolution of Monitor 1
    ;[1][1] Y Resolution of Monitor 1
    ;[1][2] X Position of Monitor 1
    ;[1][3] Y Position of Monitor 1

    [/autoit] [autoit][/autoit] [autoit]

    ;[2][0] X Resolution of Monitor 2
    ;[2][1] Y Resolution of Monitor 2
    ;[2][2] X Position of Monitor 2
    ;[2][3] Y Position of Monitor 2
    ;......

    Local $NrOfMonitors, $ResolutionX[32], $ResolutionY[32], $PositionX[32], $PositionY[32], $Ret
    Local $cbMonitorEnumProc = DllCallbackRegister("MonitorEnumProc", "ubyte", "ptr;ptr;ptr;int")

    [/autoit] [autoit][/autoit] [autoit]

    If @error Then Return SetError(1, 0, False)
    Local $strctCount = DllStructCreate("uint Count;uint Width[12];uint Height[12];int left[12];int top[12]")
    If @error Then Return SetError(2, @error, False)
    Local $iCount

    DllStructSetData($strctCount, "Count", 0)

    $Ret = DllCall("User32.dll", "ubyte","EnumDisplayMonitors","ptr", 0,"ptr", 0, "ptr", DllCallbackGetPtr($cbMonitorEnumProc), "ptr", DllStructGetPtr($strctCount))
    If @error Or $Ret[0] = 0 Then Return SetError(3, @error, False)

    DllCallbackFree($cbMonitorEnumProc)

    $iCount = Int(DllStructGetData($strctCount, "Count"))

    Local $aMonitors[$iCount+1][4] = [[$iCount]]

    For $i = 1 To $iCount
    $aMonitors[$i][0] = Int(DllStructGetData($strctCount, "Width",$i))
    $aMonitors[$i][1] = Int(DllStructGetData($strctCount, "Height",$i))
    $aMonitors[$i][2] = Int(DllStructGetData($strctCount, "left",$i))
    $aMonitors[$i][3] = Int(DllStructGetData($strctCount, "top",$i))
    Next

    [/autoit] [autoit][/autoit] [autoit]

    ;~ If Not @error Then
    ;~ $NrOfMonitors = $aMonitors[0][0]
    ;~ For $i = 1 To $NrOfMonitors
    ;~ $ResolutionX[$i] = $aMonitors[$i][0]
    ;~ $ResolutionY[$i] = $aMonitors[$i][1]
    ;~ $PositionX[$i] = $aMonitors[$i][2]
    ;~ $PositionY[$i] = $aMonitors[$i][3]
    ;~ Next
    ;~ EndIf
    Return $aMonitors
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func MonitorEnumProc($hMonitor, $hdcMonitor, $lprcMonitor, $dwData)
    Local $strctRECT = DllStructCreate("long left;long top;long right;long bottom", $lprcMonitor)
    Local $strctCount = DllStructCreate("uint Count;uint Width[12];uint Height[12];int left[12];int top[12]", $dwData)
    Local $iNumber = DllStructGetData($strctCount, "Count")
    Local $Height = Int(DllStructGetData($strctRECT, "bottom"))-Int(DllStructGetData($strctRECT, "top"))
    Local $Width = Int(DllStructGetData($strctRECT, "right"))-Int(DllStructGetData($strctRECT, "left"))

    DllStructSetData($strctCount, "Width", $Width, $iNumber+1)
    DllStructSetData($strctCount, "Height", $Height, $iNumber+1)
    DllStructSetData($strctCount, "left", Int(DllStructGetData($strctRECT, "left")), $iNumber+1)
    DllStructSetData($strctCount, "top", Int(DllStructGetData($strctRECT, "top")), $iNumber+1)
    DllStructSetData($strctCount, "Count", $iNumber+1)
    Return True
    EndFunc

    [/autoit]

    Diese Funktionen alleine stürzen nicht ab. Doch zusammen mit irgendwelchen anderen Dingen von mir dann schon.....
    Das Problem ist vermutlich, dass diese Funktion alle 500ms ausgeführt wird (Interrupt). Wenn dann das Programm genau in einer "kritischen" Phase ist....

    Sieht jemand etwas kritisches an diesen Programmteilen?
    Gruss
    Veronesi

  • Nein, leider reicht das nicht.
    An diesen (Prüfcomputer) werden im laufenden Betrieb (zum testen von Produkten) Monitore angeschlossen und wieder abgehängt.
    Da der PC 4 Grafikkarten hat, aber (aus Platzgründen) nur zwei Monitore, sind immer zwei Grafikkarten Ausgänge zur Zeit nicht belegt.

    Zuerst muss der Benutzer 2x Digital mit dem Produkt prüfen, dann 2x Analog. Wenn er die Monitore an die anderen Grafikkarten anschliesst, dann sieht er logischerweise das erste Bild nicht mehr.
    Dann sieht er auch das GUI mit den weiteren Anweisungen nicht mehr. Deshalb kann er dann nur die Maus verschieben und dann kommt automatisch das GUI.

    (blind mit Tastenkombinationen das Fenster in den sichtbaren Bereich schieben kann ich den Benutzern nicht zumuten.)

    Aber es muss nicht zwingend 500ms sein. 1000ms oder notfalls 2000ms gehen auch. Trotzdem tritt der Effekt auf!

    Gruss
    Veronesi

  • So, für den Moment konnte ich das Problem lösen.
    Viele von meinen Prüfungen sind automatisiert. Dort habe ich den Interrupt nun abgeschaltet, da der Benutzer sowieso nichts machen muss (ausser Sekundenbruchteile zu warten).

    In den Prüfungen, in welchen der Benutzer etwas machen muss, schalte ich den Interrupt kurz ein und am Ende wieder aus.

    Trotzdem wäre es schön, wenn man solche Hard-Crashes irgendwie abfangen und behandeln könnte!

    Grüsse
    Veronesi

  • Und weiter geht's mit Aufnahmeproblemen :)

    Anbei mein zusammengekürztes Teil-Script, damit man mit möglichst wenig Code mein Problem analysieren kann:

    Spoiler anzeigen
    [autoit]

    #include "Include\Bass.au3"
    #include "Include\BassConstants.au3"
    #include "Include\BassEnc.au3"
    Dim $File = @TempDir & "\1kHz.wav"

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(0,"",CheckAudio(50))

    [/autoit] [autoit][/autoit] [autoit]

    Exit

    [/autoit] [autoit][/autoit] [autoit]

    Func CheckAudio($Tolerance) ;Check for Audio
    Local $hRecord, $hMusic, $iFreqOut, $iFreqIn, $TimerAudio

    [/autoit] [autoit][/autoit] [autoit]

    FileInstall("Include\1kHz.wav", @TempDir & "\1kHz.wav", 1)
    FileInstall("Include\bass.dll", @TempDir & "\bass.dll", 1)
    FileInstall("Include\basscb.dll", @TempDir & "\basscb.dll", 1)
    FileInstall("Include\bassenc.dll", @TempDir & "\bassenc.dll", 1)

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_STARTUP(@TempDir & "\BASS.dll") ;Open Bass.DLL.
    _BASS_Init(0, 1, 44100, 0, "") ;Initalize bass.
    If @error Then
    Return -1
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_RecordInit(0)
    If @error Or _BASS_RecordGetDevice() > 10 Or _BASS_RecordGetDevice() < 0 Then
    Return -2
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_RecordSetInput(0, $BASS_INPUT_ON, -1)
    $hRecord = _BASS_RecordStart(44100, 2, 0)
    $hMusic = _BASS_StreamCreateFile(False, $File, 0, 0, 0) ;Set handle for 1kHz. Music File

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_ChannelPlay($hMusic, 1) ;Play 1kHz. Music-File
    $TimerAudio = TimerInit()
    While _BASS_ChannelIsActive($hMusic) = $BASS_ACTIVE_PLAYING ;While playing get frequency of Line-Out and Line-In
    $iFreqOut = GetFreq($hMusic)
    $iFreqIn = GetFreq($hRecord)
    ;~ ToolTip("Frequenz Out: " & $iFreqOut & @LF & "Frequenz In: " & $iFreqIn)
    If TimerDiff($TimerAudio) > 1500 Then ExitLoop
    Sleep(50)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    _BASS_Free()
    _BASS_RecordFree()

    [/autoit] [autoit][/autoit] [autoit]

    If $iFreqOut + $Tolerance > $iFreqIn And $iFreqOut - $Tolerance < $iFreqIn And $iFreqOut < 1100 And $iFreqOut > 900 Then ;If both frequencies are +/- the same and the Output frequency is +/- 1kHz. then it's OK!
    Return 1
    ElseIf $iFreqOut > 1100 Or $iFreqOut < 900 Then
    Return -3
    Else
    Return -4
    EndIf
    EndFunc ;==>CheckAudio

    [/autoit] [autoit][/autoit] [autoit]

    Func GetFreq($hHandle)
    Local $TmpData = 0, $TmpNr = 0, $fft = 0
    Local $fftstruct = DllStructCreate("float[4096]")
    _BASS_ChannelGetData($hHandle, DllStructGetPtr($fftstruct), $BASS_DATA_FFT8192)
    For $i = 0 To 4095
    $TmpData = Round(DllStructGetData($fftstruct, 1, $i + 1) * 100)
    If $TmpData > 0.2 And $fft < $TmpData Then ;Bestimme den Ort des Maximalwerts der FFT Analyse
    $fft = $TmpData
    $TmpNr = $i + 1
    EndIf
    Next
    Return Round(22000 / 4096 * $TmpNr) ;Max 22kHz.
    EndFunc ;==>GetFreq

    [/autoit]

    Damit kann ich (erfolgreich) ein 1kHz. File abspielen, es gleichzeitig "aufnehmen" und die Ein- und Ausgangsfrequenz analysieren.

    Nun sollte ich das noch erweitern können. Und zwar möchte ich beim Empfangen den linken und rechten Kanal getrennt analysieren können.

    Ich habe schon einiges getestet, doch leider bin ich nicht so recht weiter gekommen :(
    Besten Dank schon jetzt für Eure Hilfe !

    Grüsse
    Veronesi

    Einmal editiert, zuletzt von veronesi (24. April 2010 um 17:42)

  • Hi

    Sollte so funktionieren:

    [autoit]

    _BASS_ChannelSetAttribute($hMusic, $BASS_ATTRIB_PAN, -1)
    _BASS_ChannelPlay($hMusic, 1)

    [/autoit][autoit][/autoit][autoit]

    While _BASS_ChannelIsActive($hMusic) = $BASS_ACTIVE_PLAYING
    $iFreqOut = _GetFreq($hMusic)
    $iFreqIn = _GetFreq($hRecord)
    ToolTip("Frequenz Out: " & $iFreqOut & @LF & "Frequenz In: " & $iFreqIn)
    Sleep(100)
    WEnd

    [/autoit][autoit][/autoit][autoit]

    _BASS_ChannelSetAttribute($hMusic, $BASS_ATTRIB_PAN, 1)
    _BASS_ChannelPlay($hMusic, 1)

    [/autoit][autoit][/autoit][autoit]

    While _BASS_ChannelIsActive($hMusic) = $BASS_ACTIVE_PLAYING
    $iFreqOut = _GetFreq($hMusic)
    $iFreqIn = _GetFreq($hRecord)
    ToolTip("Frequenz Out: " & $iFreqOut & @LF & "Frequenz In: " & $iFreqIn)
    Sleep(100)
    WEnd

    [/autoit]

    mfgE

  • Hallo Eukalyptus,

    vielen herzlichen Dank! Es funktioniert wie immer super!
    Den Befehl _BASS_ChannelSetAttribute habe ich wirklich übersehen. Hab ihn echt nicht gefunden!

    Nochmals Dankeschön!

    Gruss
    Veronesi