annotate hsedit.cpp @ 13:de3961f74f30 tip

Add Linux/gcc Makefile; build fix
author Chris Cannam
date Mon, 05 Sep 2011 15:22:35 +0100
parents 977f541d6683
children
rev   line source
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