<> <> <> <<>> <> <<>> 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 _ "/Strowger.lark//Strowger/VoiceRopesLB"; feedback: IO.STREAM; -- for feedback during statistics gathering <> <<>> <> vrTotalSpace: CARD _ 0; vfileTotalSpace: CARD _ 0; <> maxVFID: CARD = 1000; vrsByFile: ARRAY [0..maxVFID] OF CARDINAL _ ALL[0]; maxVrsPerTune: CARD = 25; tunesByVrs: ARRAY [0..maxVrsPerTune] OF CARDINAL _ ALL[0]; <> maxVRSegs: CARD = 25; vrsByNumSegs: ARRAY [0..maxVRSegs] OF CARD _ ALL[0]; <> maxVRSize: CARD = 960000; -- two minutes of voice (8000*120) vrBucketSize: CARD = 8000; -- one second buckets vrsBySize: ARRAY [0..maxVRSize/vrBucketSize] OF CARD _ ALL[0]; vrsWithNegLength: CARD _ 0; <> vrNum: CARD _ 0; vrTotalLength: REAL _ 0; -- in samples <> maxSegSize: CARD = 480000; -- one minute of voice (8000*60) bucketSize: CARD = 8000; -- one second buckets segsBySize: ARRAY [0..maxSegSize/bucketSize] OF CARD _ ALL[0]; segsWithNegLength: CARD _ 0; segsThatStartOnZero: CARD _ 0; <> segsNum: CARD _ 0; segsTotalLength: REAL _ 0; -- in samples <> vr: VoiceRope.VoiceRope _ NEW[VoiceRope.VoiceRopeInterval]; PrintStats: PUBLIC PROC [out: IO.STREAM] RETURNS [] ~ { <> 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: BOOLEAN _ TRUE]>> 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 ANY _ NIL, msg: ROPE _ NIL]>> <> 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 ANY _ NIL, msg: ROPE _ NIL]>> <> 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.