TonePlay.mesa
Copyright Ó 1989, 1990, 1992 by Xerox Corporation. All rights reserved.
Vin, September 10, 1990 11:51 am PDT
Swinehar, September 29, 1992 5:01 pm PDT
All the procedures necessary to open and close the audio device, and to generate
ring tunes are defined in thie definitions file.
Not all of these procedures and structures need to be public. Perhaps none but PlayRingTune does.
DIRECTORY Basics, IO, TuneParse;
TonePlay: CEDAR DEFINITIONS = {
STREAM: TYPE = IO.STREAM;
Scaled: TYPE = Basics.LongNumber;
AudioDataIndex: TYPE = [0..audioDataMod);
audioDataMod: NAT = 2*1024;
AudioHistoryIndex: TYPE = [0..audioHistoryMod);
audioHistoryMod: NAT = 4*1024;
AudioBuf: TYPE = REF AudioBufRep;
AudioBufRep: TYPE = RECORD [
st: STREAM,
flush: PROC [AudioBuf, NAT],
self: PROCESS,
pos: AudioDataIndex,
data: PACKED ARRAY AudioDataIndex OF BYTE,
toneA: FMToneSpec,
toneB: FMToneSpec
];
FMToneSpec: TYPE = REF FMToneSpecBody;
FMToneSpecBody: TYPE = RECORD [
phaseStep1: Scaled,
phaseStep2: Scaled,
ampDefault: REAL,
fadeInSteps: INT,
normalSteps: INT,
fadeOutSteps: INT,
zeroSteps: INT,
ampFadeIn: Scaled,
ampFadeOut: Scaled,
ampInit: Scaled,
phaseRatio: Scaled,
delaySteps: AudioHistoryIndex,
delayRatio: Scaled,
phase1: Scaled,
phase2: Scaled,
amp: Scaled,
rem: INT,
state: ToneState,
histPos: AudioHistoryIndex,
history: ARRAY AudioHistoryIndex OF Scaled
];
ToneState: TYPE = {fadeIn, normal, fadeOut, zero};
MuLawByte: TYPE = MACHINE DEPENDENT RECORD [
SELECT OVERLAID * FROM
byte => [byte: BYTE],
coded => [positive: BOOL, code: [0..128)],
parts => [pos: BIT, octant: [0..7], rem: [0..15]]
ENDCASE
];
SumArray: TYPE = ARRAY BYTE OF ARRAY BYTE OF BYTE;
OutputBuffer: TYPE = PACKED ARRAY [0..216) OF BYTE;
OutputBufferIndex: TYPE = INT [0..216);
OpenAudioDeviceForWrite: PROC[defaultAmplitude: REAL] RETURNS [buf: AudioBuf];
buf represents an open output stream to the (shared) audio device. defaultAmplitude, preferred value around 0.1, adjusts the master gain for this stream. Appropriate ranges for this value will be published as they are determined. The functions PlayTonePair, PlayRingTune, and (for the adventurous) GenTone can be called to make noises over this stream. Through GenTone, a wide range of FM-synthesized sounds are possible, although the PlayTone/Tune routines can only produce pairs of sine-waves.
Partially-enforced MANDATE!: All activity on the stream, except Stop, MUST be initiated from the process that called OpenAudioDeviceForWrite. This permits Stop to generate a process abort, even when no tone is being played, without confusion resulting.
Client is responsible for catching ABORTED or UNWIND and at the least closing the stream. If any activity were underway at the time it will have been abandoned, so the close should be innocuous.
CloseWriteAudioDevice: PROC[buf: AudioBuf, discardQueued: BOOL¬FALSE];
discardQueued is the Unix flush (Cedar Close.abort) -- immediately abandon attempts to write any information stored anywhere in the pipeline.
PlayTonePair: PROC [buf: AudioBuf, time: REAL, freq1: REAL, freq2: REAL];
Using this procedure, both freqs are sine waves, and both are at some default amplitude. Many of the tone-generation capabilities of the GenTone routine are not used. This procedure can handle Etherphone-style ring tones, progress signals, and ring tunes. Or at least the noisy parts of them.
PlayRingTune: PROC [buf: AudioBuf, toneSpec: TuneParse.ToneSpec];
Play the entire toneSpec (a parsed ring tune). Spawns a process if necessary, to permit a number of tunes to be played sequentially.
GenTone: PROC [buf: AudioBuf];
Client must fill in the parameter specifications for the current tone pair before calling.
Stop: PROC[buf: AudioBuf];
Terminates whatever tone activity is occurring on this stream; aborts the process that called OpenAudioDeviceForWrite to create this buf.
}.
Not used these days.
InitSumArray: PROC RETURNS [REF SumArray];
DecodeReal: PROC [m: MuLawByte] RETURNS [REAL];
DecodeScaled: PROC [m: MuLawByte] RETURNS [Scaled];
EncodeScaled: PROC [s: Scaled] RETURNS [BYTE];
AddScaled: PROC [s1, s2: Scaled] RETURNS [Scaled];
HeavyEncode: PROC [r: REAL] RETURNS [BYTE];
OpenAudioDeviceForRead: PROC;
CloseReadAudioDevice: PROC;
ReadNextSample: PROC RETURNS [nextBlock: REF TEXT, nBytesRead: NAT];
WriteToAudioDevice: PROC [buffer: OutputBuffer, startIndex: OutputBufferIndex, length: INT];