Home | History | Annotate | Download | only in sonic
      1 /* Sonic library
      2    Copyright 2010
      3    Bill Cox
      4    This file is part of the Sonic Library.
      5 
      6    This file is licensed under the Apache 2.0 license.
      7 */
      8 
      9 /*
     10 The Sonic Library implements a new algorithm invented by Bill Cox for the
     11 specific purpose of speeding up speech by high factors at high quality.  It
     12 generates smooth speech at speed up factors as high as 6X, possibly more.  It is
     13 also capable of slowing down speech, and generates high quality results
     14 regardless of the speed up or slow down factor.  For speeding up speech by 2X or
     15 more, the following equation is used:
     16 
     17     newSamples = period/(speed - 1.0)
     18     scale = 1.0/newSamples;
     19 
     20 where period is the current pitch period, determined using AMDF or any other
     21 pitch estimator, and speed is the speedup factor.  If the current position in
     22 the input stream is pointed to by "samples", and the current output stream
     23 position is pointed to by "out", then newSamples number of samples can be
     24 generated with:
     25 
     26     out[t] = (samples[t]*(newSamples - t) + samples[t + period]*t)/newSamples;
     27 
     28 where t = 0 to newSamples - 1.
     29 
     30 For speed factors < 2X, the PICOLA algorithm is used.  The above
     31 algorithm is first used to double the speed of one pitch period.  Then, enough
     32 input is directly copied from the input to the output to achieve the desired
     33 speed up facter, where 1.0 < speed < 2.0.  The amount of data copied is derived:
     34 
     35     speed = (2*period + length)/(period + length)
     36     speed*length + speed*period = 2*period + length
     37     length(speed - 1) = 2*period - speed*period
     38     length = period*(2 - speed)/(speed - 1)
     39 
     40 For slowing down speech where 0.5 < speed < 1.0, a pitch period is inserted into
     41 the output twice, and length of input is copied from the input to the output
     42 until the output desired speed is reached.  The length of data copied is:
     43 
     44     length = period*(speed - 0.5)/(1 - speed)
     45 
     46 For slow down factors below 0.5, no data is copied, and an algorithm
     47 similar to high speed factors is used.
     48 */
     49 
     50 #ifdef  __cplusplus
     51 extern "C" {
     52 #endif
     53 
     54 /* Uncomment this to use sin-wav based overlap add which in theory can improve
     55    sound quality slightly, at the expense of lots of floating point math. */
     56 /* #define SONIC_USE_SIN */
     57 
     58 /* This specifies the range of voice pitches we try to match.
     59    Note that if we go lower than 65, we could overflow in findPitchInRange */
     60 #define SONIC_MIN_PITCH 65
     61 #define SONIC_MAX_PITCH 400
     62 
     63 /* These are used to down-sample some inputs to improve speed */
     64 #define SONIC_AMDF_FREQ 4000
     65 
     66 struct sonicStreamStruct;
     67 typedef struct sonicStreamStruct *sonicStream;
     68 
     69 /* For all of the following functions, numChannels is multiplied by numSamples
     70    to determine the actual number of values read or returned. */
     71 
     72 /* Create a sonic stream.  Return NULL only if we are out of memory and cannot
     73   allocate the stream. Set numChannels to 1 for mono, and 2 for stereo. */
     74 sonicStream sonicCreateStream(int sampleRate, int numChannels);
     75 /* Destroy the sonic stream. */
     76 void sonicDestroyStream(sonicStream stream);
     77 /* Use this to write floating point data to be speed up or down into the stream.
     78    Values must be between -1 and 1.  Return 0 if memory realloc failed, otherwise 1 */
     79 int sonicWriteFloatToStream(sonicStream stream, float *samples, int numSamples);
     80 /* Use this to write 16-bit data to be speed up or down into the stream.
     81    Return 0 if memory realloc failed, otherwise 1 */
     82 int sonicWriteShortToStream(sonicStream stream, short *samples, int numSamples);
     83 /* Use this to write 8-bit unsigned data to be speed up or down into the stream.
     84    Return 0 if memory realloc failed, otherwise 1 */
     85 int sonicWriteUnsignedCharToStream(sonicStream stream, unsigned char *samples, int numSamples);
     86 /* Use this to read floating point data out of the stream.  Sometimes no data
     87    will be available, and zero is returned, which is not an error condition. */
     88 int sonicReadFloatFromStream(sonicStream stream, float *samples, int maxSamples);
     89 /* Use this to read 16-bit data out of the stream.  Sometimes no data will
     90    be available, and zero is returned, which is not an error condition. */
     91 int sonicReadShortFromStream(sonicStream stream, short *samples, int maxSamples);
     92 /* Use this to read 8-bit unsigned data out of the stream.  Sometimes no data will
     93    be available, and zero is returned, which is not an error condition. */
     94 int sonicReadUnsignedCharFromStream(sonicStream stream, unsigned char *samples, int maxSamples);
     95 /* Force the sonic stream to generate output using whatever data it currently
     96    has.  No extra delay will be added to the output, but flushing in the middle of
     97    words could introduce distortion. */
     98 int sonicFlushStream(sonicStream stream);
     99 /* Return the number of samples in the output buffer */
    100 int sonicSamplesAvailable(sonicStream stream);
    101 /* Get the speed of the stream. */
    102 float sonicGetSpeed(sonicStream stream);
    103 /* Set the speed of the stream. */
    104 void sonicSetSpeed(sonicStream stream, float speed);
    105 /* Get the pitch of the stream. */
    106 float sonicGetPitch(sonicStream stream);
    107 /* Set the pitch of the stream. */
    108 void sonicSetPitch(sonicStream stream, float pitch);
    109 /* Get the rate of the stream. */
    110 float sonicGetRate(sonicStream stream);
    111 /* Set the rate of the stream. */
    112 void sonicSetRate(sonicStream stream, float rate);
    113 /* Get the scaling factor of the stream. */
    114 float sonicGetVolume(sonicStream stream);
    115 /* Set the scaling factor of the stream. */
    116 void sonicSetVolume(sonicStream stream, float volume);
    117 /* Get the chord pitch setting. */
    118 int sonicGetChordPitch(sonicStream stream);
    119 /* Set chord pitch mode on or off.  Default is off.  See the documentation
    120    page for a description of this feature. */
    121 void sonicSetChordPitch(sonicStream stream, int useChordPitch);
    122 /* Get the quality setting. */
    123 int sonicGetQuality(sonicStream stream);
    124 /* Set the "quality".  Default 0 is virtually as good as 1, but very much faster. */
    125 void sonicSetQuality(sonicStream stream, int quality);
    126 /* Get the sample rate of the stream. */
    127 int sonicGetSampleRate(sonicStream stream);
    128 /* Set the sample rate of the stream.  This will drop any samples that have not been read. */
    129 void sonicSetSampleRate(sonicStream stream, int sampleRate);
    130 /* Get the number of channels. */
    131 int sonicGetNumChannels(sonicStream stream);
    132 /* Set the number of channels.  This will drop any samples that have not been read. */
    133 void sonicSetNumChannels(sonicStream stream, int numChannels);
    134 /* This is a non-stream oriented interface to just change the speed of a sound
    135    sample.  It works in-place on the sample array, so there must be at least
    136    speed*numSamples available space in the array. Returns the new number of samples. */
    137 int sonicChangeFloatSpeed(float *samples, int numSamples, float speed, float pitch,
    138     float rate, float volume, int useChordPitch, int sampleRate, int numChannels);
    139 /* This is a non-stream oriented interface to just change the speed of a sound
    140    sample.  It works in-place on the sample array, so there must be at least
    141    speed*numSamples available space in the array. Returns the new number of samples. */
    142 int sonicChangeShortSpeed(short *samples, int numSamples, float speed, float pitch,
    143     float rate, float volume, int useChordPitch, int sampleRate, int numChannels);
    144 
    145 #ifdef  __cplusplus
    146 }
    147 #endif
    148