00001 #include "timestretchengine.h"
00002
00003
00004 #include <stdio.h>
00005 #include <string.h>
00006
00007
00008 #define WINDOW_TIME 40
00009
00010
00011 TimeStretchEngine::TimeStretchEngine(double scale, int sample_rate)
00012 {
00013 output = 0;
00014 output_allocation = 0;
00015 output_size = 0;
00016 input = 0;
00017 input_allocation = 0;
00018 input_size = 0;
00019 input_sample = 0;
00020 output_sample = 0;
00021 this->scale = scale;
00022 this->sample_rate = sample_rate;
00023 window_time = WINDOW_TIME;
00024 window_size = (int64_t)sample_rate * (int64_t)window_time / (int64_t)1000;
00025 window_skirt = window_size / 2;
00026 }
00027
00028 TimeStretchEngine::~TimeStretchEngine()
00029 {
00030 if(output) delete [] output;
00031 if(input) delete [] input;
00032 }
00033
00034 void TimeStretchEngine::overlay(double *out, double *in, int size, int skirt)
00035 {
00036
00037 for(int i = 0; i < skirt; i++)
00038 {
00039 *out = *out * (1.0 - (double)i / skirt) + *in * ((double)i / skirt);
00040 out++;
00041 in++;
00042 }
00043
00044
00045 for(int i = 0; i < size - skirt; i++)
00046 {
00047 *out++ = *in++;
00048 }
00049
00050
00051 for(int i = 0; i < skirt; i++)
00052 {
00053 *out++ = *in++;
00054 }
00055 }
00056
00057 int TimeStretchEngine::process(double *in_buffer, int in_size)
00058 {
00059
00060
00061 if(input_size + in_size > input_allocation)
00062 {
00063 int new_input_allocation = input_size + in_size;
00064 double *new_input = new double[new_input_allocation];
00065 if(input)
00066 {
00067 memcpy(new_input, input, input_size * sizeof(double));
00068 delete [] input;
00069 }
00070 input = new_input;
00071 input_allocation = new_input_allocation;
00072 }
00073
00074
00075
00076 memcpy(input + input_size, in_buffer, in_size * sizeof(double));
00077 input_size += in_size;
00078
00079
00080
00081 int done = 0;
00082 do
00083 {
00084 int64_t current_out_sample = output_sample + output_size;
00085 int64_t current_in_sample = (int64_t)((double)current_out_sample / scale);
00086
00087 if(current_in_sample - input_sample + window_size + window_skirt > input_size)
00088 {
00089
00090
00091
00092
00093
00094 if(current_in_sample - input_sample < input_size)
00095 memcpy(input,
00096 input + current_in_sample - input_sample,
00097 (input_size - (current_in_sample - input_sample)) * sizeof(double));
00098 input_size -= current_in_sample - input_sample;
00099 input_sample = current_in_sample;
00100 done = 1;
00101
00102 }
00103 else
00104 {
00105
00106
00107 if(output_size + window_size + window_skirt > output_allocation)
00108 {
00109 int new_allocation = output_size + window_size + window_skirt;
00110 double *new_output = new double[new_allocation];
00111 bzero(new_output, new_allocation * sizeof(double));
00112 if(output)
00113 {
00114 memcpy(new_output,
00115 output,
00116 (output_size + window_skirt) * sizeof(double));
00117 delete [] output;
00118 }
00119 output = new_output;
00120 output_allocation = new_allocation;
00121 }
00122
00123
00124 overlay(output + output_size,
00125 input + current_in_sample - input_sample,
00126 window_size,
00127 window_skirt);
00128 output_size += window_size;
00129
00130 }
00131 }while(!done);
00132
00133
00134 return output_size;
00135 }
00136
00137 void TimeStretchEngine::read_output(double *buffer, int size)
00138 {
00139 memcpy(buffer, output, size * sizeof(double));
00140 memcpy(output, output + size, (output_size + window_skirt - size) * sizeof(double));
00141 output_size -= size;
00142 output_sample += size;
00143 }
00144
00145 double* TimeStretchEngine::get_samples()
00146 {
00147 return output;
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157