Midi Udf

  • Ja dies ist eine Midi UDF!
    Falls jemand nicht weiß was Midi bedeutet Wikipedia:
    MIDI [ˈmiːdiˑ] (engl.: musical instrument digital interface [ˈmjuːzɪkl̩ ˈɪnstɹəmənt ˈdɪdʒɪtl̩ ˈɪntɚfeɪs] = „Digitale Schnittstelle für Musikinstrumente“) ist ein Datenübertragungs-Protokoll zum Zwecke der Übermittlung musikalischer Steuerinformationen zwischen elektronischen Instrumenten wie Keyboards, Synthesizern, Drumcomputern oder auch PCs bzw. Laptops.

    Diese UDF enthält alle Midi Funktionen von Windows (hoffentlich) alle nötigen Konstanten und zudem eine Umfangreiche Erklährung (Auf Englisch ich hatte keine Lust alles zu Übersetzen kommt aber noch)

    Die UDF ist noch unvollständig, das heißt zur zeit sind nur alle DllCall befehle drin
    An einer Einfacheren Version wird auch gearbeitet

    Wer möchte kann sich ja gerne daran Versuchen

    Midi fix by Eukalyptus
    MidiIn Example by Eukalyptus

    Und nochmals Danke an Eukalyptus

    Vorherige Downloads: 27

  • Im englischen Forum gibt es bereits eine MIDI-UDF (http://www.autoitscript.com/forum/topic/37…post__p__274785).
    Hab mir die Unterschiede der beiden UDFs aber nicht angeschaut.

    Auf jeden Fall kann man damit tolle Sachen machen!

    Spoiler anzeigen
    [autoit]

    #include <Misc.au3>

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

    Global $hWinmm_dll = DllOpen("winmm.dll")
    Global $open = _midiOutOpen(0)

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

    For $i = 27 To 87
    _midiOutShortMsg($open, 0x99 + ($i * 256) + (127 * 0x10000))
    Sleep(200)
    Next

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

    _midiOutClose($open)
    DllClose($hWinmm_dll)

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

    Func _midiOutOpen($devid = 0, $callback = 0, $instance = 0, $flags = 0)
    Local $ret = DllCall($hWinmm_dll, "long", "midiOutOpen", "uint*", 0, "int", $devid, "ptr", $callback, "ptr", $instance, "ptr", $flags)
    If Not @error Then
    Return $ret[1]
    Else
    Return SetError(1, 0, $ret[0])
    EndIf
    EndFunc ;==>_MidiOutOpen

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

    Func _midiOutClose($hmidiout)
    Local $ret = DllCall($hWinmm_dll, "long", "midiOutClose", "long", $hmidiout)
    If Not @error Then Return $ret[0]
    EndFunc ;==>_MidiOutClose

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

    Func _midiOutShortMsg($hmidiout, $msg)
    Local $ret = DllCall($hWinmm_dll, "long", "midiOutShortMsg", "ptr", $hmidiout, "dword", $msg)
    If Not @error Then Return $ret[0]
    EndFunc ;==>_MidiOutShortMsg

    [/autoit] [autoit][/autoit] [autoit][/autoit]
  • Ja ich weis doch leider ist das Script nur eine übersetzung der Orginalen Source von MSDN, enthält daher noch einige Fehler.

    Einmal editiert, zuletzt von TheDearDead (11. April 2012 um 18:11)

  • Habe über 6.000 Midi-Dateien und ganz viele incl. Songtext als TXT-Datei.
    Sogar sortiert nach Interpreten bzw. Songtitel.

    Habe ich mal von einem Kollegen bekommen und konnte ich nie was mit anfangen. Kann es eigentlich jetzt auch nicht, da ich gar nicht weiß was ich damit machen soll. 0,5 GB halt die ich noch nicht entsorgen möchte.

    Lieben Gruß,
    Alina

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Geheime Information: ;)
    OuBVU5ebLhHu5QvlnAyQB4A7SzBrvWulwL7RLl2BdH5tI6sIYspeMKeXMSXl


  • Habe über 6.000 Midi-Dateien und ganz viele incl. Songtext als TXT-Datei.
    Sogar sortiert nach Interpreten bzw. Songtitel.

    Habe ich mal von einem Kollegen bekommen und konnte ich nie was mit anfangen. Kann es eigentlich jetzt auch nicht, da ich gar nicht weiß was ich damit machen soll. 0,5 GB halt die ich noch nicht entsorgen möchte.


    Nunja es gibt einen unterschied zwischen .mid datein und MIDI (.mid datein waren der Grund wieso ich angefangen habe xD) ich versuche immer noch die Kodierung von .mid herauszufinden, um sie z.B. wie bei Synthesia mit der Maus nachklicken zu können, oder anders abspielen mit eigenen Musikdatein oder Konvertierung in MP3, usw. ist halt noch viel zu tun)

  • Viel interessanter als Midi Dateien finde ich die Steuerung von Midifähigen Geräten, bzw. die Steuerung vom AutoItscript durch Midi Controller.
    Darin hab ich etwas Erfahrung und kann auch mal ein Beispiel schreiben, wenn ich Zeit finde...

    2 Sachen musst du unbedingt noch einbauen:
    @error-check bzw. IsArray($ret)-check bei den DllCalls; sonst führt das evtl zu einem Scriptabsturz, wenn du direkt danach $ret[0] verwendest...

    $ret als Local deklarieren - Die UDF muss auch mit Opt("MustDeclareVars", 1) funktionieren.

    Ansonsten schon mal ganz ordendlich! :thumbup:

    E

  • Yes! Eine Message von eukalyptus! Sorry, okay werd ich gleich mal machen bin noch etwas mit meinen Anderen Projekten beschäftigt xD

  • Hier hab ich ein Midi-In-Beispiel:
    es werden 2 Buffer verwendet und die Daten via RegisterMsg empfangen (CALLBACK_WINDOW)

    So lassen sich AutoIt Scripte relativ einfach über einen MIDI-Controller steuern.

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <WinAPI.au3>
    #include <MIDI.au3>

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

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

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

    Global $hGui = GUICreate("Midi In Example", 1000, 420)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    Global $cCombo = GUICtrlCreateCombo("", 10, 10, 400, 20)
    Global $cButton_Start = GUICtrlCreateButton("Start", 420, 10, 80, 20)
    GUICtrlSetOnEvent(-1, "_Midi_Start")
    Global $cButton_Stop = GUICtrlCreateButton("Stop", 510, 10, 80, 20)
    GUICtrlSetOnEvent(-1, "_Midi_Stop")
    GUICtrlCreateLabel("MIM_DATA", 10, 40, 100, 20)
    Global $cEdit_Data = GUICtrlCreateEdit("", 10, 60, 485, 350)
    GUICtrlCreateLabel("MIM_LONGDATA", 505, 40, 100, 20)
    Global $cEdit_LongData = GUICtrlCreateEdit("", 505, 60, 485, 350)
    GUISetState()

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

    _Midi_Startup()
    Global $tBuffer1 = _CreateBuffer()
    Global $tBuffer2 = _CreateBuffer()
    _GetDevices()

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

    Global $hMidi = 0
    Global $bRelease = False
    Global $iDeviceCurrent = -1

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

    GUIRegisterMsg($MM_MIM_CLOSE, "_MidiWinProc")
    GUIRegisterMsg($MM_MIM_DATA, "_MidiWinProc")
    GUIRegisterMsg($MM_MIM_ERROR, "_MidiWinProc")
    GUIRegisterMsg($MM_MIM_LONGDATA, "_MidiWinProc")
    GUIRegisterMsg($MM_MIM_LONGERROR, "_MidiWinProc")
    GUIRegisterMsg($MM_MIM_MOREDATA, "_MidiWinProc")
    GUIRegisterMsg($MM_MIM_OPEN, "_MidiWinProc")

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

    While Sleep(100)
    WEnd

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

    Func _ProcessLongData($pData, $iBytes)
    Local $tGetData = DllStructCreate("byte[" & $iBytes & "];", $pData)
    GUICtrlSetData($cEdit_LongData, DllStructGetData($tGetData, 1) & @CRLF, 1)
    EndFunc ;==>_ProcessLongData

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

    Func _ProcessData($iMidiMessage)
    Local $iLoWord = _WinAPI_LoWord($iMidiMessage)
    Local $iHiWord = _WinAPI_HiWord($iMidiMessage)

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

    Local $bStatus = BitAND($iLoWord, 0xFF) ;LoByte
    Local $bData1 = BitShift($iLoWord, 8) ;HiByte
    Local $bData2 = BitAND($iHiWord, 0xFF) ;LoByte

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

    Local $Chan = BitAND($bStatus, 0xF)
    Local $MidiMsg = BitShift($bStatus, 4)

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

    GUICtrlSetData($cEdit_Data, "StatusByte: " & $bStatus & @TAB & "DataByte1: " & $bData1 & @TAB & "DataByte2: " & $bData2 & @CRLF, 1)

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

    Switch $MidiMsg

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

    Case 0x8 ; Note Off
    GUICtrlSetData($cEdit_Data, @TAB & "NoteOff: MidiChannel: " & $Chan & @TAB & "NoteNumber: " & $bData1 & @TAB & "Velocity: " & $bData2 & @CRLF, 1)

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

    Case 0x9 ; Note On
    GUICtrlSetData($cEdit_Data, @TAB & "NoteOn: MidiChannel: " & $Chan & @TAB & "NoteNumber: " & $bData1 & @TAB & "Velocity: " & $bData2 & @CRLF, 1)

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

    Case 0xA ; Polyphonic aftertouch
    GUICtrlSetData($cEdit_Data, @TAB & "Polyphonic aftertouch: MidiChannel: " & $Chan & @TAB & "NoteNumber: " & $bData1 & @TAB & "Poly Pressure: " & $bData2 & @CRLF, 1)

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

    Case 0xB ; Control Change
    GUICtrlSetData($cEdit_Data, @TAB & "Control Change: MidiChannel: " & $Chan & @TAB & "Controller: " & $bData1 & @TAB & "Value: " & $bData2 & @CRLF, 1)

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

    Case 0xC ; Program Change
    GUICtrlSetData($cEdit_Data, @TAB & "Program Change: MidiChannel: " & $Chan & @TAB & "Programm: " & $bData1 & @CRLF, 1)

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

    Case 0xD ; Channel aftertouch
    GUICtrlSetData($cEdit_Data, @TAB & "Channel aftertouch: MidiChannel: " & $Chan & @TAB & "Aftertouch : " & $bData1 & @CRLF, 1)

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

    Case 0xE ; Pitch Bend
    GUICtrlSetData($cEdit_Data, @TAB & "Pitch Bend: MidiChannel: " & $Chan & @TAB & "LSB: " & $bData1 & @TAB & "MSB: " & $bData2 & @CRLF, 1)

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

    EndSwitch

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

    EndFunc ;==>_ProcessData

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

    Func _MidiWinProc($hWnd, $iMsg, $wParam, $lParam)
    Switch $iMsg
    Case $MIM_OPEN
    ConsoleWrite("> MIM_OPEN" & @CRLF)

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

    Case $MIM_CLOSE ;hMidi Handle ab jetzt ungültig
    ConsoleWrite("> MIM_CLOSE" & @CRLF)
    $hMidi = 0

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

    Case $MIM_DATA ; Normale Midi MSG
    ConsoleWrite("> MIM_DATA" & @CRLF)
    _ProcessData($lParam)

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

    Case $MIM_MOREDATA
    ConsoleWrite("> MIM_MOREDATA" & @CRLF)

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

    Case $MIM_LONGDATA
    ConsoleWrite("> MIM_LONGDATA" & @CRLF)

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

    Switch $bRelease
    Case False ; SysEx Daten kommen rein
    Local $tMidiHDR = DllStructCreate($MIDIHDR, $lParam)
    Local $iBytesRecorded = DllStructGetData($tMidiHDR, "dwBytesRecorded")
    ConsoleWrite("+ LONGDATA IN: " & $iBytesRecorded & " bytes" & @CRLF)

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

    _ProcessLongData(DllStructGetData($tMidiHDR, "lpData"), $iBytesRecorded)

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

    _MidiIn_AddBuffer($hMidi, $lParam, 48)

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

    Case Else ; Druch _MidiIn_Reset wird hier der Buffer zurückgegeben und muss hier "unprepared" werden
    ConsoleWrite("! Unprepare Buffer" & @CRLF)
    _MidiIn_UnprepareHeader($hMidi, $lParam, 48)

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

    EndSwitch

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

    Case $MIM_ERROR
    ConsoleWrite("> MIM_ERROR" & @CRLF)

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

    Case $MIM_LONGERROR
    ConsoleWrite("> MIM_LONGERROR" & @CRLF)
    _MidiIn_AddBuffer($hMidi, $lParam, 48)

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

    EndSwitch
    EndFunc ;==>_MidiWinProc

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

    Func _Midi_Start()
    ConsoleWrite(@CRLF & "!=============================" & @CRLF)
    ConsoleWrite("! starting..." & @CRLF & @CRLF)
    Local $aRegExp = StringRegExp(GUICtrlRead($cCombo), "<(\d+)>", 3)
    If @error Or Not IsArray($aRegExp) Then Return
    Local $iDevice = $aRegExp[0]

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

    If $iDevice = $iDeviceCurrent Then
    ConsoleWrite("- already running" & @CRLF)
    Return
    EndIf

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

    $bRelease = False

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

    Local $iRet

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

    If $hMidi <> 0 Then _Midi_Stop()
    $hMidi = _MidiIn_Open($iDevice, $hGui, 0, BitOR($CALLBACK_WINDOW, $MIDI_IO_STATUS))
    ConsoleWrite("! MidiIn Open: " & $hMidi & " error: " & @error & @CRLF)
    $iDeviceCurrent = $iDevice

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

    $iRet = _MidiIn_PrepareHeader($hMidi, DllStructGetPtr($tBuffer1, "lpData"), 48)
    ConsoleWrite("! Prepare Header: " & $iRet & " error: " & @error & @CRLF)
    $iRet = _MidiIn_PrepareHeader($hMidi, DllStructGetPtr($tBuffer2, "lpData"), 48)
    ConsoleWrite("! Prepare Header: " & $iRet & " error: " & @error & @CRLF)

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

    $iRet = _MidiIn_AddBuffer($hMidi, DllStructGetPtr($tBuffer2, "lpData"), 48)
    ConsoleWrite("! Add Buffer: " & $iRet & " error: " & @error & @CRLF)
    $iRet = _MidiIn_AddBuffer($hMidi, DllStructGetPtr($tBuffer1, "lpData"), 48)
    ConsoleWrite("! Add Buffer: " & $iRet & " error: " & @error & @CRLF)

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

    $iRet = _MidiIn_Start($hMidi)
    ConsoleWrite("! MidiIn Start: " & $iRet & " error: " & @error & @CRLF)

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

    EndFunc ;==>_Midi_Start

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

    Func _Midi_Stop()
    ConsoleWrite(@CRLF & "!=============================" & @CRLF)
    ConsoleWrite("! stopping..." & @CRLF & @CRLF)

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

    $bRelease = True

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

    Local $iRet
    $iRet = _MidiIn_Reset($hMidi)
    ConsoleWrite("! MidiIn Reset: " & $iRet & " error: " & @error & @CRLF)
    $iRet = _MidiIn_Stop($hMidi)
    ConsoleWrite("! MidiIn Stop: " & $iRet & " error: " & @error & @CRLF)
    $iRet = _MidiIn_Close($hMidi)
    ConsoleWrite("! MidiIn Close: " & $iRet & " error: " & @error & @CRLF)

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

    $iDeviceCurrent = -1
    EndFunc ;==>_Midi_Stop

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

    Func _GetDevices()
    Local $tMidiInCaps = DllStructCreate($MIDIINCAPS)
    Local $pMidiInCaps = DllStructGetPtr($tMidiInCaps)
    Local $iMidiInCaps = DllStructGetSize($tMidiInCaps)

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

    Local $iDeviceCnt = _MidiIn_GetNumDevs()
    Local $sDevice = ""
    Local $sDefault = ""

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

    For $i = 0 To ($iDeviceCnt - 1)
    _MidiIn_GetDevCaps($i, $pMidiInCaps, $iMidiInCaps)
    $sDevice &= "<" & $i & "> " & DllStructGetData($tMidiInCaps, "szPname") & "|"
    If $i = 0 Then $sDefault = "<" & $i & "> " & DllStructGetData($tMidiInCaps, "szPname")
    Next

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

    GUICtrlSetData($cCombo, $sDevice, $sDefault)
    EndFunc ;==>_GetDevices

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

    Func _CreateBuffer($iSize = 256, $iID = 0)
    Local $tBuffer = DllStructCreate("uint BufferSize; byte BufferData[" & $iSize & "];" & $MIDIHDR)

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

    DllStructSetData($tBuffer, "BufferSize", $iSize)
    DllStructSetData($tBuffer, "lpData", DllStructGetPtr($tBuffer, "BufferData"))
    DllStructSetData($tBuffer, "dwBufferLength", $iSize)
    DllStructSetData($tBuffer, "dwUser", $iID)

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

    Return $tBuffer
    EndFunc ;==>_CreateBuffer

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

    Func _Exit()
    Exit
    EndFunc ;==>_Exit

    [/autoit]

    Ich hab auch die MIDI.au3 etwas angepasst: autoit.de/wcf/attachment/15614/
    und zwar die DllCall-Return Variable: Local $aResult
    und eine errorabfrage

    Ich würde auch immer $aResult[0] als Rückgabewert verwenden:

    [autoit]

    Switch $aResult[0]
    Case 0 ;$MMSYSERR_NOERROR
    Return $aResult[0]
    Case Else
    Return SetError(1, 0, $aResult[0])
    EndSwitch

    [/autoit]

    Falls du dein System beibehalten willst, dann verwende aber trotzdem Switch statt If:

    [autoit]

    Switch $aResult[0]
    Case $MMSYSERR_NOERROR
    Return 1
    Case $MMSYSERR_INVALHANDLE
    Return SetError(1,1,0)
    Case $MMSYSERR_INVALPARAM
    Return SetError(2,2,0)
    Case $MMSYSERR_NOMEM
    Return SetError(3,3,0)
    Case Else
    Return SetError(4,4,0)
    EndSwitch

    [/autoit]

    E

  • Danke eukalyptus für deine Antwort! Ich hatte in letzter Zeit ziemlich viel um die Ohren konnte deshalb bei keinem meiner Skripte weiterarbeiten, werde aber so früh wie möglich wieder anfangen. Hab da noch so ein paar andere Projekte offen, zudem wollte ich noch XNA lernen. Puh!

  • Greetings. I apologize for posting in English, and I apologize for resurrecting such an old thread. I found this UDF and I was able to work with it, unlike the MIDIudf.udf that is on the other forum.

    Is anyone still working on this UDF? I find that it locks up after knobs are moved a few times and MIDI cc messages are consistently coming in. And not fast and furious. Just after about six or sever different controller knobs have been adjusted, it'll freeze. Has anyone else experienced that? Is there a fix? This UDF is much easier for me to use for the project I have in front of me. I'd really like it to work. But it does freeze, and I've tried it on two computers, both Windows 7 and WIndows 10, and three different controllers.

    THANK YOU.

  • NEVER MIND! I changed the script so that the edit box was cleared every time the MIDI CC was changed and it stopped crashing. My apologies again. It isn't the UDF. It's the test script edit box filling up.