Added speech rate control, and by default we now use this and speed modification for pitch change.  Added vocal chord emulation based pitch change option.
diff --git a/Makefile b/Makefile
index 7c434f9..59a8d6f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-#CFLAGS=-Wall -g -ansi -fPIC
-CFLAGS=-Wall -O2 -ansi -fPIC -pthread
+CFLAGS=-Wall -g -ansi -fPIC
+#CFLAGS=-Wall -O2 -ansi -fPIC -pthread
 LIB_TAG=0.1.10
 CC=gcc
 PREFIX=/usr/local
diff --git a/doc/index.md b/doc/index.md
index 6fa0d4e..640143c 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -30,7 +30,7 @@
 changing the tempo of music.  No WSOLA based program performs well for speech
 (contrary to the inventor's estimate of WSOLA).  Listen to [this soundstretch
 sample](soundstretch.wav), which uses SoundTouch, and compare it to [this sonic
-sample](sonic.wav).  Both are sped up by 2X.  WSOLA introduces unaccepable
+sample](sonic.wav).  Both are sped up by 2X.  WSOLA introduces unacceptable
 levels of distortion, making speech impossible to understand at high speed (over
 2.5X) by blind speed listeners.
 
@@ -91,19 +91,34 @@
 
     sonicDestroyStream(stream);
 
-By default, a sonic stream sets the speed, pitch, and volume to 1.0, which means
+By default, a sonic stream sets the speed, pitch, rate, and volume to 1.0, which means
 no change at all to the sound stream.  Sonic detects this case, and simply
 copies the input to the output to reduce CPU load.  To change the speed, pitch,
-or volume, set the parameters using:
+rate, or volume, set the parameters using:
 
     sonicSetSpeed(stream, speed);
     sonicSetPitch(stream, pitch);
+    sonicSetRate(stream, rate);
     sonicSetVolume(stream, volume);
 
-These three parameters are floating point numbers.  A speed of 2.0 means to
+These four parameters are floating point numbers.  A speed of 2.0 means to
 double speed of speech.  A pitch of 0.95 means to lower the pitch by about 5%,
 and a volume of 1.4 means to multiply the sound samples by 1.4, clipping if we
-exceed the maximum range of a 16-bit integer.
+exceed the maximum range of a 16-bit integer.  Speech rate scales how fast
+speech is played.  A 2.0 value will make you sound like a chipmunk talking very
+fast.  A 0.7 value will make you sound like a giant talking slowly.
+
+By default, pitch is modified by changing the rate, and then using speed
+modification to bring the speed back to normal.  This allows for a wide range of
+pitch changes, but changing the pitch makes the speaker sound larger or smaller,
+too.  If you want to make the person sound like the same person, but talking at
+a higher or lower pitch, then enable the vocal chord emulation mode for pitch
+scaling, using:
+
+    sonicSetChordPitch(stream, 1);
+
+However, only small changes to pitch should be used in this mode, as it
+introduces significant distortion otherwise.
 
 After setting the sound parameters, you write to the stream like this:
 
diff --git a/main.c b/main.c
index 20bfd9a..2e43aee 100644
--- a/main.c
+++ b/main.c
@@ -20,7 +20,9 @@
     waveFile outFile,
     float speed,
     float pitch,
+    float rate,
     float volume,
+    int emulateChordPitch,
     int quality,
     int sampleRate,
     int numChannels)
@@ -31,7 +33,9 @@
 
     sonicSetSpeed(stream, speed);
     sonicSetPitch(stream, pitch);
+    sonicSetRate(stream, rate);
     sonicSetVolume(stream, volume);
+    sonicSetChordPitch(stream, emulateChordPitch);
     sonicSetQuality(stream, quality);
     do {
         samplesRead = readFromWaveFile(inFile, inBuffer, BUFFER_SIZE/numChannels);
@@ -55,8 +59,11 @@
 static void usage(void)
 {
     fprintf(stderr, "Usage: sonic [OPTION]... infile outfile\n"
+        "    -c         -- Modify pitch by emulating vocal chords vibrating\n"
+	"                  faster or slower.\n"
         "    -p pitch   -- Set pitch scaling factor.  1.3 means 30%% higher.\n"
         "    -q         -- Disable speed-up heuristics.  May increase quality.\n"
+        "    -r rate    -- Set playback rate.  2.0 means 2X faster, and 2X pitch.\n"
         "    -s speed   -- Set speed up factor.  2.0 means 2X faster.\n"
 	"    -v volume  -- Scale volume by a constant factor.\n");
     exit(1);
@@ -68,9 +75,11 @@
 {
     waveFile inFile, outFile;
     char *inFileName, *outFileName;
-    float speed = 1.0;
-    float pitch = 1.0;
-    float volume = 1.0;
+    float speed = 1.0f;
+    float pitch = 1.0f;
+    float rate = 1.0f;
+    float volume = 1.0f;
+    int emulateChordPitch = 0;
     int quality = 0;
     int sampleRate, numChannels;
     int xArg = 1;
@@ -82,20 +91,29 @@
 	return 1;
     }
     while(xArg < argc && *(argv[xArg]) == '-') {
-	if(!strcmp(argv[xArg], "-p")) {
+	if(!strcmp(argv[xArg], "-c")) {
+	    emulateChordPitch = 1;
+	    printf("Scaling pitch linearly.\n");
+	} else if(!strcmp(argv[xArg], "-p")) {
 	    xArg++;
 	    if(xArg < argc) {
 	        pitch = atof(argv[xArg]);
-                printf("Setting pitch to %0.2f%%\n", pitch*100.0f);
+                printf("Setting pitch to %0.2fX\n", pitch);
 	    }
 	} else if(!strcmp(argv[xArg], "-q")) {
 	    quality = 1;
 	    printf("Disabling speed-up heuristics\n");
+	} else if(!strcmp(argv[xArg], "-r")) {
+	    xArg++;
+	    if(xArg < argc) {
+	        rate = atof(argv[xArg]);
+                printf("Setting rate to %0.2fX\n", rate);
+	    }
 	} else if(!strcmp(argv[xArg], "-s")) {
 	    xArg++;
 	    if(xArg < argc) {
 	        speed = atof(argv[xArg]);
-                printf("Setting speed to %0.2f%%\n", speed*100.0f);
+                printf("Setting speed to %0.2fX\n", speed);
 	    }
 	} else if(!strcmp(argv[xArg], "-v")) {
 	    xArg++;
@@ -120,7 +138,8 @@
 	closeWaveFile(inFile);
 	return 1;
     }
-    runSonic(inFile, outFile, speed, pitch, volume, quality, sampleRate, numChannels);
+    runSonic(inFile, outFile, speed, pitch, rate, volume, emulateChordPitch, quality,
+        sampleRate, numChannels);
     closeWaveFile(inFile);
     closeWaveFile(outFile);
     return 0;
diff --git a/sonic.1 b/sonic.1
index fbf4f76..0762ed8 100644
--- a/sonic.1
+++ b/sonic.1
@@ -21,6 +21,9 @@
 Disable all speed-up heuristics, possibly improving the quality slightly.  This
 is mainly used for debugging the speed-up heuristics.
 .TP
+.B \-r rate
+Adjust the speed of playback.  This sales both the pitch and speed equally.
+.TP
 .B \-s speed
 Set speed up factor.  1.0 means no change, 2.0 means 2X faster.
 .TP
diff --git a/sonic.c b/sonic.c
index e019cbb..beac399 100644
--- a/sonic.c
+++ b/sonic.c
@@ -17,6 +17,7 @@
    License along with the GNU C Library; if not, write to the Free
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -37,6 +38,12 @@
     float speed;
     float volume;
     float pitch;
+    float rate;
+    int oldRatePosition;
+    int newRatePosition;
+    int oldSampleRate;
+    int newSampleRate;
+    int useChordPitch;
     int quality;
     int numChannels;
     int inputBufferSize;
@@ -122,6 +129,39 @@
     stream->pitch = pitch;
 }
 
+/* Get the rate of the stream. */
+float sonicGetRate(
+    sonicStream stream)
+{
+    return stream->rate;
+}
+
+/* Set the playback rate of the stream. This scales pitch and speed at the same time. */
+void sonicSetRate(
+    sonicStream stream,
+    float rate)
+{
+    stream->rate = rate;
+
+    stream->oldRatePosition = 0;
+    stream->newRatePosition = 0;
+}
+
+/* Get the vocal chord pitch setting. */
+int sonicGetChordPitch(
+    sonicStream stream)
+{
+    return stream->useChordPitch;
+}
+
+/* Set the vocal chord mode for pitch computation.  Default is off. */
+void sonicSetChordPitch(
+    sonicStream stream,
+    int useChordPitch)
+{
+    stream->useChordPitch = useChordPitch;
+}
+
 /* Get the quality setting. */
 int sonicGetQuality(
     sonicStream stream)
@@ -221,6 +261,10 @@
     stream->speed = 1.0f;
     stream->pitch = 1.0f;
     stream->volume = 1.0f;
+    stream->rate = 1.0f;
+    stream->oldRatePosition = 0;
+    stream->newRatePosition = 0;
+    stream->useChordPitch = 0;
     stream->quality = 0;
     stream->sampleRate = sampleRate;
     stream->numChannels = numChannels;
@@ -473,8 +517,9 @@
     int maxRequired = stream->maxRequired;
     int remainingSamples = stream->numInputSamples;
     float speed = stream->speed/stream->pitch;
+    float rate = stream->rate*stream->pitch;
     int expectedOutputSamples = stream->numOutputSamples +
-	(int)(remainingSamples/speed + stream->numPitchSamples/stream->pitch + 0.5f);
+	(int)((remainingSamples/speed + stream->numPitchSamples)/rate + 0.5f);
 
     /* Add enough silence to flush both input and pitch buffers. */
     if(!enlargeInputBufferIfNeeded(stream, remainingSamples + 2*maxRequired)) {
@@ -802,6 +847,80 @@
     return 1;
 }
 
+/* Interpolate the new output sample. */
+static short interpolate(
+    sonicStream stream,
+    short *in,
+    int oldSampleRate,
+    int newSampleRate)
+{
+    short left = *in;
+    short right = in[stream->numChannels];
+    int position = stream->newRatePosition*oldSampleRate;
+    int leftPosition = stream->oldRatePosition*newSampleRate;
+    int rightPosition = (stream->oldRatePosition + 1)*newSampleRate;
+    int ratio = rightPosition - position;
+    int width = rightPosition - leftPosition;
+
+    return (ratio*left + (width - ratio)*right)/width;
+}
+
+/* Change the rate. */
+static int adjustRate(
+    sonicStream stream,
+    float rate,
+    int originalNumOutputSamples)
+{
+    int newSampleRate = stream->sampleRate/rate;
+    int oldSampleRate = stream->sampleRate;
+    int numChannels = stream->numChannels;
+    int position = 0;
+    short *in, *out;
+    int i;
+
+    /* Set these values to help with the integer math */
+    while(newSampleRate > (1 << 14) || oldSampleRate > (1 << 14)) {
+	newSampleRate >>= 1;
+	oldSampleRate >>= 1;
+    }
+    if(stream->numOutputSamples == originalNumOutputSamples) {
+	return 1;
+    }
+    if(!moveNewSamplesToPitchBuffer(stream, originalNumOutputSamples)) {
+	return 0;
+    }
+    /* Leave at least one pitch sample in the buffer */
+    for(position = 0; position < stream->numPitchSamples - 1; position++) {
+	while((stream->oldRatePosition + 1)*newSampleRate >
+	        stream->newRatePosition*oldSampleRate) {
+	    if(!enlargeOutputBufferIfNeeded(stream, 1)) {
+		return 0;
+	    }
+	    out = stream->outputBuffer + stream->numOutputSamples*numChannels;
+	    in = stream->pitchBuffer + position;
+	    for(i = 0; i < numChannels; i++) {
+		*out++ = interpolate(stream, in, oldSampleRate, newSampleRate);
+		in++;
+	    }
+	    stream->newRatePosition++;
+	    stream->numOutputSamples++;
+	}
+	stream->oldRatePosition++;
+	if(stream->oldRatePosition == oldSampleRate) {
+	    stream->oldRatePosition = 0;
+	    if(stream->newRatePosition != newSampleRate) {
+		fprintf(stderr,
+		    "Assertion failed: stream->newRatePosition != newSampleRate\n");
+		exit(1);
+	    }
+	    stream->newRatePosition = 0;
+	}
+    }
+    removePitchSamples(stream, position);
+    return 1;
+}
+
+
 /* Skip over a pitch period, and copy period/speed samples to the output */
 static int skipPitchPeriod(
     sonicStream stream,
@@ -899,7 +1018,11 @@
 {
     int originalNumOutputSamples = stream->numOutputSamples;
     float speed = stream->speed/stream->pitch;
+    float rate = stream->rate;
 
+    if(!stream->useChordPitch) {
+	rate *= stream->pitch;
+    }
     if(speed > 1.00001 || speed < 0.99999) {
 	changeSpeed(stream, speed);
     } else {
@@ -908,8 +1031,14 @@
 	}
 	stream->numInputSamples = 0;
     }
-    if(stream->pitch != 1.0f) {
-	if(!adjustPitch(stream, originalNumOutputSamples)) {
+    if(stream->useChordPitch) {
+	if(stream->pitch != 1.0f) {
+	    if(!adjustPitch(stream, originalNumOutputSamples)) {
+		return 0;
+	    }
+	}
+    } else if(rate != 1.0f) {
+	if(!adjustRate(stream, rate, originalNumOutputSamples)) {
 	    return 0;
 	}
     }
diff --git a/sonic.h b/sonic.h
index e6291f1..e718261 100644
--- a/sonic.h
+++ b/sonic.h
@@ -19,12 +19,12 @@
    02111-1307 USA.  */
 
 /*
-The Sonic Library implements Pitch Based Resampling, which is a new algorithm
-invented by Bill Cox for the specific purpose of speeding up speech by high
-factors at high quality.  It generates smooth speech at speed up factors as high
-as 6X, possibly more.  It is also capable of slowing down speech, and generates
-high quality results regardless of the speed up or slow down factor.  For
-speeding up speech by 2X or more, the following equation is used:
+The Sonic Library implements a new algorithm invented by Bill Cox for the
+specific purpose of speeding up speech by high factors at high quality.  It
+generates smooth speech at speed up factors as high as 6X, possibly more.  It is
+also capable of slowing down speech, and generates high quality results
+regardless of the speed up or slow down factor.  For speeding up speech by 2X or
+more, the following equation is used:
 
     newSamples = period/(speed - 1.0)
     scale = 1.0/newSamples;
@@ -118,10 +118,19 @@
 float sonicGetPitch(sonicStream stream);
 /* Set the pitch of the stream. */
 void sonicSetPitch(sonicStream stream, float pitch);
+/* Get the rate of the stream. */
+float sonicGetRate(sonicStream stream);
+/* Set the rate of the stream. */
+void sonicSetRate(sonicStream stream, float rate);
 /* Get the scaling factor of the stream. */
 float sonicGetVolume(sonicStream stream);
 /* Set the scaling factor of the stream. */
 void sonicSetVolume(sonicStream stream, float volume);
+/* Get the chord pitch setting. */
+int sonicGetChordPitch(sonicStream stream);
+/* Set chord pitch mode on or off.  Default is off.  See the documentation
+   page for a description of this feature. */
+void sonicSetChordPitch(sonicStream stream, int useChordPitch);
 /* Get the quality setting. */
 int sonicGetQuality(sonicStream stream);
 /* Set the "quality".  Default 0 is virtually as good as 1, but very much faster. */