annotate VibratoDemoUnit.cpp @ 1:f3fd4e19cec0 tip

first binary upload
author wenx <xue.wen@eecs.qmul.ac.uk>
date Wed, 10 Aug 2011 14:56:28 +0100
parents a6a46af64546
children
rev   line source
xue@0 1 /*
xue@0 2 Harmonic Visualiser
xue@0 3
xue@0 4 An audio file viewer and editor.
xue@0 5 Centre for Digital Music, Queen Mary, University of London.
xue@0 6 This file copyright 2011 Wen Xue.
xue@0 7
xue@0 8 This program is free software; you can redistribute it and/or
xue@0 9 modify it under the terms of the GNU General Public License as
xue@0 10 published by the Free Software Foundation; either version 2 of the
xue@0 11 License, or (at your option) any later version.
xue@0 12 */
xue@0 13 //---------------------------------------------------------------------------
xue@0 14
xue@0 15 #include <vcl.h>
xue@0 16 #pragma hdrstop
xue@0 17
xue@0 18 #include <Math.hpp>
xue@0 19 #include <math.h>
xue@0 20 #include "VibratoDemoUnit.h"
xue@0 21 #include "Matrix.h"
xue@0 22 #include "Unit1.h"
xue@0 23 #include "splines.h"
xue@0 24 #include "hssf.h"
xue@0 25 //---------------------------------------------------------------------------
xue@0 26 #pragma package(smart_init)
xue@0 27 #pragma resource "*.dfm"
xue@0 28 TVibratoDemoForm *VibratoDemoForm;
xue@0 29 //---------------------------------------------------------------------------
xue@0 30 const double updb=10, downdb=-80, dbrange=updb-downdb;
xue@0 31 const double log10e=Log10(exp(1));
xue@0 32 const Bdw=5, Bdwc=2;
xue@0 33
xue@0 34
xue@0 35 __fastcall TVibratoDemoForm::TVibratoDemoForm(TComponent* Owner)
xue@0 36 : TForm(Owner)
xue@0 37 {
xue@0 38 ForceUpdate=false;
xue@0 39
xue@0 40 SUThread=0;
xue@0 41 pThread=0;
xue@0 42 memset(ThreadList, 0, sizeof(TSUThread*)*ThreadCaps);
xue@0 43
xue@0 44 WaveAudio1=new TWaveAudio(NULL);
xue@0 45 WaveAudio1->UseMemoryStream=true;
xue@0 46 WaveAudio1->Channels=1;
xue@0 47 WaveView1=new TWaveView(NULL);
xue@0 48 WaveView1->Parent=Panel2;
xue@0 49 WaveView1->Align=alClient;
xue@0 50 WaveView1->WaveAudio=WaveAudio1;
xue@0 51 WaveView1->OnGetOpMode=WaveView1OpMode;
xue@0 52 WaveView1->CreatePanes(1, 1);
xue@0 53 WaveView1->SetContent(0, 0, 0, 1);
xue@0 54 WaveView1->ClickFocus=true;
xue@0 55 WaveView1->DefaultPopupMenu=false;
xue@0 56 WaveView1->CustomInfo=WaveView1CustomInfo;
xue@0 57 WaveView1->InfoLeft=5; WaveView1->InfoTop=5;
xue@0 58
xue@0 59 WaveAudio2=new TWaveAudio(NULL);
xue@0 60 WaveAudio2->UseMemoryStream=true;
xue@0 61 WaveAudio2->Channels=1;
xue@0 62 WaveView2=new TWaveView(NULL);
xue@0 63 WaveView2->Parent=Panel3;
xue@0 64 WaveView2->Align=alClient;
xue@0 65 WaveView2->WaveAudio=WaveAudio2;
xue@0 66 WaveView2->CreatePanes(1, 1);
xue@0 67 WaveView2->SetContent(0, 0, 0, 1);
xue@0 68 WaveView2->ClickFocus=true;
xue@0 69 WaveView2->DefaultPopupMenu=false;
xue@0 70 WaveView2->CustomInfo=WaveView1CustomInfo;
xue@0 71 WaveView2->InfoLeft=5; WaveView2->InfoTop=5;
xue@0 72
xue@0 73
xue@0 74 HS=0;
xue@0 75 CurrentModCycle=-1;
xue@0 76 peaky=0;
xue@0 77 cyclefrs=0;
xue@0 78 cyclefs=0;
xue@0 79
xue@0 80 datain=0;
xue@0 81 }
xue@0 82
xue@0 83 __fastcall TVibratoDemoForm::~TVibratoDemoForm()
xue@0 84 {
xue@0 85 delete WaveAudio1;
xue@0 86 delete WaveAudio2;
xue@0 87 delete WaveView1;
xue@0 88 delete WaveView2;
xue@0 89 delete HS;
xue@0 90 delete[] peaky;
xue@0 91 delete[] cyclefrs;
xue@0 92 delete[] cyclefs;
xue@0 93 for (int i=0; i<ThreadCaps; i++) if (ThreadList[i]) delete ThreadList[i];
xue@0 94 delete[] datain;
xue@0 95 }
xue@0 96 //---------------------------------------------------------------------------
xue@0 97 void TVibratoDemoForm::FindNote(){}
xue@0 98
xue@0 99 void TVibratoDemoForm::Reset()
xue@0 100 {
xue@0 101 if (!HS) return;
xue@0 102 if (HS->M<=0 || HS->Fr<=0) return;
xue@0 103
xue@0 104 if (ListBox1->ItemIndex<0) ListBox1->ItemIndex=0;
xue@0 105 double Fs=WaveView1->SamplesPerSec;
xue@0 106 int FSMode=ListBox1->ItemIndex;
xue@0 107 double FSF=FEdit->Text.ToDouble();
xue@0 108 int FSFScale=FScaleCombo->ItemIndex;
xue@0 109 if (FSFScale==0) FSF/=Fs;
xue@0 110 else FSF/=Amel*log(1+Fs/700);
xue@0 111 double FStheta=ThetaEdit->Text.ToDouble();
xue@0 112
xue@0 113 double sps=WaveView1->SamplesPerSec;
xue@0 114 double h=WaveView1->SpecOffst;
xue@0 115 AnalyzeV(*HS, V, peaky, cyclefrs, cyclefs, sps, h, &cyclefrcount, FSMode, FSF, FSFScale, FStheta);
xue@0 116 SynthesizeV(HS, &V, WaveView1->SamplesPerSec);
xue@0 117 SaveV();
xue@0 118 UpdateDisplay();
xue@0 119 }
xue@0 120
xue@0 121 void TVibratoDemoForm::Copydata()
xue@0 122 {
xue@0 123 int dst, den;
xue@0 124 double* xrec;
xue@0 125 if (HS)
xue@0 126 {
xue@0 127 xrec=SynthesisHSp(HS, dst, den);
xue@0 128 if (dst<0) dst=0;
xue@0 129
xue@0 130 delete[] datain;
xue@0 131 datain=new __int16[den-dst];
xue@0 132
xue@0 133 DoubleToInt(datain, sizeof(__int16), xrec, den-dst);
xue@0 134
xue@0 135 free8(xrec);
xue@0 136 }
xue@0 137 }
xue@0 138
xue@0 139 void TVibratoDemoForm::Synthesize()
xue@0 140 {
xue@0 141 int dst, den;
xue@0 142 double* xrec;
xue@0 143 if (HS)
xue@0 144 {
xue@0 145 double t=GetTickCount();
xue@0 146 xrec=SynthesisHS(HS, dst, den);
xue@0 147 t=GetTickCount()-t;
xue@0 148 Label13->Caption=t;
xue@0 149 }
xue@0 150 int bips=WaveAudio1->BitsPerSample;
xue@0 151 double max=(1<<(bips-1)); for (int i=dst; i<den; i++) if (xrec[i]>max) max=xrec[i]; else if (xrec[i]<-max) max=-xrec[i];
xue@0 152 if (max>(1<<(bips-1)))
xue@0 153 {
xue@0 154 max=(1<<(bips-1))/max;
xue@0 155 for (int i=dst; i<den; i++) xrec[i]*=max;
xue@0 156 }
xue@0 157 int bps=bips/8;
xue@0 158 WaveAudio2->Clear(NULL);
xue@0 159 WaveAudio2->GetWaveProperties(WaveAudio1);
xue@0 160 if (HS)
xue@0 161 {
xue@0 162 if (dst<0) dst=0;
xue@0 163 void* data=new char[(den-dst)*bps];
xue@0 164 DoubleToInt(data, bps, xrec, den-dst);
xue@0 165
xue@0 166 WaveAudio2->Clear(NULL);
xue@0 167 WaveAudio2->WriteSamples(data, den-dst);
xue@0 168 free8(xrec);
xue@0 169 delete[] data;
xue@0 170 }
xue@0 171 }
xue@0 172
xue@0 173 //for frequency modulator shape
xue@0 174 void DrawBarMap(Graphics::TBitmap* Bitmap, TRect Rect, int Count, double* data, bool res, int* KX1=0, int* KX2=0)
xue@0 175 {
xue@0 176 TCanvas* Canvas=Bitmap->Canvas;
xue@0 177 Bitmap->Width=Rect.Width();
xue@0 178 Bitmap->Height=Rect.Height();
xue@0 179
xue@0 180 TFont* F=Canvas->Font; F->Color=clWhite; F->Height=12; F->Name="Ariel";
xue@0 181 int fh=Canvas->TextHeight("0");
xue@0 182 int DrawCount=res?(Count+1):Count;
xue@0 183
xue@0 184 double XX=Rect.right-Bdw*2, YY=Rect.bottom-Bdw-Bdwc-fh;
xue@0 185 Canvas->Brush->Color=clBlack; Canvas->Brush->Style=bsSolid; Canvas->FillRect(Rect);
xue@0 186 Canvas->Brush->Color=clAqua; Canvas->Pen->Color=clAqua; Canvas->Brush->Style=bsSolid;
xue@0 187 int empspace=XX/(DrawCount+1)/4;
xue@0 188 double r=0; for (int i=0; i<Count; i++) r+=data[i]*data[i];
xue@0 189 double sqrtr=sqrt(r);
xue@0 190 double res_amp=(r>1)?0:sqrt(1-r);
xue@0 191 for (int i=0; i<DrawCount; i++)
xue@0 192 {
xue@0 193 double ldata;
xue@0 194 if (res)
xue@0 195 {
xue@0 196 if (i==0) ldata=data[i];
xue@0 197 else if (i<Count) ldata=data[i];
xue@0 198 else ldata=res_amp;
xue@0 199 }
xue@0 200 else ldata=data[i]/sqrtr;
xue@0 201 int X=floor(Bdw+XX*(i+1)/(DrawCount+1)+0.5);
xue@0 202 int Y=floor(Bdw+YY*(1-ldata)+0.5);
xue@0 203 if (empspace>=1)
xue@0 204 {
xue@0 205 Canvas->Brush->Style=bsSolid; Canvas->Brush->Color=TColor(0xFFFF00);
xue@0 206 Canvas->Rectangle(X-empspace, Y, X+empspace, Bdw+YY);
xue@0 207 if (KX1) KX1[i]=X-empspace, KX2[i]=X+empspace-1;
xue@0 208 }
xue@0 209 else
xue@0 210 {
xue@0 211 Canvas->MoveTo(X, Y); Canvas->LineTo(X, Bdw+YY);
xue@0 212 if (KX1) KX1[i]=X-1, KX2[i]=X+1;
xue@0 213 }
xue@0 214 AnsiString S=i; if (i>=Count) S="R"; int fw=Canvas->TextWidth(S);
xue@0 215 Canvas->Brush->Style=bsClear;
xue@0 216 Canvas->TextOut(X-fw/2, Bdw+YY, S);
xue@0 217 S.sprintf("%.3g", 100*ldata*ldata); if (S[1]=='0') S=S.SubString(2, S.Length()-1); fw=Canvas->TextWidth(S);
xue@0 218 if (Y-Bdw>fh) Canvas->TextOut(X-fw/2, Y-fh, S);
xue@0 219 else Canvas->TextOut(X+empspace+1, Y, S);
xue@0 220 }
xue@0 221 Canvas->Brush->Color=clBlack; Canvas->Brush->Style=bsClear; Canvas->Pen->Color=clWhite;
xue@0 222 Canvas->Rectangle(Bdw, Bdw, Bdw+XX, Bdw+YY);
xue@0 223 }
xue@0 224
xue@0 225 TColor RotateColors[10]={clWhite, clAqua, clLime, clYellow, clRed, clTeal, clGray, clGreen, clFuchsia, clBlue};
xue@0 226 //draw A-F distribution
xue@0 227 void DrawAF(Graphics::TBitmap* Bitmap, TRect Rect, double xst, double xen, double dbst, double dben, int M, int Fr, atom** Partials, double* A0C, bool MA, bool bars, int FrStart=0, int TextHeight=12)
xue@0 228 {
xue@0 229 Bitmap->Width=Rect.Width();
xue@0 230 Bitmap->Height=Rect.Height();
xue@0 231 TCanvas* Canvas=Bitmap->Canvas;
xue@0 232 double idbrange=1.0/(dbst-dben);
xue@0 233 TFont* F=Canvas->Font; F->Color=clWhite; F->Height=TextHeight; F->Name="Ariel";
xue@0 234 int fh=Canvas->TextHeight("0");
xue@0 235
xue@0 236 double XX=Rect.right-Bdw*2, YY=Rect.bottom-Bdw-Bdwc-fh;
xue@0 237 Canvas->Brush->Color=clBlack; Canvas->Brush->Style=bsSolid; Canvas->FillRect(Rect);
xue@0 238
xue@0 239 Canvas->Pen->Color=clSilver; Canvas->MoveTo(Bdw, Bdw+YY*0.5); Canvas->LineTo(Bdw+XX, Bdw+YY*0.5);
xue@0 240
xue@0 241 double *x=new double[(Fr-FrStart)*4], *y=&x[Fr-FrStart], *newa=&x[(Fr-FrStart)*2], *neww=&x[(Fr-FrStart)*3];
xue@0 242
xue@0 243 for (int m=0; m<M; m++)
xue@0 244 {
xue@0 245 Canvas->Pen->Color=RotateColors[m%10]; Canvas->Brush->Color=RotateColors[m%10];
xue@0 246
xue@0 247 int Sc=0;
xue@0 248 bool visible=false;
xue@0 249 atom* Partialsm=Partials[m];
xue@0 250 for (int fr=FrStart; fr<Fr; fr++)
xue@0 251 {
xue@0 252 if (Partialsm[fr].f>0 && Partialsm[fr].a>0)
xue@0 253 {
xue@0 254 x[Sc]=Partials[m][fr].f;
xue@0 255 y[Sc]=20*Log10(Partialsm[fr].a/A0C[fr]);
xue@0 256 if (x[Sc]<xen) visible=true;
xue@0 257 Sc++;
xue@0 258 }
xue@0 259 }
xue@0 260 if (!visible) break;
xue@0 261
xue@0 262 if (MA)
xue@0 263 {
xue@0 264 double fw;
xue@0 265 for (int c=0; c<Sc; c++) newa[c]=y[c], neww[c]=1;
xue@0 266 for (int c=0; c<Sc; c++)
xue@0 267 {
xue@0 268 fw=0.002; if (fw>x[c]*0.05) fw=x[c]*0.05;
xue@0 269
xue@0 270 for (int c1=0; c1<c; c1++)
xue@0 271 {
xue@0 272 double df=fabs(x[c]-x[c1]);
xue@0 273 if (df<fw)
xue@0 274 {
xue@0 275 double w=0.5+0.5*cos(M_PI*df/fw);
xue@0 276 newa[c]+=y[c1]*w; neww[c]+=w;
xue@0 277 newa[c1]+=y[c]*w; neww[c1]+=w;
xue@0 278 }
xue@0 279 }
xue@0 280 }
xue@0 281 for (int c=0; c<Sc; c++) y[c]=newa[c]/neww[c];
xue@0 282 }
xue@0 283
xue@0 284 for (int c=0; c<Sc; c++)
xue@0 285 {
xue@0 286 if (x[c]<xst || x[c]>xen) continue;
xue@0 287 double ldata=(y[c]-dben)*idbrange;
xue@0 288 int X=floor(Bdw+XX*(x[c]-xst)/(xen-xst)+0.5);
xue@0 289 int Y=floor(Bdw+YY*(1-ldata)+0.5);
xue@0 290 if (bars) {Canvas->MoveTo(X, Y); Canvas->LineTo(X, Bdw+YY);}
xue@0 291 else {Canvas->MoveTo(X-1, Y); Canvas->LineTo(X+2, Y); Canvas->MoveTo(X, Y-1); Canvas->LineTo(X, Y+2);}
xue@0 292 }
xue@0 293 }
xue@0 294
xue@0 295 AnsiString S="0hz"; Canvas->Brush->Style=bsClear; Canvas->TextOut(Bdw, Bdw+YY, S);
xue@0 296 S="5.5khz"; int fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+(XX-fw)/2, Bdw+YY, S);
xue@0 297 S="11khz"; fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+XX-fw, Bdw+YY, S);
xue@0 298 S.sprintf("%gdB", dbst); fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+XX-fw, Bdw, S);
xue@0 299 S.sprintf("%gdB", (dbst+dben)/2); fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+XX-fw, Bdw+(YY-fh)/2, S);
xue@0 300 S.sprintf("%gdB", dben); fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+XX-fw, Bdw+YY-fh, S);
xue@0 301
xue@0 302 Canvas->Brush->Color=clBlack; Canvas->Brush->Style=bsClear; Canvas->Pen->Color=clWhite;
xue@0 303 Canvas->Rectangle(Bdw, Bdw, Bdw+XX, Bdw+YY);
xue@0 304
xue@0 305 delete[] x;
xue@0 306
xue@0 307 } //*/
xue@0 308 //for source-filter results
xue@0 309 void DrawSFr(Graphics::TBitmap* Bitmap, TRect Rect, double xst, double xen, double dbst, double dben, int M, int Fr, int afres, atom** Partials, double* LogAF, double* LogAS, int TextHeight=12)
xue@0 310 {
xue@0 311 Bitmap->Width=Rect.Width();
xue@0 312 Bitmap->Height=Rect.Height();
xue@0 313 TCanvas* Canvas=Bitmap->Canvas;
xue@0 314 TFont* F=Canvas->Font; F->Color=clWhite; F->Height=TextHeight; F->Name="Ariel";
xue@0 315 int fh=Canvas->TextHeight("0");
xue@0 316
xue@0 317 double XX=Rect.right-Bdw*2, YY=Rect.bottom-Bdw-Bdwc-fh;
xue@0 318 Canvas->Brush->Color=clBlack; Canvas->Brush->Style=bsSolid; Canvas->FillRect(Rect);
xue@0 319
xue@0 320 Canvas->Pen->Color=clSilver; Canvas->MoveTo(Bdw, Bdw+YY*0.5); Canvas->LineTo(Bdw+XX, Bdw+YY*0.5);
xue@0 321
xue@0 322 double xrange=xen-xst, XXixrange=XX/xrange, xstXXixrange=xst*XXixrange,
xue@0 323 xrangeiXX=xrange/XX, xstafres=xst*afres, xrangeiXXafres=xrangeiXX*afres,
xue@0 324 YYidbrange=YY/(dbst-dben);
xue@0 325
xue@0 326 int *XRec=new int[XX];
xue@0 327 for (int m=0; m<M; m++)
xue@0 328 {
xue@0 329 bool visible=false;
xue@0 330 atom* Partialsm=Partials[m];
xue@0 331 Canvas->Brush->Color=RotateColors[m%10]; Canvas->Pen->Color=RotateColors[m%10];
xue@0 332 memset(XRec, 0, sizeof(int)*XX);
xue@0 333
xue@0 334 for (int fr=0; fr<Fr; fr++)
xue@0 335 {
xue@0 336 if (Partialsm[fr].f>0 && Partialsm[fr].a>0)
xue@0 337 {
xue@0 338 double xx=Partialsm[fr].f;
xue@0 339 if (xx<xen) visible=true;
xue@0 340 if (xx<xst || xx>xen) continue;
xue@0 341 int X=floor(XXixrange*xx-xstXXixrange+0.5);
xue@0 342 if (X>=0 && X<XX && !XRec[X])
xue@0 343 {
xue@0 344 XRec[X]=true;
xue@0 345 double yy=20*log10e*(LogAF[int(xstafres+X*xrangeiXXafres)]+LogAS[m]);
xue@0 346 int Y=Bdw+floor((YY-YYidbrange*(yy-dben))+0.5);
xue@0 347 X+=Bdw;
xue@0 348 Canvas->MoveTo(X-1, Y); Canvas->LineTo(X+2, Y);
xue@0 349 Canvas->MoveTo(X, Y-1); Canvas->LineTo(X, Y+2);
xue@0 350 }
xue@0 351 }
xue@0 352 }
xue@0 353 if (!visible) break;
xue@0 354 }
xue@0 355 delete[] XRec;
xue@0 356
xue@0 357 AnsiString S="0hz"; Canvas->Brush->Style=bsClear; Canvas->TextOut(Bdw, Bdw+YY, S);
xue@0 358 S="5.5khz"; int fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+(XX-fw)/2, Bdw+YY, S);
xue@0 359 S="11khz"; fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+XX-fw, Bdw+YY, S);
xue@0 360 S.sprintf("%gdB", dbst); fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+XX-fw, Bdw, S);
xue@0 361 S.sprintf("%gdB", (dbst+dben)/2); fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+XX-fw, Bdw+(YY-fh)/2, S);
xue@0 362 S.sprintf("%gdB", dben); fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+XX-fw, Bdw+YY-fh, S);
xue@0 363
xue@0 364 Canvas->Brush->Color=clBlack; Canvas->Brush->Style=bsClear; Canvas->Pen->Color=clWhite;
xue@0 365 Canvas->Rectangle(Bdw, Bdw, Bdw+XX, Bdw+YY);
xue@0 366 }
xue@0 367 //*for source-filter model
xue@0 368 int DrawSF(Graphics::TBitmap* Bitmap, TRect Rect, double xst, double xen, double dbst, double dben, double f0, int SCount, double* LogAS, double fc0, int FCount, double* LogAF, int* SX=0, TColor* Colors=0, int TextHeight=12)
xue@0 369 {
xue@0 370 Bitmap->Width=Rect.Width();
xue@0 371 Bitmap->Height=Rect.Height();
xue@0 372 TCanvas* Canvas=Bitmap->Canvas;
xue@0 373 double *Sx=new double[SCount];
xue@0 374 for (int i=0; i<SCount; i++) Sx[i]=20*log10e*LogAS[i];
xue@0 375
xue@0 376 int result=0;
xue@0 377 TFont* F=Canvas->Font; F->Color=clWhite; F->Height=TextHeight; F->Name="Ariel";
xue@0 378 int fh=Canvas->TextHeight("0");
xue@0 379
xue@0 380 double XX=Rect.right-Bdw*2, YY=Rect.bottom-Bdw-Bdwc-fh;
xue@0 381 Canvas->Brush->Color=clBlack; Canvas->Brush->Style=bsSolid; Canvas->FillRect(Rect);
xue@0 382 Canvas->Pen->Color=clSilver; Canvas->MoveTo(Bdw, Bdw+YY*0.5); Canvas->LineTo(Bdw+XX, Bdw+YY*0.5);
xue@0 383
xue@0 384 double idbrange=1.0/(dbst-dben), xrange=xen-xst, XXixrange=XX/xrange, xstXXixrange=xst*XXixrange,
xue@0 385 YY20log10eidbrange=YY*20*log10e*idbrange, BdwpYYpYYdbenidbrange=Bdw+YY+YY*dben*idbrange,
xue@0 386 Bdw_xstXXixrange=Bdw-xstXXixrange, YYidbrange=YY*idbrange;
xue@0 387
xue@0 388 double st=xst/fc0; int ist=ceil(st); if (ist<0) ist=0;
xue@0 389 Canvas->Pen->Color=clWhite;
xue@0 390 Canvas->MoveTo(Bdw+XX*(fc0*ist-xst)/xrange+0.5, BdwpYYpYYdbenidbrange-YY20log10eidbrange*LogAF[ist]+0.5);
xue@0 391 //draw filter contour
xue@0 392 int LineCount=xrange/fc0;
xue@0 393 if (LineCount<XX)
xue@0 394 {
xue@0 395 for (int i=ist+1; i<FCount; i++)
xue@0 396 {
xue@0 397 double xi=fc0*i;
xue@0 398 if (xi>xen) break;
xue@0 399 int X=floor(Bdw_xstXXixrange+xi*XXixrange+0.5);
xue@0 400 int Y=floor(BdwpYYpYYdbenidbrange-YY20log10eidbrange*LogAF[i]+0.5);
xue@0 401 Canvas->LineTo(X, Y);
xue@0 402 }
xue@0 403 }
xue@0 404 else
xue@0 405 {
xue@0 406 double di=xrange/(XX*fc0);
xue@0 407 for (int x=0; x<XX; x++)
xue@0 408 {
xue@0 409 int i=st+x*di;
xue@0 410 int Y=floor(BdwpYYpYYdbenidbrange-YY20log10eidbrange*LogAF[i]+0.5);
xue@0 411 Canvas->LineTo(Bdw+x, Y);
xue@0 412 }
xue@0 413 }
xue@0 414 //draw source lines
xue@0 415 for (int i=0; i<SCount; i++)
xue@0 416 {
xue@0 417 double xi=f0*(i+1);
xue@0 418 if (xi<xst || xi>xen) continue;
xue@0 419 int X=floor(Bdw_xstXXixrange+XXixrange*xi+0.5);
xue@0 420 int Y=floor(BdwpYYpYYdbenidbrange-YYidbrange*Sx[i]+0.5);
xue@0 421 if (Colors) Canvas->Pen->Color=Colors[i];
xue@0 422 else Canvas->Pen->Color=RotateColors[i%10];
xue@0 423
xue@0 424 Canvas->MoveTo(X, Y); Canvas->LineTo(X, Bdw+YY);
xue@0 425
xue@0 426 if (SX) SX[i]=X, result++;
xue@0 427 }
xue@0 428 AnsiString S="0hz"; Canvas->Brush->Style=bsClear; Canvas->TextOut(Bdw, Bdw+YY, S);
xue@0 429 S="5.5khz"; int fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+(XX-fw)/2, Bdw+YY, S);
xue@0 430 S="11khz"; fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+XX-fw, Bdw+YY, S);
xue@0 431 S.sprintf("%gdB", dbst); fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+XX-fw, Bdw, S);
xue@0 432 S.sprintf("%gdB", (dbst+dben)/2); fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+XX-fw, Bdw+(YY-fh)/2, S);
xue@0 433 S.sprintf("%gdB", dben); fw=Canvas->TextWidth(S); Canvas->TextOut(Bdw+XX-fw, Bdw+YY-fh, S);
xue@0 434
xue@0 435 Canvas->Brush->Color=clBlack; Canvas->Brush->Style=bsClear; Canvas->Pen->Color=clWhite;
xue@0 436 Canvas->Rectangle(Bdw, Bdw, Bdw+XX, Bdw+YY);
xue@0 437 delete[] Sx;
xue@0 438 return result;
xue@0 439 } //*/
xue@0 440
xue@0 441 void DrawF0(Graphics::TBitmap* Bitmap, TCanvas* Canvas, TRect Rect, double* lp, int npfr, double* F0, double f_c, double f_ex, double sps, double F0Overall, int Fr, atom** Partials, double L, bool Captions=true, TColor F0Color=clLime, bool peakmark=false, TColor peakmarkcolor=clYellow, double* peaky=0, TColor peakycolor=clYellow, double* frs=0, double* fs=0)
xue@0 442 {
xue@0 443 Canvas->Brush->Color=cl3DDkShadow; Canvas->FillRect(Rect);
xue@0 444 int Width=Rect.Width(), Height=Rect.Height();
xue@0 445 Bitmap->Width=Width; Bitmap->Height=Height;
xue@0 446 TPen* P=Canvas->Pen;
xue@0 447 TFont* F=Canvas->Font;
xue@0 448
xue@0 449 int X, Y, Y1=0, Y2=Height, Y_;
xue@0 450 AnsiString S, as;
xue@0 451
xue@0 452 P->Color=clBlack; P->Style=psDot; F->Color=clBlack; F->Height=12; F->Name="Ariel";
xue@0 453 double f0max=-0.5, f0min=0.5; for (int fr=lp[0]; fr<lp[npfr-1]; fr++){if (f0max<F0[fr]) f0max=F0[fr]; if (f0min>F0[fr]) f0min=F0[fr];}
xue@0 454 Y1=Height*(0.5-(f0max-f_c)/f_ex); Canvas->MoveTo(0, Y1); Canvas->LineTo(Width, Y1);
xue@0 455 if (Captions){as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(f0max*sps)/C4)); S.sprintf("%.4ghz (%s)", f0max*sps, as.c_str()); Canvas->TextOut(1, Y1-Canvas->TextHeight(S)-1, S);}
xue@0 456 Y2=Height*(0.5-(f0min-f_c)/f_ex); Canvas->MoveTo(0, Y2); Canvas->LineTo(Width, Y2);
xue@0 457 if (Captions){as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(f0min*sps)/C4)); S.sprintf("%.4ghz (%s)", f0min*sps, as.c_str()); Canvas->TextOut(1, Y2+1, S);}
xue@0 458
xue@0 459 if (peakmark)
xue@0 460 {
xue@0 461 int Y0=0.5*(Y1+Y2), Y0ex=0.5*(Y1-Y2);
xue@0 462 if (peaky) {P->Color=peakmarkcolor; P->Style=psDot; Canvas->MoveTo(0, Y0); Canvas->LineTo(Width, Y0);}
xue@0 463
xue@0 464 for (int pfr=0; pfr<npfr; pfr++)
xue@0 465 {
xue@0 466 int fr=floor(lp[pfr]);
xue@0 467 X=Width*(Partials[1][fr].t*(fr+1-lp[pfr])+Partials[1][fr+1].t*(lp[pfr]-fr))/L;
xue@0 468 P->Color=peakmarkcolor; P->Style=psDot; Canvas->MoveTo(X, Y1); Canvas->LineTo(X, Y2);
xue@0 469 if (peaky)
xue@0 470 {
xue@0 471 Y=Y0ex*peaky[pfr];
xue@0 472 P->Color=peakycolor; P->Style=psSolid; Canvas->MoveTo(X, Y0); Canvas->LineTo(X, Y0+Y);
xue@0 473 }
xue@0 474 }
xue@0 475 }
xue@0 476
xue@0 477 if (Captions) {Y_=Height*(0.5-(F0Overall-f_c)/f_ex); P->Color=clWhite; Canvas->MoveTo(0, Y_); Canvas->LineTo(Width, Y_);}
xue@0 478
xue@0 479 P->Style=psSolid; P->Color=F0Color;
xue@0 480 for (int fr=0; fr<Fr; fr++)
xue@0 481 {
xue@0 482 if (fr>0) Canvas->MoveTo(X, Y);
xue@0 483 X=Width*Partials[1][fr].t/L, Y=Height*(0.5-(F0[fr]-f_c)/f_ex);
xue@0 484 if (fr>0) Canvas->LineTo(X, Y);
xue@0 485 }
xue@0 486
xue@0 487 if (frs)
xue@0 488 {
xue@0 489 P->Color=clRed;
xue@0 490 for (int pfr=0; pfr<npfr-1; pfr++)
xue@0 491 {
xue@0 492 int ifrs=frs[pfr]; double rfrs=frs[pfr]-ifrs;
xue@0 493 X=(Width*Partials[1][ifrs].t*(1-rfrs)+Width*Partials[1][ifrs+1].t*rfrs)/L, Y=Height*(0.5-(fs[pfr]-f_c)/f_ex);
xue@0 494 Canvas->MoveTo(X-4, Y); Canvas->LineTo(X+5, Y);
xue@0 495 Canvas->MoveTo(X, Y-4); Canvas->LineTo(X, Y+5);
xue@0 496 }
xue@0 497 }
xue@0 498
xue@0 499 if (Captions)
xue@0 500 {
xue@0 501 as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(F0Overall*sps)/C4)); S.sprintf("%.4ghz (%s)", F0Overall*sps, as.c_str());
xue@0 502 F->Color=clWhite; F->Style=F->Style<<fsBold; Canvas->TextOut(Width-Canvas->TextWidth(S), Y_+1, S); F->Style=F->Style>>fsBold;
xue@0 503 F->Color=clSilver; S="F0"; Canvas->TextOut(1, Height-Canvas->TextHeight(S), S);
xue@0 504 double f=(f_c+f_ex/2)*sps; as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(f)/C4)); S.sprintf("%.4ghz (%s)", f, as.c_str()); Canvas->TextOut(Width-Canvas->TextWidth(S), 0, S);
xue@0 505 f=(f_c-f_ex/2)*sps; as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(f)/C4)); S.sprintf("%.4ghz (%s)", f, as.c_str()); Canvas->TextOut(Width-Canvas->TextWidth(S), Height-Canvas->TextHeight(S), S);
xue@0 506 }
xue@0 507 }
xue@0 508
xue@0 509 void DrawF0C(Graphics::TBitmap* Bitmap, TCanvas* Canvas, TRect Rect, double* F0C, double& F0Cmax, double& F0Cmin, double f_c, double f_ex, double sps, double F0Overall, int Fr, atom** Partials, double L, bool clearbackground=true, int frcount=0, double* frs=0, double* fs=0, int* CX1=0, int* CX2=0, int* CY1=0, int* CY2=0)
xue@0 510 {
xue@0 511 //Draw the F0 carrier
xue@0 512 Canvas->Brush->Color=cl3DDkShadow; if (clearbackground) Canvas->FillRect(Rect);
xue@0 513 int Width=Rect.Width(), Height=Rect.Height();
xue@0 514 Bitmap->Width=Width; Bitmap->Height=Height;
xue@0 515 TPen* P=Canvas->Pen;
xue@0 516 TFont* F=Canvas->Font;
xue@0 517
xue@0 518 P->Color=clBlack;
xue@0 519 F0Cmax=f_c-f_ex, F0Cmin=f_c+f_ex;
xue@0 520 for (int fr=0; fr<Fr; fr++){if (F0Cmax<F0C[fr]) F0Cmax=F0C[fr]; if (F0Cmin>F0C[fr]) F0Cmin=F0C[fr];}
xue@0 521 P->Style=psDot;
xue@0 522 int X, Y=Height*(0.5-(F0Cmax-f_c)/f_ex);
xue@0 523 Canvas->MoveTo(0, Y); Canvas->LineTo(Width, Y);
xue@0 524 AnsiString as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(F0Cmax*sps)/C4)); AnsiString S; S.sprintf("%.4ghz (%s)", F0Cmax*sps, as.c_str());
xue@0 525 F->Color=clBlack; F->Height=12; F->Name="Ariel"; Canvas->TextOut(1, Y-Canvas->TextHeight(S)-1, S);
xue@0 526 Y=Height*(0.5-(F0Cmin-f_c)/f_ex);
xue@0 527 Canvas->MoveTo(0, Y); Canvas->LineTo(Width, Y);
xue@0 528 as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(F0Cmin*sps)/C4)); S.sprintf("%.4ghz (%s)", F0Cmin*sps, as.c_str());
xue@0 529 Canvas->TextOut(1, Y+1, S);
xue@0 530 P->Color=clWhite;
xue@0 531 as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(F0Overall*sps)/C4)); S.sprintf("%.4ghz (%s)", F0Overall*sps, as.c_str());
xue@0 532 int Y_=Height*(0.5-(F0Overall-f_c)/f_ex);
xue@0 533 Canvas->MoveTo(0, Y_); Canvas->LineTo(Width, Y_);
xue@0 534 F->Color=clWhite; F->Style=F->Style<<fsBold;
xue@0 535 if (Y_+1+Canvas->TextHeight(S)<Y) Canvas->TextOut(Width-Canvas->TextWidth(S), Y_+1, S);
xue@0 536 else Canvas->TextOut(Width-Canvas->TextWidth(S), Y+1, S);
xue@0 537 F->Style=F->Style>>fsBold;
xue@0 538
xue@0 539 P->Style=psSolid; P->Color=clLime;
xue@0 540 for (int fr=0; fr<Fr; fr++)
xue@0 541 {
xue@0 542 if (fr>0) Canvas->MoveTo(X, Y);
xue@0 543 X=Width*Partials[1][fr].t/L, Y=Height*(0.5-(F0C[fr]-f_c)/f_ex);
xue@0 544 if (fr>0) Canvas->LineTo(X, Y);
xue@0 545 }
xue@0 546
xue@0 547 if (frcount)
xue@0 548 {
xue@0 549 P->Color=clRed;
xue@0 550 for (int p=0; p<frcount; p++)
xue@0 551 {
xue@0 552 int ifrs=frs[p]; double rfrs=frs[p]-ifrs;
xue@0 553 X=(Width*Partials[1][ifrs].t*(1-rfrs)+Width*Partials[1][ifrs+1].t*rfrs)/L, Y=Height*(0.5-(fs[p]-f_c)/f_ex);
xue@0 554 Canvas->MoveTo(X-4, Y); Canvas->LineTo(X+5, Y);
xue@0 555 Canvas->MoveTo(X, Y-4); Canvas->LineTo(X, Y+5);
xue@0 556 if (CX1) CX1[p]=X-4;
xue@0 557 if (CX2) CX2[p]=X+4;
xue@0 558 if (CY1) CY1[p]=Y-4;
xue@0 559 if (CY2) CY2[p]=Y+4;
xue@0 560 }
xue@0 561 }
xue@0 562
xue@0 563 double f=(f_c+f_ex/2)*sps;
xue@0 564 F->Color=clSilver;
xue@0 565 as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(f)/C4)); S.sprintf("%.4ghz (%s)", f, as.c_str());
xue@0 566 Canvas->TextOut(Width-Canvas->TextWidth(S), 0, S);
xue@0 567 f=(f_c-f_ex/2)*sps; as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(f)/C4)); S.sprintf("%.4ghz (%s)", f, as.c_str());
xue@0 568 Canvas->TextOut(Width-Canvas->TextWidth(S), Height-Canvas->TextHeight(S), S);
xue@0 569 F->Color=clSilver; S="F0 carrier";
xue@0 570 Canvas->TextOut(1, Height-Canvas->TextHeight(S), S);
xue@0 571 }
xue@0 572
xue@0 573 void DrawF0D(Graphics::TBitmap* Bitmap, TCanvas* Canvas, TRect Rect, double* lp, int npfr, double* F0D, double& F0Dmax, double& F0Dmin, double f_c, double f_ex, double sps, double F0Overall, int Fr, atom** Partials, double L)
xue@0 574 {
xue@0 575 int Width=Rect.Width(), Height=Rect.Height();
xue@0 576 Bitmap->Width=Width; Bitmap->Height=Height;
xue@0 577
xue@0 578 Canvas->Brush->Style=bsSolid; Canvas->Brush->Color=cl3DDkShadow; Canvas->FillRect(Rect);
xue@0 579
xue@0 580 //this part draws the modulator itself
xue@0 581 F0Dmax=-f_ex, F0Dmin=f_ex;
xue@0 582 for (int fr=lp[0]; fr<lp[npfr-1]; fr++){if (F0Dmax<F0D[fr]) F0Dmax=F0D[fr]; if (F0Dmin>F0D[fr]) F0Dmin=F0D[fr];}
xue@0 583 TPen* P=Canvas->Pen; P->Color=clBlack; P->Style=psDot;
xue@0 584 int X, Y=Height*(0.5-F0Dmax/f_ex); Canvas->MoveTo(0, Y); Canvas->LineTo(Width, Y);
xue@0 585 AnsiString S; S.sprintf("%.4ghz (%.3g%%)", F0Dmax*sps, F0Dmax/F0Overall*100);
xue@0 586 TFont* F=Canvas->Font; F->Color=clBlack; F->Height=12; F->Name="Ariel";
xue@0 587 Canvas->TextOut(1, Y-Canvas->TextHeight(S)-1, S);
xue@0 588 Y=Height*(0.5-F0Dmin/f_ex);
xue@0 589 Canvas->MoveTo(0, Y); Canvas->LineTo(Width, Y);
xue@0 590 S.sprintf("%.4ghz (%.3g%%)", F0Dmin*sps, F0Dmin/F0Overall*100); Canvas->TextOut(1, Y+1, S);
xue@0 591
xue@0 592 P->Style=psSolid; P->Color=clSilver; Canvas->MoveTo(0, Height/2); Canvas->LineTo(Width, Height/2);
xue@0 593 Canvas->Pen->Color=clLime;
xue@0 594 for (int fr=0; fr<Fr; fr++)
xue@0 595 {
xue@0 596 if (fr>0) Canvas->MoveTo(X, Y);
xue@0 597 X=Width*Partials[1][fr].t/L, Y=Height*(0.5-F0D[fr]/f_ex);
xue@0 598 if (fr>0) Canvas->LineTo(X, Y);
xue@0 599 }
xue@0 600 P->Color=clBlue;
xue@0 601 for (int fr=0; fr<Fr; fr++)
xue@0 602 {
xue@0 603 X=Width*Partials[1][fr].t/L, Y=Height*(0.5-F0D[fr]/f_ex);
xue@0 604 Canvas->MoveTo(X-1, Y); Canvas->LineTo(X+2, Y); Canvas->MoveTo(X, Y-1); Canvas->LineTo(X, Y+2);
xue@0 605 }
xue@0 606 F->Color=clSilver; F->Height=12; F->Name="Ariel";
xue@0 607 S.sprintf("%.4ghz (%.3g%%)", f_ex*sps/2, f_ex/2/F0Overall*100); Canvas->TextOut(Width-Canvas->TextWidth(S), 0, S);
xue@0 608 S.sprintf("%.4ghz (%.3g%%)", -f_ex*sps/2, -f_ex/2/F0Overall*100); Canvas->TextOut(Width-Canvas->TextWidth(S), Height-Canvas->TextHeight(S), S);
xue@0 609
xue@0 610 F->Color=clSilver; S="F0 modulator"; Canvas->TextOut(1, Height-Canvas->TextHeight(S), S);
xue@0 611 }
xue@0 612
xue@0 613 //y=ax+b
xue@0 614 void linefit(int n, double* x, double* y, double* indi, double& a, double& b)
xue@0 615 {
xue@0 616 double sx=0, sy=0, sxy=0, sxx=0, m=0;
xue@0 617 for (int i=0; i<n; i++) if (indi[i]>0) sx+=x[i], sy+=y[i], sxx+=x[i]*x[i], sxy+=x[i]*y[i], m++;
xue@0 618 if (m<=0) {a=-1; b=-1; return;}
xue@0 619 double id=1.0/(m*sxx-sx*sx);
xue@0 620 a=(m*sxy-sx*sy)*id;
xue@0 621 b=(sxx*sy-sx*sxy)*id;
xue@0 622 }
xue@0 623
xue@0 624 void TVibratoDemoForm::UpdateDisplay(bool f0, bool f0c, bool f0d, bool sf)
xue@0 625 {
xue@0 626 int Fr=HS->Fr;
xue@0 627 atom** Partials=HS->Partials;
xue@0 628 //find the highest point of the 2nd partial
xue@0 629 double f2min=1, f2max=0, fst=0, fen=0.25;
xue@0 630 for (int fr=0; fr<Fr; fr++)
xue@0 631 {
xue@0 632 if (f2max<Partials[1][fr].f) f2max=Partials[1][fr].f;
xue@0 633 if (f2min>Partials[1][fr].f) f2min=Partials[1][fr].f;
xue@0 634 }
xue@0 635 f_c=(f2min+f2max)/4; f_ex=f2max-f2min;
xue@0 636
xue@0 637 if (f0) DrawF0(Image0->Picture->Bitmap, Image0->Canvas, Image0->ClientRect, V.lp, V.P, V.F0, f_c, f_ex, WaveView1->SamplesPerSec, V.F0Overall, Fr, Partials, WaveView2->Length, true, clLime, PeakMarksCheck->Checked, clYellow, 0, TColor(0), 0/*cyclefrs*/, cyclefs);
xue@0 638 if (f0c)
xue@0 639 {
xue@0 640 memset(CX1, 0xFF, sizeof(int)*128); memset(CX2, 0xFF, sizeof(int)*128); memset(CY1, 0xFF, sizeof(int)*128); memset(CY1, 0xFF, sizeof(int)*128);
xue@0 641 DrawF0C(Image1->Picture->Bitmap, Image1->Canvas, Image1->ClientRect, V.F0C, V.F0Cmax, V.F0Cmin, f_c, f_ex, WaveView1->SamplesPerSec, V.F0Overall, Fr, Partials, WaveView2->Length, true, PeakMarksCheck->Checked?cyclefrcount:0, cyclefrs, cyclefs, CX1, CX2, CY1, CY2);
xue@0 642 }
xue@0 643 if (f0d)
xue@0 644 {
xue@0 645 //Draw the F0 modulator
xue@0 646 DrawModulator();
xue@0 647 //
xue@0 648 double sps=WaveView1->SamplesPerSec;
xue@0 649 DurationEdit->Text=AnsiString().sprintf("%.4gs", WaveView2->Length/sps);
xue@0 650 RegEdit->Text=AnsiString().sprintf("%.4g", V.regularity);
xue@0 651 RateEdit->Text=AnsiString().sprintf("%.4ghz", V.rate);
xue@0 652 if (ResidueCheck->Checked) {FXX[0]=sqrt(1-V.FRes[0]); for (int i=1; i<V.K; i++) FXX[i]=sqrt(V.FRes[i-1]-V.FRes[i]);}
xue@0 653 else {FXX[0]=fabs(V.FXR[0]); for (int i=1; i<V.K; i++) FXX[i]=2*sqrt(V.FXR[2*i]*V.FXR[2*i]+V.FXR[2*i-1]*V.FXR[2*i-1]);}
xue@0 654 DrawBarMap(MImage1->Picture->Bitmap, MImage1->ClientRect, V.K, FXX, ResidueCheck->Checked, KX1, KX2);
xue@0 655 }
xue@0 656
xue@0 657 if (sf)
xue@0 658 {
xue@0 659 if (SFCheck->Checked)
xue@0 660 DrawSFr(AImage1->Picture->Bitmap, AImage1->ClientRect, fst, fen, updb, downdb, V.M, Fr, V.afres, Partials, V.LogAF, V.LogAS);
xue@0 661 else
xue@0 662 DrawAF(AImage1->Picture->Bitmap, AImage1->ClientRect, fst, fen, updb, downdb, V.M, Fr, Partials, V.A0C, MACheck->Checked, false);
xue@0 663 SXc=DrawSF(AImage3->Picture->Bitmap, AImage3->ClientRect, fst, fen, updb, downdb, V.F0Overall, V.M, V.LogAS, 1.0/V.afres, V.afres/2, V.LogAF, SX);
xue@0 664 }
xue@0 665
xue@0 666 ForceUpdate=false;
xue@0 667 }
xue@0 668
xue@0 669 void __fastcall TVibratoDemoForm::WaveView1OpMode(TObject* Sender, TShiftState Shift, int& OpMode)
xue@0 670 {
xue@0 671 if (Shift.Contains(ssShift)) OpMode=0; //drag mode
xue@0 672 else OpMode=1; //select mode
xue@0 673 }
xue@0 674
xue@0 675 int __fastcall TVibratoDemoForm::WaveView1CustomInfo(TObject* Sender)
xue@0 676 {
xue@0 677 TWaveView* WV=(TWaveView*)Sender;
xue@0 678 TStringList* List=new TStringList;
xue@0 679 double fs=WV->StartPos*1.0/WV->SamplesPerSec, fe=WV->EndPos*1.0/WV->SamplesPerSec;
xue@0 680 List->Add(AnsiString().sprintf(" Time (%.4gs): from %.4gs to %.4gs. ", fe-fs, fs, fe));
xue@0 681 List->Add(AnsiString().sprintf(" Frequency: from %.1fhz to %.1fhz. ", WV->StartDigiFreq*WV->SamplesPerSec, WV->EndDigiFreq*WV->SamplesPerSec));
xue@0 682 return int(List);
xue@0 683 }
xue@0 684
xue@0 685 void __fastcall TVibratoDemoForm::Image1MouseMove(TObject *Sender,
xue@0 686 TShiftState Shift, int X, int Y)
xue@0 687 {
xue@0 688 if (!HS) return;
xue@0 689 TImage* Image=(TImage*)Sender;
xue@0 690 Image->Parent->SetFocus();
xue@0 691
xue@0 692 double t, sps=WaveView1->SamplesPerSec, f; AnsiString S, as; TFont* F=Image->Canvas->Font;
xue@0 693
xue@0 694 if (Sender==Image1)
xue@0 695 {
xue@0 696 if (Shift.Contains(ssLeft))
xue@0 697 {
xue@0 698 if (CurrentC<0 || CurrentC>=cyclefrcount) return;
xue@0 699 double df=-(Y-StartDrag)*f_ex/Image->Height;
xue@0 700 cyclefs[CurrentC]+=df;
xue@0 701 StartDrag=Y;
xue@0 702 Smooth_Interpolate(V.F0C, V.L, cyclefrcount+1, cyclefs, cyclefrs);
xue@0 703 SynthesizeV(HS, &V, WaveView1->SamplesPerSec);
xue@0 704 UpdateDisplay(true, true, true, false);
xue@0 705
xue@0 706 t=HS->Partials[0][0].t+V.h*cyclefrs[CurrentC];
xue@0 707 f=cyclefs[CurrentC]*sps;
xue@0 708 as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(f)/C4));
xue@0 709 S.sprintf("%.3gs, %.4ghz (%s) ", t/sps, f, as.c_str());
xue@0 710 F->Color=clRed;
xue@0 711 Image->Canvas->TextOut(1, Image->Canvas->TextHeight("0"), S);
xue@0 712
xue@0 713 }
xue@0 714 else
xue@0 715 {
xue@0 716 CurrentC=-1;
xue@0 717 for (int i=0; i<cyclefrcount; i++)
xue@0 718 if (X>=CX1[i] && X<=CX2[i] && Y>=CY1[i] && Y<=CY2[i]) {CurrentC=i; break;}
xue@0 719 }
xue@0 720 if (CurrentC>=0 && CurrentC<cyclefrcount)
xue@0 721 {
xue@0 722 t=HS->Partials[0][0].t+V.h*cyclefrs[CurrentC];
xue@0 723 f=cyclefs[CurrentC]*sps;
xue@0 724 as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(f)/C4));
xue@0 725 S.sprintf("%.3gs, %.4ghz (%s) ", t/sps, f, as.c_str());
xue@0 726 F->Color=clRed;
xue@0 727 Image->Canvas->TextOut(1, Image->Canvas->TextHeight("0"), S);
xue@0 728 }
xue@0 729 else
xue@0 730 {
xue@0 731 S.sprintf(" ", t/sps, f, as.c_str());
xue@0 732 Image->Canvas->TextOut(1, Image->Canvas->TextHeight("0"), S);
xue@0 733 }
xue@0 734 }
xue@0 735
xue@0 736 t=WaveView2->Length*1.0*(X+0.5)/Image->Width;
xue@0 737 f=(f_c-(Y-0.5*Image->Height)*f_ex/Image->Height)*sps;
xue@0 738 as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(f)/C4));
xue@0 739 S.sprintf("%.3gs, %.4ghz (%s) ", t/sps, f, as.c_str());
xue@0 740 F->Color=clAqua; F->Height=12; F->Name="Ariel";
xue@0 741 Image->Canvas->TextOut(1, 0, S);
xue@0 742 }
xue@0 743 //---------------------------------------------------------------------------
xue@0 744
xue@0 745 void __fastcall TVibratoDemoForm::Image2MouseMove(TObject *Sender,
xue@0 746 TShiftState Shift, int X, int Y)
xue@0 747 {
xue@0 748 if (!HS) return;
xue@0 749 if (Shift.Contains(ssLeft)) return;
xue@0 750 atom** Partials=HS->Partials;
xue@0 751 Image2->Parent->SetFocus();
xue@0 752 double t=WaveView2->Length*1.0*(X+0.5)/Image2->Width, sps=WaveView1->SamplesPerSec;
xue@0 753 double f=-(Y-0.5*Image2->Height)*f_ex/Image2->Height;
xue@0 754
xue@0 755 if (true || Shift.Contains(ssShift))
xue@0 756 {
xue@0 757 int modcycle=0;
xue@0 758 if (t<Partials[0][0].t+V.lp[0]*V.h || t>Partials[0][0].t+V.lp[V.P-1]*V.h) modcycle=-1;
xue@0 759 else while (t>Partials[0][0].t+V.lp[modcycle]*V.h) modcycle++;
xue@0 760 if (CurrentModCycle!=modcycle)
xue@0 761 {
xue@0 762 CurrentModCycle=modcycle;
xue@0 763
xue@0 764 if (CurrentModCycle==-1)
xue@0 765 {
xue@0 766 if (PageControl1->ActivePage==ModCycleSheet)
xue@0 767 {
xue@0 768 PageControl1->ActivePage=ModOverSheet;
xue@0 769 ResidueCheck->Parent=ModOverSheet;
xue@0 770 }
xue@0 771 else if (PageControl1->ActivePage==AmpCycleSheet)
xue@0 772 {
xue@0 773 PageControl1->ActivePage=AmpOverSheet;
xue@0 774 SFCheck->Parent=AmpOverSheet;
xue@0 775 MACheck->Parent=AmpOverSheet;
xue@0 776 }
xue@0 777 }
xue@0 778 else
xue@0 779 {
xue@0 780 if (PageControl1->ActivePage==ModOverSheet)
xue@0 781 {
xue@0 782 PageControl1->ActivePage=ModCycleSheet;
xue@0 783 ResidueCheck->Parent=ModCycleSheet;
xue@0 784 }
xue@0 785 else if (PageControl1->ActivePage==AmpOverSheet)
xue@0 786 {
xue@0 787 PageControl1->ActivePage=AmpCycleSheet;
xue@0 788 SFCheck->Parent=AmpCycleSheet;
xue@0 789 MACheck->Parent=AmpCycleSheet;
xue@0 790 }
xue@0 791 ModCycleSheet->Caption="Modulator Cycle "+AnsiString(CurrentModCycle);
xue@0 792 AmpCycleSheet->Caption="Amplitudes Cycle "+AnsiString(CurrentModCycle);
xue@0 793 }
xue@0 794 DrawModulator();
xue@0 795 }
xue@0 796 }
xue@0 797
xue@0 798 AnsiString S;
xue@0 799 S.sprintf("%.3gs, %.4ghz (%.3g%%) ", t/sps, f*sps, f/V.F0Overall*100);
xue@0 800 TFont* F=Image2->Canvas->Font; F->Color=clAqua; F->Height=12; F->Name="Ariel";
xue@0 801 Image2->Canvas->TextOut(1, 0, S);
xue@0 802 }
xue@0 803 //---------------------------------------------------------------------------
xue@0 804 void TVibratoDemoForm::DrawModulator()
xue@0 805 {
xue@0 806 double fst=0, fen=0.25;
xue@0 807
xue@0 808 Image2->Picture->Bitmap->Width=Image2->Width;
xue@0 809 Image2->Picture->Bitmap->Height=Image2->Height;
xue@0 810
xue@0 811 int X, Y, L=WaveView2->Length, Fr=HS->Fr;
xue@0 812 double sps=WaveView2->SamplesPerSec;
xue@0 813 atom** Partials=HS->Partials;
xue@0 814 TCanvas* I2Canvas=Image2->Canvas; I2Canvas->Brush->Style=bsSolid; I2Canvas->Brush->Color=cl3DDkShadow; I2Canvas->FillRect(Image2->ClientRect);
xue@0 815 if (CurrentModCycle>=1 && CurrentModCycle<V.P)
xue@0 816 {
xue@0 817 CurrentModCycleStart=Partials[0][0].t+V.lp[CurrentModCycle-1]*WaveView1->SpecOffst;
xue@0 818 CurrentModCycleEnd=Partials[0][0].t+V.lp[CurrentModCycle]*WaveView1->SpecOffst;
xue@0 819
xue@0 820 int X1=Image2->Width*CurrentModCycleStart/L;
xue@0 821 int X2=Image2->Width*CurrentModCycleEnd/L;
xue@0 822 I2Canvas->Brush->Color=clDkGray; I2Canvas->FillRect(TRect(X1, 0, X2, Image2->Height));
xue@0 823 I2Canvas->Brush->Color=cl3DDkShadow;
xue@0 824
xue@0 825 //this part update the tab sheet
xue@0 826 int frst=V.peakfr[CurrentModCycle-1], fren=V.peakfr[CurrentModCycle];
xue@0 827 if (PageControl1->ActivePage==ModCycleSheet)
xue@0 828 {
xue@0 829 CycleDurationEdit->Text=AnsiString().sprintf("%.4gs (%.4gs~%.4gs)", (CurrentModCycleEnd-CurrentModCycleStart)/sps, CurrentModCycleStart/sps, CurrentModCycleEnd/sps);
xue@0 830 CycleRateEdit->Text=AnsiString().sprintf("%.4ghz", sps/(CurrentModCycleEnd-CurrentModCycleStart));
xue@0 831
xue@0 832 double af0c=(V.F0C[frst]+V.F0C[fren])*0.5, f0dmax=V.F0D[frst], f0dmin=V.F0D[frst];
xue@0 833 double np=1, nn=0;
xue@0 834 double pdp=(V.F0D[frst]*V.F0D[frst]+V.F0D[fren]*V.F0D[fren])*0.5, pdn=0;
xue@0 835 for (int fr=frst+1; fr<fren; fr++)
xue@0 836 {
xue@0 837 af0c+=V.F0C[fr];
xue@0 838 if (V.F0D[fr]>f0dmax) f0dmax=V.F0D[fr];
xue@0 839 if (V.F0D[fr]<f0dmin) f0dmin=V.F0D[fr];
xue@0 840 if (V.F0D[fr]>0) pdp+=V.F0D[fr]*V.F0D[fr], np+=1;
xue@0 841 else if (V.F0D[fr]<0) pdn+=V.F0D[fr]*V.F0D[fr], nn+=1;
xue@0 842 }
xue@0 843 af0c/=(fren-frst);
xue@0 844 pdp=(np>0)?sqrt(pdp/np):0, pdn=(nn>0)?sqrt(pdn/nn):0;
xue@0 845 AnsiString S=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(af0c*sps)/C4));
xue@0 846 CyclePitchEdit->Text=AnsiString().sprintf("%.4ghz (%s)", af0c*sps, S.c_str());
xue@0 847 CycleExtentEdit->Text=AnsiString().sprintf("%.3g%%~%.3g%%", f0dmin/af0c*100, f0dmax/af0c*100);
xue@0 848 CycleAvgPDEdit->Text=AnsiString().sprintf("-%.3g%%~%.3g%%", pdn/af0c*100, pdp/af0c*100);
xue@0 849
xue@0 850
xue@0 851 if (ResidueCheck->Checked) {FXX[0]=sqrt(1-V.fres[CurrentModCycle][0]); for (int i=1; i<V.Kp[CurrentModCycle]; i++) FXX[i]=sqrt(V.fres[CurrentModCycle][i-1]-V.fres[CurrentModCycle][i]); for (int i=V.Kp[CurrentModCycle]; i<V.K; i++) FXX[i]=0;}
xue@0 852 else {FXX[0]=fabs(V.fxr[CurrentModCycle][0]); for (int i=1; i<V.Kp[CurrentModCycle]; i++) FXX[i]=2*sqrt(V.fxr[CurrentModCycle][2*i]*V.fxr[CurrentModCycle][2*i]+V.fxr[CurrentModCycle][2*i-1]*V.fxr[CurrentModCycle][2*i-1]); for (int i=V.Kp[CurrentModCycle]; i<V.K; i++) FXX[i]=0;}
xue@0 853 DrawBarMap(MImage2->Picture->Bitmap, MImage2->ClientRect, V.K, FXX, ResidueCheck->Checked, KX1, KX2);
xue@0 854 }
xue@0 855 else if (PageControl1->ActivePage==AmpCycleSheet)
xue@0 856 {
xue@0 857 if (SFCheck->Checked)
xue@0 858 DrawSFr(AImage2->Picture->Bitmap, AImage2->ClientRect, fst, fen, updb, downdb, V.M, Fr, V.afres, Partials, V.LogAF, V.LogASp[CurrentModCycle]);
xue@0 859 else
xue@0 860 DrawAF(AImage2->Picture->Bitmap, AImage2->ClientRect, fst, fen, updb, downdb, V.M, V.peakfr[CurrentModCycle], Partials, V.A0C, MACheck->Checked, false, V.peakfr[CurrentModCycle-1]);
xue@0 861 double cf0=0; for (int i=frst; i<fren; i++) cf0+=V.F0C[i]; cf0/=(fren-frst);
xue@0 862 SXcyclec=DrawSF(AImage4->Picture->Bitmap, AImage4->ClientRect, 0, 0.25, updb, downdb, cf0, V.M, V.LogASp[CurrentModCycle], 1.0/V.afres, V.afres/2, V.LogAF, SXcycle);
xue@0 863 }
xue@0 864 }
xue@0 865 else //CurrentCycle==-1
xue@0 866 {
xue@0 867 }
xue@0 868
xue@0 869 //this part draws the modulator itself
xue@0 870 V.F0Dmax=-f_ex, V.F0Dmin=f_ex;
xue@0 871 for (int fr=V.peakfr[0]; fr<=V.peakfr[V.P-1]; fr++){if (V.F0Dmax<V.F0D[fr]) V.F0Dmax=V.F0D[fr]; if (V.F0Dmin>V.F0D[fr]) V.F0Dmin=V.F0D[fr];}
xue@0 872 I2Canvas->Pen->Color=clBlack; I2Canvas->Pen->Style=psDot;
xue@0 873 Y=Image2->Height*(0.5-V.F0Dmax/f_ex);
xue@0 874 I2Canvas->MoveTo(0, Y); I2Canvas->LineTo(Image2->Width, Y);
xue@0 875 AnsiString S; S.sprintf("%.4ghz (%.3g%%)", V.F0Dmax*sps, V.F0Dmax/V.F0Overall*100);
xue@0 876 TFont* F=I2Canvas->Font; F->Color=clBlack; F->Height=12; F->Name="Ariel";
xue@0 877 I2Canvas->TextOut(1, Y-I2Canvas->TextHeight(S)-1, S);
xue@0 878 Y=Image2->Height*(0.5-V.F0Dmin/f_ex);
xue@0 879 I2Canvas->MoveTo(0, Y); I2Canvas->LineTo(Image2->Width, Y);
xue@0 880 S.sprintf("%.4ghz (%.3g%%)", V.F0Dmin*sps, V.F0Dmin/V.F0Overall*100);
xue@0 881 I2Canvas->TextOut(1, Y+1, S);
xue@0 882 I2Canvas->Pen->Style=psSolid;
xue@0 883
xue@0 884 I2Canvas->Pen->Color=clSilver;
xue@0 885 I2Canvas->MoveTo(0, Image2->Height/2); I2Canvas->LineTo(Image2->Width, Image2->Height/2);
xue@0 886 I2Canvas->Pen->Color=clBlue;
xue@0 887 for (int fr=0; fr<Fr; fr++)
xue@0 888 {
xue@0 889 if (fr>0) I2Canvas->MoveTo(X, Y);
xue@0 890 X=Image2->Width*Partials[1][fr].t/L, Y=Image2->Height*(0.5-V.F0D[fr]/f_ex);
xue@0 891 if (fr>0) I2Canvas->LineTo(X, Y);
xue@0 892 }
xue@0 893 I2Canvas->Pen->Color=clLime;
xue@0 894 for (int fr=0; fr<Fr; fr++)
xue@0 895 {
xue@0 896 X=Image2->Width*Partials[1][fr].t/L, Y=Image2->Height*(0.5-V.F0D[fr]/f_ex);
xue@0 897 I2Canvas->MoveTo(X-1, Y); I2Canvas->LineTo(X+2, Y); I2Canvas->MoveTo(X, Y-1); I2Canvas->LineTo(X, Y+2);
xue@0 898 }
xue@0 899 F->Color=clSilver; F->Height=12; F->Name="Ariel";
xue@0 900 S.sprintf("%.4ghz (%.3g%%)", f_ex*sps/2, f_ex/2/V.F0Overall*100);
xue@0 901 I2Canvas->TextOut(Image2->Width-I2Canvas->TextWidth(S), 0, S);
xue@0 902 S.sprintf("%.4ghz (%.3g%%)", -f_ex*sps/2, -f_ex/2/V.F0Overall*100);
xue@0 903 I2Canvas->TextOut(Image2->Width-I2Canvas->TextWidth(S), Image2->Height-I2Canvas->TextHeight(S), S);
xue@0 904
xue@0 905 F->Color=clSilver; S="F0 modulator";
xue@0 906 I2Canvas->TextOut(1, Image2->Height-I2Canvas->TextHeight(S), S);
xue@0 907
xue@0 908 }
xue@0 909
xue@0 910
xue@0 911 void __fastcall TVibratoDemoForm::SFCheckClick(TObject *Sender)
xue@0 912 {
xue@0 913 if (Sender==SFCheck)
xue@0 914 {
xue@0 915 MACheck->Visible=!SFCheck->Checked;
xue@0 916 }
xue@0 917 UpdateDisplay();
xue@0 918 }
xue@0 919 //---------------------------------------------------------------------------
xue@0 920
xue@0 921
xue@0 922 void __fastcall TVibratoDemoForm::RegButtonClick(TObject *Sender)
xue@0 923 {
xue@0 924 RegularizeV(*HS, V, WaveView1->SamplesPerSec, WaveView1->SpecOffst);
xue@0 925 AnalyzeV(*HS, V, peaky, cyclefrs, cyclefs, WaveView1->SamplesPerSec, WaveView1->SpecOffst, &cyclefrcount);
xue@0 926 SaveV();
xue@0 927 Synthesize();
xue@0 928 UpdateDisplay();
xue@0 929 }
xue@0 930 //---------------------------------------------------------------------------
xue@0 931
xue@0 932
xue@0 933 void __fastcall TVibratoDemoForm::ExternalInput()
xue@0 934 {
xue@0 935 AnsiString FileName=ExtractFilePath(Application->ExeName)+"tvoin";
xue@0 936 FILE* file;
xue@0 937 if ((file=fopen(FileName.c_str(), "rb"))!=NULL)
xue@0 938 {
xue@0 939 V.LoadFromFileHandle(file);
xue@0 940 fclose(file);
xue@0 941 DeleteFile(FileName);
xue@0 942 SynthesizeV(HS, &V, WaveView1->SamplesPerSec);
xue@0 943 SaveV();
xue@0 944 Synthesize();
xue@0 945 UpdateDisplay();
xue@0 946 }
xue@0 947 }
xue@0 948
xue@0 949 //---------------------------------------------------------------------------
xue@0 950 void __fastcall TVibratoDemoForm::SaveV()
xue@0 951 {
xue@0 952 FILE* file;
xue@0 953 if ((file=fopen((ExtractFilePath(Application->ExeName)+"tvoout").c_str(), "wb"))!=NULL)
xue@0 954 {
xue@0 955 V.SaveToFileHandle(file);
xue@0 956 fclose(file);
xue@0 957 }
xue@0 958 }
xue@0 959
xue@0 960 //---------------------------------------------------------------------------
xue@0 961 void __fastcall TVibratoDemoForm::MouseWheelHandler(TMessage& Msg)
xue@0 962 {
xue@0 963 TWMMouseWheel* WMsg=(TWMMouseWheel*)&Msg;
xue@0 964
xue@0 965 bool Handled=false;
xue@0 966 TMouseWheelEvent Event=NULL;
xue@0 967 TControl* Sender;
xue@0 968 TShiftState Shift; memcpy(&Shift, &WMsg->Keys, 1);
xue@0 969
xue@0 970 if (ActiveControl==Image1->Parent) Event=Image1MouseWheel, Sender=Image1;
xue@0 971 else if (ActiveControl==Image2->Parent) Event=Image2MouseWheel, Sender=Image2;
xue@0 972 else if (ActiveControl==AImage3->Parent) Event=AImage3MouseWheel, Sender=AImage3;
xue@0 973 else if (ActiveControl==AImage1->Parent) Event=AImage3MouseWheel, Sender=AImage1;
xue@0 974 else if (ActiveControl==AImage4->Parent) Event=AImage4MouseWheel, Sender=AImage4;
xue@0 975 else if (ActiveControl==AImage2->Parent) Event=AImage4MouseWheel, Sender=AImage2;
xue@0 976 else if (ActiveControl==MImage1->Parent) Event=MImage1MouseWheel, Sender=MImage1;
xue@0 977 else if (ActiveControl==MImage2->Parent) Event=MImage1MouseWheel, Sender=MImage2;
xue@0 978 else if (ActiveControl==RateEdit || ActiveControl==CycleRateEdit) Event=RateEditMouseWheel, Sender=ActiveControl;
xue@0 979 else if (ActiveControl==DurationEdit || ActiveControl==CycleDurationEdit) Event=DurationEditMouseWheel, Sender=ActiveControl;
xue@0 980 else if (ActiveControl==CyclePitchEdit) Event=PitchEditMouseWheel, Sender=ActiveControl;
xue@0 981
xue@0 982 if (Event) Event(Sender, Shift, WMsg->WheelDelta, Sender->ScreenToClient(TPoint(WMsg->Pos.x, WMsg->Pos.y)), Handled);
xue@0 983 WMsg->Result=Handled;
xue@0 984
xue@0 985 if (!Handled) TCustomForm::MouseWheelHandler(Msg);
xue@0 986 }
xue@0 987
xue@0 988 //---------------------------------------------------------------------------
xue@0 989 void __fastcall TVibratoDemoForm::Image1MouseWheel(TObject* Sender, TShiftState Shift, int WheelDelta, const TPoint &MousePos, bool &Handled)
xue@0 990 {
xue@0 991 double cent;
xue@0 992 if (Shift.Contains(ssShift)) cent=1;
xue@0 993 else if (Shift.Contains(ssCtrl)) cent=100;
xue@0 994 else cent=10;
xue@0 995
xue@0 996 if (WheelDelta<0) cent=-cent;
xue@0 997 double rate=pow(2, cent/1200);
xue@0 998
xue@0 999 for (int l=0; l<V.L; l++) V.F0C[l]*=rate; V.F0Overall*=rate;
xue@0 1000 for (int fr=0; fr<cyclefrcount; fr++) cyclefs[fr]*=rate;
xue@0 1001
xue@0 1002 SynthesizeV(HS, &V, WaveView1->SamplesPerSec);
xue@0 1003 SaveV();
xue@0 1004 S_U();
xue@0 1005 Handled=true;
xue@0 1006 }
xue@0 1007
xue@0 1008 void __fastcall TVibratoDemoForm::Image2MouseWheel(TObject* Sender, TShiftState Shift, int WheelDelta, const TPoint &MousePos, bool &Handled)
xue@0 1009 {
xue@0 1010 double rate;
xue@0 1011 if (Shift.Contains(ssShift)) rate=1.01;
xue@0 1012 else if (Shift.Contains(ssCtrl)) rate=1.282432;
xue@0 1013 else rate=1.05101;
xue@0 1014 if (WheelDelta<0) rate=1.0/rate;
xue@0 1015 if (CurrentModCycle>0) V.Dp[CurrentModCycle]=V.Dp[CurrentModCycle]*rate;
xue@0 1016 else for (int p=1; p<V.P; p++) V.Dp[p]=V.Dp[p]*rate;
xue@0 1017
xue@0 1018 SynthesizeV(HS, &V, WaveView1->SamplesPerSec);
xue@0 1019 SaveV();
xue@0 1020 S_U();
xue@0 1021 Handled=true;
xue@0 1022 }
xue@0 1023
xue@0 1024 void __fastcall TVibratoDemoForm::AImage3MouseWheel(TObject* Sender, TShiftState Shift, int WheelDelta, const TPoint &MousePos, bool &Handled)
xue@0 1025 {
xue@0 1026 double ddb;
xue@0 1027 if (Shift.Contains(ssShift)) ddb=0.2;
xue@0 1028 else if (Shift.Contains(ssCtrl)) ddb=5;
xue@0 1029 else ddb=1;
xue@0 1030 double db=20*log10e*V.LogAS[CurrentPartial];
xue@0 1031 if (WheelDelta<0) ddb=-ddb;
xue@0 1032
xue@0 1033 db+=ddb;
xue@0 1034 AnsiString S; S.sprintf("Partial %d: %.2fdB", CurrentPartial+1, db);
xue@0 1035 if (Sender==AImage3) Label7->Caption=S;
xue@0 1036 else Label8->Caption=S;
xue@0 1037 ddb=ddb/(20*log10e);
xue@0 1038
xue@0 1039 for (int p=1; p<V.P; p++) V.LogASp[p][CurrentPartial]+=ddb;
xue@0 1040 V.LogAS[CurrentPartial]+=ddb;
xue@0 1041
xue@0 1042 SynthesizeV(HS, &V, WaveView1->SamplesPerSec);
xue@0 1043 SaveV();
xue@0 1044 S_U(true);
xue@0 1045 Handled=true;
xue@0 1046 }
xue@0 1047
xue@0 1048 void __fastcall TVibratoDemoForm::AImage4MouseWheel(TObject* Sender, TShiftState Shift, int WheelDelta, const TPoint &MousePos, bool &Handled)
xue@0 1049 {
xue@0 1050 double ddb;
xue@0 1051 if (Shift.Contains(ssShift)) ddb=0.2;
xue@0 1052 else if (Shift.Contains(ssCtrl)) ddb=5;
xue@0 1053 else ddb=1;
xue@0 1054 double db=20*log10e*V.LogASp[CurrentModCycle][CurrentPartial];
xue@0 1055 if (WheelDelta<0) ddb=-ddb;
xue@0 1056
xue@0 1057 db+=ddb;
xue@0 1058 AnsiString S; S.sprintf("Partial %d: %.2fdB", CurrentPartial+1, db);
xue@0 1059 if (Sender==AImage4) Label9->Caption=S;
xue@0 1060 else Label10->Caption=S;
xue@0 1061 ddb=ddb/(20*log10e);
xue@0 1062
xue@0 1063 V.LogASp[CurrentModCycle][CurrentPartial]+=ddb;
xue@0 1064
xue@0 1065 SynthesizeV(HS, &V, WaveView1->SamplesPerSec);
xue@0 1066 SaveV();
xue@0 1067 S_U(true);
xue@0 1068 Handled=true;
xue@0 1069 }
xue@0 1070
xue@0 1071 void __fastcall TVibratoDemoForm::MImage1MouseWheel(TObject* Sender, TShiftState Shift, int WheelDelta, const TPoint &MousePos, bool &Handled)
xue@0 1072 {
xue@0 1073 double rate;
xue@0 1074 if (Shift.Contains(ssShift)) rate=1.0192448764914566206520666016133;
xue@0 1075 else if (Shift.Contains(ssCtrl)) rate=1.61051;
xue@0 1076 else rate=1.1;
xue@0 1077 if (WheelDelta<0) rate=1.0/rate;
xue@0 1078
xue@0 1079 double* FXR;
xue@0 1080 TLabel* Label;
xue@0 1081 if (Sender==MImage1) FXR=V.FXR, Label=Label11;
xue@0 1082 else if (ActiveControl==MImage2->Parent) FXR=V.fxr[CurrentModCycle], Label=Label12;
xue@0 1083
xue@0 1084 if (CurrentK==0)
xue@0 1085 {
xue@0 1086 FXR[0]*=rate;
xue@0 1087 if (Sender==MImage1) for (int p=1; p<V.P; p++) V.fxr[p][0]*=rate;
xue@0 1088 }
xue@0 1089 else
xue@0 1090 {
xue@0 1091 FXR[2*CurrentK-1]*=rate, FXR[2*CurrentK]*=rate;
xue@0 1092 if (Sender==MImage1) for (int p=1; p<V.P; p++) V.fxr[p][2*CurrentK-1]*=rate, V.fxr[p][2*CurrentK]*=rate;
xue@0 1093 }
xue@0 1094
xue@0 1095 AnsiString S;
xue@0 1096 if (CurrentK>0) S.sprintf("%d: %.3g", CurrentK, sqrt(FXR[CurrentK*2-1]*FXR[CurrentK*2-1]+FXR[CurrentK*2]*FXR[CurrentK*2]));
xue@0 1097 else if (CurrentK==0) S.sprintf("%d: %.3g", CurrentK, fabs(FXR[0]));
xue@0 1098 Label->Caption=S;
xue@0 1099 Label->Left=ActiveControl->Left+0.5*(KX1[CurrentK]+KX2[CurrentK]-Label->Width);
xue@0 1100
xue@0 1101 SynthesizeV(HS, &V, WaveView1->SamplesPerSec);
xue@0 1102 SaveV();
xue@0 1103 S_U();
xue@0 1104 Handled=true;
xue@0 1105 }
xue@0 1106
xue@0 1107 void __fastcall TVibratoDemoForm::RateEditMouseWheel(TObject* Sender, TShiftState Shift, int WheelDelta, const TPoint &MousePos, bool &Handled)
xue@0 1108 {
xue@0 1109 double rate, irate;
xue@0 1110 if (Shift.Contains(ssShift)) rate=1.01;
xue@0 1111 else if (Shift.Contains(ssCtrl)) rate=1.282432;
xue@0 1112 else rate=1.05101;
xue@0 1113 if (WheelDelta<0) {irate=rate; rate=1.0/rate;}
xue@0 1114 else irate=1.0/rate;
xue@0 1115
xue@0 1116 if (Sender==CycleRateEdit)
xue@0 1117 {
xue@0 1118 if (CurrentModCycle>0)
xue@0 1119 {
xue@0 1120 double dlp=(V.lp[CurrentModCycle]-V.lp[CurrentModCycle-1])*(irate-1);
xue@0 1121 for (int p=CurrentModCycle; p<V.P; p++)
xue@0 1122 {
xue@0 1123 V.lp[p]+=dlp;
xue@0 1124 if (V.lp[p]>V.L) {V.P=p; break;}
xue@0 1125 }
xue@0 1126 }
xue@0 1127 }
xue@0 1128 else if (Sender==RateEdit)
xue@0 1129 {
xue@0 1130 double newP=V.GetOldP()*rate;
xue@0 1131 if (newP>2.5)
xue@0 1132 {
xue@0 1133 TVo* newV=InterpolateV(newP, rate, V);
xue@0 1134 V.~TVo();
xue@0 1135 memcpy(&V, newV, sizeof(TVo)); memset(newV, 0, sizeof(TVo));
xue@0 1136 delete newV;
xue@0 1137 }
xue@0 1138 }
xue@0 1139 SynthesizeV(HS, &V, WaveView1->SamplesPerSec);
xue@0 1140 RateAndReg(V.rate, V.regularity, V.F0D, V.peakfr[0], V.peakfr[V.P-1], 8, WaveView1->SamplesPerSec, WaveView1->SpecOffst);
xue@0 1141 SaveV();
xue@0 1142 S_U();
xue@0 1143 Handled=true;
xue@0 1144 }
xue@0 1145
xue@0 1146 void __fastcall TVibratoDemoForm::DurationEditMouseWheel(TObject* Sender, TShiftState Shift, int WheelDelta, const TPoint &MousePos, bool &Handled)
xue@0 1147 {
xue@0 1148 double rate;
xue@0 1149 if (Shift.Contains(ssShift)) rate=1.01;
xue@0 1150 else if (Shift.Contains(ssCtrl)) rate=1.282432;
xue@0 1151 else rate=1.05101;
xue@0 1152 if (WheelDelta<0) rate=1.0/rate;
xue@0 1153
xue@0 1154 if (Sender==CycleDurationEdit)
xue@0 1155 {
xue@0 1156 if (CurrentModCycle>0)
xue@0 1157 {
xue@0 1158 double dlp=(V.lp[CurrentModCycle]-V.lp[CurrentModCycle-1])*(rate-1);
xue@0 1159
xue@0 1160 for (int p=CurrentModCycle; p<V.P; p++)
xue@0 1161 {
xue@0 1162 V.lp[p]+=dlp;
xue@0 1163 }
xue@0 1164 int oldL=V.L, newL=V.L+dlp+0.5;
xue@0 1165
xue@0 1166 double *F0C=new double[V.L*2], *A0C=&F0C[V.L];
xue@0 1167 memcpy(F0C, V.F0C, sizeof(double)*oldL), memcpy(A0C, V.A0C, sizeof(double)*oldL);
xue@0 1168 V.AllocateL(newL);
xue@0 1169 for (int l=0; l<newL; l++)
xue@0 1170 {
xue@0 1171 double rl=1.0*l*oldL/newL;
xue@0 1172 int il=floor(rl); rl-=il;
xue@0 1173 if (fabs(rl)<1e-16)
xue@0 1174 {
xue@0 1175 V.F0C[l]=F0C[il];
xue@0 1176 V.A0C[l]=A0C[il];
xue@0 1177 }
xue@0 1178 else if (il>=oldL-1)
xue@0 1179 {
xue@0 1180 V.F0C[l]=F0C[oldL-1];
xue@0 1181 V.A0C[l]=A0C[oldL-1];
xue@0 1182 }
xue@0 1183 else
xue@0 1184 {
xue@0 1185 V.F0C[l]=F0C[il]*(1-rl)+F0C[il+1]*rl;
xue@0 1186 V.A0C[l]=A0C[il]*(1-rl)+A0C[il+1]*rl;
xue@0 1187 }
xue@0 1188 }
xue@0 1189
xue@0 1190 for (int c=0; c<cyclefrcount; c++)
xue@0 1191 {
xue@0 1192 cyclefrs[c]*=(1.0*newL/oldL);
xue@0 1193 int ic=floor(cyclefrs[c]);
xue@0 1194 if (ic<newL-1) cyclefs[c]=F0C[ic]*(ic+1-cyclefrs[c])+F0C[ic+1]*(cyclefrs[c]-ic);
xue@0 1195 else cyclefs[c]=F0C[newL-1];
xue@0 1196 }
xue@0 1197
xue@0 1198 delete[] F0C;
xue@0 1199 }
xue@0 1200 }
xue@0 1201 else if (Sender==DurationEdit)
xue@0 1202 {
xue@0 1203 double newP=V.GetOldP()*rate;
xue@0 1204 if (newP>2.5)
xue@0 1205 {
xue@0 1206 TVo* newV=InterpolateV(newP, 1, V); V.~TVo();
xue@0 1207 memcpy(&V, newV, sizeof(TVo)); memset(newV, 0, sizeof(TVo));
xue@0 1208 delete newV;
xue@0 1209
xue@0 1210 for (int c=0; c<cyclefrcount; c++)
xue@0 1211 {
xue@0 1212 cyclefrs[c]*=rate;
xue@0 1213 int ic=floor(cyclefrs[c]);
xue@0 1214 if (ic<V.L-1) cyclefs[c]=V.F0C[ic]*(ic+1-cyclefrs[c])+V.F0C[ic+1]*(cyclefrs[c]-ic);
xue@0 1215 else cyclefs[c]=V.F0C[V.L-1];
xue@0 1216 }
xue@0 1217 }
xue@0 1218 }
xue@0 1219 SynthesizeV(HS, &V, WaveView1->SamplesPerSec);
xue@0 1220 RateAndReg(V.rate, V.regularity, V.F0D, V.peakfr[0], V.peakfr[V.P-1], 8, WaveView1->SamplesPerSec, WaveView1->SpecOffst);
xue@0 1221 SaveV();
xue@0 1222 S_U();
xue@0 1223 Handled=true;
xue@0 1224 }
xue@0 1225
xue@0 1226 void __fastcall TVibratoDemoForm::PitchEditMouseWheel(TObject* Sender, TShiftState Shift, int WheelDelta, const TPoint &MousePos, bool &Handled)
xue@0 1227 {
xue@0 1228 if (CurrentModCycle<=0) return;
xue@0 1229
xue@0 1230 double cent;
xue@0 1231 if (Shift.Contains(ssShift)) cent=1;
xue@0 1232 else if (Shift.Contains(ssCtrl)) cent=100;
xue@0 1233 else cent=10;
xue@0 1234
xue@0 1235 if (WheelDelta<0) cent=-cent;
xue@0 1236 double rate_1=pow(2, cent/1200)-1;
xue@0 1237
xue@0 1238 int frst=ceil(V.lp[CurrentModCycle-1]), freninc=floor(V.lp[CurrentModCycle]);
xue@0 1239 for (int fr=frst; fr<=freninc; fr++) V.F0C[fr]=V.F0C[fr]*(1+rate_1);//(1+rate_1*0.5*(1-cos(2*M_PI*(fr-V.lp[CurrentModCycle-1])/(V.lp[CurrentModCycle]-V.lp[CurrentModCycle-1]))));
xue@0 1240
xue@0 1241
xue@0 1242 SynthesizeV(HS, &V, WaveView1->SamplesPerSec);
xue@0 1243 SaveV();
xue@0 1244 S_U();
xue@0 1245 Handled=true;
xue@0 1246 }
xue@0 1247 //---------------------------------------------------------------------------
xue@0 1248
xue@0 1249
xue@0 1250 void __fastcall TVibratoDemoForm::AImage3MouseMove(TObject *Sender,
xue@0 1251 TShiftState Shift, int X, int Y)
xue@0 1252 {
xue@0 1253 if (!HS) return;
xue@0 1254 TImage* Image=(TImage*)Sender;
xue@0 1255
xue@0 1256 if (Shift.Contains(ssLeft))
xue@0 1257 {
xue@0 1258 if (CurrentPartial<0) return;
xue@0 1259 int fh=Image->Canvas->TextHeight("0");
xue@0 1260 int YY=Image->Height-Bdw-Bdwc-fh;
xue@0 1261 double dbperpixel=dbrange/YY;
xue@0 1262 int dY=Y-StartDrag;
xue@0 1263 StartDrag=Y;
xue@0 1264 double ddb=-dY*dbperpixel;
xue@0 1265
xue@0 1266 if (Sender==AImage1 || Sender==AImage3)
xue@0 1267 {
xue@0 1268 double db=20*log10e*V.LogAS[CurrentPartial];
xue@0 1269 db+=ddb;
xue@0 1270 AnsiString S; S.sprintf("Partial %d: %.2fdB", CurrentPartial+1, db);
xue@0 1271 if (Sender==AImage3) Label7->Caption=S;
xue@0 1272 else Label8->Caption=S;
xue@0 1273 ddb=ddb/(20*log10e);
xue@0 1274
xue@0 1275 for (int p=1; p<V.P; p++) V.LogASp[p][CurrentPartial]+=ddb;
xue@0 1276 V.LogAS[CurrentPartial]+=ddb;
xue@0 1277 }
xue@0 1278 else if (Sender==AImage2 || Sender==AImage4)
xue@0 1279 {
xue@0 1280 double db=20*log10e*V.LogASp[CurrentModCycle][CurrentPartial];
xue@0 1281 db+=ddb;
xue@0 1282 AnsiString S; S.sprintf("Partial %d: %.2fdB", CurrentPartial+1, db);
xue@0 1283 if (Sender==AImage4) Label9->Caption=S;
xue@0 1284 else Label10->Caption=S;
xue@0 1285 ddb=ddb/(20*log10e);
xue@0 1286
xue@0 1287 V.LogASp[CurrentModCycle][CurrentPartial]+=ddb;
xue@0 1288 }
xue@0 1289
xue@0 1290 SynthesizeV(HS, &V, WaveView1->SamplesPerSec);
xue@0 1291 UpdateDisplay();
xue@0 1292 }
xue@0 1293 else
xue@0 1294 {
xue@0 1295 Image->Parent->SetFocus();
xue@0 1296
xue@0 1297 int lSXc, *lSX;
xue@0 1298 double* LogAS;
xue@0 1299 if (Sender==AImage1 || Sender==AImage3) lSXc=SXc, lSX=SX, LogAS=V.LogAS, X=Bdw+(X-Bdw)*AImage3->Width/((TImage*)Sender)->Width;
xue@0 1300 else if (Sender==AImage2 || Sender==AImage4) lSXc=SXcyclec, lSX=SXcycle, LogAS=V.LogASp[CurrentModCycle], X=Bdw+(X-Bdw)*AImage4->Width/((TImage*)Sender)->Width;
xue@0 1301
xue@0 1302 if (lSXc<=0) return;
xue@0 1303
xue@0 1304
xue@0 1305 CurrentPartial=0; while (CurrentPartial<lSXc && lSX[CurrentPartial]<X) CurrentPartial++;
xue@0 1306 if (CurrentPartial>=lSXc) CurrentPartial=lSXc-1;
xue@0 1307 if (CurrentPartial>=1 && X-lSX[CurrentPartial-1]<lSX[CurrentPartial]-X) CurrentPartial--;
xue@0 1308
xue@0 1309 double dB=20*log10e*LogAS[CurrentPartial];
xue@0 1310 AnsiString S; S.sprintf("Partial %d: %.2fdB", CurrentPartial+1, dB);
xue@0 1311
xue@0 1312 TLabel* Label;
xue@0 1313 if (Sender==AImage1) Label=Label8;
xue@0 1314 else if (Sender==AImage2) Label=Label10;
xue@0 1315 else if (Sender==AImage4) Label=Label9;
xue@0 1316 else Label=Label7;
xue@0 1317 Label->Font->Color=RotateColors[CurrentPartial%10]; Label->Caption=S;
xue@0 1318 }
xue@0 1319 }
xue@0 1320 //---------------------------------------------------------------------------
xue@0 1321
xue@0 1322 void __fastcall TVibratoDemoForm::MImage1MouseMove(TObject *Sender,
xue@0 1323 TShiftState Shift, int X, int Y)
xue@0 1324 {
xue@0 1325 if (!HS) return;
xue@0 1326 if (Shift.Contains(ssLeft))
xue@0 1327 {
xue@0 1328 if (CurrentK<0) return;
xue@0 1329
xue@0 1330 }
xue@0 1331 else
xue@0 1332 {
xue@0 1333 TImage* Image=(TImage*)Sender;
xue@0 1334 Image->Parent->SetFocus();
xue@0 1335 CurrentK=-1; for (int i=0; i<V.K; i++) if (X>=KX1[i] && X<=KX2[i]) {CurrentK=i; break;}
xue@0 1336 if (CurrentK<0) return;
xue@0 1337
xue@0 1338 double* FXR;
xue@0 1339 TLabel* Label;
xue@0 1340 if (Sender==MImage1) FXR=V.FXR, Label=Label11;
xue@0 1341 else if (Sender==MImage2)
xue@0 1342 {
xue@0 1343 if (CurrentModCycle<0) return;
xue@0 1344 FXR=V.fxr[CurrentModCycle], Label=Label12;
xue@0 1345 }
xue@0 1346
xue@0 1347 AnsiString S;
xue@0 1348 if (CurrentK>0) S.sprintf("%d: %.3g", CurrentK, sqrt(FXR[CurrentK*2-1]*FXR[CurrentK*2-1]+FXR[CurrentK*2]*FXR[CurrentK*2]));
xue@0 1349 else if (CurrentK==0) S.sprintf("%d: %.3g", CurrentK, fabs(FXR[0]));
xue@0 1350 Label->Caption=S; Label->Left=Image->Parent->Left+0.5*(KX1[CurrentK]+KX2[CurrentK]-Label->Width);
xue@0 1351 }
xue@0 1352 }
xue@0 1353 //---------------------------------------------------------------------------
xue@0 1354
xue@0 1355
xue@0 1356 void __fastcall TVibratoDemoForm::Image2DblClick(TObject *Sender)
xue@0 1357 {
xue@0 1358 TPoint P1; GetCursorPos(&P1);
xue@0 1359 TPoint P2=MImage1->ClientToScreen(TPoint(0, MImage1->Height*0.3819));
xue@0 1360 SetCursorPos(P1.x, P2.y);
xue@0 1361 }
xue@0 1362 //---------------------------------------------------------------------------
xue@0 1363
xue@0 1364
xue@0 1365
xue@0 1366 void __fastcall TVibratoDemoForm::AImage1MouseDown(TObject *Sender,
xue@0 1367 TMouseButton Button, TShiftState Shift, int X, int Y)
xue@0 1368 {
xue@0 1369 FirstStartDrag=StartDrag=Y;
xue@0 1370 }
xue@0 1371 //---------------------------------------------------------------------------
xue@0 1372
xue@0 1373 void __fastcall TVibratoDemoForm::AImage1MouseUp(TObject *Sender,
xue@0 1374 TMouseButton Button, TShiftState Shift, int X, int Y)
xue@0 1375 {
xue@0 1376 if (Y!=FirstStartDrag)
xue@0 1377 {
xue@0 1378 SaveV();
xue@0 1379 Synthesize();
xue@0 1380 UpdateDisplay();
xue@0 1381 }
xue@0 1382 }
xue@0 1383 //---------------------------------------------------------------------------
xue@0 1384
xue@0 1385 void __fastcall TVibratoDemoForm::CycleRateEditMouseMove(TObject *Sender,
xue@0 1386 TShiftState Shift, int X, int Y)
xue@0 1387 {
xue@0 1388 TEdit* Edit=(TEdit*)Sender;
xue@0 1389 Edit->SetFocus();
xue@0 1390 }
xue@0 1391 //---------------------------------------------------------------------------
xue@0 1392
xue@0 1393 void __fastcall TVibratoDemoForm::PageControl1Change(TObject *Sender)
xue@0 1394 {
xue@0 1395 if (PageControl1->ActivePage==ModOverSheet || PageControl1->ActivePage==ModCycleSheet)
xue@0 1396 ResidueCheck->Parent=PageControl1->ActivePage;
xue@0 1397 else if (PageControl1->ActivePage==AmpOverSheet || PageControl1->ActivePage==AmpCycleSheet)
xue@0 1398 {SFCheck->Parent=PageControl1->ActivePage; MACheck->Parent=PageControl1->ActivePage;}
xue@0 1399 UpdateDisplay();
xue@0 1400 }
xue@0 1401 //---------------------------------------------------------------------------
xue@0 1402
xue@0 1403
xue@0 1404 void SourceResponse(double* SV, TVo* V)
xue@0 1405 {
xue@0 1406 int N=V->afres/2;
xue@0 1407 memset(SV, 0, sizeof(double)*N);
xue@0 1408 for (int p=1; p<V->P; p++)
xue@0 1409 {
xue@0 1410 double F0p=0;
xue@0 1411 int frst=V->lp[p-1], fren=V->lp[p];
xue@0 1412 for (int fr=frst; fr<fren; fr++) F0p+=V->F0C[fr];
xue@0 1413 F0p/=(fren-frst);
xue@0 1414 F0p*=V->afres;
xue@0 1415 int lastfp;
xue@0 1416 double lastsv;
xue@0 1417 for (int m=0; m<V->M; m++)
xue@0 1418 {
xue@0 1419 int fp=F0p*(m+1);
xue@0 1420 double sv=V->LogASp[p][m];
xue@0 1421 if (m==0) for (int n=0; n<fp; n++) SV[n]+=sv;
xue@0 1422 else for (int n=lastfp; n<fp; n++) SV[n]+=(sv*(n-lastfp)+lastsv*(fp-n))/(fp-lastfp);
xue@0 1423 lastfp=fp, lastsv=sv;
xue@0 1424 }
xue@0 1425 for (int n=lastfp; n<N; n++) SV[n]+=lastsv;
xue@0 1426 }
xue@0 1427 for (int n=0; n<N; n++) SV[n]/=(V->P-1);
xue@0 1428 }
xue@0 1429
xue@0 1430 //S_U implements delayed updating of lengthy synthesizing to speed up operation
xue@0 1431 // in case the HS is updated frequently, s.a. during mouse wheeling.
xue@0 1432 //This allows a later synthesis to start before an earlier synthesis finishes,
xue@0 1433 // at which the latter is terminated and its incomplete result is discarded.
xue@0 1434 void __fastcall TVibratoDemoForm::S_U(bool sf)
xue@0 1435 {
xue@0 1436 if (SUThread)
xue@0 1437 {
xue@0 1438 SUThread->Terminate();
xue@0 1439 }
xue@0 1440 SUThread=new TSUThread(true);
xue@0 1441 SUThread->sf=sf;
xue@0 1442 SUThread->OnTerminate=SUTerminate;
xue@0 1443 SUThread->HS=new THS(HS);
xue@0 1444 ThreadList[pThread++]=SUThread;
xue@0 1445 if (pThread==ThreadCaps/2 && ThreadList[pThread])
xue@0 1446 for (int i=pThread; i<ThreadCaps; i++) {delete ThreadList[i]; ThreadList[i]=0;}
xue@0 1447 else if (pThread==ThreadCaps)
xue@0 1448 {
xue@0 1449 for (int i=0; i<ThreadCaps/2; i++) {delete ThreadList[i]; ThreadList[i]=0;}
xue@0 1450 pThread=0;
xue@0 1451 }
xue@0 1452 SUThread->Resume();
xue@0 1453 }
xue@0 1454
xue@0 1455 void __fastcall TVibratoDemoForm::SUTerminate(TObject* Sender)
xue@0 1456 {
xue@0 1457 TSUThread* CurrentThread=(TSUThread*)Sender;
xue@0 1458 if (CurrentThread==SUThread)
xue@0 1459 {
xue@0 1460 double* xrec=CurrentThread->xrec;
xue@0 1461 if (xrec)
xue@0 1462 {
xue@0 1463 int dst=CurrentThread->dst, den=CurrentThread->den;
xue@0 1464 if (dst<0) dst=0;
xue@0 1465 __int16* data=new __int16[den];
xue@0 1466 memset(data, 0, sizeof(__int16)*dst);
xue@0 1467 DoubleToInt(&data[dst], sizeof(__int16), xrec, den-dst);
xue@0 1468 WaveAudio2->Clear(NULL);
xue@0 1469 WaveAudio2->WriteSamples(data, den-dst);
xue@0 1470 delete[] data;
xue@0 1471 UpdateDisplay();
xue@0 1472 }
xue@0 1473 SUThread=0;
xue@0 1474 }
xue@0 1475 else
xue@0 1476 {
xue@0 1477 UpdateDisplay(true, true, true, CurrentThread->sf);
xue@0 1478 }
xue@0 1479 free8(CurrentThread->xrec); CurrentThread->xrec=0;
xue@0 1480 }
xue@0 1481 //---------------------------------------------------------------------------
xue@0 1482 void __fastcall TVibratoDemoForm::Panel4Resize(TObject *Sender)
xue@0 1483 {
xue@0 1484 Panel10->Height=Panel4->Height/3;
xue@0 1485 ForceUpdate=true;
xue@0 1486 }
xue@0 1487 //---------------------------------------------------------------------------
xue@0 1488
xue@0 1489 void __fastcall TVibratoDemoForm::Panel8Resize(TObject *Sender)
xue@0 1490 {
xue@0 1491 int H=(Panel8->Height-Splitter4->Height-Splitter5->Height)/3;
xue@0 1492 Panel9->Height=H; Panel7->Height=H;
xue@0 1493 ForceUpdate=true;
xue@0 1494 }
xue@0 1495 //---------------------------------------------------------------------------
xue@0 1496
xue@0 1497 void __fastcall TVibratoDemoForm::Panel1Resize(TObject *Sender)
xue@0 1498 {
xue@0 1499 Panel2->Height=(Panel1->Height-Splitter1->Height)/2;
xue@0 1500 }
xue@0 1501 //---------------------------------------------------------------------------
xue@0 1502
xue@0 1503
xue@0 1504 void __fastcall TVibratoDemoForm::AmpOverSheetResize(TObject *Sender)
xue@0 1505 {
xue@0 1506 double W=(AmpOverSheet->Width-24)/20.0;
xue@0 1507 AImage3->Parent->Width=W*9;
xue@0 1508 Label7->Width=AImage3->Parent->Width;
xue@0 1509 AImage1->Parent->Left=AImage3->Parent->Left+AImage3->Parent->Width+8;
xue@0 1510 AImage1->Parent->Width=W*11;
xue@0 1511 Label8->Left=AImage1->Parent->Left;
xue@0 1512 Label8->Width=AImage1->Parent->Width;
xue@0 1513 }
xue@0 1514 //---------------------------------------------------------------------------
xue@0 1515
xue@0 1516 void __fastcall TVibratoDemoForm::AmpCycleSheetResize(TObject *Sender)
xue@0 1517 {
xue@0 1518 double W=(AmpCycleSheet->Width-24)/20.0;
xue@0 1519 AImage4->Parent->Width=W*9;
xue@0 1520 Label9->Width=AImage4->Parent->Width;
xue@0 1521 AImage2->Parent->Left=AImage4->Parent->Left+AImage4->Parent->Width+8;
xue@0 1522 AImage2->Parent->Width=W*11;
xue@0 1523 Label10->Left=AImage2->Parent->Left;
xue@0 1524 Label10->Width=AImage2->Parent->Width;
xue@0 1525 }
xue@0 1526 //---------------------------------------------------------------------------
xue@0 1527
xue@0 1528
xue@0 1529 void __fastcall TVibratoDemoForm::ListBox1Click(TObject *Sender)
xue@0 1530 {
xue@0 1531 if (ListBox1->ItemIndex==1) ThetaEdit->Enabled=true;
xue@0 1532 else ThetaEdit->Enabled=false;
xue@0 1533 Reset();
xue@0 1534 }
xue@0 1535 //---------------------------------------------------------------------------
xue@0 1536
xue@0 1537 void __fastcall TVibratoDemoForm::Button1Click(TObject *Sender)
xue@0 1538 {
xue@0 1539 int N=WaveView1->Length, Channel=Form1->HS->Channel;
xue@0 1540
xue@0 1541 if (GetKeyState(VK_SHIFT)<0)
xue@0 1542 {
xue@0 1543 __int16* d2=WaveView2->Data16[0];
xue@0 1544 Form1->PostWaveViewData(d2, Channel, StartPos, StartPos+N, Form1->FadeInCheck->Checked, Form1->FadeInCombo->Text.ToInt());
xue@0 1545 }
xue@0 1546 else
xue@0 1547 {
xue@0 1548 __int16 *data=new __int16[N], *data1=WaveView1->Data16[0], *data2=WaveView2->Data16[0];
xue@0 1549 int NN=N;
xue@0 1550 if (NN>WaveView2->Length) NN=WaveView2->Length;
xue@0 1551 for (int n=0; n<NN; n++) data[n]=data1[n]-datain[n]+data2[n];
xue@0 1552 for (int n=NN; n<N; n++) data[n]=data1[n]-datain[n];
xue@0 1553 Form1->PostWaveViewData(data, Channel, StartPos, StartPos+NN, Form1->FadeInCheck->Checked, Form1->FadeInCombo->Text.ToInt());
xue@0 1554 if (NN!=N) Form1->PostWaveViewData(&data[NN], Channel, StartPos+NN, StartPos+N, Form1->FadeInCheck->Checked, Form1->FadeInCombo->Text.ToInt());
xue@0 1555 delete[] data;
xue@0 1556 }
xue@0 1557 }
xue@0 1558 //---------------------------------------------------------------------------
xue@0 1559
xue@0 1560
xue@0 1561
xue@0 1562 void __fastcall TVibratoDemoForm::Panel9Resize(TObject *Sender)
xue@0 1563 {
xue@0 1564 ForceUpdate=true;
xue@0 1565 }
xue@0 1566 //---------------------------------------------------------------------------
xue@0 1567
xue@0 1568 void __fastcall TVibratoDemoForm::Panel7Resize(TObject *Sender)
xue@0 1569 {
xue@0 1570 ForceUpdate=true;
xue@0 1571 }
xue@0 1572 //---------------------------------------------------------------------------
xue@0 1573