_WAVE

From QB64 Phoenix Edition Wiki
Revision as of 17:38, 23 November 2024 by RhoSigma (talk | contribs)
Jump to navigation Jump to search

_WAVE defines the waveform shape for a specified audio channel when used with SOUND or PLAY.


Syntax

_WAVE voice&, waveDefinition%%([index&])[, frameCount&]


Parameters

  • voice& specifies for which of the four audio channels the sound waveform shall be set.
  • waveDefinition%%([index&]) defines the shape of the sound wave for the specified voice. This parameter must be the name of an array of _BYTEs with at least 2 elements. Each element (sample frame) in the array must have a value in the range of -128 to 127. An optional index can be used to specify the starting point in the array.
  • frameCount& specifies the number of elements (sample frames) used to define the shape of the sound.


Description

  • The _WAVE statement enhances the versatility of the SOUND or PLAY commands.
  • By using a numeric array to define the shape of a sound wave, you can produce more specific and unique types of sounds.
  • Each element of the array specifies a amplitude value. When combined, these values form a curve that represents the shape of the waveform.
  • Audio channels can be panned to the left, right, or center using SOUND or PLAY.
  • Waveforms specified with _WAVE have a waveform ID of 10. See SOUND and PLAY for more details regarding waveforms.
  • By default, custom waveforms are initialized as a sine wave with 256 sample frames.
  • The _WAVE command was designed to resemble the WAVE command found in AmigaBasic.


Availability


Examples

Example 1
A QB64-PE port of the AmigaBasic Music/Graphic demo.
<ki>sic - AmigaBasic Music/Graphic-Demo --- 20. July 1985<iki>9191
DEFLNG A-Z

CONST VOLUME! = 0.25!

DIM F#(88), CF(19), CT#(19)

GOSUB InitSound
GOSUB InitGraphics

DO
    SOUND RESUME
    RESTORE Song
    GOSUB PlaySong

    <ki>is ensures all voices have played completely before playing the song again<iki>9191
    WHILE PLAY(0) >ext|0|#F580B1}} _ORELSE PLAY(1) >ext|0|#F580B1}} _ORELSE PLAY(2) >ext|0|#F580B1}} _ORELSE PLAY(3) >ext|0|#F580B1}}
        IF _KEYHIT = 27 THEN END
        _LIMIT 60
    WEND
LOOP

InitGraphics:
SCREEN 12
_TITLE <ki>gaBasic Music/Graphic Demo (QB64-PE port by a740g)"<iki>B100
iDraw = 30
iErase = 0
ON TIMER(1) GOSUB TimeSlice
TIMER ON
RETURN

TimeSlice:
FOR linestep = 1 TO 15
    DrawLine iDraw, 1
    DrawLine iErase, 0
    _LIMIT 60
NEXT linestep
RETURN

PlaySong:
<ki>ray VO contains the base octave for a voice.<iki>9191
FOR v = 0 TO 3
    READ VO(v)
    VO(v) = 12 * VO(v) + 3
NEXT v

DO
    SOUND WAIT
    FOR v = 0 TO 3
        t# = VT#(v)
        Fi = -1
        READ p$
        IF p$ = <ki>/nowiki>B100 THEN RETURN
        FOR I = 1 TO LEN(p$)
            Ci = INSTR(C$, MID$(p$, I, 1))
            IF Ci <Text|8|#F580B1}} THEN
                IF Fi >Text|0|#F580B1}} THEN SOUND F#(Fi), t#, VOLUME, , , , v: t# = VT#(v)
                IF Ci = 8 THEN Fi = 0 ELSE Fi = CF(Ci) + VO(v)
            ELSEIF Ci <ext|11|#F580B1}} THEN <ki>r -<iki>9191
                Fi = Fi + CF(Ci)
            ELSEIF Ci <ext|17|#F580B1}} THEN <ki>hrough 8<iki>9191
                t# = CT#(Ci)
            ELSEIF Ci <ext|19|#F580B1}} THEN <ki>r >wiki>9191
                VO(v) = VO(v) + CF(Ci)
            ELSE <ki>/nowiki>9191
                I = I + 1
                Ci = INSTR(C$, MID$(p$, I, 1))
                VT#(v) = CT#(Ci)
                IF Fi <ext|0|#F580B1}} THEN t# = VT#(v)
            END IF
        NEXT I
        IF Fi >Text|0|#F580B1}} THEN SOUND F#(Fi), t#, VOLUME, , , , v
    NEXT v
    SOUND RESUME
    IF _KEYHIT = 27 THEN END
    _LIMIT 60
LOOP

InitSound:
<ki>() contains frequencies of the chromatic scale.<iki>9191
{{{1}}}
Log2of27.5# = LOG(27.5#) / LOG(2#)
FOR x = 1 TO 88
    F#(x) = 2 ^ (Log2of27.5# + x / 12#)
NEXT x

<ki>eate the waveform of tones,<iki>9191
<ki>termines timbre.<iki>9191
DIM Timbre(255) AS _BYTE
FOR I = 0 TO 255
    READ Timbre(I)
NEXT I

<ki>e following DATA rows were created using the following formula.<iki>9191
<ki>ading from these DATAs is faster than calculating the sine 1024 times.<iki>9191
{{{1}}}
{{{1}}}
{{{1}}}
<ki>EXT I<iki>9191
DATA 0,8,15,23,30,37,44,51,57,63,69,74,79,83,87,91
DATA 93,96,98,99,100,100,100,99,98,97,95,92,89,86,83,79
DATA 75,71,66,62,57,52,48,43,39,34,30,25,21,18,14,11
DATA 8,5,3,0,-1,-3,-4,-5,-5,-6,-6,-5,-5,-4,-3,-1
DATA 0,2,3,5,7,9,11,13,15,17,18,20,21,23,24,25
DATA 26,26,27,27,27,27,27,26,25,24,23,22,20,18,17,15
DATA 13,11,9,7,5,3,1,-1,-3,-5,-6,-8,-9,-10,-11,-12
DATA -12,-13,-13,-13,-13,-13,-12,-11,-11,-10,-8,-7,-6,-4,-3,-2
DATA 0,2,3,4,6,7,8,10,11,11,12,13,13,13,13,13
DATA 12,12,11,10,9,8,6,5,3,1,-1,-3,-5,-7,-9,-11
DATA -13,-15,-17,-18,-20,-22,-23,-24,-25,-26,-27,-27,-27,-27,-27,-26
DATA -26,-25,-24,-23,-21,-20,-18,-17,-15,-13,-11,-9,-7,-5,-3,-2
DATA 0,1,3,4,5,5,6,6,5,5,4,3,1,0,-3,-5
DATA -8,-11,-14,-18,-21,-25,-30,-34,-39,-43,-48,-52,-57,-62,-66,-71
DATA -75,-79,-83,-86,-89,-92,-95,-97,-98,-99,-100,-100,-100,-99,-98,-96
DATA -93,-91,-87,-83,-79,-74,-69,-63,-57,-51,-44,-37,-30,-23,-15,-8

<ki>t AMIGA PAULA like panning (well mostly)<iki>9191
SOUND 0, 0, , -0.75!, 10, , 0 <ki>n left<iki>9191
SOUND 0, 0, , 0.75!, 10, , 1 <ki>n right<iki>9191
SOUND 0, 0, , 0.75!, 10, , 2 <ki>n right<iki>9191
SOUND 0, 0, , -0.75!, 10, , 3 <ki>n left<iki>9191

_WAVE 0, Timbre()
_WAVE 1, Timbre()
_WAVE 2, Timbre()
_WAVE 3, Timbre()

<ki>ray CF maps MML commands to frequency indices.<iki>9191
C$ = <ki>fgabp#-123468</nowiki>B100
FOR I = 1 TO 19
    READ CF(I)
NEXT I
DATA 0,2,4,5,7,9,11,0,1,-1,0,0,0,0,0,0,-12,12,0

<ki>ray CT# assigns note lengths to MML commands.<iki>9191
FOR I = 1 TO 18
    READ CT#(I)
NEXT I
<ki>L commands p1,p2,p3,p4,p6,p8 correspond to pause times 36.4 ... 4.55 units<iki>9191
DATA 0,0,0,0,0,0,0,0,0,0,36.4,18.2,12.133333,9.1,6.0666667,4.55,0,0,0
RETURN

<ki>e music is written in special commands (MML), but as per the Wiki page<iki>9191
<ki>low MML not fully implemented here, missing o, v and t commands:<iki>9191
<ki>tps://en.wikipedia.org/wiki/Music_Macro_Language#Modern_MML<iki>9191

<ki>e first 4 numbers are the base octaves (0-7) for each voice.<iki>9191
<ki>     - sets note length for the following notes of this voice:<iki>9191
{{{1}}}
<ki>     - selects the next higher octave for this voice.<iki>9191
<ki>     - selects the next lower octave for this voice.<iki>9191
<ki>to g - play the respective note,<iki>9191
<ki>        # (sharp) or - (flat) may follow directly.<iki>9191
<ki>       It may also follow a number to determine the duration of this note.<iki>9191
<ki>     - make a rest/pause length as for note length (ln) above.<iki>9191

Song:
DATA 1,3,3,3
DATA l2g>2p2de,l2p2l6g3f#g3a,l6p6gab>d
DATA <e,ge<ab3ge3d,dgf#gd<
DATA ab>dc,e3f#g3de3<dedc<
DATA df#d,c<,a3>a3f#,f#gadf#a>
DATA gec,g<d3f#g3f#g3a,bgab>d
DATA <,ge<ab3ge3g,dgf#gd<
DATA cc#d,>a3f#g3e<,e>agdgf#
DATA <g6d3<p2b3g6,<b3>,gb>bgb>Cl|DATA}} g>d<2<l2<
DATA f#ed,agf#,a1b,d1d
DATA ef#g,gag,bag,c1<Cl|DATA}} dp3d6d3d6,f#a3a6>,al6d3ef#3g,l6adef#aga>DATA <d6d3d6,f#3a6f#3d6<6,a3>f#d3f#,>#df#a>
DATA gf#e,dde,g3dg3f#g3a,bgab>d
DATA b<gd<ag3f#e3g,dgf#gd<
DATA cd<>d<al2,a3gf#3ga3c,e>agdgf#
DATA g>>b3>#g3a,gbab>d
DATA <e,ge<ab3ge3d,dgf#gd<
DATA ab>dc,e3f#g3de3<dedc<
DATA df#d,c<,a3>ga3f#,f#gadf#a>
DATA gec,g<d3f#g3f#g3a,bgab>d
DATA <,ge<ab3ge3g,dgf#gd<
DATA cc#d,>a3f#g3e<,e>agdgf#
DATA <e,d<2b1>g1g
DATA f#ed,agf#,d1d,a1b
DATA ef#g,gag,c1<g
DATA dp3d6d3d6,f#l6a3a>al6d3ef#3g,l6ddef#aga>DATA <d6d3d6,f#3af#3d<,a3>f#d3f#,>#df#a>
DATA gf#e,l2dde,l2b1>ab>d
DATA b<gd<<f#gd<
DATA cd<>d<a,a4b8>a,e>agdgf#
DATA g>2b>6g3dg3f#g3a,gbab>d
DATA <e,ge<ab3ge3d,dgf#gd<
DATA ab>dc,e3f#g3de3<dedc<
DATA df#d,c<,a3>a3f#,f#gadf#a>
DATA gec,g<d3f#g3f#g3a,bgab>d
DATA <,ge<ab3ge3g,dgf#gd<
DATA cc#d,>a3f#g3e<,e>agdgf#
DATA <g6f#3e6,dp3g6d3e6,<b3>g,gb>bdb>{Cl|DATA}} dc<dd,l2a1b,d<ag#g#ba
DATA a>f4e4,e<>a>c<e
DATA d<aag#,<c8d8<dcd<f#g#
DATA a><,al6a3g#a3b,a>ceddfe
DATA cfe,afc,>>f3a,eag#aec<
DATA dd#e,df#e,a3g#a3f#<,fedc<g#
DATA <,c<l2c1d,a>3l2d
DATA >,>e1e,l6ecdegfgb-a
DATA fdg,df#g,dd4e8f8d,a>c<f
DATA cec,geg,l6c3<<,egfgec<
DATA fdg,fag,c3ef3ab3>c<afdef
DATA cp3c6<6,gp3d6d3d6,c3<<<cdegf#gba
DATA <,dde,l2b1>ab>d
DATA <e,ge<d,dgf#gd<
DATA ab>dc,c<cdedc<
DATA dp3d6d3d6,cl6<d3d,l6a3c#d3ef#3g,f#def#aga>DATA <d6d3d6,f#3af#3d<,a3>f#d3f#,>#df#a>
DATA gf#e,l2dde,l2b1>ab>d
DATA b<gd<<f#gd<
DATA cd<>d<a,a4b8>a,e>agdgf#
DATA g1g2,l2gp3>g6,gl6<g3d,gb>bgb>Cl|DATA}} g1g2,dp3g6e3c6,<d3b>d<ded<Cl|DATA}} g1g2,<d6<6,c3<3g,f#a>gegb
DATA g1g2,<f#3>3d6,a2a3f#d3f#,>#df#a>
DATA g>de,g3dg3f#g3a,bgab>d
DATA <e,ge<ab3ge3d,dgf#gd<
DATA ab>d<f#g3de3<dedc<
DATA df#d,c<,a3>a3f#,f#gadf#a>
DATA gec,g<d3f#g3f#g3a,bgab>d
DATA <,ge<ab3ge3g,dgf#gd<
DATA cc#d,d1d2,a3f#g3e<,e>agdgf#
DATA <,p2,<,g1g2
DATA p1,p1,p1,p1
DATA x

SUB DrawLine (iStep, hue) STATIC
    winWidth = _WIDTH
    winHeight = _HEIGHT
    iStep = (iStep + 1) MOD 60
    side = iStep \ 15
    I! = (iStep MOD 15) / 15!
    i1! = 1! - I!

    ON side + 1 GOSUB dl_top, dl_left, dl_bottom, dl_right

    EXIT SUB

    dl_top:
    LINE (winWidth * I!, 0)-(winWidth, winHeight * I!), hue
    RETURN

    dl_left:
    LINE (winWidth, winHeight * I!)-(winWidth * i1!, winHeight), hue
    RETURN

    dl_bottom:
    LINE (winWidth * i1!, winHeight)-(0, winHeight * i1!), hue
    RETURN

    dl_right:
    LINE (0, winHeight * i1!)-(winWidth * I!, 0), hue
    RETURN
END SUB
QB64-PE port of an AmigaBasic example by a740g. German comments translated by RhoSigma.


See also



Navigation:
Main Page with Articles and Tutorials
Keyword Reference - Alphabetical
Keyword Reference - By usage
Report a broken link