summaryrefslogtreecommitdiff
path: root/gr-vocoder/lib/codec2/phase.c
diff options
context:
space:
mode:
Diffstat (limited to 'gr-vocoder/lib/codec2/phase.c')
-rw-r--r--gr-vocoder/lib/codec2/phase.c123
1 files changed, 57 insertions, 66 deletions
diff --git a/gr-vocoder/lib/codec2/phase.c b/gr-vocoder/lib/codec2/phase.c
index 69cc6697fc..a9c1c06b9a 100644
--- a/gr-vocoder/lib/codec2/phase.c
+++ b/gr-vocoder/lib/codec2/phase.c
@@ -27,17 +27,16 @@
#include "defines.h"
#include "phase.h"
-#include "fft.h"
+#include "kiss_fft.h"
#include "comp.h"
-#include "glottal.c"
+#include "sine.h"
#include <assert.h>
+#include <ctype.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
-#define GLOTTAL_FFT_SIZE 512
-
/*---------------------------------------------------------------------------*\
aks_to_H()
@@ -48,6 +47,7 @@
\*---------------------------------------------------------------------------*/
void aks_to_H(
+ kiss_fft_cfg fft_fwd_cfg,
MODEL *model, /* model parameters */
float aks[], /* LPC's */
float G, /* energy term */
@@ -55,7 +55,8 @@ void aks_to_H(
int order
)
{
- COMP Pw[FFT_DEC]; /* power spectrum */
+ COMP pw[FFT_ENC]; /* power spectrum (input) */
+ COMP Pw[FFT_ENC]; /* power spectrum (output) */
int i,m; /* loop variables */
int am,bm; /* limits of current band */
float r; /* no. rads/bin */
@@ -64,35 +65,35 @@ void aks_to_H(
int b; /* centre bin of harmonic */
float phi_; /* phase of LPC spectra */
- r = TWO_PI/(FFT_DEC);
+ r = TWO_PI/(FFT_ENC);
/* Determine DFT of A(exp(jw)) ------------------------------------------*/
- for(i=0; i<FFT_DEC; i++) {
- Pw[i].real = 0.0;
- Pw[i].imag = 0.0;
+ for(i=0; i<FFT_ENC; i++) {
+ pw[i].real = 0.0;
+ pw[i].imag = 0.0;
}
for(i=0; i<=order; i++)
- Pw[i].real = aks[i];
+ pw[i].real = aks[i];
- fft(&Pw[0].real,FFT_DEC,-1);
+ kiss_fft(fft_fwd_cfg, (kiss_fft_cpx *)pw, (kiss_fft_cpx *)Pw);
/* Sample magnitude and phase at harmonics */
for(m=1; m<=model->L; m++) {
- am = floor((m - 0.5)*model->Wo/r + 0.5);
- bm = floor((m + 0.5)*model->Wo/r + 0.5);
- b = floor(m*model->Wo/r + 0.5);
-
- Em = 0.0;
- for(i=am; i<bm; i++)
- Em += G/(Pw[i].real*Pw[i].real + Pw[i].imag*Pw[i].imag);
- Am = sqrt(fabs(Em/(bm-am)));
-
- phi_ = -atan2(Pw[b].imag,Pw[b].real);
- H[m].real = Am*cos(phi_);
- H[m].imag = Am*sin(phi_);
+ am = (int)((m - 0.5)*model->Wo/r + 0.5);
+ bm = (int)((m + 0.5)*model->Wo/r + 0.5);
+ b = (int)(m*model->Wo/r + 0.5);
+
+ Em = 0.0;
+ for(i=am; i<bm; i++)
+ Em += G/(Pw[i].real*Pw[i].real + Pw[i].imag*Pw[i].imag);
+ Am = sqrtf(fabsf(Em/(bm-am)));
+
+ phi_ = -atan2f(Pw[b].imag,Pw[b].real);
+ H[m].real = Am*cosf(phi_);
+ H[m].imag = Am*sinf(phi_);
}
}
@@ -188,6 +189,7 @@ void aks_to_H(
\*---------------------------------------------------------------------------*/
void phase_synth_zero_order(
+ kiss_fft_cfg fft_fwd_cfg,
MODEL *model,
float aks[],
float *ex_phase, /* excitation phase of fundamental */
@@ -196,16 +198,13 @@ void phase_synth_zero_order(
{
int m;
float new_phi;
- COMP Ex[MAX_AMP]; /* excitation samples */
- COMP A_[MAX_AMP]; /* synthesised harmonic samples */
- COMP H[MAX_AMP]; /* LPC freq domain samples */
+ COMP Ex[MAX_AMP+1]; /* excitation samples */
+ COMP A_[MAX_AMP+1]; /* synthesised harmonic samples */
+ COMP H[MAX_AMP+1]; /* LPC freq domain samples */
float G;
- float jitter = 0.0;
- float r;
- int b;
G = 1.0;
- aks_to_H(model, aks, G, H, order);
+ aks_to_H(fft_fwd_cfg, model, aks, G, H, order);
/*
Update excitation fundamental phase track, this sets the position
@@ -213,50 +212,42 @@ void phase_synth_zero_order(
I found that using just this frame's Wo improved quality for UV
sounds compared to interpolating two frames Wo like this:
- ex_phase[0] += (*prev_Wo+mode->Wo)*N/2;
+ ex_phase[0] += (*prev_Wo+model->Wo)*N/2;
*/
ex_phase[0] += (model->Wo)*N;
- ex_phase[0] -= TWO_PI*floor(ex_phase[0]/TWO_PI + 0.5);
- r = TWO_PI/GLOTTAL_FFT_SIZE;
+ ex_phase[0] -= TWO_PI*floorf(ex_phase[0]/TWO_PI + 0.5);
for(m=1; m<=model->L; m++) {
- /* generate excitation */
+ /* generate excitation */
if (model->voiced) {
- /* I think adding a little jitter helps improve low pitch
- males like hts1a. This moves the onset of each harmonic
- over at +/- 0.25 of a sample.
- */
- jitter = 0.25*(1.0 - 2.0*rand()/RAND_MAX);
- b = floor(m*model->Wo/r + 0.5);
- if (b > ((GLOTTAL_FFT_SIZE/2)-1)) {
- b = (GLOTTAL_FFT_SIZE/2)-1;
- }
- Ex[m].real = cos(ex_phase[0]*m - jitter*model->Wo*m + glottal[b]);
- Ex[m].imag = sin(ex_phase[0]*m - jitter*model->Wo*m + glottal[b]);
- }
- else {
-
- /* When a few samples were tested I found that LPC filter
- phase is not needed in the unvoiced case, but no harm in
- keeping it.
- */
- float phi = TWO_PI*(float)rand()/RAND_MAX;
- Ex[m].real = cos(phi);
- Ex[m].imag = sin(phi);
- }
-
- /* filter using LPC filter */
-
- A_[m].real = H[m].real*Ex[m].real - H[m].imag*Ex[m].imag;
- A_[m].imag = H[m].imag*Ex[m].real + H[m].real*Ex[m].imag;
-
- /* modify sinusoidal phase */
-
- new_phi = atan2(A_[m].imag, A_[m].real+1E-12);
- model->phi[m] = new_phi;
+
+ Ex[m].real = cosf(ex_phase[0]*m);
+ Ex[m].imag = sinf(ex_phase[0]*m);
+ }
+ else {
+
+ /* When a few samples were tested I found that LPC filter
+ phase is not needed in the unvoiced case, but no harm in
+ keeping it.
+ */
+ float phi = TWO_PI*(float)codec2_rand()/CODEC2_RAND_MAX;
+ Ex[m].real = cosf(phi);
+ Ex[m].imag = sinf(phi);
+ }
+
+ /* filter using LPC filter */
+
+ A_[m].real = H[m].real*Ex[m].real - H[m].imag*Ex[m].imag;
+ A_[m].imag = H[m].imag*Ex[m].real + H[m].real*Ex[m].imag;
+
+ /* modify sinusoidal phase */
+
+ new_phi = atan2f(A_[m].imag, A_[m].real+1E-12);
+ model->phi[m] = new_phi;
}
}
+