[futurebasic] Re: [FB] Simultaneous sounds

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : November 2004 : Group Archive : Group : All Groups

From: Robert Purves <robert.purves@...>
Date: Mon, 29 Nov 2004 19:20:27 +1300
Hayden Coon wrote:

>    I'd like to ask for pointers to getting sounds initiated, 
> sustained, turned on and off (without going the whole Midi route).  
> For example, using symbols to indicate pitch and length of line to 
> show duration, I'd like to be able to do things like:
> cccccccccccccc   ccccccccccccccccccccccccccccccccc     ccccccccc
> xxxxxxxxxxxxxxxxxxxxxxxx  xxxxxxxxxxxxxx  xxxxxxxxxxxxxxxxxx
> ooooooooooooooooo   oooooooooooooo        oooooooooooooooo
>
> all playing simultaneously with the interruptions indicated by the 
> blanks. I'd then want to fool with the relative timing of individual 
> segments.   I don't need complicated things as in simulating a Toccata 
> and Fugue, just simple discriminable tones  with on-offs and 
> overlapping simultaneity.

The little demo below shows how to play square-wave sounds 
simultaneously, with independently controlled left and right speaker 
volumes in 3 sound channels.  The tune is from an oratorio 'The 
Ill-Tempered Mouse' by P.D.Q. Bach. The demo has been tested only in OS 
X 10.3.6.

U.S. readers: note that quaver = eighth-note, bar = measure, and centre 
= center.

Robert P.

'------------------
_volumeCmd = 46

begin enum
_leftChan
_centreChan
_rightChan
end enum

_maxChan = _rightChan

begin globals
dim as Ptr  gSndChannel(_maxChan)
end globals

local fn AllocateChannels
'~'1
dim as long   j
dim as OSErr  err

err = _noErr
for j = 0 to _maxChan
long if ( err == _noErr )
   err = fn SndNewChannel( @gSndChannel(j), _squareWaveSynth, 0, 0 )
end if
next
if ( err ) then shutdown "Could not allocate sound channel " + str$( j )
end fn


local fn SetVolume( chan as long, leftVol as UInt8, rightVol as UInt8 )
'~'1
dim as SndCommand  cmd

cmd.cmd    = _volumeCmd
cmd.param1 = 0
cmd.param2 = leftVol + (rightVol<<16)
end fn = fn SndDoCommand( gSndChannel(chan), cmd, _false )


local fn DurationAndFreq( chan as long, freq as short, duration as long 
)
'~'1
dim as SndCommand  cmd
dim as OSErr       ignore
cmd.cmd    = _freqDurationCmd
cmd.param1 = freq // MIDI freq
cmd.param2 = duration // half-milliseconds
end fn = fn SndDoCommand( gSndChannel(chan), cmd, _false )


_quaver         = 220 // half milliseconds
_crotchet       = _quaver * 2
_dottedCrotchet = _quaver * 3
_bar            = _dottedCrotchet * 2

local fn Tune( chan as long )
'~'1
fn DurationAndFreq( chan, _dottedCrotchet, 60 )
fn DurationAndFreq( chan, _dottedCrotchet, 58 )
fn DurationAndFreq( chan, _bar,            56 )

fn DurationAndFreq( chan, _dottedCrotchet, 63 )
fn DurationAndFreq( chan, _dottedCrotchet, 61 )
fn DurationAndFreq( chan, _dottedCrotchet _crotchet, 60 )
fn DurationAndFreq( chan, _quaver,    63 )

fn DurationAndFreq( chan, _crotchet,  68 )
fn DurationAndFreq( chan, _quaver,    68 )
fn DurationAndFreq( chan, _quaver,    67 )
fn DurationAndFreq( chan, _quaver,    65 )
fn DurationAndFreq( chan, _quaver,    67 )
fn DurationAndFreq( chan, _crotchet,  68 )
fn DurationAndFreq( chan, _quaver,    63 )
fn DurationAndFreq( chan, _crotchet,  63 )
fn DurationAndFreq( chan, _quaver,    61 )

fn DurationAndFreq( chan, _dottedCrotchet, 60 )
fn DurationAndFreq( chan, _dottedCrotchet, 58 )
fn DurationAndFreq( chan, _bar,            56 )

end fn


// main program
_mf = 150 // volume value
_mp = 120

fn AllocateChannels
fn SetVolume( _leftChan, _mf, 0 )
fn Tune( _leftChan )

fn SetVolume( _centreChan, 0, 0 ) // zero volume
fn DurationAndFreq( _centreChan, _bar*2, 1 ) // silence
fn SetVolume( _centreChan, _mp, _mp )
fn Tune(_centreChan)

fn SetVolume( _rightChan, 0, 0 ) // zero volume
fn DurationAndFreq( _rightChan, _bar*4, 1 ) // silence
fn SetVolume( _rightChan, 0, _mf )
fn Tune( _rightChan )


// grand closing cadence
fn SetVolume( _leftChan, 0, 0 ) // zero volume
fn DurationAndFreq( _leftChan, _bar*5, 1 ) // silence
fn SetVolume( _centreChan, 0, 0 ) // zero volume
fn DurationAndFreq( _centreChan, _bar*3, 1 ) // silence
fn SetVolume( _rightChan, 0, 0 ) // zero volume
fn DurationAndFreq( _rightChan, _bar, 1 ) // silence

fn SetVolume( _leftChan,   _mf, 0 )
fn SetVolume( _centreChan, _mp, _mp )
fn SetVolume( _rightChan,   0, _mf )

fn DurationAndFreq( _leftChan,   _bar*3, 61 )
fn DurationAndFreq( _centreChan, _bar,   64 )
fn DurationAndFreq( _rightChan,  _bar,   68 )
fn DurationAndFreq( _centreChan, _bar*3, 63 )
fn DurationAndFreq( _rightChan,  _bar,   67 )
fn DurationAndFreq( _rightChan,  _bar*2, 68 )
fn DurationAndFreq( _leftChan,   _bar,   60 )

stop
'-------------------