Changing Patterns (on-time) Manually...

Started by ryansupak, November 22, 2020, 18:22:21

Previous topic - Next topic

ryansupak

Hi! <3 I'm attempting to use the WASM version of libopenmpt to play an Impulse Tracker pattern -- and to play a second pattern "perfectly" on-time once the first one is completed. (I'm using an overlaid metadata framework, specified by a JSON, as part of an engine for game music to control this flow. I do *not* want to use the standard "Order" mechanic of the .IT file itself to schedule pattern sequences.)

I'm hoping that someone can sanity-check my proposed approach to do this for correctness, simplicity, and stability:

***

1) Pre-prepare the .IT file by setting each Order to the corresponding Pattern number (Order 000 to play Pattern 000, Order 001 to play Pattern 001, etc...). This must be done because libopenmpt can play a specific Order, but not a specific Pattern. So this just keeps things organized ;)

2) In the code, check the "playhead position" every tick (one tick=2500ms/current tempo). (We care about keeping a current tally of the total Rows in the current Pattern, and the total Ticks in the current Row.)

3) If the playhead position is the final row AND the final tick of the current pattern, schedule the next pattern (again, the Pattern to play next is controlled by external code and not the Order of the file itself) to play on the next tick.

***

Thanks for any thoughts or guidance! This seems like the easiest approach but want to be sure I'm not missing something...
rs

Saga Musix

#1
If you have full control over the content, this should work, I think. Otherwise, you would have to keep in mind that there are different tempo modes, which cannot currently be queried from the libopenmpt interface. You can somewhat work around this by using the get_current_estimated_bpm function which gives you the real BPM for every tempo mode, but it may still not be 100% accurate. We plan to provide functions to make this easier in the future but that may still take some time.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

ryansupak

1) I do have full control over the .IT files being used, and the only Tempo/Speed parameters I'm using are those available from Schism Tracker (which AFAIK is the ability to set Initial Tempo and Initial Speed in Song Variables, and the ability to manually set Tempo and Speed via Channel Effects TXX and AXX, respectively.)

2) Honestly, give-or-take a few milliseconds of precision on timing is fine. It sounds like the approach I'm using will get me 99% of the way to perfect accuracy...

Thank you!
rs

ryansupak

#3
Yes -- the aforementioned approach turned out to work perfectly in-browser. As long as you check the Speed at the beginning of each Row (to account for the possibility of an effect AXX changing it), you can even optimize the Web Worker that tracks the "Playhead Status" to only fire as often as it needs to, and not more often than needed.

To achieve what I wanted to (since I'm using chiptune2.js), I did have to expose the following methods in chiptune2.js -- and I will try to Pull Request these back to the main codebase if they want them:


ChiptuneJsPlayer.prototype.getCurrentSpeed()
ChiptuneJsPlayer.prototype.getCurrentTempo()
ChiptuneJsPlayer.prototype.getPatternNumRows(patternNumber)
ChiptuneJsPlayer.prototype.setPositionOrderRow(orderNumber, rowNumber)


rs

Saga Musix

» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.