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

MIDI Update #517

Merged
merged 27 commits into from
Jul 6, 2024
Merged

MIDI Update #517

merged 27 commits into from
Jul 6, 2024

Conversation

a740g
Copy link
Contributor

@a740g a740g commented Jul 3, 2024

This PR moves MIDI support in QB64-PE out of $UNSTABLE. Additionally, it addresses the issue highlighted here.

Changes:

  • The compiled executable will no longer include an embedded soundfont.
  • To address the issue discussed in the forum, ymfmidi, Opal, and a tiny FM bank are now used.
  • Soundfonts can be loaded using the _MIDISOUNDBANK command.
  • Depending on the sound bank type, a suitable MIDI rendering backend is selected.
  • The available backends are primesynth (SF2), TinySoundFont (SF3, SFO), and Opal (AD, OPL, OP2, TMB, WOPL).
  • For Windows users, a VSTi 2.x based renderer that is configurable by the user is also provided.
  • Multiple MIDI file formats are supported: MUS, HMI, HMP, HMQ, KAR, LDS, MDS, MIDS, RCP, R36, G18, G36, RMI, MID, MIDI, XFM, XMI
  • The use of $UNSTABLE:MIDI and $MIDISOUNDFONT triggers an appropriate warning message.

New command:

_MIDISOUNDBANK fileName$[, flags$] ' flags$ can be "memory" and one of the supported soundfont/FM bank types

@a740g a740g added the enhancement New feature or request label Jul 3, 2024
@a740g a740g self-assigned this Jul 3, 2024
// Only bother setting up the format if we are loading from memory
switch (format) {
case SoundBankFormat::SF2:
g_InstrumentBankManager.SetData(qbsFileName->chr, qbsFileName->len, InstrumentBankManager::Type::Primesynth);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could anything bad happen if someone calls this while audio is playing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a very good question.
primesynth does not support loading banks from memory. So, that's ok.
ymfmidi must parse the bank into its internal structures. So, that should be good too.
TinySoundFont is the only one what uses the sample memory directly from soundfont data during runtime. At least that's what I remember. I'll need to check on this one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good news. I checked the code inside tsf.h and it appears that it allocate the necessary memory and then load the structures and sample data.

Just to be sure. I ran a test with 2 different midis using 2 different soundfonts playing at the same time in streaming mode and it worked fine without blowing up.

}

// Check if the user wants to unset the decode flag
if (requirements.find("nodecode") != std::string::npos) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are decode and stream not mutually exclusive? It's possible to use both, or use neither?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, we were setting up those that way previously. But it turns out, it's really not required.

Without nodecode the sound will be decoded "on-load" to PCM format else it will be loaded in the original compressed format and decoded "on-mix".
Without steam the entire file is loaded into memory (either decoded as PCM or in the original format based on the nodecode flag). However, with steam only small chunks are either decoded or loaded in the original format.

So, in the end, it boils down to when the decoding happens - on load or during mixing. I ran some tests to confirm the behavior.

I think doing it this way allows the user a lot of control. The only problem is _MEMSOUND. But for that, we do check if "stream" is off and "decode" enabled.

@a740g a740g merged commit dbf2c75 into QB64-Phoenix-Edition:main Jul 6, 2024
4 checks passed
@a740g a740g deleted the midi-update branch July 6, 2024 14:18
@a740g a740g added this to the Stabilize MIDI support milestone Jul 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants