QB64-Phoenix-Edition / QB64pe

The QB64 Phoenix Edition Repository
https://qb64phoenix.com
Other
125 stars 26 forks source link

Add MIDI support to _SNDOPEN() #115

Closed hackwrench closed 2 years ago

hackwrench commented 2 years ago

No sounds currently mix and play one after each other. Sound effects/speech can't play in music.

mkilgore commented 2 years ago

Can you give an example of what you're doing that doesn't work? I just did a sanity check with two _SndPlayCopys and they play at the same time and get mixed as expected. Whether you get the mixing will depend on what commands you're using to play the sounds though.

hackwrench commented 2 years ago

QB64pe still compiles the two parameter _SNDOPEN no longer apparently mentioned in the wiki. SELECT CASE UCASE$(RIGHT$(Filename$, 4)) CASE ".WAV": SoundSet$ = "VOL,SYNC,LEN,PAUSE" CASE ".OGG": SoundSet$ = "VOL,SYNC,LEN,PAUSE" CASE ".AIF": SoundSet$ = "VOL,SYNC,LEN,PAUSE" CASE ".RIF": SoundSet$ = "VOL,SYNC,LEN,PAUSE" CASE ".VOC": SoundSet$ = "VOL,SYNC,LEN,PAUSE" CASE ".MID": SoundSet$ = "VOL" CASE ".MOD": SoundSet$ = "VOL,PAUSE" CASE ".MP3": SoundSet$ = "VOL,PAUSE,SETPOS" END SELECT IF SoundSet$ <> "" THEN LoadSound& = _SNDOPEN(Filename$, SoundSet$)

mkilgore commented 2 years ago

I see, I'm not sure why the wiki doesn't mention that parameter at all but I believe those settings are unnecessary now. A change was made to the backend of QB64 and all the settings are applicable to all calls to _SNDOPEN() (AFAIK anyway...).

Are you seeing a behavior difference due to this compared to previous versions, and can you give a more complete example that doesn't work?

I would note that for each sound you want to play mixed you need a new _snd handle, either via _SNDOPEN() or _SNDCOPY().

hackwrench commented 2 years ago

This file compiles, runs and doesn't play the MIDI file. Comment appears to be ignoring the code delimiter. `

Filename$ = "TONOWH~2.MID" Select Case UCase$(Right$(Filename$, 4)) Case ".WAV": SoundSet$ = "VOL,SYNC,LEN,PAUSE" Case ".OGG": SoundSet$ = "VOL,SYNC,LEN,PAUSE" Case ".AIF": SoundSet$ = "VOL,SYNC,LEN,PAUSE" Case ".RIF": SoundSet$ = "VOL,SYNC,LEN,PAUSE" Case ".VOC": SoundSet$ = "VOL,SYNC,LEN,PAUSE" Case ".MID": SoundSet$ = "VOL" Case ".MOD": SoundSet$ = "VOL,PAUSE" Case ".MP3": SoundSet$ = "VOL,PAUSE,SETPOS" End Select If SoundSet$ <> "" Then LoadSound& = _SndOpen(Filename$, SoundSet$)

MySound& = _SndCopy(LoadSound&) _SndPlay MySound& Do: Loop Until Not _SndPlaying(MySound&) _SndClose MySound& _SndClose LoadSound& `

hackwrench commented 2 years ago

` Print "Press any key to start" Do: Loop Until InKey$ <> "" Filename$ = "TONOWH~2.MID" LoadSound& = _SndOpen(Filename$)

MySound& = _SndCopy(LoadSound&) _SndPlay MySound& Do: Loop Until InKey$ <> "" _SndClose MySound& _SndClose LoadSound& ` My current Testing Code. The MIDI doesn't play and wavs apparently have noise before and after.

mkilgore commented 2 years ago

I'm not sure about the noise with the wav file, but I believe MIDI files are not supported (and the Wiki seems to say as much). I believe they were supported in the past at one point but it was dropped when the audio backend was changed.

hackwrench commented 2 years ago

A pity. A lot of QB programs used SBMIDI to play midi files, so it'll be more difficult to port them.

mkilgore commented 2 years ago

I think that's a reasonable ask, I'd be happy to turn this card into a card for adding midi support if you'd like.

hackwrench commented 2 years ago

Yes please.

hackwrench commented 2 years ago

At one point, oddly enough, wave files WERE mixing with midi files if the midi files were played first, but it broke in whatever version of QB64 I last used that had midi support. I can download the various midi supporting QB64s from archive.org and report their behaviors if you'd like.

mkilgore commented 2 years ago

I very much appreciate the offer, but unfortunately I don't think it would be very helpful. Those versions are quite old and all the relevant code has been replaced, that's why it broke xD

Really the big first step is to figure out a candidate C or C++ library (or maybe write it ourselves?) that we could integrate for midi support. It would need to be able to take the MIDI file and produce 16-bit audio, and from there we can feed that into all the regular audio stuff and it should work as expected.

You can see examples of audio libraries we already use here.

a740g commented 2 years ago

I got MIDI working using a tiny C header library that I put together. Repo: https://github.com/a740g/AlienAlleyQB64 C header: https://github.com/a740g/AlienAlleyQB64/blob/master/MIDIPlayer.h

'-----------------------------------------------------------------------------------------------------
' EXTERNAL LIBRARIES
'-----------------------------------------------------------------------------------------------------
Declare Library "./MIDIPlayer"
    Sub MIDIInit ' Initializes stuff - call this before using the library
    Sub MIDIDone ' Frees allocated memory - this must be called once we are done with the MIDI (or else we will leak memory)
    Function MIDIRegister& (mididata As String) ' Sets up and opens the WinMM MIDI stream - mididata here is string buffer!
    Sub MIDIUnregister ' Closes the WinMM MIDI stream
    Sub MIDIPlay (ByVal looping As Long) ' Kickstarts MIDI stream playback
    Sub MIDIPause ' Pauses a MIDI stream
    Sub MIDIResume ' Resumes a paused MIDI stream
    Sub MIDIStop ' Stops playing the MIDI file - this does not free resources!
End Declare
'-----------------------------------------------------------------------------------------------------

See Sub PlayMIDIFile (fileName As String) to see how this is used.

The only drawback is that it uses WinMM MIDI Streaming APIs. So, it is Windows only.

My recommendation would be to implement MIDI using FluidSynth so that the sample bits are stored in a sound buffer (just like wav, ogg, mp3 etc.) and played from there (in case someone needs those).

mkilgore commented 2 years ago

I took a look at FluidSynth, it definitely has potential but I think it looks a bit complicated to integrate into QB64pe (IE. Complicated/messy to compile it ourselves and statically link it into QB64pe), and also I really think we should avoid taking on any more LGPL licensed dependencies if possible (I would argue the existing audio ones need to be replaced, but that's a separate conversion...). Still it seems like a reasonable option.

That said, the good news is that SDL_Mixer (literally the library we used to use for MIDI support) just uses another separate library called timidity to implement support. It both has a fairly easy API to use that can give us a produced sound buffer from the MIDI file, and also a reasonably open license. So from my view this seems like the best option, since it can be added relatively easily and is basically guaranteed to provide the support we had before.

If someone wants to give it a try I would definitely encourage you to do so :) If not then I can put it on my (ever growing...) list. #46 is quite close to having an MVP done, and then I think I'll take a look at some of these asks we've received.

a740g commented 2 years ago

Well, the only issue I have with Timidity is that it has poor support for SoundFonts compared to FluidSynth. There is a standalone version of libTimidity without the SDL dependencies. I'll try to play with this to see if there is anything interesting.

mkilgore commented 2 years ago

The libTimidity you found is fairly convenient, I assumed we'd have to do that work ourselves :) And that's a very fair point on FluidSynth, I don't really know much on how the features compare. I will say that getting FluidSynth integrated may not be as hard as I anticipated, so it might still be worth consideration, but the LGPL license will still be an issue unfortunately.

a740g commented 2 years ago

Ok. I tried using libTimidity and here are my findings:

Naturally, I began to think about using FluidSynth. However I resisted myself because of the licensing issue you mentioned.

Luckily, while researching, I stumbled upon TinySounFont. This is a MIT licensed C single-header STB style library. It also includes a zlib licensed C single-header SMF parser TinyMidiLoader (TML). Although these may not be feature packed or accurate as FuildSynth, these are quite good considering the amount of code and size. This is also used by the EDuke32 game engine.

So, I tasked myself to write a TSF+TML based multiplatform MIDI library for QBPE and here it is. 🙂 There is a soundfont included that gets compiled as a C data array. So, the user does not need to distribute any supporting files.

mkilgore commented 2 years ago

The limitations for libTimidity are odd to me, just because we basically used to use it and I don't remember it having any huge issues. Perhaps they were always there though and I just never noticed, that's entirely possible XD

That said TinySoundFont looks even nicer to use, and the example you made is perfect, it shows pretty much exactly what we would need to do to use it :) The only thing that jumps out a bit is the size of the soundfont.h file, but I'm not sure how much that actually translates to increased EXE size.

I don't know if you were planning on trying to implement this functionality in QB64 yourself, but it seems straight-forward enough that I might give it a go later and let you know what happens.

a740g commented 2 years ago

I would love to do the QB64 integration myself but I really do not know if I can do justice with my day job and the limited time I have. Plus, there is one more issue that we need to solve and you mentioned it above - soundfont.h. This is another can of worms.

Basically, this is a .sf2 file converted to a C header using the xxd -i -c 16 soundfont.sf2 soundfont.h Linux command. The problem here is, if you use this, it will add ~3.5 MB to the executable because that is the size of the soundfont.

The important issue here is finding a soundfont that is free and small that we can distribute with QB64. The soundfont in my example is a Roland SCC1 quality soundfont from https://www.vogonsdrivers.com/getfile.php?fileid=500&menustate=0. I am currently not sure if we can distribute thus stuff. GZDoom uses a soundfont which should be free. But I have not played with it yet and am not sure about the licensing.

a740g commented 2 years ago

Ok. Quick update.

I checked gzdoom.sf2 from GZDoom and they are using the same soundfount that I was using. I just spent some time listening to a dozen MIDI tunes as they all sound decent with this 3.5 MB soundfont.

Now the real question is - are we ok to add this 3.5 MB to the executables that QB64 compiles?

mkilgore commented 2 years ago

I could potentially see it as acceptable if we made MIDI support optional via some meta-command - that way you don't pay that file-size cost unless you explicitly opt-in to MIDI support. We could also potentially compress it internally via libz, that might be able to shrink it a bit. I feel like something's missing though, I don't think SDL_Mixer ever had to pay this file size cost or needed any extra files, I might take a look to understand what it was doing.

We could also probably just allow the user to specify the soundfont file to use (either compiled in, or loaded separately) and ship a default one. That way it's up to the user how big of a file they want to use.

a740g commented 2 years ago

Ok. I figured it out. SDL_Mixer uses a codec called native_midi. This uses the OS native MIDI capabilities (just like the one I made for Alien Alley QB64). Hence, even if no soundfont is present for Timidity SDL_Mixer will fall back to native_midi.

native_midi has a zlib License and looks easy since I've already done something like this for Windows. I can easily test the Linux side of things. But macOS stuff would be a no-go for me because I do not have any Apple system.

We will surely be lean if we use this but:

We can also restore some lost functionality by looking at the code from QB64-SDL.

Also, now that you have motivated me enough, I am also thinking about replacing the entire QB64 audio stack with miniaudio in an effort to move away from the GPL OpenAL-soft which I think is overkill for QB64. This will be my personal project for now and I'll make the code public once I have something going. Let me know what you think.

mkilgore commented 2 years ago

I really appreciate you looking into this :) I think the native MIDI support is workable, I agree the fact that it won't generate the 'samples' might cause some problems for support, but if we change the _SND internals a bit we should be able to work arond it. Some things like _SNDBAL might go unsupported for MIDI handles but I think that's acceptable.

I agree the quality might be a concern, but it presumably should be good enough. Sometime later if it's wanted we could add optional support for another MIDI handler that could be provided a soundfont for those who want better quality.

Also interesting find with miniaudio. I looked for replacements for OpenAL not that long ago but didn't really find anything great. miniaudio looks quite promising, if you make progress on it I'd definitely be interested to see it :)

mkilgore commented 2 years ago

I'm finally giving this a good look and will hopefully start on some code :) I think this is a sane path forward, but I'd like to get your (@a740g) opinion on it:

  1. Use TinySoundFont for universal support for Windows, Linux, and OSX.

    • MIDI support will be enabled via a metacommand to specify usage of either a soundfont supplied by the programmer, or a default one provided by QB64pe. In either case, the soundfont is compiled directly into the program and loaded on start-up. The point of enabling via metacommand is to avoid paying the file size cost for the soundfont if you don't need MIDI support.
    • An additional command for loading in a soundfont at runtime could be provided as well. This would allowing shipping the soundfont separately from the executable.
    • The default soundfont needs to be decided upon. gzdoom.sf2 is an option but the size is on the bigger side for embedding. TinySoundFont has a florestan-subset.sf2 which is only 500kb, which seems more reasonable to me. That said I have no idea how to evaluate if the quality is acceptable or if it will destroy everyone's ears, I'd like to defer to you on that 😆
  2. Add optional support for native MIDI playing on Windows.

    • This is an alternative for TinySoundFont, only for Windows (Linux has no native MIDI support, OSX is unclear and would be hard to test...). QB64pe would allow the programmer to pick which one of these providers is used to play MIDI files on Windows.
    • The reason to provide this option is to allow avoiding the file size increase from providing a soundfont. With that, because there is no file size real cost to this provider it can potentially be enabled all the time, even without the metacommand required for TinySoundFont support. How we actually want this to work needs to be determined.
    • _SND handles for MIDI files using this provider will be restricted in what they can do, likely no more than setting the volume, and play/pause/loop/etc. What happens when you use the other commands on these handles (Nothing? Error?) needs to be determined. SDL previous worked this way, so we could probably just copy that behavior (if it seems to make sense).
    • Providing this support probably requires some factoring of the sound internals, since there will be no associated sound buffer for these handles.

With that said, that's a long list of things and I don't think it makes sense to try to add it all at once :) For an 'MVP' I'm thinking it makes sense to focus on just TinySoundFont support along with using a default provided soundfont, since I think that's the most straight-forward stuff to implement and provides support for all of our platforms. Specifying your own soundfont (at compile time or runtime), and native MIDI support for Windows, would be separate things worked on after the initial support is finished.

a740g commented 2 years ago

Use TinySoundFont for universal support for Windows, Linux, and OSX.

Yes. This is a good way to go forward. TSF has much better quality than system MIDI (especially when using a superior quality soundfont).

MIDI support will be enabled via a metacommand to specify usage of either a soundfont supplied by the programmer, or a default one provided by QB64pe. In either case, the soundfont is compiled directly into the program and loaded on start-up. The point of enabling via metacommand is to avoid paying the file size cost for the soundfont if you don't need MIDI support.

Agreed. There are smaller soundfonts like the 1 MB GM soundfont 1mgm.sf2 from E-mu. I'm not sure about the license. However, the dos-like project seems to use this with a MIT license. I like the idea of embedding a small soundfont and let the user load a better one should they choose. I have already coded such a setup in QB64-MIDI-Player, where the tiny 1mgm.sf2 soundfont will be part of the executable and if the user chooses, they can make the library load a custom soundfont by naming it soundfont.sf2 and placing it in the same directory as the executable.

An additional command for loading in a soundfont at runtime could be provided as well. This would allowing shipping the soundfont separately from the executable. The default soundfont needs to be decided upon. gzdoom.sf2 is an option but the size is on the bigger side for embedding.

Agreed.

TinySoundFont has a florestan-subset.sf2 which is only 500kb, which seems more reasonable to me. That said I have no idea how to evaluate if the quality is acceptable or if it will destroy everyone's ears, I'd like to defer to you on that 😆

Negative. This was one of the first soundfonts I tested. This is missing a lot of standard GM instruments to cut down the file size. Alomst all MIDIs played with this comes out wrong. It seems like this soundfont is designed to play the example MIDI included in the TSF repo.

Add optional support for native MIDI playing on Windows.

Totally agree!

This is an alternative for TinySoundFont, only for Windows (Linux has no native MIDI support, OSX is unclear and would be hard to test...). QB64pe would allow the programmer to pick which one of these providers is used to play MIDI files on Windows. The reason to provide this option is to allow avoiding the file size increase from providing a soundfont. With that, because there is no file size real cost to this provider it can potentially be enabled all the time, even without the metacommand required for TinySoundFont support. How we actually want this to work needs to be determined.

Hmmm. I that case we really need to check what native_midi in SDL_mixer is doing while supporting MIDI on Linux and macOS.

_SND handles for MIDI files using this provider will be restricted in what they can do, likely no more than setting the volume, and play/pause/loop/etc. What happens when you use the other commands on these handles (Nothing? Error?) needs to be determined. SDL previous worked this way, so we could probably just copy that behavior (if it seems to make sense).

Agreed. I vote against throwing errors. It should silently ignore commands that do not make sense. Now that I am re-implementing the whole QB64 audio stack with miniaudio, I feel that the API could have been designed a lot better. Steaming media (music) and sound effects should have different APIs. But I guess it's too late for changes. It's been like this since the QB64-SDL days. Oh well. This is my personal opinion.

Providing this support probably requires some factoring of the sound internals, since there will be no associated sound buffer for these handles. With that said, that's a long list of things and I don't think it makes sense to try to add it all at once :) For an 'MVP' I'm thinking it makes sense to focus on just TinySoundFont support along with using a default provided soundfont, since I think that's the most straight-forward stuff to implement and provides support for all of our platforms. Specifying your own soundfont (at compile time or runtime), and native MIDI support for Windows, would be separate things worked on after the initial support is finished.

Totally agree. Setup a roadmap and implement features in small chunks so that we have enough time for testing. While we are at this, we should also consider adding MOD, XM, S3M & IT support using LibXMP. The way TSF and LibXMP expose some of its APIs are remarkably similar and using LibXMP would be trivial if we had already used TSF. 🙂

mkilgore commented 2 years ago

Negative. This was one of the first soundfonts I tested. This is missing a lot of standard GM instruments to cut down the file size. Alomst all MIDIs played with this comes out wrong. It seems like this soundfont is designed to play the example MIDI included in the TSF repo.

Fair enough :) We have a bit of time to figure out which one to use. I definitely like your suggestion of 1mgm.sf2, I tried to do some digging on where it came from but was unsuccessful so far :-/

Hmmm. I that case we really need to check what native_midi in SDL_mixer is doing while supporting MIDI on Linux and macOS.

I'm pretty sure it just doesn't do anything. None of the source files would provide support for Linux, and the build scripts seem to check the host, which also doesn't include Linux. I don't think this is surprising though because Linux doesn't offer any native MIDI capabilities like Windows does. It does include OSX support, but I see some issues/PRs about it and the challenge of us supporting it seems high since none of the active developers use OSX. I think we can probably just stick with TinySoundFont for OSX unless someone actually asks about it.

On that note I made pretty good progress today on adding MIDI support. It's in my add-initial-midi-support branch and you can see the bulk of the changes here. It's actually functional :D I think the only big thing left is compiling in the soundfont, adding the metacommand to enable it, and writing some tests. I might also refactor the code structure a bit, the midi_init() thing is a little messy in my view, I might try to tie it into snd_init() somehow.

You can try it from one of these CI builds if you want. You need a file called soundfont.sf2 in the same directory as your exe when you run it, and just use _SNDOPEN() to open the MIDI file.

a740g commented 2 years ago

I'm pretty sure it just doesn't do anything. None of the source files would provide support for Linux, and the build scripts seem to check the host, which also doesn't include Linux. I don't think this is surprising though because Linux doesn't offer any native MIDI capabilities like Windows does. It does include OSX support, but I see some issues/PRs about it and the challenge of us supporting it seems high since none of the active developers use OSX. I think we can probably just stick with TinySoundFont for OSX unless someone actually asks about it.

Ok. I took a closer look and you are right. Agree with sticking with TSF for all platforms for now. As you said, we can explore native MIDI option for Windows later.

On that note I made pretty good progress today on adding MIDI support. It's in my add-initial-midi-support branch and you can see the bulk of the changes here. It's actually functional :D I think the only big thing left is compiling in the soundfont, adding the metacommand to enable it, and writing some tests. I might also refactor the code structure a bit, the midi_init() thing is a little messy in my view, I might try to tie it into snd_init() somehow.

You can try it from one of these CI builds if you want. You need a file called soundfont.sf2 in the same directory as your exe when you run it, and just use _SNDOPEN() to open the MIDI file.

This is fantastic! I'll give it a spin. Since you are rendering the whole tune in one go, it should nicely work with the rest of the audio API. 🙂

a740g commented 2 years ago

@mkilgore I have tested the add-initial-midi-support branch and it's working well. However, the program just crashes if no soundfont.sf2 file is present. In these cases, it should silently ignore the request to play the midi file. I eyeballed the code a little and I can see that you've used if (!midi_soundfont) in the right places. However, I guess something is escaping this. Not really sure though.

mkilgore commented 2 years ago

Good catch, I need to adjust that logic anyway but midi_init() isn't handling midi_soundfont being NULL after the return. It passes it to tsf_channel_set_bank_preset which probably blows up if it is NULL.

a740g commented 2 years ago

Good catch, I need to adjust that logic anyway but midi_init() isn't handling midi_soundfont being NULL after the return. It passes it to tsf_channel_set_bank_preset which probably blows up if it is NULL.

Yes. That's exactly what is blowing up. 🙂

You may also want to emulate QB64 path behavior (the CWD$ & STARTDIR$ stuff) since you are letting TSF load the soundfont. midi_soundfont = tsf_load_filename("soundfont.sf2")

Running programs from the QB64 IDE looks for soundfont.sf2 in the QB64 directory and running the compiled executable standalone looks for it in the program directory or whatever directory it is started from. Alternatively, you can simply load the whole file in memory (like func__sndopen does) and then pass the buffer to tsf_load_memory. I am quite certain the buffer can be freed after TSF is initialized.

mkilgore commented 2 years ago

You may also want to emulate QB64 path behavior (the CWD$ & STARTDIR$ stuff) since you are letting TSF load the soundfont. midi_soundfont = tsf_load_filename("soundfont.sf2")

That's all fixed :) I implemented build logic to include the soundfont in the executable, so the path is no longer a concern. There is still the issue surrounding the path resolution at compile time (similar to the other issues you've found like #124) but that can be fixed, I don't think it's quite ready to be merged just yet anyway.

That said, if you get a chance please try it out :) The commit with the new stuff is here, and there's a built currently going that should hopefully pass. I've introduced two new commands:

$Unstable: Midi

$MidiSoundFont: Default
$MidiSoundFont: "soundfont.sf2"

The $Unstable command is required to be able to use any of the other commands, and simply signifies that this functionality isn't finalized yet. My intention is that the next release will have this hidden behind $Unstable: Midi so we can gather some feedback on it, and then we'll have the opportunity to potentially change the API a bit before it becomes as a proper part of the language.

The $MidiSoundFont command is how you specify the soundfont to use. Default just makes use of the one we ship with QB64, and otherwise you can specify a path to one you supply yourself.

a740g commented 2 years ago

$Unstable: Midi

$MidiSoundFont: Default $MidiSoundFont: "soundfont.sf2"

I finally got some time to test this. I cloned your repo (add-initial-midi-support branch) and then built QB64 using setup_win.bat. However, when I am running the example, I am not getting any sound. I am running this directy from the repo directory and the midi file is in the same directory along with a soundfont. Seems like it is not loading the file for some reason (handle = 0).

untitled.bas

Dim l As Long
l = _SndOpen("foobar.mid")

Print "Handle ="; l

_SndPlay l

Do
    _Delay .1
    Locate 3, 3
    Print "Position: "; _SndGetPos(l); "             ";
Loop While _KeyHit <> 27

End

Output

image

Also, I am not able to use the Unstable meta commands.

image

What am I doing wrong?

mkilgore commented 2 years ago

Sorry, I should have clarified a bit on how to get it to work :-/ I was hoping you could just use one of the CI builds, but they failed and I haven't had a chance to fix it yet.

To get Midi to work you need to have both of those commands in your program, that's why your first example doesn't work. When MIDI support is not enabled the file just fails to load at runtime (the same as it did before).

./setup_win.bat builds a precompiled copy of QB64 located in ./internal/source. I haven't updated that precompiled copy to have my changes (that happens automatically when merging to the main repo), so the QB64 you got from ./setup_win.bat doesn't understand the MIDI commands. To create a copy of QB64 that does understand them, you should use the copy of QB64 you got from ./setup_win.bat to build ./source/qb64.bas. That will build a new version of QB64 directly from the source I changed, and that new one will understand the MIDI commands.

a740g commented 2 years ago

Ok. I compiled QB64 from ./source/qb64.bas. Now it understands the MIDI command and compiles the example. However, the example crashes with an access violation when started.

Second chance exception 0xC0000005 (Access Violation) occurred in "NTDLL.DLL" at address 0x00007FFB3FF91A22.

I checked the executable with a hex editor and can see that the soundfont is being linked correctly. So not sure what is going on.

mkilgore commented 2 years ago

Well that's not great :-/ Unfortunately I don't get that. Can you check if a program with nothing in it (besides the two midi commands) still blows up? And if it doesn't, can you try adding commands back in until it does?

a740g commented 2 years ago

Well that's not great :-/ Unfortunately I don't get that. Can you check if a program with nothing in it (besides the two midi commands) still blows up? And if it doesn't, can you try adding commands back in until it does?

With a program with just those two lines, we get a compilation error.

image

Here is the compiler log.

internal\c\c_compiler\bin\c++.exe  -w -std=gnu++11 -DGLEW_STATIC -DFREEGLUT_STATIC -Iinternal\c\libqb/include -DDEPENDENCY_NO_SOCKETS -DDEPENDENCY_NO_PRINTER -DDEPENDENCY_NO_ICON -DDEPENDENCY_NO_SCREENIMAGE internal\c/qbx.cpp -c -o internal\c/qbx.o
cd internal\temp && ..\..\internal\c\c_compiler\bin\objcopy.exe -Ibinary -Oelf64-x86-64 -Bi386:x86-64 soundfont.sf2 soundfont.o
internal\c\c_compiler\bin\c++.exe  -w -std=gnu++11 -DGLEW_STATIC -DFREEGLUT_STATIC -Iinternal\c\libqb/include -DDEPENDENCY_NO_SOCKETS -DDEPENDENCY_NO_PRINTER -DDEPENDENCY_NO_ICON -DDEPENDENCY_NO_SCREENIMAGE internal\c/libqb_make_0000000000000.o  internal\c/qbx.o -o 'C:\Users\samue\Downloads\QB64pe-add-initial-midi-support\untitled.exe'  internal\c\libqb/src/threading.o internal\c\libqb/src/buffer.o internal\c\libqb/src/threading-windows.o internal\c/parts/audio/decode/midi/tml_impl.o internal\c/parts/audio/decode/midi/tsf_impl.o internal\c/parts/audio/decode/midi/midi.o internal\temp/soundfont.o internal\c/parts/core/src.a  -static-libgcc -static-libstdc++ -mwindows -lopengl32 -lglu32 -lwinmm
internal\c/parts/audio/decode/midi/midi.o:midi.cpp:(.rdata$.refptr.snd_sequences[.refptr.snd_sequences]+0x0): undefined reference to `snd_sequences'
collect2.exe: error: ld returned 1 exit status
mingw32-make: *** [Makefile:375: C:\Users\samue\Downloads\QB64pe-add-initial-midi-support\untitled.exe] Error 1
mkilgore commented 2 years ago

Oh, sorry that part is my fault, I hadn't decided what to do with that and forgot about it :-/ To compile correctly Midi (and the other decoders) require the rest of the audio system to be include. At the moment you have to use at least one _SND command in your program to get it to compile. You could probably put it after a SYSTEM or END command so it doesn't actually execute.

That said, I'll fix that compilation issue and also try to get the build working, that way you could just try the prebuilt CI version rather than having to build it yourself. There shouldn't be anything wrong with your built version, but it's one less variable to worry about. I'll also try a bit more to recreate your issue.

a740g commented 2 years ago

Oh, sorry that part is my fault, I hadn't decided what to do with that and forgot about it :-/ To compile correctly Midi (and the other decoders) require the rest of the audio system to be include. At the moment you have to use at least one _SND command in your program to get it to compile. You could probably put it after a SYSTEM or END command so it doesn't actually execute.

That said, I'll fix that compilation issue and also try to get the build working, that way you could just try the prebuilt CI version rather than having to build it yourself. There shouldn't be anything wrong with your built version, but it's one less variable to worry about. I'll also try a bit more to recreate your issue.

Ok. I compiled the following.

$Unstable:Midi
$MidiSoundFont:Default

End

l = _SndOpen("foobar.mid")

This too crashed with an access violation. So, I did the following:

None of these worked and the outcome was the same. Guess I'll wait for the prebuilt CI version.

mkilgore commented 2 years ago

Sorry, I should have followed up with you, I got a passing CI build on my branch two days ago, you can find it here. Try downloading the qb64-win-x64-0.8.2--71068afa8 artifact, and then extract the 7zip file inside, that file is the same as a regular release of QB64. I tried it on my machine and the compiled programs work, if they don't for you then that's concerning. My test program:

$Unstable:Midi
$MidiSoundFont:Default

l = _SndOpen("foobar.mid")

_SndPlay l
a740g commented 2 years ago

Sorry, I should have followed up with you, I got a passing CI build on my branch two days ago, you can find it here. Try downloading the qb64-win-x64-0.8.2--71068afa8 artifact, and then extract the 7zip file inside, that file is the same as a regular release of QB64. I tried it on my machine and the compiled programs work, if they don't for you then that's concerning. My test program:

$Unstable:Midi
$MidiSoundFont:Default

l = _SndOpen("foobar.mid")

_SndPlay l

The issue remains the same for me even with the CI build. But here is what I discovered.

If I run the following it works:

Beep
End

I get an access violation when I run this:

$Unstable:Midi
$MidiSoundFont:Default

Dim h As Long
h = _SndOpen("examples_venture.mid")

End

This also gives me an access violation:

$Unstable:Midi
$MidiSoundFont:Default

End

Beep
mkilgore commented 2 years ago

Well that's unfortunate :-/ Sorry about that, I'll play around with it and see if I can figure out what's happening.