int d_idwt(double coeffs_a[], int coeffs_a_len, double coeffs_d[], int coeffs_d_len, Wavelet* wavelet, double output[], int output_len, int mode, int correct_size) { int input_len; if(coeffs_a != NULL && coeffs_d != NULL){ if(correct_size){ if( (coeffs_a_len > coeffs_d_len ? coeffs_a_len - coeffs_d_len : coeffs_d_len-coeffs_a_len) > 1) { // goto errorIDWT; exit(0); } input_len = coeffs_a_len>coeffs_d_len? coeffs_d_len : coeffs_a_len; // min } else { if(coeffs_a_len != coeffs_d_len) { // goto errorIDWT; exit(0); } input_len = coeffs_a_len; } } else if(coeffs_a != NULL){ input_len = coeffs_a_len; } else if (coeffs_d != NULL){ input_len = coeffs_d_len; } else { // goto errorIDWT; exit(0); } int supposed_len = idwt_buffer_length(input_len, wavelet->rec_len, mode); if(output_len != supposed_len) { goto errorIDWT; } memset(output, 0, output_len * sizeof(double)); if(coeffs_a){ if(upsampling_convolution_valid_sf(coeffs_a, input_len, wavelet->synthesisLow->coeff, wavelet->rec_len, output, output_len, mode) < 0) { goto errorIDWT; } } // += if(coeffs_d){ if(upsampling_convolution_valid_sf(coeffs_d, input_len, wavelet->synthesisHigh->coeff, wavelet->rec_len, output, output_len, mode) < 0) { goto errorIDWT; } } return 0; errorIDWT: // cout << "Invalid input size for output array. This is " << // "unrecoverable and should not have happened " << endl; exit(0); }
// IDWT reconstruction from aproximation and detail coeffs // // If fix_size_diff is 1 then coeffs arrays can differ by one in length (this // is useful in multilevel decompositions and reconstructions of odd-length signals) // Requires zoer-filled output buffer int double_idwt(double coeffs_a[], index_t coeffs_a_len, double coeffs_d[], index_t coeffs_d_len, Wavelet* wavelet, double output[], index_t output_len, MODE mode, int fix_size_diff){ int input_len; // If one of coeffs array is NULL then the reconstruction will be performed // using the other one if(coeffs_a != NULL && coeffs_d != NULL){ if(fix_size_diff){ if( (coeffs_a_len > coeffs_d_len ? coeffs_a_len - coeffs_d_len : coeffs_d_len-coeffs_a_len) > 1){ // abs(a-b) goto error; } input_len = coeffs_a_len>coeffs_d_len ? coeffs_d_len : coeffs_a_len; // min } else { if(coeffs_a_len != coeffs_d_len) goto error; input_len = coeffs_a_len; } } else if(coeffs_a != NULL){ input_len = coeffs_a_len; } else if (coeffs_d != NULL){ input_len = coeffs_d_len; } else { goto error; } // check output size if(output_len != idwt_buffer_length(input_len, wavelet->rec_len, mode)) goto error; // // set output to zero (this can be ommited if output array is already cleared) // memset(output, 0, output_len * sizeof(double)); // reconstruct approximation coeffs with lowpass reconstruction filter if(coeffs_a){ if(double_upsampling_convolution_valid_sf(coeffs_a, input_len, wavelet->rec_lo_double, wavelet->rec_len, output, output_len, mode) < 0){ goto error; } } // and add reconstruction of details coeffs performed with highpass reconstruction filter if(coeffs_d){ if(double_upsampling_convolution_valid_sf(coeffs_d, input_len, wavelet->rec_hi_double, wavelet->rec_len, output, output_len, mode) < 0){ goto error; } } return 0; error: return -1; }
int $DTYPE$_upsampling_convolution_valid_sf_periodization(const $DTYPE$* input, const_index_t N, const $DTYPE$* filter, const_index_t F, $DTYPE$* output, const_index_t O) { $DTYPE$ *ptr_out = output; $DTYPE$ *filter_even, *filter_odd; $DTYPE$ *periodization_buf = NULL; $DTYPE$ *periodization_buf_rear = NULL; $DTYPE$ *ptr_base; $DTYPE$ sum_even, sum_odd; index_t i, j, k, N_p = 0; index_t F_2 = F/2; if(F%2) return -3; // Filter must have even-length. /////////////////////////////////////////////////////////////////////////// // Handle special situation when input coeff data is shorter than half of // the filter's length. The coeff array has to be extended periodically. // This can be only valid for PERIODIZATION_MODE if(N < F_2) // ======= { // Input data for periodization mode has to be periodically extended // New length for temporary input N_p = F_2-1 +N; // periodization_buf will hold periodically copied input coeffs values periodization_buf = wtcalloc(N_p, sizeof($DTYPE$)); if(periodization_buf == NULL) return -1; // Copy input data to it's place in the periodization_buf // -> [0 0 0 i1 i2 i3 0 0 0] k = (F_2-1)/2; for(i=k; i < k+N; ++i) periodization_buf[i] = input[(i-k)%N]; //if(N%2) // periodization_buf[i++] = input[N-1]; // [0 0 0 i1 i2 i3 0 0 0] // points here ^^ periodization_buf_rear = periodization_buf+i-1; // copy cyclically () to right // [0 0 0 i1 i2 i3 i1 i2 ...] j = i-k; for(; i < N_p; ++i) periodization_buf[i] = periodization_buf[i-j]; // copy cyclically () to left // [... i2 i3 i1 i2 i3 i1 i2 i3] j = 0; for(i=k-1; i >= 0; --i){ periodization_buf[i] = periodization_buf_rear[j]; --j; } // Now perform the valid convolution if(F_2%2){ $DTYPE$_upsampling_convolution_valid_sf(periodization_buf, N_p, filter, F, output, O, MODE_ZEROPAD); // The F_2%2==0 case needs special result fix (oh my, another one..) } else { // Cheap result fix for short inputs // Memory allocation for temporary output is done. // Computed temporary result is copied to output* ptr_out = wtcalloc(idwt_buffer_length(N, F, MODE_PERIODIZATION), sizeof($DTYPE$)); if(ptr_out == NULL){ wtfree(periodization_buf); return -1; } // Convolve here as for (F_2%2) branch above $DTYPE$_upsampling_convolution_valid_sf(periodization_buf, N_p, filter, F, ptr_out, O, MODE_ZEROPAD); // rewrite result to output for(i=2*N-1; i > 0; --i){ output[i] += ptr_out[i-1]; } // and the first element output[0] += ptr_out[2*N-1]; wtfree(ptr_out); // and voil`a!, ugh } } else { // Otherwise (N >= F_2) // Allocate memory for even and odd elements of the filter filter_even = wtmalloc(F_2 * sizeof($DTYPE$)); filter_odd = wtmalloc(F_2 * sizeof($DTYPE$)); if(filter_odd == NULL || filter_odd == NULL){ if(filter_odd == NULL) wtfree(filter_odd); if(filter_even == NULL) wtfree(filter_even); return -1; } // split filter to even and odd values for(i = 0; i < F_2; ++i){ filter_even[i] = filter[i << 1]; filter_odd[i] = filter[(i << 1) + 1]; } /////////////////////////////////////////////////////////////////////////// // This part is quite complicated and has some wild checking to get results // similar to those from Matlab(TM) Wavelet Toolbox k = F_2-1; // Check if extending is really needed N_p = F_2-1 + (index_t) ceil(k/2.); /*split filter len correct. + extra samples*/ // ok, if is then do: // 1. Allocate buffers for front and rear parts of extended input // 2. Copy periodically appriopriate elements from input to the buffers // 3. Convolve front buffer, input and rear buffer with even and odd // elements of the filter (this results in upsampling) // 4. Free memory if(N_p > 0){ // ======= // Allocate memory only for the front and rear extension parts, not the // whole input periodization_buf = wtcalloc(N_p, sizeof($DTYPE$)); periodization_buf_rear = wtcalloc(N_p, sizeof($DTYPE$)); // Memory checking if(periodization_buf == NULL || periodization_buf_rear == NULL){ if(periodization_buf == NULL) wtfree(periodization_buf); if(periodization_buf_rear == NULL) wtfree(periodization_buf_rear); wtfree(filter_odd); wtfree(filter_even); return -1; } // Fill buffers with appriopriate elements memcpy(periodization_buf + N_p - k, input, k * sizeof($DTYPE$)); // copy from beginning of input to end of buffer for(i = 1; i <= (N_p - k); ++i) // kopiowanie 'cykliczne' od końca input periodization_buf[(N_p - k) - i] = input[N - (i%N)]; memcpy(periodization_buf_rear, input + N - k, k * sizeof($DTYPE$)); // copy from end of input to begginning of buffer for(i = 0; i < (N_p - k); ++i) // kopiowanie 'cykliczne' od początku input periodization_buf_rear[k + i] = input[i%N]; /////////////////////////////////////////////////////////////////// // Convolve filters with the (front) periodization_buf and compute // the first part of output ptr_base = periodization_buf + F_2 - 1; if(k%2 == 1){ sum_odd = 0; for(j = 0; j < F_2; ++j) sum_odd += filter_odd[j] * ptr_base[-j]; *(ptr_out++) += sum_odd; --k; if(k) $DTYPE$_upsampling_convolution_valid_sf(periodization_buf + 1, N_p-1, filter, F, ptr_out, O-1, MODE_ZEROPAD); ptr_out += k; // k0 - 1 // really move backward by 1 } else if(k){ $DTYPE$_upsampling_convolution_valid_sf(periodization_buf, N_p, filter, F, ptr_out, O, MODE_ZEROPAD); ptr_out += k; } } /////////////////////////////////////////////////////////////////////////// // Perform _valid_ convolution (only when all filter_even and filter_odd elements // are in range of input data). // // This part is simple, no extra hacks, just two convolutions in one loop ptr_base = ($DTYPE$*)input + F_2 - 1; for(i = 0; i < N-(F_2-1); ++i){ // sliding over signal from left to right sum_even = 0; sum_odd = 0; for(j = 0; j < F_2; ++j){ sum_even += filter_even[j] * ptr_base[i-j]; sum_odd += filter_odd[j] * ptr_base[i-j]; } *(ptr_out++) += sum_even; *(ptr_out++) += sum_odd; } // /////////////////////////////////////////////////////////////////////////// if(N_p > 0){ // ======= k = F_2-1; if(k%2 == 1){ if(F/2 <= N_p - 1){ // k > 1 ? $DTYPE$_upsampling_convolution_valid_sf(periodization_buf_rear , N_p-1, filter, F, ptr_out, O-1, MODE_ZEROPAD); } ptr_out += k; // move forward anyway -> see lower if(F_2%2 == 0){ // remaining one element ptr_base = periodization_buf_rear + N_p - 1; sum_even = 0; for(j = 0; j < F_2; ++j){ sum_even += filter_even[j] * ptr_base[-j]; } *(--ptr_out) += sum_even; // move backward first } } else { if(k){ $DTYPE$_upsampling_convolution_valid_sf(periodization_buf_rear, N_p, filter, F, ptr_out, O, MODE_ZEROPAD); } } } if(periodization_buf != NULL) wtfree(periodization_buf); if(periodization_buf_rear != NULL) wtfree(periodization_buf_rear); wtfree(filter_even); wtfree(filter_odd); } return 0; }
int upsampling_convolution_valid_sf(const DTYPE* input, const int N, const double* filter, const int F, double* output, const int O, const int mode){ double *ptr_out = output; double *filter_even, *filter_odd; DTYPE *periodization_buf = NULL, *periodization_buf_rear = NULL; DTYPE *ptr_base; double sum_even, sum_odd; int i, j, k, N_p = 0; int F_2 = F/2; // F/2 if(F%2) return -3; if(F_2 > N){ if(mode == MODE_PERIODIZATION){ N_p = F_2-1 +N; periodization_buf = (double*) wtcalloc(N_p, sizeof(DTYPE)); k = (F_2-1)/2; for(i=k; i < k+N; ++i) periodization_buf[i] = input[(i-k)%N]; //if(N%2) // periodization_buf[i++] = input[N-1]; periodization_buf_rear = periodization_buf+i-1; j = i-k; for(; i < N_p; ++i) periodization_buf[i] = periodization_buf[i-j]; j = 0; for(i=k-1; i >= 0; --i){ periodization_buf[i] = periodization_buf_rear[j]; --j; } if(F_2%2==0){ // cheap result fix ptr_out = (double*) wtcalloc(idwt_buffer_length(N, F, MODE_PERIODIZATION), sizeof(double)); if(ptr_out == NULL) return -3; upsampling_convolution_valid_sf(periodization_buf, N_p, filter, F, ptr_out, O, MODE_ZEROPAD); for(i=2*N-1; i > 0; --i){ output[i] += ptr_out[i-1]; } output[0] += ptr_out[2*N-1]; wtfree(ptr_out); } else { upsampling_convolution_valid_sf(periodization_buf, N_p, filter, F, output, O, MODE_ZEROPAD); } return 0; } else { return -2; // invalid lengths } } // allocate memory for even and odd elements of filter filter_even = (double*) malloc(F_2 * sizeof(double)); filter_odd = (double*) malloc(F_2 * sizeof(double)); if(filter_odd == NULL || filter_odd == NULL){ return -1; } // copy values for(i = 0; i < F_2; ++i){ filter_even[i] = filter[i << 1]; filter_odd[i] = filter[(i << 1) + 1]; } /////////////////////////////////////////////////////////////////////////// // MODE_PERIODIZATION // this part is quite complicated if(mode == MODE_PERIODIZATION){ k = F_2-1; N_p = F_2-1 + (int) ceil(k/2.); /*split filter len correct. + extra samples*/ if(N_p > 0){ periodization_buf = (double*) calloc(N_p, sizeof(double)); periodization_buf_rear = (double*) calloc(N_p, sizeof(double)); if(k <= N){ memcpy(periodization_buf + N_p - k, input, k * sizeof(double)); // copy from beginning of input to end of buffer for(i = 1; i <= (N_p - k); ++i) // kopiowanie 'cykliczne' od koñca input periodization_buf[(N_p - k) - i] = input[N - (i%N)]; memcpy(periodization_buf_rear, input + N - k, k * sizeof(double)); // copy from end of input to begginning of buffer for(i = 0; i < (N_p - k); ++i) // kopiowanie 'cykliczne' od pocz¹tku input periodization_buf_rear[k + i] = input[i%N]; } else { //printf("see %d line in %s!!\n", __LINE__, __FILE__); // TODO: is this ever called? if yes check for errors for(i = 0; i < k; ++i) periodization_buf[(N_p - k) + i] = input[i % N]; for(i = 1; i < (N_p - k); ++i) periodization_buf[(N_p - k) - i] = input[N - (i%N)]; //for(i = 0; i < N_p; ++i) // printf("%f ", periodization_buf[i]); //printf("--\n"); //for(i = 0; i < N_p; ++i) // printf("%f ", periodization_buf_rear[i]); //printf("\n"); } ptr_base = periodization_buf + F_2 - 1; if(k%2 == 1){ sum_odd = 0; for(j = 0; j < F_2; ++j) sum_odd += filter_odd[j] * ptr_base[-j]; *(ptr_out++) += sum_odd; --k; if(k) upsampling_convolution_valid_sf(periodization_buf + 1, N_p-1, filter, F, ptr_out, O-1, MODE_ZEROPAD); ptr_out += k; // k0 - 1 // really move backward by 1 } else if(k){ upsampling_convolution_valid_sf(periodization_buf, N_p, filter, F, ptr_out, O, MODE_ZEROPAD); ptr_out += k; } } } // MODE_PERIODIZATION /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // perform _valid_ convolution (only when all filter_even and filter_odd elements are in range of input data) // this part is quite simple, no extra hacks ptr_base = (DTYPE*)input + F_2 - 1; for(i = 0; i < N-(F_2-1); ++i){ // sliding over signal from left to right sum_even = 0; sum_odd = 0; // iterate filters elements for(j = 0; j < F_2; ++j){ sum_even += filter_even[j] * ptr_base[i-j]; sum_odd += filter_odd[j] * ptr_base[i-j]; } *(ptr_out++) += sum_even; *(ptr_out++) += sum_odd; } // /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // MODE_PERIODIZATION if(mode == MODE_PERIODIZATION){ if(N_p>0){ k = F_2-1; if(k%2 == 1){ if(F/2 <= N_p - 1) // k > 1 ? upsampling_convolution_valid_sf(periodization_buf_rear , N_p-1, filter, F, ptr_out, O-1, MODE_ZEROPAD); ptr_out += k; // move forward anyway -> see lower if(F_2%2 == 0){ // remaining one element ptr_base = periodization_buf_rear + N_p - 1; sum_even = 0; for(j = 0; j < F_2; ++j) sum_even += filter_even[j] * ptr_base[-j]; *(--ptr_out) += sum_even; // move backward first } } else { if(k) upsampling_convolution_valid_sf(periodization_buf_rear, N_p, filter, F, ptr_out, O, MODE_ZEROPAD); } } if(periodization_buf != NULL) wtfree(periodization_buf); if(periodization_buf_rear != NULL) wtfree(periodization_buf_rear); } // MODE_PERIODIZATION /////////////////////////////////////////////////////////////////////////// wtfree(filter_even); wtfree(filter_odd); return 0; }