Converting QBasic Code with PLAY statements into FreeBasic?

New to FreeBASIC? Post your questions here.
Post Reply
davidshq
Posts: 52
Joined: Oct 29, 2008 3:28
Contact:

Converting QBasic Code with PLAY statements into FreeBasic?

Post by davidshq »

Hi,
I have some code that contains PLAY statements. I was wondering what the best way is to replace these play statements with similar functionality within FB?
Thanks,
Dave.
davidshq
Posts: 52
Joined: Oct 29, 2008 3:28
Contact:

Re: Converting QBasic Code with PLAY statements into FreeBas

Post by davidshq »

Thanks! When I include that code in my application though I get the following error:
SOUND.bas(11) error 56: Illegal specification, at parameter 1 (freq) of Sound()
DECLARE SUB Sound(ByVal freq As Uinteger, dur As Uinteger)
Any idea why?
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: Converting QBasic Code with PLAY statements into FreeBas

Post by TJF »

it seems that your code uses the symbol name 'freq' anywhere above that declaration. (Check it by a #PRINT TYPEOF(freq) and watch the compiler output; try NAMESPACE to solve the conflict.)
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Converting QBasic Code with PLAY statements into FreeBas

Post by counting_pine »

Variable names can be reused as parameter names, especially in Declares. I think more likely it's been #defined as something. Doing just '#print freq' might tell you what it is.

One workaround is to simply rename the parameter (e.g. freq_), or to remove it entirely (byval as uinteger), or - equivalently - to multi-line-comment it out (byval /'freq'/ as integer).

Note: if you compile with fbc -w pedantic|-w param, you'll be warned that dur doesn't have an explicit byval/byref. It should probably be 'byval dur as uinteger', unless it was written in an old dialect of FB.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Converting QBasic Code with PLAY statements into FreeBas

Post by dodicat »

Here's the PLAY sub from JTF link, but with a differend sound sub.

The Sound sub here is only alias "Beep" (one line at top)
It sounds ok though, maybe you'll be able to debug your code more easily.

Code: Select all

declare sub sound alias "Beep"(freq as uinteger,dur as integer)

SUB Play (Melodie  AS STRING)
' Spielen einer Melodie. Subset aus dem PLAY-Befehls von QBASIC.
' Melodie ist ein String aus folgenden Kommandos (Gross- oder Kleinbuchstaben):
' - Tn = Tempo = Anzahl von Viertelnoten pro Minute (n = 32 bis 255, 
'   Default 120). Beispiel: "T180"
' - On = aktuelle Oktave (n = 0 bis 5). Beispiel: "O3"
' - < = eine Oktave tiefer
' - > eine Oktave hoeher
' - C, D, E, F, G, A, B: Noten in der aktuellen Oktave. Moegliche Suffixe:
'   + oder # Erhoehung um einen halben Ton. Beispiel: "C#" 
'   - Erniedrigung um einen halben Ton. Beispiel: "D-"
' - . = Eineinhalbfache Notenlaenge. Beispiele: "C.", "C+." oder "D-."
' - Ln = Laenge einer Note (n = 1 bis 64,  1 = ganze Note, 2 = halbe Note, 
'   4 = Viertelnote usw). Beispiel: "L4". (Individuelle Notenlaengen (Beispiel "C4")
'   werden nicht unterstuetzt.)
' - Pn = Laenge einer Pause (n = 1 bis 64,  1 = ganze Pause, 2 = halbe Pause, 
'   4 = Viertelpause usw). Beispiel: "P4"
' Beispiel: Alle meine Entchen schwimmen auf dem See 
' Play("O3 L8 CDEF L4 GG O3 L8 AAAA L2 G")

  'Tonfrequenzen in Hertz:
  DIM AS INTEGER C(5)   = { 65, 131, 262, 523, 1046, 2093}, _
                 Cis(5) = { 69, 139, 277, 554, 1109, 2217}, _
                 D(5)   = { 73, 147, 294, 587, 1175, 2349}, _
                 Dis(5) = { 78, 155, 311, 622, 1244, 2489}, _
                 E(5)   = { 82, 165, 330, 659, 1328, 2637}, _
                 F(5)   = { 87, 175, 349, 698, 1397, 2794}, _
                 Fis(5) = { 92, 185, 370, 740, 1480, 2960}, _
                 G(5)   = { 98, 196, 392, 784, 1568, 3136}, _
                 Gis(5) = {104, 208, 415, 831, 1661, 3322}, _
                 A(5)   = {110, 220, 440, 880, 1760, 3520}, _
                 Ais(5) = {116, 233, 466, 932, 1865, 3729}, _
                 B(5)   = {123, 245, 494, 988, 1975, 3951}
                 
  DIM AS STRING s, s1, s2
  DIM AS INTEGER k, Wert, Okt, LWert, Tempo, Pause, freq, dur1, dur2, dur
  
  'Default-Werte:
  Okt = 3
  LWert = 4
  Tempo = 120
  dur = 60000 / (LWert * Tempo)
  dur1 = (7 / 8) * dur
  dur2 = dur - dur1
  
  s = TRIM(Melodie)
  
  'Alle Leerzeichen entfernen (repariert Fehleingaben wie "L 16" oder "O 3"):
  DO
    k = INSTR(s, " ")
    s = LEFT(s, k - 1) + RIGHT(s, LEN(s) - k)
  LOOP UNTIL k = 0
  
  DO
    
    k = INSTR(s, ANY "OCDEFGABLPTocdefgablpt<>")
    'Eventuellen Schrott vorn entfernen (kann durch Formatfehler entstehen,
    'z.B. "C32", oder ungueltige Zeichen)
    IF k > 1 THEN s = RIGHT(s, LEN(s) - k + 1)
    s1 = UCASE(LEFT(s, 1))
    s2 = ""
                
    SELECT CASE s1
            
    CASE "T", "L", "P"
      k = 0
      DO
        k = k + 1
        s2 = MID(s, 1 + k, 1)
        'Wenn s2 eine Ziffer 0 bis 9 ist, an "T" dranhaengen:
        IF ASC(s2) >=48 AND ASC(s2) <=57 THEN s1 = s1 + s2
      LOOP UNTIL ASC(s2) < 48 OR ASC(s2) > 57
      IF LEN(s1) > 1 THEN
        Wert = VAL(RIGHT(s1, LEN(s1) - 1))
        IF LEFT(s1, 1) = "T" THEN
          Tempo = Wert
          IF Tempo < 32 THEN Tempo = 32
          IF Tempo > 255 THEN Tempo = 255
          dur = 4 * 60000 / (LWert * Tempo)
          dur1 = (7 / 8) * dur
          dur2 = dur - dur1          
        ELSEIF LEFT(s1, 1) = "L" THEN
          LWert = Wert
          IF LWert > 64 THEN LWert = 64
          IF LWert < 1 THEN LWert = 1
          dur = 4 * 60000 / (LWert * Tempo)
          dur1 = (7 / 8) * dur
          dur2 = dur - dur1
        ELSEIF LEFT(s1, 1) = "P" THEN
          Pause = Wert
          IF Pause > 64 THEN Pause = 64
          IF Pause < 1 THEN Pause = 1        
          'Pause spielen:
          SLEEP 4 * 60000 / (Pause * Tempo)
        END IF
      END IF
      
    CASE "O"
      s2 = MID(s, 2, 1)
      IF ASC(s2) >=48 AND ASC(s2) <=57 THEN
        s1 = s1 + s2
        Okt = VAL(s2)
        IF Okt < 0 THEN Okt = 0
        IF Okt > 5 THEN Okt = 5
      END IF
      
    CASE ">"
      IF Okt < 5 THEN Okt = Okt + 1
      
    CASE "<"
      IF Okt > 0 THEN Okt = Okt - 1
      
    CASE "C", "D", "E", "F", "G", "A", "B"
      s2 = MID(s, 2, 1)
      IF s2 = "+" OR s2 = "#" THEN
        SELECT CASE s1
        CASE "C": freq = Cis(Okt)
        CASE "D": freq = Dis(Okt)
        CASE "E": freq = F(Okt)
        CASE "F": freq = Fis(Okt)
        CASE "G": freq = Gis(Okt)
        CASE "A": freq = Ais(Okt)
        CASE "B": IF Okt < 5 THEN freq = C(Okt + 1)
        END SELECT
        s1 = s1 + s2
      ELSEIF s2 = "-" THEN
        SELECT CASE s1
        CASE "C": IF Okt > 0 THEN freq = B(Okt - 1) 
        CASE "D": freq = Cis(Okt)
        CASE "E": freq = Dis(Okt)
        CASE "G": freq = Fis(Okt)
        CASE "A": freq = Gis(Okt)
        CASE "B": freq = Ais(Okt)
        END SELECT
        s1 = s1 + s2
      ELSE
        SELECT CASE s1
        CASE "C": freq = C(Okt)
        CASE "D": freq = D(Okt)
        CASE "E": freq = E(Okt)
        CASE "F": freq = F(Okt)
        CASE "G": freq = G(Okt)
        CASE "A": freq = A(Okt)
        CASE "B": freq = B(Okt)
        END SELECT
      END IF
      IF s2 = "." OR MID(s, 3, 1) = "." THEN
        'Ton spielen:
        Sound(freq, 1.5 * dur1)
        SLEEP 1.5 * dur2 
        s1 = s1 + "."
      ELSE
        'Ton spielen:
        Sound(freq, dur1)
        SLEEP dur2
      END IF
           
    END SELECT
    
    'Ausgewerteten Teil des Strings s vorn abtrennen:
    s = TRIM(s)
    s = RIGHT(s, LEN(s) - LEN(s1))
    
  LOOP UNTIL LEN(s) = 0
  
END SUB
'+++++++++++++++++++++++++++++++++++++++++++++++++++++
'TEST
dim as single t1, t2
dim as integer i

PRINT "Test der Sound-Funktion: Langsame Tonleiter, C3 bis C4"
t1 = timer
Sound(523, 500)  'C3
Sound(587, 500)  'D3
Sound(659, 500)  'E3
Sound(698, 500)  'F3
Sound(784, 500)  'G3
Sound(880, 500)  'A3
Sound(988, 500)  'B3
Sound(1046, 500) 'C4
t2 = timer
PRINT "Dauer (Soll: 4 Sekunden): "; t2 - t1
PRINT

PRINT "Test der PLAY-Funktion, Tonleiter C4 bis C5:"
Play("T130 L4 O4 CDEFG AB O5 C")
PRINT

PRINT "Und nun ein kleines Liedchen:"
PRINT "Alle meine Entchen"
Play("O3 L8 CDEF L4 GG")
FOR i = 1 TO 2
  PRINT "schwimmen auf dem See"
  Play("O3 L8 AAAA L2 G")
NEXT i
PRINT "Koepfchen in das Wasser, Schwaenzchen in die Hoeh"
Play("O3 L8 FFFF L4 EE L8 DDDDC")


sleep
  
Post Reply