{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;\f2\fmodern Courier;\f1\fmodern Ohlfs;}
\paperw13700
\paperh10200
\margl120
\margr120
{\colortbl;\red0\green0\blue0;}
\pard\tx1340\tx2680\tx4020\tx5360\tx6720\tx8060\tx9400\tx10740\tx12080\tx13440\f0\b0\i0\ulnone\fs28\fc0\cf0 \
Ideas:\
logged	done\
\
To Do:\
logged	done\

\fi-2680\li2680 921992		Put in separate control for pitch and rate.  Note that rate from Procrustes's point of view is really pitch * rate.  \

\fi0\li0 \
Limiting P1 to some # of zero crossings seems to work well.\
\
Perhaps try limiting P2 similarly, or just the product of P1 and P2?  Try getting rid of the stage size limit and let the placement of zero crossings determine how faw we slip the relative sound segments against each other.\
\
Try to convert compute_error to all fixpoint arithmetic.\
\
Holy grail: is there a way to quit from compute_error early, or to quit from the loop when we find something "good enough"?\
\
Start thinking about how to convert this for a stream of data for real-time stuff.\
\
Gather a standard suite of sound sources to test:\
	Voice in clean background\
	Voice in noisy background\
	Acoustic guitar or piano\
	Jazz\
	Rock\
	Orchestral\
\
17-Sep-92\
\
TimeWarp7 speaks in real time!!!!  \
\
At large:\
	* several bug fixes (why won't it stop at the end of source file?)\
	* make it work on monophonic files\
	* hook up completionView based on source sound\
	* use memmove whenever possible\
	cc -O and pick over inner loops with gdb/i\
	* try averaging filter when finding zero crossings\
	* rewrite procrustian interface to say "start playing (near) frame nnn"\
	I wonder if dithering the fixed length segment size would break\
	  up periodicity in a reasonable way?\
	\
\
17-Sep-92\
\
Andy Moorer was right - string quartets are hard.  Using Dvorak's 12th Quartet, a little snippet near the beginning of the first movement.\
\
Rate = relative rate\
MaxTest = sqrt(# of correlation tests)\
FixLen = length of fixed buffer we write out\
CompLen = max number of samples we can deviate from ideal time\
Correl = width of correlation window\
XFadLen = length of crossfade\
\
Rate	MaxTest	FixLen	CompLen	Correl	XFadLen	\
0.95	8	4000	5000	2000	2000	Sounds good\
0.95	8	4000	500	2000	2000	Sounds almost as good\
0.95	8	4000	200	2000	2000	Sounds almost as good\
0.95	8	4000	50	2000	2000	starts to flutter\
0.95	8	4000	1000	2000	2000	Sounds good\
0.95	8	4000	1000	500	500	flutter\
0.95	8	4000	1000	1000	1000	a little flutter\
\
0.90	8	4000	1000	2000	2000	still pretty good\
0.90	8	4000	1000	4000	4000	outright good\
0.90	8	3000	1000	3000	3000	not as good\
0.90	8	3500	1000	3500	3500	not as good\
\
0.85	8	4000	1000	2000	2000	attacks echo\
0.85	8	3000	1000	2000	2000	attacks flutter, some burbles\
0.85	8	3000	1000	3000	3000	not bad, considering...\
\
1.05	8	4000	1000	4000	4000	outright good\
1.05	8	4000	1000	500	500	some burbles\
1.05	8	4000	1000	2000	2000	pretty good\
\
1.10	8	4000	1000	2000	2000	pretty good\
1.10	8	4000	1000	4000	4000	outright good\
\
But with the long correlation windows and high rates (= 1.5), we don't always have time for 64 correlations (e.g. when we're paging in a sound file that hasn't yet been played).  Dropping MaxTest down to 5 (= 25 tests) seems to produce equally good results and give us enough time.\
\
What we're using for testing (and the best results for each of a few different speeds):\
\
First minute from Dvorak String Quartet 96 "American" - Emerson String Quartet on Deutsche Grammonphon 1986\
\
Rate	MaxTest	FixLen	CompLen	Correl	XFadLen	\
0.85	8	3000	1000	3000	3000	not bad, considering...\
0.90	8	4000	1000	4000	4000	outright good\
0.95	8	4000	5000	2000	2000	Sounds good\
1.05	8	4000	1000	4000	4000	outright good\
1.10	8	4000	1000	4000	4000	outright good\
1.15	8	4000	1000	4000	4000	outright good\
\
From Sergey Rachmaninov's "Etudes-Tableaux Op 39 1916-1917, No 8 in D Minor\
\
On Rachmaninov's work, a crossfade of 4000 make a definite tremeo effect.  A shorter correlation window and crossfade length seem to work better:\
\
Rate	MaxTest	FixLen	CompLen	Correl	XFadLen	\
1.15	5	4000	1000	500	200\
0.90	5	4000	1000	500	200\
0.85	5	3000	1000	1000	1000	(not great)\
\
William S. Burroughs - excerpt from "After-dinner Conversation" from "Dead City Radio" - Island Records 1990\
\
0.85	5	3000	1000	1000	1000	definite flutter\
0.85	5	3000	1000	3000	3000	worse flutter\
0.85	5	3000	1000	500	500	pretty good\
0.85	5	3000	1000	500	200	better\
0.9	5	3000	1000	500	200	just fine\
0.90	5	4000	1000	4000	4000	too much flutter\
0.90	5	4000	1000	500	200	good, a little burble\
0.95	5	4000	1000	500	200	good, some burble\
1.05	5	4000	1000	1000	1000	some flutter\
1.05	5	4000	1000	500	200	good, tiny burbles\
1.10	5	4000	1000	500	200	good, tiny burbles\
1.15	5	4000	1000	500	200	just fine\
1.5(!!)	5	1500	1000	500	200	surprisingly good, some flutter\
\
Pat Metheny - excerpt from "River Quay" from "Watercolors" - 1977 ECM records\
\
0.85	5	4000	1000	500	200	some echo (but not much)\
0.85	5	3000	1000	500	200	better\
0.85	5	2000	1000	500	200	bass burbles some\
0.85	5	2000	1000	1000	1000	"edgy" flutter\
<>	5	4000	1000	500	250	works well for a wide range, but below .85 the echo becomes extreme.  This except works very convincingly...\
\
Excerpt from Dr. John - Making Whoopee from In a Sentimental Mood - Warner Bros Records 1989\
\
Prominant bass burbles some, especially above 1.25, but the following seems pretty good:\
<>	5	4000	1000	500	250	works well for a wide range\
\
Excerpt from Jan Garbarek "Folk Song" from "Works" album, ECM 1984\
\
Seems to work fine with what's becoming the defaults, but I'll probably have to delete it for want of disk space.  It's not clear enough on the rhythm to make a convincing example -- you can play it .85 or 1.15 and still think it's at tempo.\
<>	5	4000	1000	500	250	works well for a wide range\
\
Jesus Jones "Right Here Right Now" from "Doubt" - SBK Records 1991  (Could be better recorded - I think it clipped a bunch of times while recording.)\
\
Works just fine with all the standard parameters over a huge range.  Let's hear it for R&R.  Except for the fade out on the bass note...\
\
====== 18 Sep 92 =====\
\
To do:\
\
* Fix Procrustes so it works on mono as well as stereo [Done 19 Sep]\
* Fix Procrustes to stop properly at the end of the source sound file. 
\fc1\cf1 [Done 19 Sep]\
* Fix the app with appDidInit: to set up initial parameters [Done 19 Sep]\
\
Future ideas:\
widen the crossfade window when the correlation is low.\
compute maximuim possible correlation, use it to normalize returned values\
try dithering fixedLength to break up periodic artifacts\
\
Dinking with the semantics of stageLength.  Currently stageLength is the size of the buffer we use in looking for zero crossings.  The last zero crossing possible is at stageLength - windowLength.  Better (more intuitive) would be to have the last possible zero crossing at complianceLength, which means how sloppy we can get with time on any given snippet.\
\
===== 19 Sep 92 =====\
\
To do:\
\
Eliminate rate altogether from Procrustes.  Instead, writeOneSegment: inherits a startingAt:frame argument.  The Controller will take care of current time and rate and such.  (Although someday in the future, Procrustes may want to know the current rate in order to adjust parameters better.) [Done 19-Sep-92]\
\
Normalize the correlation function (if only to help monitor its performance).\
\
Come up with a way to watch the behaviour of the zero crossings.  Do they all bunch up near the beginning of the window?  Am I getting screwed by high frequencies?\
\
Run an average function before taking the zero crossings.\
\
Don't bother to find all the zero crossings if I'm not going to use them.\
\
Strange, but for +/-12% changes, the following parameters seem to be working really well on ZOutro and Dvorak (which are tough cases):\
\
Rate	MaxTest	FixLen	CompLen	Correl	XFadLen	\
.88	10	2000	1000	1000	1000\
1.12	10	2000	1000	1000	1000\
\
This is a more correlation tests, a shorter fixed length, a longer correlation window and longer crossfade than I'd been doing.  It also eats up much more CPU - idle time has dropped from 70% to 30% or less.  Maybe its time finally to look at those inner loops.\
\
920919 16:00\
If I could normalize the correlation value returned, it would serve as an indication of how good the splice was.  Idea: if it's a good splice, make it a fast crossfade.  If it's a bad splice (low correlation), do a slow crossfade to smooth things out.\
\
920919 17:00\
Conversation with Dana Massie - emu - sketched out what I was doing, asked what papers might have been published on time compresion:\
	Harmonizer Patent by Tony Agnello (call him at Ariel)\
	Douglas ?? and Tom Parks "Synchronized Overlap/Add for Time Compression" ICAASP\
	John Datorro - AES paper or preprint, ca 1989\
	The original: Dennis Gabor ca 1940 - built an optical device\
Dana points out that synchronized overlap/add is first cousin to Phase Vocoder of one channel, and wonders what would happen if you divided the spectrum into a few bands (maybe only two) and ran the overlap/add algorithm on the channels separately.\
\
[AES note: Roger Powell at SGI is a friend of Dana's, plays with Utopia, worked at Waveframe, straightforwarding marketing guy.  Contact him about relative positioning between NeXTstation and SGI Iris/Indigo.]\
\
920919	17:20\
Putting in code to normalize the correlation value to a value between -1 and 1.  Works.  Graphically, it isn't that interesting.\
\
920919	20:47\
Averaging before the zero detection appears to be a big win, expecially for something with prominant bass and lots of hash up at the high end (e.g. Dr. John sound sample).  I was expecting that averaging five samples or so would make sense, but it seems to work well with values more like 100.\
\
920919	22"09\
Profiling.  Here are the top few time consumers.  The compute_correlation is to be expected, though it's certainy a place to pore over to coax out some cycles.  I'm surprised that writeSegmentInto:: is so high.  And there may be some change of data type that will eliminate the calls to __fixdsi, if I can figure out where that's happening.  Ahh - most of the calls happen within findXFadePoint - 790000 of them, to be exact.\
\
 14.2	 7.85	3.68	21439	0.17	0.17	_compute_correlation [8]\
 14.1	11.49	3.64	1581	2.30	7.73	-[Procrustes writeSegmentInto::] [6]\
 12.1	14.63	3.14				_memmove [9]\
 10.9	17.45	2.81	3162	0.89	0.89	-[Procrustes _findPlacesToCompare:::]\
 10.8	20.24	2.80				rcopy [11]\
  7.2	22.12	1.88	796949	0.00	0.00	__fixdfsi [12]\
  1.8	22.59	0.48				_objc_msgSend [18]\
  1.1	22.89	0.30	4006	0.07	0.08	__class_lookupMethodAndLoadCache\
  0.5	23.03	0.14	1581	0.09	4.25	-[Procrustes findXFadePoint::::] [7]\
\
Modified the cross-fade code to use fixpoint arithmetic.\
\
Added an option for "dynamic cross fade" - if the correlation is bad, it uses more of the full Crossfade Length.  As the correlation improves, it shortens the crossfade time.  For a "perfect" splice, it simply cuts from one snip to the other.  But after playing with it, it's not clear that this feature provides any audible imrpovement.\
\
===== 20 Sep 92 =====\
\
It would be useful to set Fixed Length + Compliant Length in terms of the maximum time error we can tolerate across splices, and vary the lengths according to the current rate.  For example, with a rate of 1.0, it doesn't matter how long F + C is - the splices will always line up.  If SpliceLength = the total length of the previous splice, then the amount of time we need to make up in the new splice is:\
	FrameError = SpliceLength * (1 - rate)\
FrameError is the number of frames we need to drop (for rate > 1) or overlap (for rate < 1).\
	TimeError = FrameError/SamplingRate\
If we wish to hold TimeError to some minumum (say 30 ms):\
	MaxSpliceLength = MaxTimeError * SamplingRate / (1 - rate)\
\
It may be useful to create a new object that are the "brains" for Procrustes.  The brains would dynamically modify the Procrustean parameters based on higher-level control information.\
\
920920	1900\
Tried automatically scaling down snipLength, stageLength, xFadeLength if the frame error exceeded a threshold.  Sort of works, but I need to be smarter in how the parameters relate to one another as they scale.  For example, near rate=1.0, it's okay if snipLength is 4000 and stageLength is 1000.  But at extreme speeds, you don't want snipLength=400 and stageLength=100; you'd rather have snipLength=100 and stageLength=400.\
\
So I'll revisit my favorite parameters for various speeds and try to deduce some rules as to what's going on...\
\
NB: maximum tests = 5 in every case.\
\
ClarkeVox.snd\
speed	fixed	compliant	xFade	window	lowPass\
0.5	100	400	100	100	5-50\
0.8	100	400	100	100	5-50\
...\
1.2	100	250	50	100	1-4\
2.0	100	250	50	100	1-4\
\
DrJohnWhopee.snd\
speed	fixed	compliant	xFade	window	lowPass\
0.5	100	1000	200	200	75\
0.8	100	1000	200	200	75\
...\
1.2	100	1000	200	200	75\
2.0	100	1000	200	200	75	lots of tremelo during vocals\
2.0	100	1000	200	200	50	better...\
2.0	100	750	200	200	25	okay at the expense of the bass\
2.0	200	1000	500	200	75	wider xfade hides artifacts\
extra credit:\
2.0	100	500	200	2000	500	space age!!!!\
\
DvorakQ12.snd\
speed	fixed	compliant	xFade	window	lowPass\
0.5	100	2000	250	500	20	pretty bad still...\
0.8	100	1000	250	200	75	messes up opening violin ppp figure\
0.8	100	1000	250	200	20	okay for opening, not as good otherwise\
0.8	1000	1000	1000	1000	75	surprisingly good\
0.8	750	750	250	750	75	still pretty good\
0.9	1000	1000	250	200	75	good\
1.2	1000	1000	250	200	75	good\
2.0	400	400	500	200	75	wide xfade hides tremelo (some)\
\
JesusJonesRHRN.snd\
speed	fixed	compliant	xFade	window	lowPass\
0.5	100	750	200	200	75	guess you can't fool nature...\
0.8	100	750	200	200	75\
1.2	100	750	200	200	75\
2.0	100	750	200	1000	75	wide window seems to work?\
\
MethenyRiverQuay.snd\
speed	fixed	compliant	xFade	window	lowPass\
0.8	100	1000	200	200	75\
0.8	100	750	200	200	75	bass warbles\
0.8	100	750	200	200	60	still warbles, but better...\
0.8	100	750	200	2000[*]	60	even better.  good even.\
1.2	100	1000	200	200	75\
2.0	100	1000	100	1000	75	pretty bad...\
\
RachmaninovOp39DMin.snd\
speed	fixed	compliant	xFade	window	lowPass\
0.5	100	1000	250	1000[*]	75	as good as it gets...\
0.8	100	1000	250	1000[*]	75\
1.2	100	1000	250	1000	75\
2.0	100	1000	250	1000[*]	75	running out of CPU cycles...\
2.0	100	1000	250	250	75	quite spacey sounding\
\
WSBurroughs.snd\
speed	fixed	compliant	xFade	window	lowPass\
0.8	100	500	100	1000	75\
1.2	100	500	100	500	75\
2.0	100	500	100	1000	10	running out of CPU\
2.0	100	500	100	500	10\
\
[*] What's really happening (in the code) when the correlation window is longer than the compliance window???  Lengthening it seems to improve the bass/frequency accuracy without increasing the total segment size.\
\
920920	2100\
\
Observation: The goal is to get things sounding good at either speed extreme (fast or slow) -- the more moderate speeds take care of themselves in every case.  We can trade off temporal accuracy against good frequency accuracy.  ClarkeVox is extreme temporal, DvorakQ12 goes for frequency.  Compliance length ranges from 100 to 1000.   Correlation window is 1/4 of Compliance length (except it seems to help to lengthen it for high speed?).   Maybe everything else can stay constant?\
\
Thinking about it in the abstract, we can trade off temporal accuracy (i.e. minimum length segment lengths) against not just frequency accuracy, but bandwidth accuracy.  If we know that the source material is limited to a particular range of frequencies, then we can make the compliance window just long enough to fit.  If the source material is broad band, then it's harder.\
\
Next step: Run the set over again from the start, starting with the numbers I ended up with.  \
\
===== 920921 =====\
\
The design goals:\
\
Support two modes: voice mode and music mode.\
For voice mode, support speeds from .5 to 2.0 (+/- one octave)\
For music mode, support speeds from .89 to 1.12 (+/- two semitones)\
\
Read in more sound examples: Beethoven symphonic section, solo piano, vocal choir.\
\
A guess for music (+/- 3 semitones)\
\
speed	fixed	compliant	xFade	window	lowPass\
0.84	100	500	100	1000	75\
0.89	100	500	100	1000	75\
0.94\
1.0	- -\
1.06	100	500	100	1000	75\
1.12	100	500	100	1000	75\
1.19	100	500	100	1000	75\
\
Beethoven:\
1.12	1000	1000	250	1000	10	still edgy at the beginning\
1.12	2000	1000	1000	1000	10	pretty good, beginning not edgy\
raising zero detector average to 75 forces opening note up 12%.\
\
DebussyMenuet\
1.12	2000	1000	1000	1000	10	good.\
1.12	100	1000	250	1000	10	also good.\
1.12	100	500	100	1000	10	also good - teeny warble in bass\
1.12	100	500	100	1000	75	more warble?\
\
Dr. John Whoopie\
speed	fixed	compliant	xFade	window	lowPass\
1.12	100	500	100	1000	75	too much warble in bass\
1.12	100	1000	100	1000	10	too much warble in bass\
1.12	100	1000	100	1000	75	good\
1.12	100	1000	100	250	75	good, but piano starts to lose out\
1.12	500	800	100	250	75	good, start to hear time abberations\
\
DvorakQ12\
1.12	500	1000	100	250	75	coreces opening notes out of tune\
1.12	500	1000	100	250	10	better, but thumps a bit\
1.12	1000	1000	250	500	75	opening notes pretty good, rest great\
1.12	1000	1000	250	500	10	opening notes better, more chorble\
\
JesusJones\
1.12	1000	1000	250	500	10	just fine, thank you\
\
Pat Metheny\
1.12	1000	1000	250	500	10	pretty good, some bass warble\
1.12	1000	1000	250	500	75	good\
\
Nono Liebslied \
1.12	1000	1000	250	500	75	some xfade artifacts...\
1.12	1000	500	500	500	10	good (stolen from Voice settings)\
\
Tuck Andress Beguine\
speed	fixed	compliant	xFade	window	lowPass\
1.12	1000	1000	100	500	10	very good. \
1.12	100	2000	100	500	10	also very good.\
1.12	4000	1000	250	500	10	still even good.\
This solo electric guitar was much easier than I though it would be.\
\
===== 25 Sep 92 ====\
\
Looking for parameters that work well for a variety of music for speeds from .88 to 1.12:\
\
speed	fixed	compliant	xfade	window	lowpass	maxtests\
1.12	100	1000	1000	500	10	8 (=64)\
\
we can steal a bit from the compliant window and make it fixed.  Also, a shorter xfade helps for speeds less than unity:\
speed	fixed	compliant	xfade	window	lowpass	maxtests\
1.12	300	800	500	500	10	8 (=64)\
\
^^^ Pretty good overall ^^^\
\
These parameters eat up about 65% of the (25Mhz) 68040 (this includes a big LCD style display that's updated whenever we send a buffer to DACPlayer).  By and large, we're still limited by disk bandwidth.  For the presentation at AES, tune an external disk with rotdelay=0, which will increase the read performance (at the expense of write performance).  Try firing up the DAT drive to see if I can archive and restore the sounds.  (Actually, they'll fit on an MO drive without trouble.)\
\
Modified Controller.m so that the repeat function takes place from within playData:::, meaning that the sound will repeat instantly without shutting down the DACs, etc.  Works great.\
\
===== 25 Sep 92 =====\
\
Modified the defaults at startup to be:\
speed	fixed	compliant	xfade	window	lowpass	maxtests\
1.12	300	800	500	500	20	8 (=64)\
\
Backing up the sound files to optical for now.  I would like to:\
	reformat the xternal disk\
	run benchmarks on it (writing and reading)\
	reformat it\
	tunefs -rotdelay to zero\
	run benchmarks again\
to see if I can get better read performance off the disk.  That would help in this case.\
\
===== 26 Sep 92 =====\
\
Experiments with tuning a filesystem:\
\
On a freshly formatted and initialized SEAGATE ST1480 (external disk drive):\
\
Writing 24.4 Meg of data on a 4ms rotdelay partition, it takes about 29 seconds to write 24402140 bytes of data (841 Kbytes/sec): \
\

\f2\fs22 % /bin/time cat BigMix.snd BigMix.snd BigMix.snd BigMix.snd BigMix.snd > /WalkDisk/file1\
       28.4 real         0.0 user        20.1 sys  \
% /bin/time cat BigMix.snd BigMix.snd BigMix.snd BigMix.snd BigMix.snd > /WalkDisk/file2\
       29.4 real         0.0 user        19.9 sys  \
\

\f0\fs28 Reading the data goes about 1100 KBytes/sec:\

\f2\fs22 \
% cd /WalkDisk\
% dr file1\
Reading 24402140 bytes from file1\
23830.21 Kbytes in 21.696719 sec = 1098.33KBytes/sec\
% dr file2\
Reading 24402140 bytes from file2\
23830.21 Kbytes in 21.983321 sec = 1084.01KBytes/sec\
% dr file1\
Reading 24402140 bytes from file1\
23830.21 Kbytes in 21.041022 sec = 1132.56KBytes/sec\
% dr file2\
Reading 24402140 bytes from file2\
23830.21 Kbytes in 21.969360 sec = 1084.70KBytes/sec\
% dr file2\
Reading 24402140 bytes from file2\
23830.21 Kbytes in 21.863819 sec = 1089.94KBytes/sec\
\

\f0\fs28 Now we tune the filesystem 0 ms rotational delay:\

\f2\fs22 \
# umount /WalkDisk\
# tunefs -d 0 /dev/rsd1a\
rotational delay between contiguous blocks changes from 4ms to 0ms\
# mount /dev/sd1a /WalkDisk\
# exit\

\f0\fs28 \
Writing data on a 0ms rotdelay partition.  Write times have slowed way down, from 841 Kbytes/sec to 480 KBytes/sec:\

\f2\fs22 \
% /bin/time cat BigMix.snd BigMix.snd BigMix.snd BigMix.snd BigMix.snd > /WalkDisk/file3\
       70.3 real         0.0 user        23.9 sys  \
% /bin/time cat BigMix.snd BigMix.snd BigMix.snd BigMix.snd BigMix.snd > /WalkDisk/file4\
       77.9 real         0.0 user        23.6 sys  \
% /bin/time cat BigMix.snd BigMix.snd BigMix.snd BigMix.snd BigMix.snd > /WalkDisk/file5\
       60.4 real         0.0 user        19.4 sys  \
\

\f0\fs28 But the newly written files read back much faster, an average of 1500 KBytes/sec:\

\f2\fs22 \
% foreach f (file1 file2 file3 file4 file5 file1 file2 file3 file4 file5)\
? dr $f\
? end\
Reading 24402140 bytes from file1\
23830.21 Kbytes in 20.940486 sec = 1138.00KBytes/sec\
Reading 24402140 bytes from file2\
23830.21 Kbytes in 21.985657 sec = 1083.90KBytes/sec\
Reading 24402140 bytes from file3\
23830.21 Kbytes in 17.318922 sec = 1375.96KBytes/sec\
Reading 24402140 bytes from file4\
23830.21 Kbytes in 15.725457 sec = 1515.39KBytes/sec\
Reading 24402140 bytes from file5\
23830.21 Kbytes in 14.826515 sec = 1607.27KBytes/sec\
Reading 24402140 bytes from file1\
23830.21 Kbytes in 20.943236 sec = 1137.85KBytes/sec\
Reading 24402140 bytes from file2\
23830.21 Kbytes in 22.910556 sec = 1040.14KBytes/sec\
Reading 24402140 bytes from file3\
23830.21 Kbytes in 17.243762 sec = 1381.96KBytes/sec\
Reading 24402140 bytes from file4\
23830.21 Kbytes in 15.867428 sec = 1501.83KBytes/sec\
Reading 24402140 bytes from file5\
23830.21 Kbytes in 14.862942 sec = 1603.33KBytes/sec\
%  \

\pard\tx960\tx1920\tx2880\tx3840\tx4800\tx5760\tx6720\tx7680\tx8640\tx9600\f0\fs28\fc1\cf1 \
==== 27 Sep 92 ====\
\
Wiring in SMPTE sync via midi time code.\
\
When syncing to SMPTE, we need to figure out both the starting sample and the relative current rate.\
	startingSample = currentMTCTime  * framesPerSecond;\
	rate = (currentMTCTime - previousMTCTime) / secondsPerBuffer\
where:\
	secondsPerBuffer = framesPerBuffer / framesPerSecond\
\
When manually controlling the rate:\
	rate = currentRate\
	currentManualTime = framesPlayed / framesPerSecond\
	startingSample = currentManualTime * framesPerSecond;\
\
Gosh - seems to be working mostly.  (Amusing bug where I determined rate as previousTime - currentTime, so rate was negative of what it should have been.  Did a pretty good job playing sound backwards...)\
\
About that SMPTE offset field:\
	good initial value is 7232.5\
	if the computer's playback falls behind, decrease the number\
	if the computer leads the tape deck, increase the number\
	start of song: 7232.5\
	drums (second verse) 7232.4\
	chorus 7232.3\
	around acoustic, smpte offset = 7232.1\
	around guitar solo = 7231.9\
\
===== 28 Sep 92 =====\
\
Conversation with Tony Agnello - Ariel.    He says that nothing that I described to him is patented nor proprietary.  He also suggests the trick of treating strong negative correlation as a phase inversion of the positive signal...  Gains an octave in the low frequency.  Way cool.\

}
