/* * Project 25 IMBE Encoder/Decoder Fixed-Point implementation * Developed by Pavel Yazev E-mail: pyazev@gmail.com * Version 1.0 (c) Copyright 2009 * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * The software is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Boston, MA * 02110-1301, USA. */ #include "typedef.h" #include "globals.h" #include "imbe.h" #include "basic_op.h" #include "aux_sub.h" #include "math_sub.h" #include "dsp_sub.h" #include "tbls.h" #include "pitch_ref.h" #include #include #include #define PITCH_REF_FRAME 221 #define MIN_INDEX 50 void pitch_ref(IMBE_PARAM *imbe_param, Cmplx16 *fft_buf) { Word16 i, j, index_a_save, pitch_est, tmp, shift, index_wr, up_lim; Cmplx16 sp_rec[FFTLENGTH/2]; Word32 fund_freq, fund_freq_2, fund_freq_acc_a, fund_freq_acc_b, fund_freq_acc, L_tmp, amp_re_acc, amp_im_acc, L_sum, L_diff_min; Word16 ha, hb, index_a, index_b, index_tbl[20], it_ind, re_tmp, im_tmp, pitch_cand=0; Word32 fund_freq_cand=0; pitch_est = shl(imbe_param->pitch, 7); // Convert to Q8.8 pitch_est = sub(pitch_est, CNST_1_125_Q8_8); // Sub 1.125 = 9/8 L_diff_min = MAX_32; for(i = 0; i < 19; i++) { shift = norm_s(pitch_est); tmp = shl(pitch_est, shift); tmp = div_s(0x4000, tmp); fund_freq = L_shl(tmp, shift + 11); fund_freq_acc = fund_freq; fund_freq_2 = L_shr(fund_freq, 1); fund_freq_acc_a = L_sub(fund_freq, fund_freq_2); fund_freq_acc_b = L_add(fund_freq, fund_freq_2); // Calculate upper limit for spectrum reconstruction up_lim = extract_h(L_shr((UWord32)CNST_0_9254_Q0_16 * pitch_est, 1)); // 0.9254/fund_freq up_lim = sub(up_lim, CNST_0_5_Q8_8); // sub 0.5 up_lim = up_lim & 0xFF00; // extract fixed part up_lim = mult(up_lim, extract_h(fund_freq)); up_lim = shr(up_lim, 1); index_b = 0; while(index_b <= up_lim) { ha = extract_h(fund_freq_acc_a); hb = extract_h(fund_freq_acc_b); index_a = (ha >> 8) + ((ha & 0xFF)?1:0); index_b = (hb >> 8) + ((hb & 0xFF)?1:0); if(index_b >= MIN_INDEX) { L_tmp = L_shl(L_deposit_h(index_a), 8); L_tmp = L_sub(L_tmp, fund_freq_acc); L_tmp = L_add(L_tmp, 0x00020000); // for rounding purpose L_tmp = L_shr(L_tmp, 2); index_a_save = index_a; it_ind = 0; amp_re_acc = amp_im_acc = 0; while(index_a < index_b) { index_wr = extract_h(L_tmp); if(index_wr < 0 && (L_tmp & 0xFFFF)) // truncating for negative number index_wr = add(index_wr, 1); index_wr = add(index_wr, 160); index_tbl[it_ind++] = index_wr; if(index_wr >= 0 && index_wr <= 320) { amp_re_acc = L_mac(amp_re_acc, fft_buf[index_a].re, wr_sp[index_wr]); amp_im_acc = L_mac(amp_im_acc, fft_buf[index_a].im, wr_sp[index_wr]); } index_a++; L_tmp = L_add(L_tmp, 0x400000); } it_ind = 0; index_a = index_a_save; while(index_a < index_b) { index_wr = index_tbl[it_ind++]; if(index_wr < 0 || index_wr > 320) { sp_rec[index_a].im = sp_rec[index_a].re = 0; } else { sp_rec[index_a].im = mult(mult(extract_h(amp_im_acc), wr_sp[index_wr]), 0x6666); sp_rec[index_a].re = mult(mult(extract_h(amp_re_acc), wr_sp[index_wr]), 0x6666); } index_a++; } } fund_freq_acc_a = L_add(fund_freq_acc_a, fund_freq); fund_freq_acc_b = L_add(fund_freq_acc_b, fund_freq); fund_freq_acc = L_add(fund_freq_acc, fund_freq); } L_sum = 0; for(j = MIN_INDEX; j <= up_lim; j++) { re_tmp = sub(fft_buf[j].re, sp_rec[j].re); im_tmp = sub(fft_buf[j].im, sp_rec[j].im); L_sum = L_mac(L_sum, re_tmp, re_tmp); L_sum = L_mac(L_sum, im_tmp, im_tmp); } if(L_sum < L_diff_min) { L_diff_min = L_sum; pitch_cand = pitch_est; fund_freq_cand = fund_freq; } pitch_est = add(pitch_est, CNST_0_125_Q8_8); // Add 0.125 = 1/8 } imbe_param->ref_pitch = pitch_cand; imbe_param->fund_freq = fund_freq_cand; }