Music and WAV files in Liberty BASIC and JB.

There is a lot of fun in making and playing your own sounds- programmatically you can create a whole synthesizer.

A sound wave is a mixture of waves of sound pressure, transmitted longitudinally. The simplest wave shape is a sine wave of constant amplitude and constant frequency.

If the frequency stays the same but the amplitude decays, we get a dying-away tone. You can also alter the 'attack' of how quickly the tone starts, and the 'sustain' or how long it stays at a constant amplitude before the decay.

Further affects are got by adding simultaneous tones ( Fourier showed us how this can generate ANY wave shape). Interesting cases include the beats we get when you add two waves of similar frequency.

Sounds on a computer

There are two easy ways on a computer to generate 'music'. MIDI is basically a language /file format that specifies frequencies and times and 'voice' or musical characteristics. I have examples like using this to make a mouse-operated theremin elsewhere on this site.

WAV files are basically a digital record of any chosen wave shape. Any time-dependent wave you can make programmatically can be turned into a WAV file. BUT there are a range of WAV file types, depending on whether you want stereo or mono; how many samples per second; whether you want 8-bit or 16-bit precision, etc. HOWEVER don't expect to calculate in real-time. Generate your sounds in advance and play the resulting wav files in your chosen time!

For experimental purposes the simplest I usually use is 11,025 samples per second, mono, 8 bit. 16 bit is a bit smoother, but files are twice as big and slower to calculate. I 'cheat' by using a stored preamble of 44 bytes with the correct bits set to this or to 16 bits, then complete the file ( or display on-screen as a waveform) The screen shot shows which parts do what- here it is for a 16 bit WAV file.

Make a mouse-operated keyboard?

One of my programs generates the correct note for all the keys. Use mouseX to find where you clicked... and you have the beginnings of a synthesizer. It could be easily modified to give attack/sustain/decay or mix in harmonics to give different voices.

Existing code

There are great programs to make wav files out there- particularly Thomas and Alyce's one from near twenty years ago on her website. There are also part-correct ones like bluatigro's.


LB code examples- more will be put up soon in a zip file.


    nomainwin

    'open an existing wav file of length 3 seconds,
    '1 channel, 16 bits/sample, 11025 samples/second
    'remember the first 44 bytes of preamble
    goto [skip]'    _____________________________  REMOVE to strip and save the preamble.


    open "original.wav" for input as #fIn
        i$ =input$( #fIn, 44)
    close #fIn

    'save preamble for re-use.
    open "preamble.wav" for output as #fOut
        #fOut i$;
    close #fOut

    '_____________________________________________

[skip]

    WindowWidth  = 980
    WindowHeight = 840

    global fOutOpen

    open "Making WAV files" for graphics_nsb as #wg

    #wg "trapclose quit"
    #wg "down ; fill 160 160 60"

    're-load the preamble bytes...
    open "preamble.wav" for input as #fIn
        c$ =input$( #fIn, lof( #fIn))
    close #fIn

    'and add on the new data as 33075 byte-pairs, then save
    'frequency =440Hz, 1 channel, 16 bits, 11025 per second

    'freqy =440
    for n =49 to 73
        'n       =int( 49 +24 *rnd( 1))   '   in range 1 to 88 for piano keyboard
        #wg " up ; goto 5 "; 80 +10 *( n -49); " ; down"
        color   =int( ( n -49) /24 *256)
        #wg "color "; color; " 50 "; 255 -color
        freqy   =2^( ( n -49) /12) *440
        amplt   =2^15

        fOutOpen =0

        open "newWav" +right$( "000" +str$( n), 3) +".wav" for output as #fOut
            fOutOpen =1
            #fOut c$;
            for i =1 to 33075
                amplitudeOfWave     =int( amplt *sin( i /11025 *freqy)) '   +/-2^15
                #fOut bytePair$( amplitudeOfWave);
                if i <=5000 then #wg "goto "; int( 5 +i /5); " "; int( 80 +10 *( n -49) +( amplitudeOfWave -128) /2^9)
                scan
                'freqy               =freqy *1.00005   '   this exponentially increases freq'y
                amplt               =amplt *0.99985   '   this exponentially reduces   volume
            next i
        close #fOut

        'and finally play it...
        playwave "newWav" +right$( "000" +str$( n), 3) +".wav", sync

    next n

    wait

    end

    function bytePair$( A)  '   receives -2^15 to +2^15
        if A <=0 then A =2^16 +A -1' else A =2^15 -A
        hi          =int( A /256)
        lo          =A -256 *hi'
        bytePair$   =chr$( lo) +chr$( hi)
    end function

    sub quit h$
        if fOutOpen =1 then close #fOut
        close #h$
        end
    end sub