QB, PLAY statement and library

Headers, Bindings, Libraries for use with FreeBASIC, Please include example of use to help ensure they are tested and usable.
N3trunn3r
Posts: 110
Joined: Feb 14, 2008 15:48

QB, PLAY statement and library

Post by N3trunn3r »

I have some old QB code and would like to compile it on modern systems.
But the PLAY statement is missing.

The FB manual states:
PC Speaker commands no longer function: Any references to SOUND or PLAY statements will result in an error message.
There is a third party library available to emulate this functionality, but it's not included with FreeBASIC.
Where can I find this elusive third party library that allows PLAY to be used once again?
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: QB, PLAY statement and library

Post by dodicat »

angros47
Posts: 2321
Joined: Jun 21, 2005 19:04

Re: QB, PLAY statement and library

Post by angros47 »

The one dodicat linked is very old, and uses only the PC speaker.

Try this one: https://www.freebasic.net/wiki/ExtLibsfx

It supports Linux, Windows and DOS. Implements polyphonic PLAY command through the MIDI output
N3trunn3r
Posts: 110
Joined: Feb 14, 2008 15:48

Re: QB, PLAY statement and library

Post by N3trunn3r »

Can't compile either under Debian 11 x64. FreeBASIC Compiler - Version 1.07.1

PLAY from freebasic-portal.de fails
fbc Menuett_Krieger.bas
Menuett_Krieger.c: In function ‘SOUND_DOS_LIN’:
Menuett_Krieger.c:59:2: warning: listing the stack pointer register ‘rsp’ in a clobber list is deprecated [-Wdeprecated]
59 | __asm__ __volatile__( "mov dx, 97 " : : : "cc", "memory", "rax", "rbx", "rcx", "rdx", "rsp", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" );
...
ExtLibsfx fails too
buildlinux.sh seems to work, but comp. the example fails.
example.bas:

Code: Select all

#include "sfx.bi"
#inclib "fbsfx"
SoundmidiSet ()
PLAY "a4e4g4a4g4e4c2f4f4f2d4d4d2"
fbc example.bas -m all -exx
example.bas() warning 20(2): Object files or libraries with mixed multithreading (-mt) options, ./libfbsfx.a
ld: /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crt1.o: in function `_start':
(.text+0x20): undefined reference to `main'
angros47
Posts: 2321
Joined: Jun 21, 2005 19:04

Re: QB, PLAY statement and library

Post by angros47 »

Do not worry about the "warning 20(2): Object files or libraries with mixed multithreading (-mt) options, ./libfbsfx.a": it only means that the library is multithreading (it uses a thread to activate the midi player), and the rest of the code is not, so it might cause errors if some subroutines are used at the same time by both threads, but actually the MIDI thread is pretty isolated, it should not cause issues.

I don't know why you get the second error ("undefined reference to `main'"): I have just tried compiling your example under Linux, and I didn't get that error, and it worked fine
N3trunn3r
Posts: 110
Joined: Feb 14, 2008 15:48

Re: QB, PLAY statement and library

Post by N3trunn3r »

angros47 wrote: Jul 19, 2022 17:22 Do not worry about the "warning 20(2): Object files or libraries with mixed multithreading (-mt) options, ./libfbsfx.a": it only means that the library is multithreading (it uses a thread to activate the midi player), and the rest of the code is not, so it might cause errors if some subroutines are used at the same time by both threads, but actually the MIDI thread is pretty isolated, it should not cause issues.

I don't know why you get the second error ("undefined reference to `main'"): I have just tried compiling your example under Linux, and I didn't get that error, and it worked fine
ExtLibsfx works just fine now :)
I must have done something wrong before...
hhr
Posts: 205
Joined: Nov 29, 2019 10:41

Re: QB, PLAY statement and library

Post by hhr »

The reason for "undefined reference to `main'" is "-m all".
Compile without options: 'fbc example.bas'.
Coolman
Posts: 294
Joined: Nov 05, 2010 15:09

Re: QB, PLAY statement and library

Post by Coolman »

I don't see how the library can compile, the file fbsfx.bas (archive sfx.zip) is empty ?
hhr
Posts: 205
Joined: Nov 29, 2019 10:41

Re: QB, PLAY statement and library

Post by hhr »

In Windows you have to alter "buildwindows.bat". Change "..\fbc " to your own fbc-path and run buildwindows.bat.
angros47
Posts: 2321
Joined: Jun 21, 2005 19:04

Re: QB, PLAY statement and library

Post by angros47 »

The only purpose of the file fbsfx.bas is to be put as the first module of the list, so the library will be named after it. The code of the library is in the other files

@N3trunn3r
Glad it works now. Is the sound quality good enough?
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: QB, PLAY statement and library

Post by dodicat »

I simply wrote

#cmdline "-lib fbsfx.bas midievent.bas wave.bas SoundFunction.bas playtomidi.bas writemidi.bas writewav.bas sequencer.bas .\windows\dsp.bas .\windows\midi.bas .\windows\seqthread.bas"

to fbsfx.bas and saved it.

and compiled fbsfx.bas with my ide.
(I am not a fan of executing batch files)
You need the latest fb version (1.09) to do this.
You get the static lib file libfbsfx.a, about 83 kb with the 64 bit compiler.
angros47
Posts: 2321
Joined: Jun 21, 2005 19:04

Re: QB, PLAY statement and library

Post by angros47 »

dodicat wrote: Jul 19, 2022 21:27 You get the static lib file libfbsfx.a, about 83 kb with the 64 bit compiler.
I assume you are using WIndows. In Linux it is bigger, because it includes a FM synthesizer as fall back in case no midi is available.
N3trunn3r
Posts: 110
Joined: Feb 14, 2008 15:48

Re: QB, PLAY statement and library

Post by N3trunn3r »

angros47 wrote: Jul 19, 2022 20:58 @N3trunn3r
Glad it works now. Is the sound quality good enough?
Sounds good on Win and Linux :) midi, wav, play, all works fine, testing for DOS soon...

But the main reason to use fbsfx was actually to be able to recompile old QB games that use the "PLAY" statement.
fbsfx does not seem to be "-lang qb" compatible.
I am looking for an inline replacement without refactoring QB to modern freebasic dialect.

I just want to do something like adding this:

Code: Select all

#include "sfx.bi"
#inclib "fbsfx"
SoundmidiSet ()
Without changing much else of the original QB code.

fbsfx fails when I try to compile this:

Code: Select all

#include "sfx.bi"
#inclib "fbsfx"

SoundmidiSet ()

'Play scale in 7 different octaves
scale$ = "CDEFGAB"
PLAY "L16"
FOR i% = 0 TO 6
  PLAY "O" + STR$(i%)
  PLAY "X" + VARPTR$(scale$)
NEXT i%
Error is:
wave.bi(2) error 14: Expected identifier, found 'ULONG'
RiffID AS ULONG 'should be 'RIFF'
...
Maybe i can tell fbc to use QB on the main program but ignore QB dialect on includes "sfx.bi" and "fbsfx"? :?
angros47
Posts: 2321
Joined: Jun 21, 2005 19:04

Re: QB, PLAY statement and library

Post by angros47 »

You are right, it is not QB compatible (since it internally uses a lot of OOP features). I haven't tested it, but I think you can make an include file to call only the PLAY command (its syntax is simple, and it should be compatible with QB mode). For the SOUND command, instead, the header cannot be ported to QB mode since it uses OOP features (although a wrapper could be made, especially if you only want to emulate the original SOUND command)

Instead of including all the sfx.bi (that provides support for ALL features, you might only put the DECLAREs for what you actually need:

Code: Select all

declare sub SoundMidiSet
declare sub play overload (Midi as MidiSequence ptr, playstr as string, playstr1 as string="", playstr2 as string="", playstr3 as string="", _
	playstr4 as string="", playstr5 as string="", playstr6 as string="", playstr7 as string="", _
	playstr8 as string="", playstr9 as string="", playstr10 as string="", playstr11 as string="", _
	playstr12 as string="", playstr13 as string="", playstr14 as string="", playstr15 as string="")

declare sub play overload (playstr as string, playstr1 as string="", playstr2 as string="", playstr3 as string="", _
	playstr4 as string="", playstr5 as string="", playstr6 as string="", playstr7 as string="", _
	playstr8 as string="", playstr9 as string="", playstr10 as string="", playstr11 as string="", _
	playstr12 as string="", playstr13 as string="", playstr14 as string="", playstr15 as string="")
(not sure how to deal with "overload", I don't know if it's supported in QB mode)

Oh, another thing: the "x" command is not supported, because it is completely useless. Instead of

Code: Select all

PLAY "X" + VARPTR$(scale$)
just use

Code: Select all

PLAY scale$
Actually, the "x" command for DRAW and PLAY was useless in the original QBASIC, as well, since the second syntax was perfectly valid in QBASIC as well. The reason many users used it was that the guide was not clear about it, and by reading it, it seemed that the only way to use a variable with DRAW or PLAY was to use the "x" command. That was not true. The real purpose of the X command was to specify the name of a variable inside the string itself, like this:

Code: Select all

A$="EFG"
PLAY "CD XA$;"
It worked in an interpreter like GWBASIC, but not in a compiled language, since the symbol A$ was ditched during compiling, so to allow compilation it has been modified to accept the pointer converted to a string, instead of the name. A lame solution, that has almost no practical usage.
Coolman
Posts: 294
Joined: Nov 05, 2010 15:09

Re: QB, PLAY statement and library

Post by Coolman »

nice job. it works well. it would be better if examples were provided. note that the mit license would have been better than lgpl.
Post Reply