VoiceRopeUsage.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Doug Terry, August 3, 1987 1:29:20 pm PDT
Gathers statistics about voice ropes by analyzing the database.
DIRECTORY
BluejayUtils,
BluejayUtilsRpcControl,
Commander USING [CommandProc, Register],
IO USING [card, int, rope, PutF, PutRope, real, STREAM],
Rope USING [ROPE, Cat],
VoiceRope,
VoiceRopeServer,
VoiceRopeDB USING [Handle, --Header, Interest, InterestInfo,-- VoiceRopeInfo, Error, Open, EnumerateVoiceRopes, EnumProc, --EnumerateInterestClass, InterestProc, UnpackHeader, UnpackInterest,-- NextTuneOnList, TuneID, TuneList];
VoiceRopeUsage: CEDAR PROGRAM
IMPORTS BluejayUtils, BluejayUtilsRpcControl, Commander, IO, Rope, VoiceRope, VoiceRopeDB
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
vrdb: ROPE ← "/Morley.lark//DCS/VoiceRopeServer/VoiceRopesLB";
vrdb: ROPE ← "/Strowger.lark//Strowger/VoiceRopesLB";
feedback: IO.STREAM; -- for feedback during statistics gathering
Usage statistics:
Storage
vrTotalSpace: CARD ← 0;
vfileTotalSpace: CARD ← 0;
Number of voice ropes that use a given voice file
maxVFID: CARD = 1000;
vrsByFile: ARRAY [0..maxVFID] OF CARDINALALL[0];
maxVrsPerTune: CARD = 25;
tunesByVrs: ARRAY [0..maxVrsPerTune] OF CARDINALALL[0];
Number of segments in a voice rope
maxVRSegs: CARD = 25;
vrsByNumSegs: ARRAY [0..maxVRSegs] OF CARDALL[0];
Lengths of voice ropes
maxVRSize: CARD = 960000; -- two minutes of voice (8000*120)
vrBucketSize: CARD = 8000; -- one second buckets
vrsBySize: ARRAY [0..maxVRSize/vrBucketSize] OF CARDALL[0];
vrsWithNegLength: CARD ← 0;
Average length
vrNum: CARD ← 0;
vrTotalLength: REAL ← 0; -- in samples
Segment sizes for voice ropes
maxSegSize: CARD = 480000; -- one minute of voice (8000*60)
bucketSize: CARD = 8000; -- one second buckets
segsBySize: ARRAY [0..maxSegSize/bucketSize] OF CARDALL[0];
segsWithNegLength: CARD ← 0;
segsThatStartOnZero: CARD ← 0;
Average length
segsNum: CARD ← 0;
segsTotalLength: REAL ← 0; -- in samples
An actual voice rope
vr: VoiceRope.VoiceRope ← NEW[VoiceRope.VoiceRopeInterval];
PrintStats: PUBLIC PROC [out: IO.STREAM] RETURNS [] ~ {
Prints the gathered stats.
numVrs, numTunes, numSegs: CARD ← 0;
IO.PutRope[out, "\n\n"];
IO.PutRope[out, "Voice ropes by number of tune segments:\n"];
FOR i: CARD IN [0..maxVRSegs] DO
IO.PutF[out, " %g: %g\n", IO.card[i], IO.card[vrsByNumSegs[i]]];
numVrs ← numVrs + vrsByNumSegs[i];
ENDLOOP;
IO.PutF[out, "%g total voice ropes\n", IO.card[numVrs]];
IO.PutRope[out, "\n"];
IO.PutF[out, "Voice rope sizes (%g samples):\n", IO.card[vrBucketSize]];
FOR i: CARD IN [0..maxVRSize/vrBucketSize] DO
IO.PutF[out, " <%g: %g\n", IO.card[i], IO.card[vrsBySize[i]]];
ENDLOOP;
IO.PutF[out, "Total # of voice ropes = %g\n", IO.card[vrNum]];
IO.PutF[out, "Total voice rope storage = %g\n", IO.real[vrTotalLength]];
IO.PutF[out, "Average voice rope length (in seconds) = %g\n", IO.real[(vrTotalLength/vrNum)/8000]];
IO.PutF[out, "%g voice ropes have negative length\n", IO.card[vrsWithNegLength]];
IO.PutRope[out, "\n"];
IO.PutF[out, "Segment sizes (%g samples):\n", IO.card[bucketSize]];
FOR i: CARD IN [0..maxSegSize/bucketSize] DO
IO.PutF[out, " <%g: %g\n", IO.card[i], IO.card[segsBySize[i]]];
numSegs ← numSegs + segsBySize[i];
ENDLOOP;
IO.PutF[out, "Total # of segments = %g\n", IO.card[segsNum]];
IO.PutF[out, "Total segment storage = %g\n", IO.real[segsTotalLength]];
IO.PutF[out, "Average segment length (in seconds) = %g\n", IO.real[(segsTotalLength/segsNum)/8000]];
IO.PutF[out, "%g total segments\n", IO.card[numSegs]];
IO.PutF[out, "%g segments have negative length\n", IO.card[segsWithNegLength]];
IO.PutF[out, "%g segments start at zero\n", IO.card[segsThatStartOnZero]];
IO.PutRope[out, "\n"];
IO.PutRope[out, "Tunes by number of voice ropes:\n"];
FOR i: CARD IN [1..maxVFID] DO
vrs: CARD = vrsByFile[i];
SELECT vrs FROM
IN [1..maxVrsPerTune] => tunesByVrs[vrs] ← tunesByVrs[vrs] + 1;
> maxVrsPerTune => tunesByVrs[0] ← tunesByVrs[0] + 1;
ENDCASE => NULL;
ENDLOOP;
FOR i: CARD IN [0..maxVrsPerTune] DO
IO.PutF[out, " %g: %g\n", IO.card[i], IO.card[tunesByVrs[i]]];
numTunes ← numTunes + tunesByVrs[i];
ENDLOOP;
IO.PutF[out, "%g total tunes\n", IO.card[numTunes]];
IO.PutRope[out, "\n"];
};
CollectStats: VoiceRopeDB.EnumProc ~ {
[info: VoiceRopeInfo] RETURNS [continue: BOOLEANTRUE]
numSegs: CARD ← 0;
tid: VoiceRopeDB.TuneID;
tstart, tlen: INT;
tl: VoiceRopeDB.TuneList ← info.struct;
vrNum ← vrNum + 1;
WHILE tl#NIL DO
[tune: tid, start: tstart, length: tlen, rest: tl] ← VoiceRopeDB.NextTuneOnList[tl];
IF tid IN INT[1..maxVFID]
THEN vrsByFile[tid] ← vrsByFile[tid] + 1
ELSE vrsByFile[0] ← vrsByFile[0] + 1;
numSegs ← numSegs + 1;
IF NOT (tl=NIL AND numSegs=1) THEN { -- only gather for multi-segment vrs
IF tlen>=0 THEN {
segsTotalLength ← segsTotalLength + tlen;
tlen ← tlen/bucketSize + 1;
};
SELECT tlen FROM
<0 => {
segsWithNegLength ← segsWithNegLength + 1;
IO.PutF[feedback, "\nWarning: vr=%g segment length=%g\n", IO.rope[info.vrID], IO.int[tlen]];
};
IN [1..maxSegSize/bucketSize] => segsBySize[tlen] ← segsBySize[tlen] + 1;
ENDCASE => segsBySize[0] ← segsBySize[0] + 1;
IF tstart = 0 THEN segsThatStartOnZero ← segsThatStartOnZero + 1;
};
segsNum ← segsNum + 1; -- total number of segments
ENDLOOP;
IF info.length < 0 THEN {
vr.ropeID ← info.vrID;
info.length ← VoiceRope.Length[vr: vr];
};
IF info.length>=0 THEN {
vrTotalLength ← vrTotalLength + info.length;
info.length ← info.length/vrBucketSize + 1;
};
SELECT info.length FROM
<0 => {
vrsWithNegLength ← vrsWithNegLength + 1;
IO.PutF[feedback, "\nWarning: vr=%g length=%g\n", IO.rope[info.vrID], IO.int[info.length]];
};
IN [1..maxVRSize/vrBucketSize] => vrsBySize[info.length] ← vrsBySize[info.length] + 1;
ENDCASE => {
vrsBySize[0] ← vrsBySize[0] + 1;
IO.PutF[feedback, "\nWarning: vr=%g length (in buckets)=%g\n", IO.rope[info.vrID], IO.int[info.length]];
};
IF numSegs IN [0..maxVRSegs]
THEN vrsByNumSegs[numSegs] ← vrsByNumSegs[numSegs] + 1
ELSE vrsByNumSegs[0] ← vrsByNumSegs[0] + 1;
IO.PutRope[feedback, " ."];
};
Analyze: Commander.CommandProc = {
[cmd: Commander.Handle] RETURNS [result: REF ANYNIL, msg: ROPENIL]
Enumerates the voice rope database and gathers statistics.
ENABLE VoiceRopeDB.Error => {msg ← Rope.Cat["ERROR: ", explanation]; GOTO Error};
handle: VoiceRopeDB.Handle ← VoiceRopeDB.Open[dbName: vrdb];
IO.PutF[cmd.out, "Analyzing %g ...\n", IO.rope[vrdb]];
feedback ← cmd.out;
VoiceRopeDB.EnumerateVoiceRopes[handle: handle, start: NIL, proc: CollectStats];
PrintStats[cmd.out];
EXITS
Error => RETURN;
};
AnalyzeTunes: Commander.CommandProc = {
[cmd: Commander.Handle] RETURNS [result: REF ANYNIL, msg: ROPENIL]
Enumerates the the jukebox and computes total tune length.
exists: BOOL;
size: INT;
num: CARD ← 0;
feedback ← cmd.out;
BluejayUtilsRpcControl.ImportInterface[interfaceName: [type: "BluejayUtils", instance: "Strowger.lark"]];
FOR tid: CARD IN [0..maxVFID] DO
[exists, size] ← BluejayUtils.DescribeTune[tid];
IF exists THEN {
vfileTotalSpace ← vfileTotalSpace + size;
num ← num + 1;
};
ENDLOOP;
IO.PutF[cmd.out, "Total # of tunes = %g\n", IO.card[num]];
IO.PutF[cmd.out, "Total length of tunes (in chirps) = %g\n", IO.card[vfileTotalSpace]];
};
Commander.Register[key: "VRUsage", proc: Analyze, doc: "Gathers statistics about voice ropes by analyzing the database"];
Commander.Register[key: "TuneStorage", proc: AnalyzeTunes, doc: "Computes total tune storage."];
END.