Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Callback function for (custom) midi events #146

Open
Ghabry opened this issue Jul 22, 2016 · 16 comments
Open

Callback function for (custom) midi events #146

Ghabry opened this issue Jul 22, 2016 · 16 comments

Comments

@Ghabry
Copy link
Contributor

Ghabry commented Jul 22, 2016

Hello, I'm one of the https://github.com/EasyRPG/Player developers which is a reimplementation of the RPG Maker 2000/2003 engine.

We support WildMidi for Midi playback but it lacks one special feature that we need:
MIDI tracks in this engine use midi message 0xB0 (controller change) with argument "111" (0x6F) which is used for defining loop points (when the track ends it loops from the position where it encountered 0x6F) in the MIDI file and we need a way to know when this event happens so we can handle it.

Would it be possible to add a callback function for reacting to midi events from external code or is there any API available in WildMidi that allows us to detect this? Thx.

@Ghabry Ghabry changed the title Enhacement: Callback function for (optional) midi events Enhacement: Callback function for (custom) midi events Jul 22, 2016
@psi29a
Copy link
Member

psi29a commented Jul 25, 2016

Thank you for this!

We're in the middle of figuring out how to deal with looping in general, for things like XMI and other file formats. So this will likely end up in the next release. :)

Thanks.

@Ghabry
Copy link
Contributor Author

Ghabry commented Jul 25, 2016

Cool. Thanks :)

CC @fdelapena (one of our devs):
Could you provide some of the Midi files with a short explanation? Iirc good candidates were boss3.mid and the "broken" item.mid with the command on the wrong track 0 instead of 1.

@Ghabry Ghabry changed the title Enhacement: Callback function for (custom) midi events Callback function for (custom) midi events Jul 25, 2016
@psi29a
Copy link
Member

psi29a commented Jul 25, 2016

Are these MIDI Type 2 files by any chance?

If a file is 'broken' then there is little that we can do at the moment, we're aiming to be strict on MIDI rendering.

Is there anyway that you can remake your 'broken' item.mid file?

@fdelapena
Copy link

Thank you for the support!
As far as I know, there is no standard specification of loop in standard midi files, at least in formats 0 and 1.

The channel 1 controller change (0xB0) with param1 with 111 (0x6F) value is a propietary way used by RPG Maker 2000 to specify this. It seems to be allowed to be placed in any track (usually in track 1 but still works even in track 0, which is clearly incorrect for MIDI format type 1). The event time where is placed is the loop start place.

I remember other MIDI files using their own propietary way by using text markers with specific values to do the same, but for unrelated projects.

For this reason, a possible way to handle these is public API to read midi events and parameters to handle them, and then some API for setting/getting start/end loop for WildMIDI playback control or just play from a specific position (by midi ticks or equivalent), could be a way do this.

@chrisisonwildcode
Copy link
Contributor

I am considering using an api to specify a loop type to enable looping for the different looping instructions. This would enable us to manage looping instructions sanely.

In addition to this I am considering adding support to wildmidi MIDI file output to add the loop instructions to the file data along with a meta event to identify the loop instruction format.

Keep in mind this is just one of the options being considered. Other options may come to light as we explore this further.

Chris

Sent from my iPhone

On 26 Jul 2016, at 6:09 AM, Francisco de la Peña notifications@github.com wrote:

Thank you for the support!
As far as I know, there is no standard specification of loop in standard midi files, at least in formats 0 and 1.

The channel 1 controller change (0xB0) with param1 with 111 (0x6F) value is a propietary way used by RPG Maker 2000 to specify this. It seems to be allowed to be placed in any track (usually in track 1 but still works even in track 0, which is clearly incorrect for MIDI format type 1). The event time where is placed is the loop start place.

I remember other MIDI files using their own propietary way by using text markers with specific values to do the same, but for unrelated projects.

For this reason, a possible way to handle these is public API to read midi events and parameters to handle them, and then some API for setting/getting start/end loop for WildMIDI playback control or just play from a specific position (by midi ticks or equivalent), could be a way do this.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.

@carstene1ns
Copy link
Contributor

Take your time. Until this is implemented, I have created a hack to suffice for us now: master...carstene1ns:rpgmakerloops
Good thing is we can control the used libraries for all embedded platforms we support (i.e. Wii, 3ds, PSP, ...), so we can use my fork for them. Only GNU/Linux users (and maybe Windows in the future, when we drop the direct midi stuff) have no working loop points for now (as they had since beginning of developing the Player anyway)..

@chrisisonwildcode
Copy link
Contributor

You know what, I like this idea. The only issue is do we say something like WildMidi_CustomEventCallback(some function, WMCBO_CONTROLER or _WMCBO_META, event data) ... Or something else ...

In the above example the event data would be the byte[s] following the first byte of the event in big endian order.

Chris

Sent from my iPhone

On 30 Jul 2016, at 11:18 AM, Carsten Teibes notifications@github.com wrote:

Take your time. Until this is implemented, I have created a hack to suffice for us now: master...carstene1ns:rpgmakerloops
Good thing is we can control the used libraries for all embedded platforms we support (i.e. Wii, 3ds, PSP, ...), so we can use my fork for them. Only GNU/Linux users (and maybe Windows in the future, when we drop the direct midi stuff) have no working loop points for now (as they had since beginning of developing the Player anyway)..


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.

@psi29a
Copy link
Member

psi29a commented Jul 30, 2016

@carstene1ns would this be useful for you guys?

@carstene1ns
Copy link
Contributor

Yeah, that should be okay. One problem though, we would need to know from this, when the event occurred. So that we have a sample position we can feed into WildMidi_FastSeek() later.
Is this available in the event data or should we query WildMidi_GetInfo() for current_sample in the callback?

@chrisisonwildcode
Copy link
Contributor

First up, looping itself would be handled elsewhere, I am currently looking into that.

The callback would be intended as a way to setup post-processing of an audio chunk with standard or custom events triggering the setup parameters.

However I can see a possible way that callbacks could be used to alter the internal data being used by the lib ... This would be an at your own risk way of using callbacks and completely unsupported by us as we do not intend the lib or its data to be used in such a way.

Sent from my iPhone

On 30 Jul 2016, at 10:08 PM, Carsten Teibes notifications@github.com wrote:

Yeah, that should be okay. One problem though, we would need to know from this, when the event occurred. So that we have a sample position we can feed into WildMidi_FastSeek() later.
Is this available in the event data or should we query WildMidi_GetInfo() for current_sample in the callback?


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.

@chrisisonwildcode
Copy link
Contributor

Caffeine is slowly making its way into my brain.

How about something like

WildMidi_SetLoopEvent(WMSLE_LOOPSTART|LOOPEND|RETURNTOBEGINING, char* event, int event length)

To tell wildmidi lib that such and such is a loopevent so please do ...

Added bonus is that since you can tell it what event are looping event you could use EOT events to loop tracks that have no looping information *** WITH CAUTION AND USUAL DISCLAIMERS

@chrisisonwildcode
Copy link
Contributor

Add into the previous LOOPCOUNT since I think xmi have a loop count event

@carstene1ns
Copy link
Contributor

Well, these are 2 different things.
In the first case, we handle the looping ourselves, our audio decoder will:

  1. tell the library to open the file
  2. start playback
  3. use WildMidi_CustomEventCallback() to react to the loop point event and store the current sample position
  4. wait for the end of playback
  5. do a fastseek to the loop point that was stored before, go back to step 4.

In the second case, the library handles the loop point, so our audio_decoder will:

  1. tell the library to open the file
  2. start playback
  3. use WildMidi_SetLoopEvent() to make the library loop the track

While the second approach is of course simpler for us, we do not know when the music has looped at all.
In the first approach we know this once we reach step 5.
For the second approach it could be added a new variable loop_count to WildMidi_GetInfo() to make this possible, of course.

@chrisisonwildcode
Copy link
Contributor

They could also work together, with the lib handling the looping and the callback being used to notify the player that the loop event has occurred

I like both ideas so much that I aim to have this done for the next feature release.

Sent from my iPhone

On 1 Aug 2016, at 7:35 AM, Carsten Teibes notifications@github.com wrote:

Well, these are 2 different things.
In the first case, we handle the looping ourselves, our audio decoder will:

tell the library to open the file
start playback
use WildMidi_CustomEventCallback() to react to the loop point event and store the current sample position
wait for the end of playback
do a fastseek to the loop point that was stored before, go back to step 4.
In the second case, the library handles the loop point, so our audio_decoder will:

tell the library to open the file
start playback
use WildMidi_SetLoopEvent() to make the library loop the track
While the second approach is of course simpler for us, we do not know when the music has looped at all.
In the first approach we know this once we reach step 5.
For the second approach it could be added a new variable loop_count to WildMidi_GetInfo() to make this possible, of course.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.

@psi29a
Copy link
Member

psi29a commented Aug 1, 2016

This works very well, also for handling formats with looping built in.

@carstene1ns
Copy link
Contributor

Great, looking forward to that!

@sezero sezero modified the milestones: 0.4.2, 1.0 - Wishlist Nov 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants