Load midi files from SD consecutively, in order


#1

Hello,

I have a patch with a sort of a synth that is driven by CC messages recorded in midi files that are played in the patch itself using jt/midi/play object, and directed to internal port .

For this particular case it would be very useful to be able to automatically load a series of midi files present in the SD, in a certain order.

But jt/midi/play has no inputs, so it does not seem like I can tell it to do anything at all automatically.

And I cannot find any other object that deals with midi files... Is there really no option to do this?

Any ideas?

Thank you


Loop midi with jt/midi/play or equivalent
#2

on it! Just tried it out and I'm able to load the twinkle midi file from the SDcard.
So now I'll try and see if I can use a string-mux and a string inlet to enable loading multiple files one by one.

One little problem though.. as I still cannot upload to the contrib folder, you'll have to do some things yourself.
When I finish the module, I'll upload the code parts to here and you'll need to create the module yourself, saving it to your home folder (or contributions) (or perhaps someone else with experience can do that).
For it to work you'll need to do a couple of things (you can already do this, then later edit the code when I got it ready)

-click on the triangle in the top left corner and select "edit object definition"
-then save the file to a folder in your home-directory, or contrib folder if you have one, by going to:
"File"->"Copy to library"->select your folder->"ok". This will save a copy of the module to your own folder.
-Then go to the contrib/jt/midi folder and copy the "tml" and "tmp_impl" header files to the folder you've put the module in. These files are needed for the module to work and it will search for them in the folder it's in.

When it's time to edit, you'll load the module you saved in your folder.


#3

midiPlay.axo (6.0 KB)

I'm not sure if it works, but you can try to directly copy this into your home folder (not contributions! This should only be done by saving inside the axoloti patcher program in the "copy to library" way)

don't forget to add the "tmp" and "tmp_impl" from the jt folder to the same folder you put the module in.

if it doesn't work, perhaps you can try the way I explained in the reply above to copy jt's file to your own home-folder, then copy and paste the code parts from my module to his.
Just go to the file using explorer and open it with the basic text editor.
You'll see it will start like:

< patch-1.0 appVersion="1.0.12">
< comment type="patch/comment" x="14" y="14" text="standard midi file playback demo"/>
< comment type="patch/comment" x="28" y="28" text="requires sdcard!"/>
<obj type="ctrl/toggle" uuid="42b8134fa729d54bfc8d62d6ef3fa99498c1de99"
* copy everything from here till the end of the file*

just copy everything behind that "uuid" number from my module and overwrite the same part of the code in your copy of the module and save it again. Then reload the axoloti patcher and it should open with the new code.

it should now have:
-an input for start/stop
-an input for loading
-an input for connecting a string (use the string&mux modules to set your file names)
-a tempo-adjust input. Though it doesn't work really well while adjusting live (actually works pretty bad..), you could set the tempo a bit faster or slower from the start.

-it does have an "end" output, but I couldn't get this to work. The display was meant to go high after "end of track", but it seems this message isn't send/received at all or I'm not using it properly in the code. Maybe someone else can find out how to get this message..


Help with logic in axo
#4

Oh wov, thank you very much @SirSickSik, much appreciated

Let me get straight to it and get back to you

Thanks again


#5

OK @SirSickSik I got it to load on my patch.

Let me see if I understand. I should use a string such as -for testing, I understand I should use a muxer for example- with the object 'string/c' (constant string?) directed to the 'file' input, then 'load' then 'play' ? Do I have to sequence these ?

Also... the midi file should be in the same folder than my patch I guess, right?

Thank you again very much


#6

you can place the midi-file anywhere you like but you have to enter the directory like this to make sure it searches from the main folder (0:/) like:
../midi000.mid (here you'ld use the indexed string to select from midi files with a common prefix)
the "../" makes sure it starts from the main folder of the SDcard.

So you could also search by specific strings in certain folders like:
../MIDI/REGGEA/bobMarley_I_SHOT_THE_SHERIFF.mid

Just take a set of string modules and use a mux to select any one of these inputs and hit "load"

I couldn't get an automatic "end of song" working, but you might use a counter that gets reset when a midi-note gets played. As soon as it goes over a maximum time without any notes being played, it would trigger to load the next midi file.


#7

Ok thank you.

So I was correct in my assumption that "load" and "play" should be sequenced, correct ?

Btw I tried to load the patch with your code on the Axoloti and got multiple errors, I will attempt the other way you suggested, to replace part of the code from the original midi player, see if that works, and get back to you.

Thanks again


#8

@SirSickSik When I follow your instructions to copy jjt/midi using "file"->"copy to library", the file I get does not start with:

< patch-1.0 appVersion="1.0.12">
< comment type="patch/comment" x="14" y="14" text="standard midi file playback demo"/>
< comment type="patch/comment" x="28" y="28" text="requires sdcard!"/>
<obj type="ctrl/toggle" uuid="42b8134fa729d54bfc8d62d6ef3fa99498c1de99"

This seems to belong to midi_play.axh, the help file from jt/midi, right ?

The actual module starts with:

<objdefs appVersion="1.0.12">
   <obj.normal id="custommidiplayer" uuid="81d2a4c2-2a8d-4753-942b-506827cb53fd">
      <sDescription>Plays a standard midi file. 
Can only start playback from the beginning of the midi file.</sDescription>
      <author>Johannes Taelman</author>
      <license>BSD</license>
      <helpPatch>midi_play.axh</helpPatch>
      <providesModulationSource>false</providesModulationSource>
      <rotatedParams>false</rotatedParams>
      <inlets>

The same goes for the file you attach here, it starts with:

<objdefs appVersion="1.0.12">
   <obj.normal id="midiPlay" uuid="22a051e3-a68c-4cf9-910d-93925ed0454a">
      <sDescription>Plays a standard midi file from SDcard.
I added some inputs for loading new midi files on the fly and a tempo adjust.
Can only start playback from the beginning of the midi file.</sDescription>
      <author>Johannes Taelman editted by Remco van der Most</author>
      <license>BSD</license>
      <helpPatch>midi_play.axh</helpPatch>
      <providesModulationSource>false</providesModulationSource>
      <rotatedParams>false</rotatedParams>
      <inlets>

... which makes sense, actually. So what should I replace then?

Thanks again


#9

@SirSickSik sorry for triple posting.

I got it working :)))

I noticed the error messages seemed to relate to a re-definition of the midi minilibrary, so I assumed there was some sort of 'scope' error on my side. I had placed your module in the root of the 'home' folder, and so I moved it into its own folder, including the library (tml.h and tml_impl.h). Then it worked.

Very grateful.

Although a working "done playing" output would be great, the 'counter' hack you propose seems like a very good idea.

Thanks again.


#10

I searched the header file to find out what kind of message would show the end of the midi-file and tried to incorporate this (you can actually still see this in the code as the last "case" of the switch function), but it didn't respond to it even though I got the code right (at least it didn't give any errors telling me the message didn't exist). I tried several different ones, but none of them gave any response, so I'm not sure whether there is anything at all in the midi-file that tells you that it has ended.. Or maybe the midi-files I got here are incomplete..I don't know.. I'll see if I can still come up with something to enable an auto-load and loop function.

Anyways, you can make a simple load&auto-play structure by using a logic-XOR.
To this you attach both the play toggle button and load momentary button. Then send the output to the play input. As soon as you hit "load" the current midi file is stopped, new one is loaded and then starts the new file when the load is released.


#11

This link may be of help. A discussion on MIDI files End of Track message (EOT).

Someone pastes this from the midi manual:

End of Track

This event is not optional. It is included so that an exact ending point may be specified for the track, so that it has an exact length, which is necessary for tracks which are looped or concatenated.

I checked the manual , and this event is refered to as "FF 2F 00".

Here is a copy, you may want to check page 137-138 to find this.

Thanks again.


#12

yes!
I got it!

-add this code at the end of the k-rate code:

outlet_playing=g_MidiMessage && g_Msec < g_MidiMessage->time;

-and add a boolean output called "playing"

this will go high as long as the song plays and off when the song has ended.
Then use a logic inverter and a timed pulse (timers) to trigger the next load.


#13

Ah!

Simultaneous posting!

Ok, should I add this on the file itself with an editor or on the object definiition window in axoloti ?

Cheers.


#14

ps. don't embed the file, just open it, edit it and save it. If you embed it, it cannot find the header files anymore..


#15

you can also just edit it using the windows text editor, but changing it in the object definition window is easier and faster, but again, don't embed the module :wink:


#16

Ok,

I am unsure about what "embed" means in this context.

Should I remove the other outlet you already had there ? <bool32 name="end"/>

Also, at the end of the k-rate code, you have a for loop, with all the cases... where, in relation to this loop, should I place the code above? after the loop, outside of it ?

Thanks again


#17

oh, the module just crashed overhere after looping 4 midi files a couple of times (at a very fast rate)..
It seems it's overflowing the sdram, so there's probably a code needed to remove the old midi data from the table to prevent this. It's probably just adding tables to tables to tables etc..


Reloading init patch every 60 minutes, safe?
#18

yes, you can remove that one, but you'll also need to remove the parts where it's mentioned in the code.
The last case of the switch can be removed (the one with the EOT)
and also somewhere above the switch it says:
outlet_end=0;
you'll have to remove that one too


Help with logic in axo
#19

Hello @SirSickSik, I've encountered the SDRAM overflow you mentioned, even without the "done playing" code.

Any idea where to start trying to remove that problem ?

For now, even an automatic 'reset' of the patch would be an acceptable workaround, if that fixes the SDRAM overflow, as this patch is going to be running for hours in an installation. (I'll share the whole project in the forum as soon as I can).

Thank you !


#20

there should be a way to remove these from the sdram I think, but I don't know the code for that. I would like to though, so if anyone mentions it somewhere, please let me know.
But you could indeed try to re-init the patch.
For that you might try to just save an extra patch that only has a patch-change in it.
So that after your files have ended playing, it will switch over to that other patch, which will order it to switch back to the midi patch.
Don't know if it will work correctly though, you just have to try it out..