MidiMon 1.00, a USB MIDI app
Lauren Etc. (8147) 52 posts |
Very cool, Peter! I was always open to adapting it to support other MIDI systems as well, so I’ll be checking that out very soon. Although currently, I’m hung up on the module thing. Semi-off topic but maybe Rick can give me advice if he has a moment since I already found part of the answer through one of his old posts, I’m trying to retool it to use a pollword to communicate the “right” way, and it very nearly works but I’m not sure necessarily where this pollword should be allocated or how to manage its lifespan. The documentation on this seems scant for something that seems to be common procedure… I’m a bit out of my element here. |
Rick Murray (539) 13850 posts |
It cannot be in application space because that gets swapped out when you call Wimp_Poll. The usual way is to put it in the module area. Since you already have a module that responds to the key presses, and since you’ll be wanting to change that to some sort of key press buffer (given that you can’t SendMessage in that manner), simply define your buffer to stay that a null word terminates the list of keys. This means if the buffer is empty, the first word of the buffer will be &0. As for it’s lifespan, there are two interconnected things. The first is the application. Once this quits, the Wimp will no longer be instructed to look at that address. The second is that address, which will be a part of your module’s workspace, which will be freed when the module is quit.
Let me know if you get it working. I tried all sorts of permutations but couldn’t get anything to happen. I don’t know if it didn’t recognise my piano (there doesn’t appear to be built in diagnostics) or if I’m just doing it wrong. I’m not familiar with how the ESP stuff worked so it might just be that… |
Peter Everett (9846) 59 posts |
Run !MidiSupport. It should now work, connecting your keyboard to midi port 0 in both directions. |
Rick Murray (539) 13850 posts |
Yup, done all of that. Thank you for clarifying it.
Unfortunately, it doesn’t. My sequencer (talks to MIDI port 0) is able to receive notes, but it plays nothing. Connection info: *USBMidi -i+ Device: USB9: (USBPort0) VID=499 PID=1604 VERS=100 Manufacturer: YAMAHA Corporation Product: DigitalKBD Serial number: Interface 1 Endpoint 1 Input address: 2 attributes: 2 Bulk size: 64 Endpoint 2 Output address: 1 attributes: 2 Bulk size: 64 options = 1 * In the log, far far too many: 0: 0 <- [] <- event 00000000 Should probably have an option to filter those out. There are quite a number of MIDI beat clock events: 0: 0 <- [F8] <- event 0000F80F And a few ActiveSense events: 0: 0 <- [FE] <- event 0000FE0F Lurking in the morass are a few key press events: 0: 0 <- [90 54 00] <- event 00549009 And here’s my software playing the music (having recorded me pressing all the Cs): 0: 0 -> [C0 00] -> event 0000C00C 0: 0 -> [C1 18] -> event 0018C10C 0: 0 -> [C2 20] -> event 0020C20C 0: 0 -> [C3 28] -> event 0028C30C 0: 0 -> [C4 2A] -> event 002AC40C 0: 0 -> [C5 30] -> event 0030C50C 0: 0 -> [C6 39] -> event 0039C60C 0: 0 -> [C7 42] -> event 0042C70C 0: 0 -> [C8 49] -> event 0049C80C 0: 0 -> [C9 01] -> event 0001C90C 0: 0 -> [CA 47] -> event 0047CA0C 0: 0 -> [CB 13] -> event 0013CB0C 0: 0 -> [CC 07] -> event 0007CC0C 0: 0 -> [CD 15] -> event 0015CD0C 0: 0 -> [CE 2E] -> event 002ECE0C 0: 0 -> [CF 09] -> event 0009CF0C It then pauses briefly (32 clock ticks), as some hardware needs a moment to get itself together after setting up all of the instruments, then here’s C2 to C7 being played: 0: 0 -> [90 24 39] -> event 39249009 0: 0 -> [90 30 3B] -> event 3B309009 0: 0 -> [90 3C 3C] -> event 3C3C9009 0: 0 -> [90 48 37] -> event 37489009 0: 0 -> [90 54 42] -> event 42549009 0: 0 -> [90 60 42] -> event 42609009 So it looks like something is supposed to be sent. But not a ding, beep, or clang is heard. This is shortly (four ticks later – my software works with semiquavers as the shortest note) followed by turning the notes off: 0: 0 -> [80 24 00] -> event 00248008 0: 0 -> [80 30 00] -> event 00308008 0: 0 -> [80 3C 00] -> event 003C8008 0: 0 -> [80 48 00] -> event 00488008 0: 0 -> [80 54 00] -> event 00548008 0: 0 -> [80 60 00] -> event 00608008 I’m using NoteOff events as it’s USB, so there’s no running status, so there’s no need to optimise with NoteOn velocity 0. Just after that, the tidyup routine which is a bit paranoid and probably not necessary now as I keep a track of all active notes to ensure they’re all stopped correctly. This was because my software can play an entire piece or the bar currently being edited, and if you’re using a string instrument where the note extends beyond the current bar (thus doesn’t get to the note end), it’s a headache and an earache that ensures one keeps better track of everything in order to correctly turn it all off at the end. ;) 0: 0 -> [B0 7B] -> event 007BB00B 0: 0 -> [B1 7B] -> event 007BB10B 0: 0 -> [B2 7B] -> event 007BB20B 0: 0 -> [B3 7B] -> event 007BB30B 0: 0 -> [B4 7B] -> event 007BB40B 0: 0 -> [B5 7B] -> event 007BB50B 0: 0 -> [B6 7B] -> event 007BB60B 0: 0 -> [B7 7B] -> event 007BB70B 0: 0 -> [B8 7B] -> event 007BB80B 0: 0 -> [B9 7B] -> event 007BB90B 0: 0 -> [BA 7B] -> event 007BBA0B 0: 0 -> [BB 7B] -> event 007BBB0B 0: 0 -> [BC 7B] -> event 007BBC0B 0: 0 -> [BD 7B] -> event 007BBD0B 0: 0 -> [BE 7B] -> event 007BBE0B 0: 0 -> [BF 7B] -> event 007BBF0B Now, if I run my MIDI module and call up the connection info: *MIDIUSBInfo MIDI USB information: Timestamp type is MIDI clock MIDI Clock is 0 (Song Position = 0) Current TX channel is 0 (real channel 1 on real port 0). MIDI device (#0) is USB9, VID 0499, PID 1604, Manufacturer YAMAHA Corporation Product DigitalKBD using IN file handle 252 Endpoint 2 Size 64, and OUT file handle 247 Endpoint 1 Size 64. number of cables 1. * Interestingly my module is reporting the input and output endpoints the other way around to yours. Hmm… |
Rick Murray (539) 13850 posts |
Speaking of all of those null events in the log, would I be right in assuming that they are temporally equidistant? There’s no timestamp indicated. I’m asking because I notice this: 0: 0 <- [F8] <- event 0000F80F 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [F8] <- event 0000F80F 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [FE] <- event 0000FE0F 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [F8] <- event 0000F80F 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [] <- event 00000000 0: 0 <- [F8] <- event 0000F80F It is quite regular, in that there are fifteen null events in between every MIDI beat broadcast from my keyboard in its default settings (90bpm). Surely that’s wrong? It’ll be skipping beats in that case, wouldn’t it? It’s also a bit odd that it seems sort of haphazard whether the ActiveSense is sent after seven beats or eight. Let’s calc this, because I’m bored and it’s hot outside and I would rather do something other than the washing up. :) There are 24 clock ticks per crotchet (or quarter note if you talk leftpondian). At 90bpm, there are 90 crotchets per minute. There are 60,000,000 microseconds per minute, so each crotchet/beat will occur every 666666.66’ microseconds, or in RISC OS friendly nomenclature, every ~67 centiseconds. Now, in your log there are fifteen null events in between each tick. Since there’s no timestamp, we’ll just assume that there are sixteen active events (fifteen nulls plus the tick). Okay, now I guess I have to go do the washing up… |
Dave Higton (1515) 3534 posts |
The log above would be typical of a USB connection opened without setting it not to pad. OTOH I wrote the firmware years ago for a USB MIDI device that always sent out 64-byte packets, with the rest cleared to 0, because, when I tested reception of various USB MIDI devices using RISC OS, all the incoming packets appeared to be 64 bytes, zero filled, so I assumed that was how MIDI devices worked. At that time I didn’t know that RISC OS padded packets by default. So maybe some other manufacturer has made a similar mistake. |
Rick Murray (539) 13850 posts |
Ah, yes… I remember. In my module there’s some code to filter out the actual MIDI data from the nulls in the buffer, because asking for no padding… seems to pad anyway. Dunno if it’s the hardware, RISC OS, or just something MIDI does, but it’s easy enough to discard the unwanted junk. |
Peter Everett (9846) 59 posts |
Rick, |
Rick Murray (539) 13850 posts |
Hmm, did anything ever come of the discussion on FastTickerV? This is the sort of service the OS is supposed to provide…..! |
Peter Everett (9846) 59 posts |
Definately. Before retirement I was an embedded hardware/software design engineer. For USB, the class code went right down to the peripheral’s Fifo’s and there was always access to the 1ms frame timer if needed. Easy peasy. |
Jean-Michel BRUCK (3009) 362 posts |
Hi, Rick and Peter Back to ESP Rick , I’m following your blog Simple seq. For people interested in music, it’s a missing link. Quick question: can we retrieve songs played by QTM or MilkyTracker via a MIDI file, for example? |
Rick Murray (539) 13850 posts |
Well… concerning Rhapsody, your 230406 release included v0.08 of the MIDI module, and for some inexplicable reason your (current) 230819 release includes v0.06 (Feb 2019, FFS!) of the MIDI module. You do realise, I hope, that the current version is 0.10 and a fair few connection issues have been sorted out, right? Get it from https://heyrick.eu/blog/index.php?diary=20230624 and please stop distributing those ancient versions. They’re not as good/useful as the current one.
Thanks. I find it helps me in getting the relationship between music and time that I just wasn’t wrapping my head around looking at notation.
He was going to tidy up and release the source code. There’s a message on the forum someplace to that effect. Well, actually, not waiting. Given up. Between Rhapsody and writing my own little thingy…
If you know the file format, yes, I’d imagine so. You won’t have the same instruments as the ones contained in the tracker, but the notes and timing should be in there, it’d just be a question of stripping them out and translating them into something that resembles MIDI. |
André Timmermans (100) 655 posts |
A tracker is basically a spreadsheet where you can specify for each channel: For effects, take the case of pitch. It comes in 3 variants: So use an effect to slide the pitch from X to X + S and it has a completely different result for each of the 3 variants, which will be difficult map to the MIDI equivalent. |
Rick Murray (539) 13850 posts |
For me, semi real time doesn’t work, and fully real time always crashes. I fixed a bug where the MIDI module wasn’t using the MIDI beat clock (I think maybe something got lost in making the variable a global) as it could only be turned on/off by receiving Start/Continue/Stop messages from the MIDI device. So I’ve added this behaviour to the Start/Continue/Stop SWIs. I notice from my simple test program that Peter’s module outputs a millisecond time value (counting from system start?) with each bit of data received. Mine doesn’t do that until you use the FastClock SWI, as the old docs kind of give the impression that the module is supposed to use the beat counter by default. Likewise, I can see the beat messages turning up in the data stream, whereas mine suppresses those unless asked for (what is it, bit 30 of the Init SWI?). I noticed, from a quick look in Zap, that Rhapsody issues Init, 15 to set bits 0-4 (basically clear buffers and so on) and never seems to call FastClock to switch to the millisecond timer (which, in my case, begins counting from zero). So, do you know your way around Rhapsody’s internals well enough to be able to tell me what it actually expects for timing when it comes to semi/fully realtime recording of notes?
That’s my problem too. Fat fingered and dyspraxic, a brilliant combination.
Offset how? The wrong time interval or the wrong note?
I got Peter’s module working with Rhapsody, and the realtime recording worked (semi didn’t) but it came up with some seriously peculiar notation. I just pressed a key and held it down a bit, and repeated. Basically playing Twinkle Twinkle Little Star in slow motion (or, about as fast as I can play it). I think part of my problem, also, is that I never had any functioning MIDI setup to compare with (sadly my AKA10 I/O podule doesn’t have the MIDI part fitted). So, yeah… what does Rhapsody actually expect the timing value to be? MIDI clock? Millisecs? Something else? |
Jean-Michel BRUCK (3009) 362 posts |
@Rick Sequencer: Tracker files: |
Colin Ferris (399) 1818 posts |
Have you been upsetting Ricks AI ‘Toaster’ :-) |
Dave Higton (1515) 3534 posts |
Do/did you check the return value from the call? |
Jean-Michel BRUCK (3009) 362 posts |
I don’t hope otherwise it’s me who will end up in his device :-) Semi realtime no longer works at all :-(
Alas, yes, Rhap4 does not receive the associated timing (time stamp) for each note received. I had tested
The answer is in the StrongHelp MIDI manual, and I use the guide to the MIDI Software Specification: From Strong help manuel: I will reread your questionnaire to answer it correctly, this is the right way to move forward.There is a lot of work… From Rhapsody4 manuel: Rhapsody has some of the most sophisticated real-time capture routines available on any computer at this time and provided you are a reasonably competent keyboard player and can actually play the notes you want to transcribe,(Jo Linton) I’m curious to see the result. |
Peter Everett (9846) 59 posts |
there must be bugs (starting with me, I’m not a pianist!!!) Well that makes 3 of us. This should be fun ! I get the notes but they are offset I think these are all time errors and not pitch errors. I also don’t think it’s a problem with either mine or Ricks modules as such. I’ve been playing around with capture and it does all seem to work, but for me at least it’s a case learning to do it as intended, i.e. RTFM.
For debug output it’s from module initialisation. Not resetable, counts forever, well for 24.8 days when it overflows (not tested this!). For RxCommand/RxByte it’s the queue clock, see further down. In Midi Support, the equivalent functionality of Ricks USB module is provided by my MIDI and USBMidi modules with the MidiSupport module inbetween doing the routing. The USB module doesn’t use timestamps and just passes data through it asap. It does buffer Tx data, more on that later. Time stamps (time from startup) are used for debug output and are vital to track data through the system as it invloves 3 separate modules and so up to 3 log files.
I decided to do the following. For my USBMidi module: I also found that “Waking the Rx” after emptying the Rx buffer in the upcall did not always work. To ensure that intermittent data was requested as soon as possible I had to additionally “Wake up Rx” every frame so it always requested a packet every frame and there was never a delay. There may be reasons why I had to do all this, I don’t know, but I do know that it made it work reliably. |
Peter Everett (9846) 59 posts |
Forgot to say, |
Jean-Michel BRUCK (3009) 362 posts |
Bonjour, @Peter, Yesterday, impossible to capture with Rhapsody4, grrr!!!
Results with Rhapsody: the pitch of the notes is correct, the duration too, but on the other hand there is a time lag of approximately one semiquaver I don’t know if this is a Rhapsody problem or a misinterpretation of the timing? (see MIDI_TxStart SH manual) RealTime Capture KO….I’m thinking of a Rhapsody problem, I’m looking for it. |
Rick Murray (539) 13850 posts |
I’m getting that too, after it working before. I used the command line to set up the associations. But, Grrrr! “Unknown error”. That’s about as useful as nothing, isn’t it? 🤦 I have a suspicion that the appropriate word here might be “unexpected”, not “unknown”.
Okay, so it looks like the module should be defaulting to using fast timing.
Fast timing isn’t supposed to start until after this has been called…? (see Midi_Fastclock in MIDI StrongEd Manual 😉 ) Aside: This, ladies and gentlemen, is the sort of thing that happens when one follows the published API when said API is outdated, obsolete, or just plain wrong. <sigh> If I’m not too frazzled this evening, I’ll see about throwing together a test version of my MIDI that does fast timing by default.
How about leave it (as there are already other issues with the error handling 1, let’s not complicate things) and instead when the program starts, see if it’s already there and if it is, do something with it then? We’ll get there, eventually. 1 Seems all too easy to get it stuck in a loop where one needs to Alt-Break out of it. |
Peter Everett (9846) 59 posts |
There’s only one place in the MidiMan code that can produce that error, and it’s when it can’t find the error message in the Messages file. So how about “Can’t find error message”, Which is about as useful as “unknown error”. |
Rick Murray (539) 13850 posts |
Better. It indicates that there’s something wrong with the messages file. Which isn’t the actual problem as you say, but it’s something tangible in a way that “Unknown error” simply isn’t. ;)
Something has gone wrong. Freshly booted system, started as you describe, the error happens. Archive 230901, two files Templates and Templates1. No “USBOpt” window in either. Archive 230619, USBOpt is present. Copy-drag the window from the old to the new, save it (overwriting the archive copy, oops) and MidiMan starts. |
Peter Everett (9846) 59 posts |
Thanks Rick, |