r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / timestretch / timestretchengine.C
blob3483ca3764bb527f695a3a1058f13733694dfab4
1 #include "timestretchengine.h"
4 #include <stdio.h>
5 #include <string.h>
8 TimeStretchEngine::TimeStretchEngine(double scale, int sample_rate)
10         output = 0;
11         output_allocation = 0;
12         output_size = 0;
13         input = 0;
14         input_allocation = 0;
15         input_size = 0;
16         input_sample = 0;
17         output_sample = 0;
18         this->scale = scale;
19         this->sample_rate = sample_rate;
20         window_time = 20;
21         window_size = (int64_t)sample_rate * (int64_t)window_time / (int64_t)1000;
22         window_skirt = window_size / 2;
25 TimeStretchEngine::~TimeStretchEngine()
27         if(output) delete [] output;
28         if(input) delete [] input;
31 void TimeStretchEngine::overlay(double *out, double *in, int size, int skirt)
33 // Fade in
34         for(int i = 0; i < skirt; i++)
35         {
36                 *out = *out * (1.0 - (double)i / skirt) + *in * ((double)i / skirt);
37                 out++;
38                 in++;
39         }
41 // Center
42         for(int i = 0; i < size - skirt; i++)
43         {
44                 *out++ = *in++;
45         }
47 // New skirt
48         for(int i = 0; i < skirt; i++)
49         {
50                 *out++ = *in++;
51         }
54 int TimeStretchEngine::process(double *in_buffer, int in_size)
56 //printf("TimeStretchEngine::process 1\n");
57 // Stack on input buffer
58         if(input_size + in_size > input_allocation)
59         {
60                 int new_input_allocation = input_size + in_size;
61                 double *new_input = new double[new_input_allocation];
62                 if(input)
63                 {
64                         memcpy(new_input, input, input_size * sizeof(double));
65                         delete [] input;
66                 }
67                 input = new_input;
68                 input_allocation = new_input_allocation;
69         }
71 //printf("TimeStretchEngine::process 10\n");
73         memcpy(input + input_size, in_buffer, in_size * sizeof(double));
74         input_size += in_size;
76 //printf("TimeStretchEngine::process 20\n");
77 // Overlay windows from input buffer into output buffer
78         int done = 0;
79         do
80         {
81                 int64_t current_out_sample = output_sample + output_size;
82                 int64_t current_in_sample = (int64_t)((double)current_out_sample / scale);
84                 if(current_in_sample - input_sample + window_size + window_skirt > input_size)
85                 {
86 // Shift input buffer so the fragment that would have been copied now will be
87 // in the next iteration.
88 // printf("TimeStretchEngine::process 1 %lld %d\n", 
89 // current_in_sample - input_sample, 
90 // input_size);
91                         if(current_in_sample - input_sample < input_size)
92                                 memcpy(input,
93                                         input + current_in_sample - input_sample,
94                                         (input_size - (current_in_sample - input_sample)) * sizeof(double));
95                         input_size -= current_in_sample - input_sample;
96                         input_sample = current_in_sample;
97                         done = 1;
98 //printf("TimeStretchEngine::process 10\n");
99                 }
100                 else
101                 {
102 //printf("TimeStretchEngine::process 20\n");
103 // Allocate output buffer
104                         if(output_size + window_size + window_skirt > output_allocation)
105                         {
106                                 int new_allocation = output_size + window_size + window_skirt;
107                                 double *new_output = new double[new_allocation];
108                                 bzero(new_output, new_allocation * sizeof(double));
109                                 if(output)
110                                 {
111                                         memcpy(new_output, 
112                                                 output, 
113                                                 (output_size + window_skirt) * sizeof(double));
114                                         delete [] output;
115                                 }
116                                 output = new_output;
117                                 output_allocation = new_allocation;
118                         }
120 // Overlay new window
121                         overlay(output + output_size, 
122                                 input + current_in_sample - input_sample,
123                                 window_size,
124                                 window_skirt);
125                         output_size += window_size;
126 //printf("TimeStretchEngine::process 30 %d\n", output_size);
127                 }
128         }while(!done);
130 //printf("TimeStretchEngine::process 100 %d\n", output_size);
131         return output_size;
134 void TimeStretchEngine::read_output(double *buffer, int size)
136         memcpy(buffer, output, size * sizeof(double));
137         memcpy(output, output + size, (output_size + window_skirt - size) * sizeof(double));
138         output_size -= size;
139         output_sample += size;
142 double* TimeStretchEngine::get_samples()
144         return output;