Need a little help with Midi In Anyone ??

Started by wadmixfm, August 27, 2024, 21:08:51

Previous topic - Next topic

wadmixfm

Hello again , here is my scenario

what i am trying to achieve is

Using a daw something like Reaper or anything you prefer cubase cakewalk anything as long as it transmits midi timecode or sync

what i am looking for is a way to detect the midi clock from the daw and display it on a program created with Blitzmax

i am using reaper on the mac with a virtual midi device so reaper can transmit through this to a program written in blitzmax

when the Daw starts playing it then starts the program written with blitzmax

i have tried the example that comes with RTMidi and used the midi in.bmx and it does detect the clock as 248 Timestamp

but when i try to use that timestamp to do something in my program i can't get it to do anything.

can someone please point me in the right direction

Lee

p.s hope this makes sense

Yes its really me :)

Midimaster

#1
The 248 is a clock message. It tells you nothing about start, end or position in a song. It has no content no second or third byte!

248 is a continuous message, to which you can listen as a metronom tick. Every time it ticks a 1/24 of a quarter note has passed. Something like a 1/96 note metronom. Anywhere in your MIDI system is a sequencer (MASTER) that has a given TEMPO. This device sends those ticks to inform the others (SLAVES) about music speed

It is the base for all timing based calculations in MIDI. Measure the time it takes for 24 messages to arrive... and you know the msec time for a Quarter note.

here is a very simplified example:

SuperStrict
Import Audio.Midi

Graphics 400,300
Global Counter:Int=-1, StartTime:Int, QuarterTime:Int, Tempo:Int, Beat:Int
Global MidiIn:TMidiIn = New TMidiIn.Create()
MidiIn.OpenPort(0)

Repeat
    Cls
    Local stampvoid: Double
    Local Message:Byte[] = MidiIn.GetMessage(stampvoid)
    If Message[0]=248
        If Counter=-1
            StartTime   = MilliSecs()
            Beat        = 1
        EndIf
        Counter:+1       
        If Counter=24
            QuarterTime = MilliSecs()-StartTime
            Tempo       = 60000/QuarterTime
            Counter     = 0
            Beat        = Beat+1
            StartTime   = MilliSecs()
        EndIf
    EndIf
    DrawText "   Music TEMPO : " + Tempo + " bpm", 100,100
    DrawText "Quarter Length : " + QuarterTime + " msec", 100,130
    DrawText "Music Position : " + Beat + " Quarters", 100,160
    Flip 0
Until AppTerminate()
midiIn.Free()
End






...crossing the alps with my bike at the moment

wadmixfm

Oh wow ,thank you so much

Will try this out tonight

Cheers midimaster

Top star 🌟

Lee
Yes its really me :)

wadmixfm

Is the 24 sort of like 24.997 fps English and in the US 29.997

Or is it throughout ???

Lee
Yes its really me :)

Midimaster

#4
No, no! The 24 is a MIDI thing.  It is notation related and not fps related. So everywhere in the world it is the same.
The SENDER sends 24 of the 248-Events within one QUARTER note.

Why do the use 24?
MIDI uses a fine resolution of 24ticks/quarter note to be able to enable 1/32-notes also as 1/16-triblets.


MIDI note length in Ticks

a 1/4-note lasts 24 ticks
a 1/8-note lasts 12 ticks
a 1/16-note lasts 6 ticks

a 1/16-triplet-note lasts 4 ticks (3x4=12)
a  1/8-triplet-note lasts 8 ticks (3x8=24)

a complete 4/4-bar lasts 96 ticks


How long does it last to send 24 ticks?

In a tempo of 60bpm this sending needs 1000msec, means the intervall between each 248 is ~41.6msec (=1000/24)
 In a tempo of 120bpm this sending needs 500msec, means the intervall between each 248 is ~20.8msec (=500/24)
In a tempo of 240bpm this sending needs 250msec, means the intervall between each 248 is ~10.4msec (=250/24)


So you see, it has nothing to do with real time, but note relative timing.
This also means, that a good MIDI software should also internal tick with 24ticks/quarter to correspond with this incoming messages. Or 48, or 96. This is international standard.


...crossing the alps with my bike at the moment

wadmixfm

Wow your a top bloke

Thanks very much for the explanation

Lee
Yes its really me :)

wadmixfm

hmmmmm Midimaster i am having trouble with it

the code runs but when i press play on the sequencer arent the numbers in your code supposed to increment ??

Lee
Yes its really me :)

wadmixfm

SuperStrict
Import Audio.Midi
Global ln:Int


Graphics 400,300
Global Counter:Int=-1, StartTime:Int, QuarterTime:Int, Tempo:Int, Beat:Int
Global MidiIn:TMidiIn = New TMidiIn.Create()
MidiIn.OpenPort(0)


Repeat
    Cls
    Local stampvoid: Double
    Local Message:Byte[] = MidiIn.GetMessage(stampvoid)

    If Message
=248
Print message
        If Counter=-1
            StartTime   = MilliSecs()
            Beat        = 1
        EndIf
        Counter:+1      
        If Counter=24
            QuarterTime = MilliSecs()-StartTime
            Tempo       = 60000/QuarterTime
            Counter     = 0
            Beat        = Beat+1
            StartTime   = MilliSecs()
        EndIf
    EndIf
'checks how many ports are available
For Local mi:Int = 0 Until MidiIn.getPortCount()
ln=mi
DrawText  "Midi Port #" + ln + " : " + MidiIn.getPortName(mi),0,0+mi*26
Next
    DrawText "   Music TEMPO : " + Tempo + " bpm", 100,100
    DrawText "Quarter Length : " + QuarterTime + " msec", 100,130
    DrawText "Music Position : " + Beat + " Quarters", 100,160
    Flip 0
Until AppTerminate()
midiIn.Free()
End
all i have added to it is so it can check how many ports it has

my mac has a IAC Driver which is macs Virtual driver for midi

it works all the same but with the example in RTmidi midi in example it shows stuff coming in but
your code is not detecting anything !!!!!

lee
Yes its really me :)

Midimaster

#8
Sorry, but I did not check my code, when I wrote it. I wrote it on the fly.

I can see bugs in your code. The SyntaxBomb Editor destroyed your post:

    If Message
=248
Print message

...needs to be...

If Message[0]=248
    Print message[0]
    ....





The check for the ports must happen before the main loop:

Global MidiIn:TMidiIn = New TMidiIn.Create()

'checks how many ports are available
For Local mi:Int = 0 Until MidiIn.getPortCount()
    DrawText  "Midi Port #" + mi + " : " + MidiIn.getPortName(mi),0,0+mi*26
Next
MidiIn.OpenPort(0)

Repeat
    .....


As a third change: If you have more than one MIDI-IN-PORT in your mac, you of course have to change the "0" to "1" or "2":
Local TakeThisPort:Int=0 ' <--- depends on your selection
MidiIn.OpenPort(TakeThisPort)


And I forgot to tell you, that you need to switch on the incoming of 248-messages before the main loop:

MidiIn.OpenPort(TakeThisPort)
MidiIn.IgnoreTypes(True, False, True)

Repeat
    ....
...crossing the alps with my bike at the moment

wadmixfm

adding the midiin ignoretypes

got it working

thanks

Lee

Yes its really me :)

wadmixfm

yes the syntax editor destroyed my code lol it was nothing like what come up lol

anyways

its now doing its thing

thanks pal

:)
Yes its really me :)

wadmixfm

Are there any messages to detect stop and reset

I know the 248 is on but when I press stop should the values reset back with the timing code because when I press play again ,it carries on from when I press stop

Cheers

Lee
Yes its really me :)

Midimaster

#12
STOP is more like "Pause"
START means "Play with Reset"
CONTINUE is "Play without reset"

More information about MIDI synchronisation commands  START STOP CONTINUE, etc...

http://midi.teragonaudio.com/tech/midispec/seq.htm

and here the START STOP CONTINUE commands:
https://www.zem-college.de/midi/mc_srm1.htm

and here the POSITION commands:
https://www.zem-college.de/midi/mc_scm3.htm
...crossing the alps with my bike at the moment

wadmixfm

Thanks for the help midimaster :)

I did get it working with the drum program but..... i ran into a few minor hurdles

1 was even though the code worked fine there were latency issues regarding midi to blitzmax

i did everything you told me and i did get it to sync up for over an hour using

Reaper as the Daw (sequencer - Master) and my program as the slave using the Mac's built in virtual midi device Iac Driver and yes i know its a virtual device but it did work , now on the blitzmax side of things i am using your Mima Audio Plug in and it does help on the mac but with out syncing back to the sequencer i dont think they will stay in time forever , there is a slight drift of 0.5ms and then it comes back together and then drifts again.

but as i say i did manage to get it working but for now , i wont release it as part of my program it was an experiment , i think if i am going to use midi fully with user capability then i will have to learn to program it in full machine language or C++ natively.

i was almost there with it.....

the 2nd thing was when using the Sequencer with a couple of synths in and then try to sync up with the blitzmax program it tried to stick together but when you went to quantize your notes and then play back it was all over the place.... until i used the drift with Ms facility in the Sequencer. It worked out that it was out by about 6ms , thats a lot when your playing a keyboard to it, if you just recorded to the drum track without quantize it was bearable but you have to think about the end user and how they would use it.

thirdly , this is a conversion of a commodore 64 Program and in them days hmmmmm commodore thought Midi was a dress lol

but anyways i have decided to shelve the midi side of the program ...... For Now :)

Cheers Again

Lee

P.s hope you understand all this :) i know i jibber on a bit :)

thanks for listening

Yes its really me :)

Midimaster

Quote.... there is a slight drift of 0.5ms a....It worked out that it was out by about 6ms....

But 0.5msec are not out of sync! Human cannot hear latency below 30msec. Are you talking about 0.5sec = 500msec?

Then I can say to you, that this is not caused by BlitzMax, but your code. With a good code style, you do not get latency over 30msec! Writing MIDI or using MINI-AUDIO is perfect possible on BlitzMax. No need to change to C oder ASM

QUARTER notes, played at TEMPO=120, have a distance of 500msec. So 1/32-notes have 63msec. All values below 60msec are in the area of human inaccuracy, and this sounds human and natural. So do not try to correct this. Otherwise the music becomes sterile.



 
...crossing the alps with my bike at the moment