Sinus Sweep berechnen?

  • Hi

    Ich will einen Sinus-Verlauf berechnen z.B.: 110Hz - 440Hz
    Das Ergebnis ist leider nicht korrekt: autoit.de/wcf/attachment/21482/

    Die ersten 4 Wellen sind richtig und zeigen eine Sinuskurve in 110, 220, 440 u 880Hz
    Die letzten 3 sind Sweeps und sollten jeweils bis 440Hz gehen, allerdings ist die Wellenlänge am Ende deutlich kürzer als erwartet.

    Weiß jemand, wie man solche Sweeps berechnet?


    Ein möglicher Lösungsansatz wäre:
    Immer eine ganze Schwingung mit gleicher Frequenz berechnen. Wellenlänge = Lambda = Samplerate / Frequenz.
    Die nächste Schwingung beginnt wieder im Nulldurchgang (Step (in meinem Script "$j") beginnt jedesmal wieder bei 0)
    Das ist dann aber kein linearer Verlauf mehr!

    Es muss doch eine einfache Lösung geben?!

    Vielen Dank!

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>

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

    Opt("GUIOnEventMode", 1)
    Opt("MustDeclareVars", 1)

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

    Global Const $cPI = ATan(1) * 4
    Global Const $c2PI = $cPI * 2

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

    _GDIPlus_Startup()

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

    Global $iWidth = 800
    Global $iHeight = 600

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

    Global $hGui = GUICreate("AutoIt GDI+", $iWidth, $iHeight)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
    Global $hBmpBuffer = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
    Global $hGfxBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBuffer)
    _GDIPlus_GraphicsSetSmoothingMode($hGfxBuffer, 2)
    _GDIPlus_GraphicsClear($hGfxBuffer, 0xFFFFFFFF)

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

    Global $hPen = _GDIPlus_PenCreate(0xFFFF0000)

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

    GUIRegisterMsg($WM_PAINT, "_WM_PAINT")
    GUISetState()

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

    Global $tSine

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

    Global $aHz[3][2] = [[2]]
    $aHz[1][0] = 110
    $aHz[1][1] = 1
    $aHz[2][0] = 110
    $aHz[2][1] = 2000
    $tSine = _SineSweep($aHz)
    _DrawSine($aHz, $tSine, 80)

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

    $aHz[1][0] = 220
    $aHz[2][0] = 220
    $tSine = _SineSweep($aHz)
    _DrawSine($aHz, $tSine, 160)

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

    $aHz[1][0] = 440
    $aHz[2][0] = 440
    $tSine = _SineSweep($aHz)
    _DrawSine($aHz, $tSine, 240)

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

    $aHz[1][0] = 880
    $aHz[2][0] = 880
    $tSine = _SineSweep($aHz)
    _DrawSine($aHz, $tSine, 320)

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

    $aHz[1][0] = 110
    $aHz[2][0] = 440
    $tSine = _SineSweep($aHz)
    _DrawSine($aHz, $tSine, 400)

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

    Global $aHz[4][2] = [[3]]
    $aHz[1][0] = 110
    $aHz[1][1] = 1
    $aHz[2][0] = 220
    $aHz[2][1] = 1000
    $aHz[3][0] = 440
    $aHz[3][1] = 2000

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

    $tSine = _SineSweep($aHz)
    _DrawSine($aHz, $tSine, 480)

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

    $aHz[1][0] = 110
    $aHz[2][0] = 110
    $aHz[3][0] = 440

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

    $tSine = _SineSweep($aHz)
    _DrawSine($aHz, $tSine, 560)

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

    While 1
    Sleep(10)
    WEnd

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

    Func _DrawSine($aHz, $tSine, $iY, $fAmp = 16)
    Local $iSamples = DllStructGetData($tSine, "Cnt")
    Local $tCurve = DllStructCreate("float[" & $iSamples * 2 & "]")
    Local $fTmp

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

    For $i = 1 To $iSamples
    $fTmp = DllStructGetData($tSine, "Sine", $i) * $fAmp
    DllStructSetData($tCurve, 1, ($i - 1) / $iSamples * $iWidth, ($i - 1) * 2 + 1)
    DllStructSetData($tCurve, 1, $fTmp + $iY, ($i - 1) * 2 + 2)
    Next

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

    DllCall($ghGDIPDll, "uint", "GdipDrawCurve2", "hwnd", $hGfxBuffer, "hwnd", $hPen, "ptr", DllStructGetPtr($tCurve), "int", $iSamples, "float", 0.5)

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

    For $i = 1 To $aHz[0][0]
    _GDIPlus_GraphicsDrawString($hGfxBuffer, $aHz[$i][0] & "Hz", $aHz[$i][1] / $iSamples * ($iWidth - 40), $iY - $fAmp - 16)
    Next

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

    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    EndFunc ;==>_DrawSine

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

    Func _SineSweep($aHz, $fRate = 44100.0)
    Local $iCnt = $aHz[0][0]
    Local $iSamples = $aHz[$iCnt][1]

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

    Local $tSine = DllStructCreate("int Cnt; float Sine[" & $iSamples & "]")
    DllStructSetData($tSine, "Cnt", $iSamples)

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

    Local $fHZ_Start, $fHZ_End
    Local $iSmp_Start, $iSmp_End

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

    Local $fTmp, $fS

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

    For $i = 1 To $iCnt - 1
    $fHZ_Start = $aHz[$i][0]
    $fHZ_End = $aHz[$i + 1][0]
    ConsoleWrite("> Sweep: " & $fHZ_Start & "Hz -> " & $fHZ_End & "Hz" & " | " & $aHz[$i][1] & " -> " & $aHz[$i + 1][1] & @CRLF)

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

    For $j = $aHz[$i][1] To $aHz[$i + 1][1]
    $fTmp = $fHZ_Start + (($fHZ_End - $fHZ_Start) * ($j - $aHz[$i][1]) / ($aHz[$i + 1][1] - $aHz[$i][1]))
    ConsoleWrite("! Hz: " & $fTmp & @CRLF)
    $fS = Sin($j * $c2PI / ($fRate / $fTmp))
    DllStructSetData($tSine, "Sine", $fS, $j)
    Next
    Next

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

    Return $tSine
    EndFunc ;==>_SineSweep

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

    Func _WM_PAINT($hWnd, $iMsg, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_PAINT

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

    Func _Exit()
    _GDIPlus_PenDispose($hPen)

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

    _GDIPlus_GraphicsDispose($hGfxBuffer)
    _GDIPlus_BitmapDispose($hBmpBuffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    GUIDelete($hGui)
    Exit
    EndFunc ;==>_Exit

    [/autoit]
  • Danke! Das hat schonmal sehr geholfen!

    Aber ganz korrekt ist deine Berechnung auch nicht.
    Wenn du in deiner Darstellung den Zeitbereich von 2.5 bis 3 betrachtest, dann siehst du dort etwa 4 Schwingungen = 8 Schwingungen / Sekunde

    Deshalb musste ich "m" noch durch 2 Teilen um am Ende auf 4 Hz zu kommen.

    Warum ist das so?


    Hier mein Script dazu:

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>

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

    Opt("GUIOnEventMode", 1)
    Opt("MustDeclareVars", 1)

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

    Global Const $cPI = ATan(1) * 4
    Global Const $c2PI = $cPI * 2

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

    _GDIPlus_Startup()

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

    Global $iWidth = 800
    Global $iHeight = 600

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

    Global $hGui = GUICreate("AutoIt GDI+", $iWidth, $iHeight)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
    Global $hBmpBuffer = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
    Global $hGfxBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBuffer)
    _GDIPlus_GraphicsSetSmoothingMode($hGfxBuffer, 2)
    _GDIPlus_GraphicsClear($hGfxBuffer, 0xFFFFFFFF)

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

    Global $hPen_R = _GDIPlus_PenCreate(0xFFFF0000)
    Global $hPen_G = _GDIPlus_PenCreate(0xFF00FF00)

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

    GUIRegisterMsg($WM_PAINT, "_WM_PAINT")
    GUISetState()

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

    Global $fFreqS = 1
    Global $fFreqE = 4
    Global $fTime = 3

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

    _DrawSine($fFreqS, $fTime, $iHeight * 0.25)
    _DrawSine($fFreqE, $fTime, $iHeight * 0.5)
    _DrawSineSweep($fFreqS, $fFreqE, $fTime, $iHeight * 0.75)

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

    While 1
    Sleep(10)
    WEnd

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

    Func _DrawSineSweep($fFreqS, $fFreqE, $fTime, $fYOff, $fAmp = 20)
    Local $fS, $fX1, $fY1, $fX2, $fY2
    $fX1 = 0
    $fY1 = $fYOff

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

    Local $iSteps = 2000
    Local $fW = $iWidth / $iSteps
    Local $fT = $fTime / $iSteps
    Local $fTmp, $fVal1, $fVal2

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

    $fVal1 = ($fFreqE - $fFreqS) / ($fTime)
    $fVal2 = $fFreqE - $fVal1 * $fTime
    $fVal1 /= 2

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

    ConsoleWrite("! " & $fVal1 & @CRLF)
    ConsoleWrite("! " & $fVal2 & @CRLF)

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

    For $i = 0 To $iSteps
    $fTmp = ($i * $fT)
    $fS = Sin($c2PI * $fTmp * ($fVal1 * $fTmp + $fVal2)) * $fAmp

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

    $fX2 = $i * $fW
    $fY2 = $fYOff + $fS
    DllCall($ghGDIPDll, "int", "GdipDrawLine", "handle", $hGfxBuffer, "handle", $hPen_R, "float", $fX1, "float", $fY1, "float", $fX2, "float", $fY2)
    DllCall($ghGDIPDll, "int", "GdipDrawEllipse", "handle", $hGfxBuffer, "handle", $hPen_G, "float", $fX2 - 1, "float", $fY2 - 1, "float", 2, "float", 2)
    $fX1 = $fX2
    $fY1 = $fY2
    Next
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    EndFunc ;==>_DrawSineSweep

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

    Func _DrawSine($fFreq, $fTime, $fYOff, $fAmp = 20)
    Local $fS, $fX1, $fY1, $fX2, $fY2
    $fX1 = 0
    $fY1 = $fYOff

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

    Local $iSteps = 2000
    Local $fW = $iWidth / $iSteps
    Local $fT = $fTime / $iSteps
    Local $fTmp

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

    For $i = 0 To $iSteps
    $fTmp = ($i * $fT)
    $fS = Sin($c2PI * $fTmp * $fFreq) * $fAmp

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

    $fX2 = $i * $fW
    $fY2 = $fYOff + $fS
    DllCall($ghGDIPDll, "int", "GdipDrawLine", "handle", $hGfxBuffer, "handle", $hPen_R, "float", $fX1, "float", $fY1, "float", $fX2, "float", $fY2)
    DllCall($ghGDIPDll, "int", "GdipDrawEllipse", "handle", $hGfxBuffer, "handle", $hPen_G, "float", $fX2 - 1, "float", $fY2 - 1, "float", 2, "float", 2)
    $fX1 = $fX2
    $fY1 = $fY2
    Next
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    EndFunc ;==>_DrawSine

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

    Func _WM_PAINT($hWnd, $iMsg, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_PAINT

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

    Func _Exit()
    _GDIPlus_PenDispose($hPen_R)
    _GDIPlus_PenDispose($hPen_G)

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

    _GDIPlus_GraphicsDispose($hGfxBuffer)
    _GDIPlus_BitmapDispose($hBmpBuffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    GUIDelete($hGui)
    Exit
    EndFunc ;==>_Exit

    [/autoit]

    Danke
    E

  • Das machen wir in Physik II auch grade :)
    Sehr schön hergeleitet und verständlich erklärt.
    Ich wünschte die Vorlesungsnotizen wären dementsprechend.
    Da steht dann nur: f(t) ist Zeitabhängig, "Lösungsweg trivial", Lösung

    lg
    M

  • Zitat

    Ich wünschte die Vorlesungsnotizen wären dementsprechend. Da steht dann nur: f(t) ist Zeitabhängig, "Lösungsweg trivial", Lösung

    Dann warte mal auf die Vorlesung Regelungstechnik, wenn du 4 DIN A4-Blätter quer aneinanderkleben musst, nur um die Gleichung draufzubekommen....Nach 1,5h ausmultiplizieren und umstellen raucht dir abends um 8 Uhr die Rübe, die Gleichung ist kaum kleiner geworden, und dann fällt vom Prof so ein knochentrockener Spruch: "Na meine Damen und Herren, wie lösen wir das Problem? Ganz einfach, bei Omega (oder war es t?? ) gleich unendlich führt die Funktion zu..........einer Spirale! Das sieht man doch auf den ersten Blick! Und nach einigen Sekunden schwingt sich das System ein, nächstes Thema!"