xue@11
|
1 /*
|
xue@11
|
2 Harmonic sinusoidal modelling and tools
|
xue@11
|
3
|
xue@11
|
4 C++ code package for harmonic sinusoidal modelling and relevant signal processing.
|
xue@11
|
5 Centre for Digital Music, Queen Mary, University of London.
|
xue@11
|
6 This file copyright 2011 Wen Xue.
|
xue@11
|
7
|
xue@11
|
8 This program is free software; you can redistribute it and/or
|
xue@11
|
9 modify it under the terms of the GNU General Public License as
|
xue@11
|
10 published by the Free Software Foundation; either version 2 of the
|
xue@11
|
11 License, or (at your option) any later version.
|
xue@11
|
12 */
|
xue@1
|
13 //---------------------------------------------------------------------------
|
xue@1
|
14
|
xue@1
|
15 #include "hsedit.h"
|
xue@1
|
16 #include "splines.h"
|
xue@1
|
17
|
Chris@5
|
18 /** \file hsedit.h */
|
Chris@5
|
19
|
xue@1
|
20 //---------------------------------------------------------------------------
|
xue@1
|
21
|
Chris@5
|
22 /**
|
xue@1
|
23 function DeFM: frequency de-modulation
|
xue@1
|
24
|
xue@1
|
25 In: peakfr[npfr]: segmentation into FM cycles, peakfr[0]=0, peakfr[npfr-1]=Fr-1
|
xue@1
|
26 a1[Fr], f1[Fr]: sequence of amplitudes and frequencies
|
xue@1
|
27 arec[Fr]: amplitude-based weights for frequency averaging
|
xue@1
|
28 Out: a2[Fr], f2[Fr]: amplitude and frequency sequance after demodulation
|
xue@1
|
29
|
xue@1
|
30 No return value.
|
xue@1
|
31 */
|
xue@1
|
32 void DeFM(double* a2, double* f2, double* a1, double* f1, double* arec, int npfr, int* peakfr)
|
xue@1
|
33 {
|
xue@1
|
34 double *frs=new double[npfr*12], *a=&frs[npfr], *f=&frs[npfr*2],
|
xue@1
|
35 *aa=&frs[npfr*3], *ab=&frs[npfr*4], *ac=&frs[npfr*5], *ad=&frs[npfr*6],
|
xue@1
|
36 *fa=&frs[npfr*7], *fb=&frs[npfr*8], *fc=&frs[npfr*9], *fd=&frs[npfr*10];
|
xue@1
|
37 a[0]=a1[0], f[0]=f1[0], frs[0]=peakfr[0];
|
xue@1
|
38 for (int i=1; i<npfr-1; i++)
|
xue@1
|
39 {
|
xue@1
|
40 a[i]=f[i]=frs[i]=0; double lrec=0;
|
xue@1
|
41 for (int fr=peakfr[i-1]; fr<peakfr[i+1]; fr++)
|
xue@1
|
42 a[i]+=a1[fr]*a1[fr], f[i]+=f1[fr]*arec[fr], frs[i]+=fr*arec[fr], lrec+=arec[fr];
|
xue@1
|
43 a[i]=sqrt(a[i]/(peakfr[i+1]-peakfr[i-1])), f[i]/=lrec, frs[i]/=lrec;
|
xue@1
|
44 }
|
xue@1
|
45 a[npfr-1]=a1[peakfr[npfr-1]], f[npfr-1]=f1[peakfr[npfr-1]], frs[npfr-1]=peakfr[npfr-1];
|
xue@1
|
46 CubicSpline(npfr-1, aa, ab, ac, ad, frs, a, 1, 1, a2);
|
xue@1
|
47 CubicSpline(npfr-1, fa, fb, fc, fd, frs, f, 1, 1, f2);
|
xue@1
|
48 delete[] frs;
|
xue@1
|
49 }//DeFM
|
xue@1
|
50
|
Chris@5
|
51 /**
|
xue@1
|
52 function DFMSeg: segments HS frames into FM cycles
|
xue@1
|
53
|
xue@1
|
54 In: partials[M][Fr]: HS partials
|
xue@1
|
55 Out: peakfr[npfr]: segmentation, peakfr[0]=0, peakfr[npfr-1]=Fr-1.
|
xue@1
|
56 arec[Fr]: total amplitudes of frames
|
xue@1
|
57
|
xue@1
|
58 No return value.
|
xue@1
|
59 */
|
xue@1
|
60 void DFMSeg(double* arec, int& npfr, int* peakfr, int M, int Fr, atom** partials)
|
xue@1
|
61 {
|
xue@1
|
62 double *frec=new double[Fr];
|
xue@1
|
63 memset(arec, 0, sizeof(double)*Fr); memset(frec, 0, sizeof(double)*Fr);
|
xue@1
|
64 for (int m=0; m<M; m++) for (int fr=0; fr<Fr; fr++) {double la=partials[m][fr].a; la=la*la; arec[fr]+=la; frec[fr]+=partials[m][fr].f/(m+1)*la;}
|
xue@1
|
65 for (int fr=0; fr<Fr; fr++) frec[fr]=frec[fr]/arec[fr];
|
xue@1
|
66 peakfr[0]=0; npfr=1;
|
xue@1
|
67 for (int fr=1; fr<Fr-1; fr++)
|
xue@1
|
68 {
|
xue@1
|
69 if ((frec[fr]<frec[fr-1] && frec[fr]<frec[fr+1]) || (frec[fr]>frec[fr-1] && frec[fr]>frec[fr+1]))
|
xue@1
|
70 {
|
xue@1
|
71 peakfr[npfr]=fr;
|
xue@1
|
72 if (peakfr[npfr]-peakfr[npfr-1]>2) npfr++;
|
xue@1
|
73 }
|
xue@1
|
74 }
|
xue@1
|
75 peakfr[npfr++]=Fr-1;
|
xue@1
|
76 delete[] frec;
|
xue@1
|
77 }//DFMSeg
|
xue@1
|
78
|
Chris@5
|
79 /**
|
xue@1
|
80 function HSAM: harmonic sinusoid amplitude modulation
|
xue@1
|
81
|
xue@1
|
82 In: SrcHS: source harmonic sinusoid
|
xue@1
|
83 dep: modulation depth
|
xue@1
|
84 fre: modulator frequency
|
xue@1
|
85 ph: modulator phase
|
xue@1
|
86 Out: HS: destination harmonic sinusoid
|
xue@1
|
87
|
xue@1
|
88 No reutrn value.
|
xue@1
|
89 */
|
xue@1
|
90 void HSAM(THS* HS, THS* SrcHS, double dep, double fre, double ph)
|
xue@1
|
91 {
|
xue@1
|
92 double omg=M_PI*2*fre;
|
xue@1
|
93 for (int m=0; m<HS->M; m++)
|
xue@1
|
94 for (int fr=0; fr<HS->Fr; fr++)
|
xue@1
|
95 HS->Partials[m][fr].a=SrcHS->Partials[m][fr].a*(1+dep*cos(omg*SrcHS->Partials[m][fr].t+ph));
|
xue@1
|
96 }//HSAM
|
xue@1
|
97
|
Chris@5
|
98 /**
|
xue@1
|
99 function HSFM: harmonic sinusoid frequency modulation
|
xue@1
|
100
|
xue@1
|
101 In: SrcHS: source harmonic sinusoid
|
xue@1
|
102 a: modulation extent, in semitones
|
xue@1
|
103 fre: modulator frequency
|
xue@1
|
104 ph: modulator phase
|
xue@1
|
105 Out: HS: destination harmonic sinusoid
|
xue@1
|
106
|
xue@1
|
107 No reutrn value.
|
xue@1
|
108 */
|
xue@1
|
109 void HSFM(THS* HS, THS* SrcHS, double a, double freq, double ph)
|
xue@1
|
110 {
|
xue@1
|
111 double omg=M_PI*2*freq, pa=pow(2, a/12.0)-1;
|
xue@1
|
112 for (int m=0; m<HS->M; m++)
|
xue@1
|
113 for (int fr=0; fr<HS->Fr; fr++)
|
xue@1
|
114 HS->Partials[m][fr].f=SrcHS->Partials[m][fr].f*(1+pa*cos(omg*SrcHS->Partials[m][fr].t+ph));
|
xue@1
|
115 }//HSFM
|
xue@1
|
116
|
Chris@5
|
117 /**
|
xue@1
|
118 function HSFM_SF: harmonic sinusoid frequency modulation with source-filter model
|
xue@1
|
119
|
xue@1
|
120 In: SrcHS: source harmonic sinusoid
|
xue@1
|
121 a: modulation extent, in semitones
|
xue@1
|
122 fre: modulator frequency
|
xue@1
|
123 ph: modulator phase
|
xue@1
|
124 SF: source-filter model
|
xue@1
|
125 Out: HS: destination harmonic sinusoid
|
xue@1
|
126
|
xue@1
|
127 No reutrn value.
|
xue@1
|
128 */
|
xue@1
|
129 void HSFM_SF(THS* HS, THS* SrcHS, double a, double freq, double ph, TSF* SF)
|
xue@1
|
130 {
|
xue@1
|
131 double omg=M_PI*2*freq, pa=pow(2, a/12.0)-1;
|
xue@1
|
132 for (int m=0; m<HS->M; m++) for (int fr=0; fr<HS->Fr; fr++)
|
xue@1
|
133 {
|
xue@1
|
134 double f0=SrcHS->Partials[m][fr].f;
|
xue@1
|
135 double f1=f0*(1+pa*cos(omg*SrcHS->Partials[m][fr].t+ph));
|
xue@1
|
136 HS->Partials[m][fr].f=f1;
|
xue@1
|
137 HS->Partials[m][fr].a=SrcHS->Partials[m][fr].a*exp(SF->LogAF(f1)-SF->LogAF(f0));
|
xue@1
|
138 }
|
xue@1
|
139 }//HSFM_SF
|
xue@1
|
140
|
Chris@5
|
141 /**
|
xue@1
|
142 function: HSPitchShift: harmonic sinusoid pitch shifting
|
xue@1
|
143
|
xue@1
|
144 In: SrcHS: source harmonic sinusoid
|
xue@1
|
145 ps12: amount of pitch shift, in semitones
|
xue@1
|
146 Out: HS: destination harmonic sinusoid
|
xue@1
|
147
|
xue@1
|
148 No return value.
|
xue@1
|
149 */
|
xue@1
|
150 void HSPitchShift(THS* HS, THS* SrcHS, double ps12)
|
xue@1
|
151 {
|
xue@1
|
152 double pa=pow(2, ps12/12.0);
|
xue@1
|
153 for (int m=0; m<HS->M; m++) for (int fr=0; fr<HS->Fr; fr++) HS->Partials[m][fr].f=SrcHS->Partials[m][fr].f*pa;
|
xue@1
|
154 }//HSPitchShift
|
xue@1
|
155
|
Chris@5
|
156 /**
|
xue@1
|
157 function ReFM: frequency re-modulation
|
xue@1
|
158
|
xue@1
|
159 In: partials[M][Fr]: HS partials
|
xue@1
|
160 amount: relative modulation depth after remodulation
|
xue@1
|
161 rate: relateive modulation rate after remodulation
|
xue@1
|
162 SF: a source-filter model, optional
|
xue@1
|
163 Out: partials2[M][Fr]: remodulated HS partials. Must be allocated before calling.
|
xue@1
|
164
|
xue@1
|
165 No return value.
|
xue@1
|
166 */
|
xue@1
|
167 void ReFM(int M, int Fr, atom** partials, atom** partials2, double amount, double rate, TSF* SF)
|
xue@1
|
168 {
|
xue@1
|
169 double *arec=new double[Fr]; int *peakfr=new int[Fr], npfr;
|
xue@1
|
170 DFMSeg(arec, npfr, peakfr, M, Fr, partials);
|
xue@1
|
171
|
xue@1
|
172 double *a1=new double[Fr*8];
|
xue@1
|
173 double *f1=&a1[Fr], *a2=&a1[Fr*3], *f2=&a1[Fr*4], *da=&a1[Fr*5], *df=&a1[Fr*6];
|
xue@1
|
174
|
xue@1
|
175 for (int m=0; m<M; m++)
|
xue@1
|
176 {
|
xue@1
|
177 atom *part=partials[m], *part2=partials2[m]; bool fzero=false;
|
xue@1
|
178 for (int fr=0; fr<Fr; fr++)
|
xue@1
|
179 {
|
xue@1
|
180 if (part[fr].f<=0){fzero=true; break;}
|
xue@1
|
181 a1[fr]=part[fr].a*2;
|
xue@1
|
182 f1[fr]=part[fr].f;
|
xue@1
|
183 }
|
xue@1
|
184 if (fzero){part2[0].f=0; break;}
|
xue@1
|
185 DeFM(a2, f2, a1, f1, arec, npfr, peakfr);
|
xue@1
|
186 for (int i=0; i<Fr; i++) da[i]=a1[i]-a2[i], df[i]=f1[i]-f2[i];
|
xue@1
|
187 for (int fr=0; fr<Fr; fr++)
|
xue@1
|
188 {
|
xue@1
|
189 double frd=fr/rate; int dfrd=floor(frd); frd-=dfrd;
|
xue@1
|
190 double lda=0, ldf=0;
|
xue@1
|
191 if (dfrd<Fr-1) lda=da[dfrd]*(1-frd)+da[dfrd+1]*frd, ldf=df[dfrd]*(1-frd)+df[dfrd+1]*frd;
|
xue@1
|
192 else if (dfrd==Fr-1) lda=da[dfrd]*(1-frd), ldf=df[dfrd]*(1-frd);
|
xue@1
|
193 part2[fr].f=f2[fr]=f2[fr]+ldf*amount;
|
xue@1
|
194 if (SF) part2[fr].a=part[fr].a*exp(SF->LogAF(part2[fr].f)-SF->LogAF(part[fr].f));
|
xue@1
|
195 else part2[fr].a=(a2[fr]+lda*amount)*0.5;
|
xue@1
|
196 }
|
xue@1
|
197 }
|
xue@1
|
198 delete[] a1;
|
xue@1
|
199 delete[] arec; delete[] peakfr;
|
xue@1
|
200 }//ReFM
|
xue@1
|
201
|
xue@1
|
202
|
xue@1
|
203
|
xue@1
|
204
|