Author Topic: how to play MIDI files in QB64 ?  (Read 4765 times)

0 Members and 1 Guest are viewing this topic.

Offline mynameispaul

  • Newbie
  • Posts: 49
    • View Profile
how to play MIDI files in QB64 ?
« on: November 24, 2018, 08:10:20 am »
can someone explain or show me how to play MID (midi) files with QB64 ?
thank you in advance.

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: how to play MIDI files in QB64 ?
« Reply #1 on: November 24, 2018, 09:18:43 am »
Hi. Use external DLL:

Code: QB64: [Select]
  1. DECLARE DYNAMIC LIBRARY "playmidi32"
  2.     FUNCTION PlayMIDI& (filename AS STRING)
  3.  
  4.  
  5. status = PlayMIDI ("midi.mid")
  6.  

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: how to play MIDI files in QB64 ?
« Reply #2 on: November 24, 2018, 09:27:31 am »
Use 32bit IDE for it, please, or it return "CAN NOT FIND DYNAMIC LIBRARY FILE" error. Why 64bit IDE can not use 32bit DLL for backward compatibility i know not...

Offline mynameispaul

  • Newbie
  • Posts: 49
    • View Profile
Re: how to play MIDI files in QB64 ?
« Reply #3 on: November 24, 2018, 12:05:52 pm »
Where within my QB64 folder do I put that DLL file?
And in the source BAS file, what code do I add so that QB64 finds that DLL?

I've been using QB(64) for a long time, but I don't usually write programs that are all that complex.

Thanks again
« Last Edit: November 24, 2018, 12:09:00 pm by mynameispaul »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: how to play MIDI files in QB64 ?
« Reply #4 on: November 24, 2018, 12:47:18 pm »
Use 32bit IDE for it, please, or it return "CAN NOT FIND DYNAMIC LIBRARY FILE" error. Why 64bit IDE can not use 32bit DLL for backward compatibility i know not...

It's because of the way Windows memory works.  https://blogs.msdn.microsoft.com/oldnewthing/20081020-00/?p=20523/

32-bit apps use up to 2GB of memory, which is addressed using a 4-byte offset.  64-bit apps bypass this limit by using 8-byte offsets to address memory...

So think of it as writing a datafile.  Your 32-bit file would write data in chunks of 4 bytes: 1234, 1234, 1234, 1234.  Your 64-bit file would then try and read that as chunks of 8 bytes: 12341234, 12341234...  And one value of 12341234 is not the same thing as two values of 1234...

Windows simply won't mix 32-bit and 64-bit processes.  It's not an issue where QB64 is doing anything wrong; it's simply a limitation in the OS itself.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: how to play MIDI files in QB64 ?
« Reply #5 on: November 24, 2018, 01:29:30 pm »
Quote
Where within my QB64 folder do I put that DLL file?
And in the source BAS file, what code do I add so that QB64 finds that DLL?

I've been using QB(64) for a long time, but I don't usually write programs that are all that complex.

Thanks again

Place DLL file to the same folder as BAS file, but in IDE set "Output EXE to Source folder" as enabled. Also MIDI file place to the same folder. Works in 32bit IDE only.

Quote
Windows simply won't mix 32-bit and 64-bit processes.  It's not an issue where QB64 is doing anything wrong; it's simply a limitation in the OS itself.

Hi Steve. If 32bit IDE works in 64bit Windows 7, so as 64bit IDE works in 64bit Windows 7, why os not IDE writed as in this pseudo code:

SELECT CASE SystemVersion
CASE 32bites: Read memory offset size = 4 bytes _UNSIGNED LONG
CASE 64bites: Read memory offset size = 8 bytes _UNSIGNED INTEGER64
END SELECT

It is the same case as WAV data area: Is it mono and 8 bit? Then read one _UNSIGNED _BYTE value. Is it Stereo and 8 bit? Read two bytes _UNSIGNED _BYTE. Is it 16 bit wav stereo? Read two _UNSIGNED INTEGER values (2 x 2 bytes)..... so in this way. I see none problem to do back compatibility.

Yeah, if there is a problem in having a 64 bit application read a 32-bit DLL, then it could be done by running a 32-bit helper EXE file or not?

Or maybe better: Contains C++ some function, that return how type is DLL file? If it is 32 or 64 bit? Then set offset size...
« Last Edit: November 24, 2018, 01:44:25 pm by Petr »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: how to play MIDI files in QB64 ?
« Reply #6 on: November 24, 2018, 01:47:52 pm »
Quote
Hi Steve. If 32bit IDE works in 64bit Windows 7, so as 64bit IDE works in 64bit Windows 7, why os not IDE writed as in this pseudo code:

The thing is, 32-bit programs don't actually run in 64-bit Windows -- they run in WOW64, which is basically an emulation program.  In this case, think of it as being similar to running in a virtual machine.  I might put Linux Mint inside a virtual machine and then run it flawlessly in Windows, but that doesn't mean Linux executables will work directly in Windows.  https://www.techsupportalert.com/content/how-windows7-vista64-support-32bit-applications.htm

32-bit programs are basically ran in their own virtual machine on your 64-bit machine, so their components are no more mix-and-matchable than Linux components would be on your Windows system. 

What you can do is write a 32-bit program, use it with the dll, and then shell the result back to your 64-bit program (or write to a file, share it over TCP/IP, or memory-mapped file).  Or, even easier, if you can get the source file:  simply recompile the library in a 64-bit compiler.

You can emulate 32-bit programs on a 64-bit OS, but you can't run hybrid "part-32,part-64" programs on anything.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: how to play MIDI files in QB64 ?
« Reply #7 on: November 24, 2018, 01:54:50 pm »
Aha. Thank you for the clear answer. So, the solution is, but it is tricky. I need to add knowledge about this. Thanks, Steve.

Offline mynameispaul

  • Newbie
  • Posts: 49
    • View Profile
Re: how to play MIDI files in QB64 ?
« Reply #8 on: November 25, 2018, 02:33:45 pm »
Petr,
I did finally figure out to get the MIDI to play using the DLL and your sample code.
But the only way I can make the program stop playing the MIDI is to end the program.
Is there a command to make the program stop playing the MIDI?...such as using _SNDCLOSE or something else?

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: how to play MIDI files in QB64 ?
« Reply #9 on: November 25, 2018, 03:56:53 pm »
Hi. Yes, here is way - for stopping midi playing insert to function invalid track name, as in this example:

Code: QB64: [Select]
  1. DECLARE DYNAMIC LIBRARY "playmidi32"
  2.     FUNCTION PlayMIDI& (filename AS STRING)
  3.  
  4.     PRINT "Press spacebar for stop music or Esc for end"
  5.     status = PlayMIDI("ps2battl.mid")
  6.  
  7.     DO WHILE i$ <> CHR$(32) OR i$ = CHR$(27)
  8.         i$ = INKEY$
  9.         IF i$ = CHR$(27) THEN SYSTEM
  10.     LOOP
  11.     stat2 = PlayMIDI("")
  12.     PRINT "Paused. Press other key (no spacebar or Esc) for continue playing"
  13.     SLEEP
  14.     i$ = ""
  15.  

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: how to play MIDI files in QB64 ?
« Reply #10 on: December 03, 2018, 12:40:00 pm »
Since you're using Windows, you could also use MCI commands to play midi files..  Here's a snippet doing that which works for me in win7-32bit.

- Dav

Code: QB64: [Select]
  1.  
  2. '=========
  3. 'PLAYMIDI.BAS
  4. '=========
  5. 'Simple code to play MIDI files using Windows MCI
  6. 'Coded  by Dav
  7.  
  8.     FUNCTION mciSendStringA% (lpstrCommand AS STRING, lpstrReturnString AS STRING, BYVAL uReturnLength AS INTEGER, BYVAL hwndCallback AS INTEGER)
  9.     FUNCTION mciGetErrorStringA% (BYVAL dwError AS INTEGER, lpstrBuffer AS STRING, BYVAL uLength AS INTEGER)
  10.  
  11. DECLARE SUB StartMID (filename$)
  12. DECLARE SUB StopMID (filename$
  13.  
  14.  
  15. StartMID ("silentnight.mid")
  16.  
  17. '=== Play MID...
  18.     _LIMIT 30
  19.  
  20. '=== Stop MID...
  21. StopMID ("silentnight.mid")
  22.  
  23.  
  24.  
  25. '==================================================================
  26.  
  27. SUB StartMID (filename$)
  28.     ReturnString$ = SPACE$(255): ErrorString$ = SPACE$(255)
  29.     a% = mciSendStringA%("open " + filename$ + " type sequencer ", ReturnString$, LEN(ReturnString$), 0)
  30.     IF a% THEN
  31.         x% = mciGetErrorStringA%(a%, ErrorString$, LEN(ErrorString$))
  32.         PRINT ErrorString$
  33.         END
  34.     END IF
  35.     b% = mciSendStringA%("play " + filename$, "", 0, 0)
  36.  
  37. SUB StopMID (filename$)
  38.     x% = mciSendStringA%("stop " + filename$, "", 0, 0)
  39.     x% = mciSendStringA%("close " + filename$, "", 0, 0)
  40.