X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Ffourier.C;fp=cinelerra-5.1%2Fcinelerra%2Ffourier.C;h=f78a45bd1e092a990864e9efd716a88cd430d954;hp=401a5faa1e3a56e2a452df630f3c1658a127ea9d;hb=0e6cf5b52d1ebce9272270144bcf43df4683507e;hpb=f068b73c1d4afafbf6d86e7f5bc8f1c96b5366d3 diff --git a/cinelerra-5.1/cinelerra/fourier.C b/cinelerra-5.1/cinelerra/fourier.C index 401a5faa..f78a45bd 100644 --- a/cinelerra-5.1/cinelerra/fourier.C +++ b/cinelerra-5.1/cinelerra/fourier.C @@ -109,7 +109,7 @@ int FFT::do_fft(int samples, // must be a power of 2 int j = i, k = i+1; // cos(0)=1, sin(0)=0 rj = real_out[j]; ij = imag_out[j]; rk = real_out[k]; ik = imag_out[k]; - real_out[j] += rk; imag_out[j] += ik; + real_out[j] += rk; imag_out[j] += ik; real_out[k] = rj - rk; imag_out[k] = ij - ik; } } @@ -119,12 +119,12 @@ int FFT::do_fft(int samples, // must be a power of 2 int j = i, k = j+2; // cos(0)=1,sin(0)=0 rj = real_out[j]; ij = imag_out[j]; rk = real_out[k]; ik = imag_out[k]; - real_out[j] += rk; imag_out[j] += ik; + real_out[j] += rk; imag_out[j] += ik; real_out[k] = rj - rk; imag_out[k] = ij - ik; j = i+1; k = j+2; // cos(-pi/2)=0, sin(-pi/2)=-1 rj = real_out[j]; ij = imag_out[j]; rk = real_out[k]; ik = imag_out[k]; - real_out[j] += ik; imag_out[j] -= rk; + real_out[j] += ik; imag_out[j] -= rk; real_out[k] = rj - ik; imag_out[k] = ij + rk; } } @@ -133,12 +133,12 @@ int FFT::do_fft(int samples, // must be a power of 2 int j = i, k = j+2; // cos(0)=1,sin(0)=0 rj = real_out[j]; ij = imag_out[j]; rk = real_out[k]; ik = imag_out[k]; - real_out[j] += rk; imag_out[j] += ik; + real_out[j] += rk; imag_out[j] += ik; real_out[k] = rj - rk; imag_out[k] = ij - ik; j = i+1; k = j+2; // cos(pi/2)=0, sin(pi/2)=1 rj = real_out[j]; ij = imag_out[j]; rk = real_out[k]; ik = imag_out[k]; - real_out[j] -= ik; imag_out[j] += rk; + real_out[j] -= ik; imag_out[j] += rk; real_out[k] = rj + ik; imag_out[k] = ij - rk; } } @@ -167,7 +167,7 @@ int FFT::do_fft(int samples, // must be a power of 2 double rk = *rkp, ik = *ikp; double tr = ar[0] * rk - ai[0] * ik; double ti = ar[0] * ik + ai[0] * rk; - *rjp++ += tr; *ijp++ += ti; + *rjp++ += tr; *ijp++ += ti; *rkp++ = rj - tr; *ikp++ = ij - ti; } } @@ -204,7 +204,7 @@ unsigned int FFT::reverse_bits(unsigned int index, unsigned int bits) { unsigned int i, rev; - for(i = rev = 0; i < bits; i++) { + for( i = rev = 0; i < bits; i++ ) { rev = (rev << 1) | (index & 1); index >>= 1; } @@ -259,8 +259,7 @@ unsigned int FFT::reverse_bits(unsigned int index, unsigned int bits) int FFT::symmetry(int size, double *freq_real, double *freq_imag) { int h = size / 2; - for(int i = h + 1; i < size; i++) - { + for( int i = h + 1; i < size; i++ ) { freq_real[i] = freq_real[size - i]; freq_imag[i] = -freq_imag[size - i]; } @@ -273,6 +272,7 @@ int FFT::symmetry(int size, double *freq_real, double *freq_imag) CrossfadeFFT::CrossfadeFFT() : FFT() { + bands = 1; reset(); window_size = 4096; } @@ -288,6 +288,8 @@ int CrossfadeFFT::reset() output_buffer = 0; freq_real = 0; freq_imag = 0; + freq_real2 = 0; + freq_imag2 = 0; output_real = 0; output_imag = 0; first_window = 1; @@ -303,12 +305,17 @@ int CrossfadeFFT::reset() int CrossfadeFFT::delete_fft() { - if(input_buffer) delete input_buffer; - if(output_buffer) delete [] output_buffer; - if(freq_real) delete [] freq_real; - if(freq_imag) delete [] freq_imag; - if(output_real) delete [] output_real; - if(output_imag) delete [] output_imag; + delete input_buffer; input_buffer = 0; + if( output_buffer ) { + for( int i=0; iwindow_size = window_size; + this->bands = bands; first_window = 1; reconfigure(); return 0; @@ -341,277 +349,172 @@ int CrossfadeFFT::reconfigure() { delete_fft(); fix_window_size(); + return 0; +} +void CrossfadeFFT::allocate_output(int new_allocation) +{ +// Allocate output buffer + if( new_allocation > output_allocation ) { + if( !output_buffer ) { + output_buffer = new double*[bands]; + bzero(output_buffer, sizeof(double) * bands); + } + for( int i = 0; i < bands; i++ ) { + double *new_output = new double[new_allocation]; + if( output_buffer[i] ) { + memcpy(new_output, output_buffer[i], + sizeof(double) * (output_size + HALF_WINDOW)); + delete [] output_buffer[i]; + } + output_buffer[i] = new_output; + } + output_allocation = new_allocation; + } +} - - return 0; +int CrossfadeFFT::process_buffer(int64_t output_sample, long size, + Samples *output_ptr, int direction) +{ + Samples *output_temp[1]; + output_temp[0] = output_ptr; + return process_buffer(output_sample, size, output_temp, direction); } -// int CrossfadeFFT::process_fifo(long size, -// double *input_ptr, -// double *output_ptr) +// int CrossfadeFFT::get_read_offset() // { -// // Load next input buffer -// if(input_size + size > input_allocation) -// { -// double *new_input = new double[input_size + size]; -// if(input_buffer) -// { -// memcpy(new_input, input_buffer, sizeof(double) * input_size); -// delete [] input_buffer; -// } -// input_buffer = new_input; -// input_allocation = input_size + size; -// } -// -// memcpy(input_buffer + input_size, -// input_ptr, -// size * sizeof(double)); -// input_size += size; -// -// -// -// -// -// -// -// // Have enough to do some windows -// while(input_size >= window_size) -// { -// if(!freq_real) freq_real = new double[window_size]; -// if(!freq_imag) freq_imag = new double[window_size]; -// if(!output_real) output_real = new double[window_size]; -// if(!output_imag) output_imag = new double[window_size]; -// -// -// -// do_fft(window_size, // must be a power of 2 -// 0, // 0 = forward FFT, 1 = inverse -// input_buffer, // array of input's real samples -// 0, // array of input's imag samples -// freq_real, // array of output's reals -// freq_imag); -// -// int result = signal_process(); -// -// if(!result) -// { -// do_fft(window_size, // must be a power of 2 -// 1, // 0 = forward FFT, 1 = inverse -// freq_real, // array of input's real samples -// freq_imag, // array of input's imag samples -// output_real, // array of output's reals -// output_imag); -// } -// -// -// // Crossfade into the output buffer -// long new_allocation = output_size + window_size; -// if(new_allocation > output_allocation) -// { -// double *new_output = new double[new_allocation]; -// -// if(output_buffer) -// { -// memcpy(new_output, output_buffer, sizeof(double) * output_size); -// delete [] output_buffer; -// } -// output_buffer = new_output; -// output_allocation = new_allocation; -// } -// -// if(output_size >= HALF_WINDOW) -// { -// for(int i = 0, j = output_size - HALF_WINDOW; -// i < HALF_WINDOW; -// i++, j++) -// { -// double src_level = (double)i / HALF_WINDOW; -// double dst_level = (double)(HALF_WINDOW - i) / HALF_WINDOW; -// output_buffer[j] = output_buffer[j] * dst_level + output_real[i] * src_level; -// } -// -// memcpy(output_buffer + output_size, -// output_real + HALF_WINDOW, -// sizeof(double) * (window_size - HALF_WINDOW)); -// output_size += window_size - HALF_WINDOW; -// } -// else -// { -// // First buffer has no crossfade -// memcpy(output_buffer + output_size, -// output_real, -// sizeof(double) * window_size); -// output_size += window_size; -// } -// -// -// // Shift input buffer forward -// for(int i = window_size - HALF_WINDOW, j = 0; -// i < input_size; -// i++, j++) -// input_buffer[j] = input_buffer[i]; -// input_size -= window_size - HALF_WINDOW; -// } -// -// -// -// -// // Have enough to send to output -// int samples_rendered = 0; -// if(output_size - HALF_WINDOW >= size) -// { -// memcpy(output_ptr, output_buffer, sizeof(double) * size); -// for(int i = size, j = 0; i < output_size; i++, j++) -// output_buffer[j] = output_buffer[i]; -// output_size -= size; -// samples_rendered = size; -// } -// else -// { -// bzero(output_ptr, sizeof(double) * size); -// } -// -// return samples_rendered; // } - - int CrossfadeFFT::process_buffer(int64_t output_sample, - long size, - Samples *output_ptr, - int direction) + long size, Samples **output_ptr, int direction) { int result = 0; int step = (direction == PLAY_FORWARD) ? 1 : -1; // User seeked so output buffer is invalid - if(output_sample != this->output_sample) - { + if( output_sample != this->output_sample ) { output_size = 0; input_size = 0; first_window = 1; this->output_sample = output_sample; - this->input_sample = output_sample; + input_sample = output_sample; } -// Fill output buffer half a window at a time until size samples are available - while(output_size < size) - { - if(!input_buffer) input_buffer = new Samples(window_size); - if(!freq_real) freq_real = new double[window_size]; - if(!freq_imag) freq_imag = new double[window_size]; - if(!output_real) output_real = new double[window_size]; - if(!output_imag) output_imag = new double[window_size]; - -// Fill enough input to make a window starting at output_sample - if(first_window) - result = read_samples(this->input_sample, - window_size, - input_buffer); - else - { - input_buffer->set_offset(HALF_WINDOW); -// printf("CrossfadeFFT::process_buffer %d %lld %lld\n", -// __LINE__, -// this->input_sample + step * HALF_WINDOW, -// this->input_sample + step * HALF_WINDOW + HALF_WINDOW); - result = read_samples(this->input_sample + step * HALF_WINDOW, - HALF_WINDOW, - input_buffer); - input_buffer->set_offset(0); - } - input_size = window_size; - - if(!result) - do_fft(window_size, // must be a power of 2 - 0, // 0 = forward FFT, 1 = inverse - input_buffer->get_data(), // array of input's real samples - 0, // array of input's imag samples - freq_real, // array of output's reals - freq_imag); - if(!result) - result = signal_process(); - - if(!result) - do_fft(window_size, // must be a power of 2 - 1, // 0 = forward FFT, 1 = inverse - freq_real, // array of input's real samples - freq_imag, // array of input's imag samples - output_real, // array of output's reals - output_imag); // array of output's imaginaries - - if(!result) - result = post_process(); +// printf("CrossfadeFFT::process_buffer %d size=%ld input_size=%ld output_size=%ld window_size=%ld\n", +// __LINE__, size, input_size, output_size, window_size); -// Allocate output buffer - int new_allocation = output_size + window_size; - if(new_allocation > output_allocation) - { - double *new_output = new double[new_allocation]; - if(output_buffer) - { - memcpy(new_output, - output_buffer, - sizeof(double) * (output_size + HALF_WINDOW)); - delete [] output_buffer; - } - output_buffer = new_output; - output_allocation = new_allocation; +// must call read_samples once so the upstream plugins don't have to seek +// must be a multiple of 1/2 window + int need_samples = (size - output_size) / HALF_WINDOW * HALF_WINDOW; +// round up a half window + if( need_samples + output_size < size ) { + need_samples += HALF_WINDOW; + } +// half window tail + need_samples += HALF_WINDOW; + +// extend the buffer to need_samples + if( !input_buffer || input_buffer->get_allocated() < need_samples ) { + Samples *new_input_buffer = new Samples(need_samples); + + if( input_buffer ) { + memcpy(new_input_buffer->get_data(), + input_buffer->get_data(), + input_size * sizeof(double)); + delete input_buffer; } -// Overlay processed buffer - if(first_window) - { - memcpy(output_buffer + output_size, - output_real, - sizeof(double) * window_size); - first_window = 0; - } - else - { - for(int i = 0, j = output_size; i < HALF_WINDOW; i++, j++) - { - double src_level = (double)i / HALF_WINDOW; - double dst_level = (double)(HALF_WINDOW - i) / HALF_WINDOW; - output_buffer[j] = output_buffer[j] * dst_level + - output_real[i] * src_level; + input_buffer = new_input_buffer; + } + + input_buffer->set_offset(input_size); + result = read_samples(input_sample, need_samples-input_size, input_buffer); + input_buffer->set_offset(0); + input_sample += step * (need_samples - input_size); + input_size = need_samples; + + + if( !freq_real ) freq_real = new double[window_size]; + if( !freq_imag ) freq_imag = new double[window_size]; + if( !freq_real2 ) freq_real2 = new double[window_size]; + if( !freq_imag2 ) freq_imag2 = new double[window_size]; + if( !output_real ) output_real = new double[window_size]; + if( !output_imag ) output_imag = new double[window_size]; + +// Fill output buffer half a window at a time until size samples are available + while( !result && output_size < size ) { + do_fft(window_size, 0, // forward + input_buffer->get_data(), 0, // input, real only + freq_real2, freq_imag2); // output + allocate_output(output_size + window_size); +// process & overlay each band separately + for( int band=0; bandget_data(); - for(int i = window_size - HALF_WINDOW, j = 0; - i < input_size; - i++, j++) - { - input_samples[j] = input_samples[i]; - } +// Shift input buffer half a window forward + memcpy(input_buffer->get_data(), + input_buffer->get_data() + HALF_WINDOW, + (input_size - HALF_WINDOW) * sizeof(double)); +// for( int i = HALF_WINDOW, j = 0; +// i < input_size; +// i++, j++ ) +// { +// input_buffer->get_data()[j] = input_buffer->get_data()[i]; +// } - input_size = HALF_WINDOW; - this->input_sample += step * HALF_WINDOW; + input_size -= HALF_WINDOW; } -// Transfer output buffer - if(output_ptr) - { - memcpy(output_ptr->get_data(), output_buffer, sizeof(double) * size); +// Transfer output buffer if the user wants it + if( output_ptr ) { + for( int band = 0; band < bands; band++ ) { + memcpy(output_ptr[band]->get_data(), output_buffer[band], sizeof(double) * size); + } + } + +// shift output buffers forward + for( int band = 0; band < bands; band++ ) { + memcpy(output_buffer[band], output_buffer[band] + size, + sizeof(double) * (output_size + HALF_WINDOW - size)); } - for(int i = 0, j = size; j < output_size + HALF_WINDOW; i++, j++) - output_buffer[i] = output_buffer[j]; this->output_sample += step * size; this->output_size -= size; @@ -621,8 +524,7 @@ int CrossfadeFFT::process_buffer(int64_t output_sample, int CrossfadeFFT::read_samples(int64_t output_sample, - int samples, - Samples *buffer) + int samples, Samples *buffer) { return 1; } @@ -640,9 +542,18 @@ int CrossfadeFFT::post_process() } +int CrossfadeFFT::signal_process(int band) +{ + signal_process(); + return 0; +} - +int CrossfadeFFT::post_process(int band) +{ + post_process(); + return 0; +}