Search Unity

Maestro Midi Player Tool Kit - Good news for your rhythm game !

Discussion in 'Made With Unity' started by BachmannT, Apr 14, 2018.

  1. JWerner

    JWerner

    Joined:
    Dec 18, 2016
    Posts:
    8
    Glad you mentioned this setting. I had overlooked it in the documentation and wondered why the volume was fading in at the beginning.

    But I really wanted to compliment the recent update. I can confirm there are no issues if the demo isn't imported, and the 24-bit SoundFont support is working. Also the support for pitch wheel sensitivity was a nice surprise. I have a couple of MIDI files that use pitch bend that weren't playing back correctly, but they sound great with this update.

    The most useful update for me was exposing the SoundFont effect parameters. Especially since I keep changing my mind about the best settings. :)
    I don't expect you to change the defaults, but I think a Level of 1 for both Reverb and Chorus result in the best mix, since that basically results in using the unchanged value set in the SoundFont. Turns out the people that created the SoundFont I'm using had a great ear, no need to second guess their settings.
    I would also suggest trying different settings for Reverb Width. The difference between the default of 0.5 and a setting of 2 or 3 is remarkable.
    I did have one issue though. The MidiStreamPlayer prefab does not read the effect parameters set in the Inspector. Regardless of settings, it always starts with the default values. It does respond to settings changes during runtime however. I've only tested this in the editor, I'm not sure of the behavior of a build. And I haven't tested any of the other prefabs.

    Also one quick question. What is the best way to reset the MidiStreamPlayer? I have a small test program, basically a simple MIDI player. Works fine, but it currently isn't resetting or stopping the player between different songs, so settings modified through MIDI events sometimes effect the playback of the next song.
     
  2. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Hello, thank for detailed information. I'm currently in Holliday, no desktop, low connection, I will come back 3 juicy with more availability . Thierry.
     
  3. clagrens

    clagrens

    Joined:
    May 19, 2017
    Posts:
    96
    Hi I try to use midi stream player to play only one instrument but every time I start it load the whole soundfont library.
    I didn't toggle the load all wave option.(so it take 20~30 second to load soundfont from harddisk)


    I use this soundfont.
    https://sites.google.com/site/soundfonts4u/
    SGM-v2.01-YamahaGrand-Guit-Bass-v2.7 (528mb)
     
  4. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
  5. clagrens

    clagrens

    Joined:
    May 19, 2017
    Posts:
    96
    I figure out how to load samples I need now, so I can control which samples get loaded in one present.
    Reduce memory usage, Quickly than before!

    In MidiPlayerGlobal.cs, Original LoadAudioclip() is the same as LoadWave() , so I do some modify.

    Thanks for your reply!
    upload_2021-6-30_23-18-30.png
     
  6. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Sorry for the delay I was away with no desktop and low connection.I'm astonished because LoadAudioclip() is called only in legacy mode (non core mode). That was the first version of MPTK and not really ... good! I keep this version because in some cases that could be useful. I forecast to remove this mode with the next major version.
    Could you check that you are in core mode ?
    upload_2021-7-2_19-25-29.png

    Only LoadWave() is used to load sample in core mode.

    All my best
    Thierry
     
  7. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Thank, you recommendation are precious!

    I will answer to your questions ASAP !
     
  8. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Yes, funny! The algo is from the last version of fluidsynth, I like it also.
    Right, same issue with all prefab ... corrected for the next version. Thank to inform me (always the same error with Unity : c# Get Set properties can't be serialized, of course it's a method not a data)
    Try this method :
    MPTK_InitSynth()
    http://autogam.free.fr/MPTK/html/d3..._synth.html#a12950350e7680dede8d571871496238c

    All my best
    Thierry
     
  9. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Hello
    Yes, Viena is a bit hard to manage, in particular just for copying preset between SoundFont. I checked this tool (free also) with easy function of copy paste. Polyphone

    The next version will be able to defined free sample rate ;-)
    But, for MacOS you will have as usual to defined the sample rate from the Unity menu "Edit / Project Setting / Audio" Finally, I have enabled the sample rate change in inspector for Mac. Seems ok now with new version of Unity ... to be confirmed.
     
    Last edited: Jul 4, 2021
    Deleted User likes this.
  10. Deleted User

    Deleted User

    Guest

    Sounds great. I've got two question regarding gaining control over midi file player.
    - Is it possible to switch between soundfont's through a script?
    - Is it possible to check if a song has been ended and then play from section01 instead of section00? (So it skips the intro part.)
     
  11. BasicallyGames

    BasicallyGames

    Joined:
    Aug 31, 2018
    Posts:
    91
    I'm wondering, is there any way to transpose individual channels, instead of just the entire MIDI? I ask because currently if you change the transpose value, it also affects the percussion channel, which messes all the drums up since transposing that channel changes the percussion values, not the pitch. I'd like to be able transpose individual channels to avoid this issue, among other reasons.
     
  12. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Hello, great ! I never detected this issue. You are right, I will correct this with the next version: transpose will not affect the drums channel. Thank
     
  13. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Yes but with some limitations: if a midi is playing it is restarted, and a little time is need to switch depending the size of the soundfont.
    Look the demo script here Demo\FreeDemos\Script\GUISelectSoundFont.cs,
    MidiPlayerGlobal.MPTK_SelectSoundFont(MidiPlayerGlobal.MPTK_ListSoundFont[midiindex]);
     
    Deleted User likes this.
  14. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Yes, with the event
    midiPlayer.OnEventEndPlayMidi.AddListener((string midiname, EventEndMidiEnum reason) =>
    {
    Debug.Log($"End playing {midiname} {reason} Duration={(DateTime.Now - startPlaying).TotalSeconds:F3}");
    });

    But what is section ?
     
    Deleted User likes this.
  15. Deleted User

    Deleted User

    Guest

    Oh I don't remember if it said section or session. In the info console it said that.
    'Session0' is start of song and when the intro part of Gerudo Valley has played, the song outputs a message called session1. So I know exactly that is the point from which the song repeats itself after the end.
     
  16. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Perhaps in the midi metadata ? If you know the position in tick it's easy with MPTK to jump at this position.
     
    Deleted User likes this.
  17. Deleted User

    Deleted User

    Guest

    Yes, I managed to do it correctly. It also searches for the soundfont by name rather than it's index.

    Code (CSharp):
    1.  
    2. private void PrepareSong(string SongName)
    3. {
    4.         var Section1Position = -1;
    5.         var SoundfontID = 0;
    6.         switch (SongName)
    7.         {
    8.             case "Kaepora Gaebora":
    9.                 Section1Position = 1920;
    10.                 SoundfontID = SoundFonts.IndexOf("Main Orchestra");
    11.                 break;
    12.             case "Gerudo Valley":
    13.                 Section1Position = 13440;
    14.                 SoundfontID = SoundFonts.IndexOf("Gerudo Valley");
    15.                 break;
    16.         }
    17. MidiPlayerGlobal.MPTK_SelectSoundFont(MidiPlayerGlobal.MPTK_ListSoundFont[SoundfontID], true);
    18. MusicPlayer.OnEventEndPlayMidi.AddListener((string midiname, EventEndMidiEnum reason) =>
    19. {
    20.             MusicPlayer.MPTK_TickCurrent = Section1Position;
    21. });
    22. }
    EDIT - Btw, your tool is flawless in playing the midi's. I've done my own direct rip from the Oot3D rom with a tool I found online and now it doens't have the issue at the start with the first note being wrong.
     
    Last edited by a moderator: Jul 10, 2021
  18. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Excellent! thank to you!
     
    Deleted User likes this.
  19. Deleted User

    Deleted User

    Guest

    I'm struggling understanding how to use this still:

    Code (CSharp):
    1. midiPlayer.OnEventEndPlayMidi.AddListener((string midiname, EventEndMidiEnum reason) =>
    2. {
    3. Debug.Log($"End playing {midiname} {reason} Duration={(DateTime.Now - startPlaying).TotalSeconds:F3}");
    4. });
    DateTime seems to be System.DateTime, but I have no clue what I should do in "startPlaying". I have an int variable that I set for each song after the midi player has began.
    But MPTK_TickCurrent = LoopPosition; doesn't seem to do the correct thing for each song eihter.
    And I cannot do DateTime.Now - LoopPosition; o_O
     
  20. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Tick position is a special MIDI concept able to locate MIDI events independantly of the tempo and the real time.
    Here with SynthFont editor:
    upload_2021-7-12_18-5-57.png


    Or in Maestro :
    upload_2021-7-12_18-9-8.png

    Or when playing:
    upload_2021-7-12_18-10-49.png
     
  21. Deleted User

    Deleted User

    Guest

    Ah.. because it's set to loop, the song restarts after the tick has been correctly set. So the song starts from the start for some reason..
    Edit -

    Code (CSharp):
    1. MusicPlayer.OnEventEndPlayMidi.AddListener((string midiname, EventEndMidiEnum reason) =>
    2.         {
    3.             MusicPlayer.MPTK_Pause(int.MinValue);
    4.             StartCoroutine(SetTick(float.MinValue,LoopPosition));
    5.         });
    6.     private IEnumerator SetTick(float Wait, int loopPos)
    7.     {
    8.         yield return new WaitForSeconds(Wait);
    9.         MusicPlayer.MPTK_TickCurrent = loopPos;
    10.         MusicPlayer.MPTK_UnPause();
    11.     }
    I've come up with this hack. After fiddling around with it for quite some time, it now goes back to the correct spot.
     
    Last edited by a moderator: Jul 12, 2021
  22. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Interesting!
    Have you seen how TestMidiFilePlayerScripting.cs is looping between two ticks positions ?
    upload_2021-7-12_21-53-30.png
     
    Deleted User likes this.
  23. Deleted User

    Deleted User

    Guest

    Ah, no not yet. But Ocarina Of Time only loops between one point. I mean, after the song has started, it decides where to play from after the song has completed.

    Code (CSharp):
    1.  
    2. private void PrepareSong(string SongName)
    3. {
    4.         hasStarted = false;
    5.         setPosition = 0;
    6.         LoopPosition = 0;
    7.         var SoundfontID = SoundFonts.IndexOf("Main Orchestra");
    8.         musicPlayer.MPTK_Loop = true;
    9.         switch (SongName)
    10.         {
    11.             //Main Orchestra Theme's
    12.             case "Miniboss Battle":
    13.                 LoopPosition = 241;
    14.                 break;
    15.            //Ect...
    16.         }
    17.         if (currentSoundFontID != SoundfontID)
    18.         {
    19.             MidiPlayerGlobal.MPTK_SelectSoundFont(
    20.             MidiPlayerGlobal.MPTK_ListSoundFont[SoundfontID], true);
    21.             soundfontChanged = true;
    22.             currentSoundFontID = SoundfontID;
    23.         }
    24.         musicPlayer.OnEventStartPlayMidi.AddListener((StartPlay) =>
    25.         {
    26.             if (!hasStarted)
    27.             {
    28.                 StartCoroutine(SongHasBeenStarted());
    29.             }
    30.             else
    31.             {
    32.                 SetTick(setPosition);
    33.             }
    34.         });
    35. }
    36.  
    Code (CSharp):
    1.  
    2. private IEnumerator SongHasBeenStarted()
    3. {
    4.         yield return new WaitForSeconds(1.0f);
    5.         hasStarted = true;
    6.         setPosition = LoopPosition;
    7. }
    8. private void SetTick(int loopPos)
    9. {
    10.         musicPlayer.MPTK_TickCurrent = loopPos;
    11. }
    12.  
    There was a problem I had that the tick position was ignored or that the song always started from the loop point instead of the beginning. So I have made it so it's called and delayed within a coroutine and then it's correct loop position has been set. The loop is now seamless when set correctly.

    Right now I have one more issue. When going on rampage of button presses and consistantly switching songs, then stopping, the soundfont bugs out and the song gets played with a wrong faulty version of the soundfont.

    Code (CSharp):
    1.  
    2. private IEnumerator Music_Play(float Seconds, string MidiName)
    3. {
    4.         yield return new WaitForSeconds(Seconds);
    5.         PrepareSong(MidiName);
    6.         musicPlayer.MPTK_SearchMidiToPlay(MidiName);
    7.         if (soundfontChanged)
    8.         {
    9.             while (!MidiPlayerGlobal.MPTK_IsReady())
    10.             {
    11.                     yield return new WaitForSeconds(.25f);
    12.             }
    13.         }
    14.         musicPlayer.StopAndPlayMidi(SongIndex, MidiName);
    15.         soundfontChanged = false;
    16. }
    17.  
    I tried doing it like this, but it seems that sometimes ThreadWaitAllStop gets called during the song start and it immediately cuts off the correct soundfont even though it has been loaded correctly. I guess the coroutines cancel eachother out due to the queue not being thrown out for the previous song switch.
     
    Last edited by a moderator: Jul 14, 2021
  24. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Hello
    Yes, I confirm, this mechanism could disrupt when a lot of songs start/stop are triggered in a short time. Perhaps you could try this code for waiting all notes off before next midi.

    midiFilePlayer.MPTK_Stop();
    yield return midiFilePlayer.MPTK_WaitAllNotesOff(midiFilePlayer.IdSession);
     
    Deleted User likes this.
  25. Deleted User

    Deleted User

    Guest

    ...I tried updating, and like you recommended, made a backup. Specifically of the MidiDB, SoundfontsDB and MidiSet.txt. Unfortunately, the update revoked the 'pro' rights from the midifileplayer inspector. So I wanted to roll back. And now all my soundfonts and midi files aren't there anymore after putting them back into my project.. that's hours of work, gone in an instant.

    Yeah, this is horrible. Is there a way of getting them back?
     
    Last edited by a moderator: Jul 19, 2021
  26. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    It's horrible for sure. Could you check your backup ? have you MidiDB, SoundfontsDB folders and MidiSet.txt file ?
    One good news, all theses files are compatible with previous version.
    Perhaps, the simpler is to :
    Create from scratch a new project, download and setup Maestro MPTK¨Pro,
    Try to import only one Midi file and a small SoundFont, that will create the folders structure
    Restore your scripts,
    Restore contents of MidiDB, SoundfontsDB folders and MidiSet.txt.
    Display the popup Midi File and SoundFont setup, that force Unity to import files and synchronize the MidiSet.txt
    I hope that will help you
     
    Deleted User likes this.
  27. Deleted User

    Deleted User

    Guest

    https://www.mediafire.com/file/nmr9n4zdjh63f50/CouldNotFind.jpg/file
    These 3 functions I was using disappeared in the new version as well.
    Sorry, but Unity forum doesn't let me embed Mediafire for some great reason.

    Edit - Phew. It was in the resources folder, not in MidiPlayer's main folder. Must have been the lack of sleep that I managed to not notice that. It's been successfully restored. Didn't even need to create a new project.

    Edit 2 -
    Code (CSharp):
    1. yield return midiFilePlayer.MPTK_WaitAllNotesOff(midiFilePlayer.IdSession);
    Works like a charm. Thank you so much! :)
     
    Last edited by a moderator: Jul 19, 2021
  28. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Deleted User likes this.
  29. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    These 3 functions are in the PRO version !!!
    It seems that all scripts from the pro version has not been yet deployed in your project.
    For example, search the script :
    ...\MidiPlayer\Scripts\MPTKGameObject\Pro\MidiPlayerGlobalPro.cs
     
  30. Deleted User

    Deleted User

    Guest

    Hm.. clean slate project and MidiPlayerGlobalPro.cs not found. I think something went wrong. o_O
     
  31. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Try to remove the folder MidiPlayer (check your backup before !)
    Update from package manager, which is sometime tricky
    upload_2021-7-19_9-50-35.png
     
    Deleted User likes this.
  32. Deleted User

    Deleted User

    Guest

    I suspect it had to do with me installing from the older asset store system. I barely use packet manager to install from my bought assets. Im curious now, in which order did you update the midi toolkit asset? First the pro then the lite version?

    Ah ignore the previous statement.. I had the new version in my appdata folder allong with the lite version. It seems my Unity version is getting a bit old. :eek:

    EDIT - I'm sorry if I post too much in this thread. I don't want to flood all pages with my issues. Shall I delete a few of my posts in order to clean it up a bit for other users?
     
    Last edited by a moderator: Jul 19, 2021
  33. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    No problem :) the forum is here for that!
    Which Unity version are you using ?
     
    Deleted User likes this.
  34. Deleted User

    Deleted User

    Guest

    Version 2019.1.0f2 Personal.
     
  35. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
  36. Deleted User

    Deleted User

    Guest

    Hm.. I forgot about implementing this mechanic.. I've got another question.

    Is it possible to get the midi player to wait and listen to player input? So I can press the arrow keys at runtime and play a specific note with a soundfont?
     
  37. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Hi, sure! By script with the MidiStreamPlayer, see here https://paxstellar.fr/midi-file-player-detailed-view-2-2/
    And waiting a player input is quite easy with Unity!
     
  38. Deleted User

    Deleted User

    Guest

    I figured it out suprisingly easily.
    However, I think I'm now at a new roadblock.
    Is it possible for me to make it so the player's input is done overlayed onto the already active MPTK player?
    So the game's music just gets turned down slightly but is still audably in the background. I also need to make sure the soundfont for the ocarina playing is "Title screen" at all times, even though the background music is a different soundfont. Also, the midi stream player doesn't seem to work alongside the midifileplayer.
     
  39. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    There is no difficulties for adding a Midi Stream Player and a Midi File Player on the same scne in the hierarchy. Even you can add 10 of each without problem ;-) But they share the same SoundFont because the SoundFont is global to all your project.
     
  40. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    There is a global volume available for each Midi File Player.
    I'm not sure to understanding your question, I hope it's clear ?
     
  41. Deleted User

    Deleted User

    Guest

    I worded it badly. I now have them alongside eachother in the same prefab and can indeed easily control their seperate volumes, but just like you said, I wanted to point out that the soundfont is global. And that there's probably no way to have both be playing from seperate soundfonts at the same time.. :(
     
  42. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    I confirm the SoudFont is global and shared with all Maestro components. Only one can be enabled at a time but you can change or load SF at runtime.
    Don't forget, you can have more than 16000 presets/instruments (127 x 128) with one SoundFont. Is it not enough ?
    More of that, it's also possible to create your own SoundFont by copy/paste between them. See here https://www.polyphone-soundfonts.com/download-soundfonts
    It's a free tool to build SoundFont + a huge referential of SoundFonts. A must have!
    Thierry

    upload_2021-8-14_8-43-5.png

    upload_2021-8-14_8-44-21.png
     
  43. HEATH3N

    HEATH3N

    Joined:
    Jul 19, 2014
    Posts:
    17
    Hello,

    What is the best way to get a list of each track's events? Specifically, I am making a piano application and want to automatically figure out the left hand and right hand tracks. Sometimes my MIDI files have random extra tracks so I want to get the two tracks with the most notes and then take the average value of all NoteOn events. The higher number will probably be the right hand and the lower number will probably be the left hand.

    I have looked at MidiFilePlayer.midiLoaded.midiFile.Events but that only gives me MidiEvent objects which don't have the values for NoteOn. Is there a different place I should look to get MPTKEvent objects and do what I want?
     
  44. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Hello, If I well understand, you want to analyse the MIDI file between playing it ?
    The prefab MidiFileLoader could help you:
    upload_2021-8-15_10-1-0.png

    Have a look to the demo and the source code TestMidiFileLoad.cs
    upload_2021-8-15_10-0-4.png

    Hope that help!

    Thierry
     
  45. GroveJr

    GroveJr

    Joined:
    Nov 15, 2019
    Posts:
    17
    Hi, I've got this confusing error and it only happens to MidiStreamPlayer not MidiFilePlayer where the channel will randomly changes its bank after MidiFilePlayer is played again, making you unable to force set the preset on that channel. I created a custom script that will change the channel's preset with my data. For debugging purpose, I printed on the console which bank is used by which channel.

    upload_2021-8-20_16-52-57.png

    After restarting several times, channel 3's bank switches to -1 causing an error that will make you unable to change its preset during runtime for the duration of the midi.

    upload_2021-8-20_17-1-6.png

    After 18 tries, channel 3's bank is switched to -1 twice and 1 once. Do you know what's causing it to change the bank? All instrument channels are using bank 0 by default. Thank you.
     
  46. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Hello, I'm sorry but it's quite hard to understand your concern. You want to change bank for a MidiStreamPlayer ? If possible, you could send me a Unity package with your issue ?
     
  47. GroveJr

    GroveJr

    Joined:
    Nov 15, 2019
    Posts:
    17
    Hi, I'm sorry but I don't have the right to share the project. Basically, what I'm trying to do is to force change a channel with a specific preset but sometimes it looks in the wrong bank as shown on my example screenshot. As you can see, channel 3 is using bank 0 but sometimes the MPTK_ChannelForcePreset is looking at the wrong bank (-1 or 1) resulting in an error as bank -1 is non existent and my SoundFont doesn't have bank 1 yet. Even if my SoundFont has bank 1, it will result in changing to the wrong preset because I wanted to change it to, say, preset 4 on bank 0 not bank 1.
     
  48. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Hi. That will be hard to find a solution if I can't reproduce the issue. Nevermind, I will try with the demo TestStramPlayer.
     
  49. BachmannT

    BachmannT

    Joined:
    Nov 20, 2016
    Posts:
    387
    Could you explain to me what method are you using for changing bank ?
    MPTK_ChannelPresetChange?
    or standard MIDI change message ?
    like
    midiStreamPlayer.MPTK_PlayEvent(new MPTKEvent() { Command = MPTKCommand.ControlChange, Controller = MPTKController.BankSelectMsb, Value = index, Channel = 0, });
     
  50. GroveJr

    GroveJr

    Joined:
    Nov 15, 2019
    Posts:
    17
    I'm not changing the bank at all. All I did was call MPTK_ChannelForcedPreset for each channel detected on the current midi played. I had to use midiStreamPlayer.MPTK_ChannelForcedPreset instead of midiStreamPlayer.MPTK_ChannelPresetChange because MPTK_ChannelPresetChange gets overwritten when MidiFilePlayer starts playing for the first time. If there's a similar method like MPTK_ChannelForcedPreset(int channel, int preset, int bank), that would help me a lot.