Jump to content

Midi UDF


MattyD
 Share

Recommended Posts

Hi all,

Attached below are two segments of this project.

The first "Midi API" is a wrap of the windows functions below.
https://docs.microsoft.com/en-us/windows/win32/multimedia/midi-functions

The second "Midi UDF" library is built on the first, and aims to provide a user friendly code base for people working with midi.
This UDF so far covers:

  • Channel Voice and Mode Messaging
  • Registered Parameters (Channel Tuning, Mod Wheel/Pitch Bend ranges)
  • Some prolific Non-Registered Parameters.
    • Drum editing
    • Envelope control
    • Vibrato control
    • Filter control
  • General SysEx messaging
  • Roland Data Transfer (DT1/RQ1)
  • Yamaha XG Data Transfer & SysEx Parameter Control
  • Global parameter control (GM2 Reverb & Chorus control)
  • Device Control (Master Volume/Balance/Tuning)
  • Octive/Scale Tuning
  • Controller Destination settings (aftertouch/cc modulation editing)
  • Active Sensing for Output Devices
  • 3D Sound Controllers
  • Importing and exporting midi files (experimental)
  • Recording midi event sequences. (experimental)

Midi Machine and Show Control are not currently supported by the UDF.

 

Thank yous

A quick shoutout shoutout to Water and Mr_Creator for the Simple Library Docs Generator - which was the originaly the basis of the helpfiles. 
Also a double to Water for the advanced help example (f1 key integration with scite).


A couple of notes on synths.

I've based the UDF on a couple of different RPs published many years apart, so implementation can be quite instrument specific.
Don't expect too much of the builtin MS Wavetable Synth! I've had some more joy with the coolsoft midisynth if anyone is looking for a free alternative to test with.

The two software synths mentioned above are also very slow responding to midi messages. If you forward messages to a physical instrument you should be able to play in real time.

 

Previous versions:

If anyone is after a previous release, they are all available on the sourceforge page.

 

 

 

midi.zip

Edited by MattyD
Link to comment
Share on other sites

MattyD

I just found your posting and I am most grateful, I've been hoping for something like this for a very long time. I enjoy working with AutoIt but have never able to use it much with midi. Since I'm not a programmer I often use something else for the midi parts and AutoIt for most everything else. (Not the greatest way of doing things - it gets surprisingly messy.) I've been running your examples all morning and and have not had even the smallest of issues. Your work on this is top shelf and your commitment to it's thorough development is blatantly obvious. As to your mention of a second layer, I very much look forward to seeing it. I'm sure that whatever you come up with will make a great addition to the AutoIt language. Please keep up your great work.

Link to comment
Share on other sites

  • 4 weeks later...

I was playing with the excellent new "midiAPI" today and I found I had to add a line for the sake of
one of the functions. I could not get _midiAPI_InGetNumDevs to tell me how many devices I had until I
added:

    Global Const $__g_hWinMMDll = DllOpen("winmm.dll")
        
I found "$__g_hWinMMDll" listed as a global variable at the top of midiAPI.au3 but not in midiAPIConstants.
Just thought you'd like know.

I was taking my project forward this morning when I found the  _MidiInStart() & _MidiInStop() functions. My apologies for my mistake and solemnly swear to not do it again. I should have gone a little farther yesterday, I've never used  MidiInStart/Stop in this or any other way. They say "You can learn something new every day" but what they don't tell you is you have to have your head outside of your own butt  to thoroughly benefit from the experience. 

 

Edited by JAPP
Correction
Link to comment
Share on other sites

  • 2 weeks later...

Hi folks.

First release of the general midi UDF.

The underlying API library is pretty much unchanged and bedded down, but the UDF I would treat as a "beta" at this stage.
The functions themselves shouldn't be too buggy, but I haven't really proofed the doco as of yet so hopefully it makes sense!

Any comments, thoughts, suggestions for change are most welcome. Hopefully no fundemental changes are needed, but I'd like to stamp out anything that is particularly bad or nonsensical while the project is young.

Enjoy!

Link to comment
Share on other sites

Hi all - quick heads up,

There are a couple of silly things that have been corrected since yesterday around doco, calltips and one of the examples.

I'm sure there'll be a few more, so for now I won't make an announcement every time I release for these minor fixes. I will keep try to keep the changelog up to date though.

Any changes or additions to the actual code (beyond a tidyup) will still get a special mention.

Link to comment
Share on other sites

Just a couple of small changes today.

UDF v1.2

- Added "address" and "size" un/packing functions to complement the existing SysEx data transfer functions.
(Roland DT1/RQ1, XG Data Dump etc.)
- Added functions for retrieving names from midi device handles
- Fixed scite integration script stripping out _midiAPI_* keywords/calltips instead of old _midi_* ones.
- Fixed _midi_SetDrumLevel example refrencing a non-exsiting function

Link to comment
Share on other sites

Version UDF 1.4 release:

This release is mainly around better GM2 support.
There are a couple of script breaking things this time around (sorry), though I've tried to keep this at a minimum.

- Removed the notification window parameter when opening devices (moved to _midi_Startup).
- Common patchs are better supported with the new functions, GM2 patch names are now inbult and can be filtered by category.
- Modified some GM1 $PGM_* (program) names to bring into line with the new GM2 $PAT_* (patch) definitions.
- Fixed/added a few other constants to better suit modern implementations
- extended $NTE_* (note) constants for better GM2 compatability, added $NTE_* constants for the SFX rhythm percussion set.

Link to comment
Share on other sites

  • 3 weeks later...

@MattyD Thanks for this wonderful library! It was very easy to use it for creating the midi interface of the Peace equalizer. I only had to make one small adjustment in the library to make it work with the Peace source code architecture. Thanks 🙂

Creator of the Peace equalizer, an interface for Equalizer APO. Besides Peace, my library of functions is also available on SourceForge.

Link to comment
Share on other sites

Added your MIDI UDF to the wiki :)

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

  • 4 weeks later...

Hi MattyD, 

I noticed something strange ?

When I tried to create a MIDI debugger to read in / out messages.

I saw that the result from the MIDI UDF does not result the same byte values for the STATUS byte as I see with other debuggers.

In this example that output of the status byte is 176 which is 'B0' in Hex, but it should be 'BF' which is 191 Decimal. 

All the other values seem to be OK??

image.thumb.png.f8170a6b4356a03edc6e0a216352508c.png

Link to comment
Share on other sites

Hi MattyD, 

I checked as well the inbound as outbound messages and for both the STATUS byte is not showing correct ?

The other 3 bytes are fine.

Can you have a look to see if you have the same experience please.

It would be great the get the data correct of course.

Thanks !

 

Link to comment
Share on other sites

Hey ptrex

yeah so this was by design - If i've named that first element a "status byte" anywhere, I've got the doco wrong! The thought was to split the message type and channel up to make message filtering and editing super simple.

So $aMsg[0] is only the high 4 bits ($MSG_NOTE_ON, $MSG_CC etc.) and  $aMsg[1] is the 1-based channel number (low 4 bits + 1). Note also that $aMsg[2] holds the entire 14bit data value for pitch bends, so it should not be treated as the "second byte" of a short message.

I could add a flag to _midi_ReadMsg & _midi_SendMsg if its useful to have the actual 3 byte message as an array??

Otherwise its possible to use _midi_RegDebugFunc to grab the message in full as it comes in. - but if we're doing this, it may be better to just use the underlying "midiAPI" UDF.

 

 

Link to comment
Share on other sites

I'm a bit confused. Looking at this midi table I see that a control change is B0 (176) starting at channel 0. So BF (191) isn't right from a channel perspective? Your implementation seems to be the most logical one.

Creator of the Peace equalizer, an interface for Equalizer APO. Besides Peace, my library of functions is also available on SourceForge.

Link to comment
Share on other sites

Hi MattyD,

I checked again using the Midi_debug function and indeed the input shows correct ...

0x920009 = OFF

0x92097F = ON

Quote
Quote
>Running AU3Check (3.3.14.5)  from:C:\Program Files (x86)\AutoIt3  input:C:\_\Apps\AutoIT3\UDF's\Sound\Midi\UDF\_midi_ReadMsg Test MIXXX.au3
+>11:23:13 AU3Check ended.rc:0
>Running:(3.3.14.5):C:\Program Files (x86)\AutoIt3\autoit3.exe "C:\_\Apps\AutoIT3\UDF's\Sound\Midi\UDF\_midi_ReadMsg Test MIXXX.au3"    
--> Press Ctrl+Alt+Break to Restart or Ctrl+Break to Stop
In: 0x920009
 Status 144 Ctrl 9 Value 0 Channel 3
In: 0x92097F
 Status 144 Ctrl 9 Value 127 Channel 3
In: 0x920900
 Status 144 Ctrl 9 Value 0 Channel 3
In: 0x92097F
 Status 144 Ctrl 9 Value 127 Channel 3
In: 0x920900
 Status 144 Ctrl 9 Value 0 Channel 3
In: 0x92097F
 Status 144 Ctrl 9 Value 127 Channel 3

 

 

Of course it would be nice to have this output correctly represented using the UDF.

If you don't mind to have the 'flag' introduced that would take away a lot of hassle to get everything translated in the script itself back and forth.

 

Hi PeterVerbeek,

Not all hardware in the market is keeping to the MIDI standards unfortunately.

That's why I am writing the debug script to analyse the input and output messages ...

 

 

Link to comment
Share on other sites

@ptrex You're right of course. It's a bit messy out there 😀 I do hope B0 isn't changed to BF. If so, the existing users of the Peace midi panel have to set up their controllers again. On the other hand I don't expect to have many midi users by now. I presume it to be lower than 100.

Creator of the Peace equalizer, an interface for Equalizer APO. Besides Peace, my library of functions is also available on SourceForge.

Link to comment
Share on other sites

Hi Peter,

Indeed there will be a very limited nr. of users digging in this deep into the MIDI protocol. 🙂

Since I am debugging DJ controllers which don't respect the MIDI protocol at all ... I need to read the in and out messages from scratch to do the MIDI mapping.

 

@MattyD,

In the mean time I wrote a quick helper function for the read message 

 

; Split Hex Message in 3 Bytes 0x92097F"

Local $Input = "0x92097F"
Local Static $tMsg = DllStructCreate("byte[3]")

DllStructSetData($tMsg, 1, $Input)

$ret1 = DllStructGetData($tMsg, 1,3)
$ret2 = DllStructGetData($tMsg, 1,2)
$ret3 = DllStructGetData($tMsg, 1,1)

;~ DllStructGetData is in Reverse Order
ConsoleWrite($ret1 & $ret2 & $ret3 & @CRLF)

Local $Array[3]

$Array[0] = DllStructGetData($tMsg, 1, 3)
$Array[1] = DllStructGetData($tMsg, 1, 2)
$Array[2] = DllStructGetData($tMsg, 1, 1)

For $i = 0  to 2
    ConsoleWrite($Array[$i] & @CRLF)
Next

 

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...