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 '-------------------