Sped up the code a bunch
diff --git a/sonic.c b/sonic.c
index a77add7..390e42f 100644
--- a/sonic.c
+++ b/sonic.c
@@ -93,7 +93,6 @@
 	stream->outputBuffer = (float *)realloc(stream->outputBuffer,
 	    stream->outputBufferSize*sizeof(float));
 	if(stream->outputBuffer == NULL) {
-            sonicDestroyStream(stream);
 	    return 0;
 	}
     }
@@ -110,7 +109,6 @@
 	stream->inputBuffer = (float *)realloc(stream->inputBuffer,
 	    stream->inputBufferSize*sizeof(float));
 	if(stream->inputBuffer == NULL) {
-            sonicDestroyStream(stream);
 	    return 0;
 	}
     }
@@ -237,32 +235,66 @@
     return stream->numOutputSamples;
 }
 
+/* Find the best frequency match in the range, and given a sample skip multiple. */
+static int findPitchPeriodInRange(
+    sonicStream stream,
+    float *samples,
+    int minPeriod,
+    int maxPeriod,
+    int skip)
+{
+    int period, bestPeriod = 0;
+    double minDiff = 0.0;
+    double diff;
+    float value, *s, *p;
+    int xSample;
+
+    for(period = minPeriod; period <= maxPeriod; period += skip) {
+	diff = 0.0;
+	s = samples;
+	p = samples + period;
+	for(xSample = 0; xSample < period; xSample += skip) {
+	    value = *s - *p;
+	    s += skip;
+	    p += skip;
+	    diff += value >= 0.0? value : -value;
+	}
+	if(bestPeriod == 0 || diff < minDiff*period) {
+	    diff /= period;
+	    minDiff = diff;
+	    bestPeriod = period;
+	}
+    }
+    return bestPeriod;
+}
+
 /* Find the pitch period.  This is a critical step, and we may have to try
-   multiple ways to get a good answer.  This version uses AMDF. */
+   multiple ways to get a good answer.  This version uses AMDF.  To improve
+   speed, we down sample by an integer factor get in the 11KHz range, and then
+   do it again with a narrower frequency range without down sampling */
 static int findPitchPeriod(
     sonicStream stream,
     float *samples)
 {
     int minPeriod = stream->minPeriod;
     int maxPeriod = stream->maxPeriod;
-    int period, bestPeriod = 0;
-    double minDiff = 0.0;
-    double diff, value;
-    int xSample;
+    int sampleRate = stream->sampleRate;
+    int skip = 1;
+    int period;
 
-    for(period = minPeriod; period <= maxPeriod; period++) {
-	diff = 0.0;
-	for(xSample = 0; xSample < period; xSample++) {
-	    value = samples[xSample] - samples[xSample + period];
-	    diff += value >= 0.0? value : -value;
-	}
-	diff /= period;
-	if(bestPeriod == 0 || diff < minDiff) {
-	    minDiff = diff;
-	    bestPeriod = period;
-	}
+    if(sampleRate > SONIC_AMDF_FREQ) {
+	skip = sampleRate/SONIC_AMDF_FREQ;
     }
-    return bestPeriod;
+    period = findPitchPeriodInRange(stream, samples, minPeriod, maxPeriod, skip);
+    minPeriod = period*(1.0 - SONIC_AMDF_RANGE);
+    maxPeriod = period*(1.0 + SONIC_AMDF_RANGE);
+    if(minPeriod < stream->minPeriod) {
+	minPeriod = stream->minPeriod;
+    }
+    if(maxPeriod > stream->maxPeriod) {
+	maxPeriod = stream->maxPeriod;
+    }
+    return findPitchPeriodInRange(stream, samples, minPeriod, maxPeriod, 1);
 }
 
 /* Skip over a pitch period, and copy period/speed samples to the output */