// ChatAudio.bcpl -- Generate audio output through Diablo printer interface
// Copyright Xerox Corporation 1979

//	Last modified April 24, 1979  1:37 PM

get "ChatAudio.d"
get "AltoDefs.d"

external
[
// outgoing procedures
EnqueueAudioOut; AudioFinish

// incoming procedures
DisableInterrupts; CauseInterrupt

// outgoing statics
audioSavedSCP; audioSavedUFP

// incoming statics
@acb; lvSwatContextProc; lvUserFinishProc
]

static [ audioSavedSCP; audioSavedUFP ]


// ---------------------------------------------------------------------------
let EnqueueAudioOut(pitch, duration) = valof
// ---------------------------------------------------------------------------
// Pitch is one-half the period of the signal to be generated, in units of
// 38.08 microseconds, and in the range 1 to 1023.  That is,
//	pitch = 1 / (2 * 38.08 * 10↑-6 * f)
// where f is the desired frequency.  This accomodates frequencies from
// approximately 12.8 Hz to 13.1 KHz, though the highest frequencies are
// unattainable due to latency limitations.
// Duration is the length of time to generate the signal, in units of
// the "pitch" interval.
// Returns true iff the queue didn't overflow.
// Special actions: if pitch=0, generates duration*39 ms of silence.
// If duration=0, stops everything and resets the queue.
[
if (pitch & -1024) ne 0 resultis false
let write = acb>>ACB.write
if duration eq 0 & acb>>ACB.duration ne 0 then
   [  // stop current output and reset the queue
   DisableInterrupts()
   acb>>ACB.read = write
   acb>>ACB.duration = 1
   CauseInterrupt(@itInterruptMask)  // Re-enables interrupts
   resultis true
   ]
write!0 = pitch lshift acb>>ACB.sitShiftCount
write!1 = duration
write = write+2
if write eq acb>>ACB.end then write = acb>>ACB.base
test write eq acb>>ACB.read
   ifso resultis false
   ifnot
      [
      acb>>ACB.write = write
      if acb>>ACB.duration eq 0 then
         [ acb>>ACB.duration = 1; CauseInterrupt(@itInterruptMask) ]
      resultis true
      ]
]

// ---------------------------------------------------------------------------
and AudioFinish() be
// ---------------------------------------------------------------------------
[
@itInterruptMask = 0
@lvSwatContextProc = audioSavedSCP
@lvUserFinishProc = audioSavedUFP
]