annotate Unit1.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 #pragma hdrstop
xue@0 16
xue@0 17 #include <vcl.h>
xue@0 18 #include <inifiles.hpp>
xue@0 19 #include "Unit1.h"
xue@0 20 #include "BackUpTool.h"
xue@0 21 #include <math.h>
xue@0 22 #include <Math.hpp>
xue@0 23 #include "UnitRangeEdit.h"
xue@0 24 #include "EditorPanelUnit.h"
xue@0 25 #include "VibratoDemoUnit.h"
xue@0 26 #include "RecordingUnit.h"
xue@0 27 #include "opt.h"
xue@0 28 #include "Matrix.h"
xue@0 29 #include "SFDemoUnit.h"
xue@0 30 #include "SinEst.h"
xue@0 31 #include "splines.h"
xue@0 32 #include "SinSyn.h"
xue@0 33 #include "hsedit.h"
xue@0 34 //---------------------------------------------------------------------------
xue@0 35 #pragma package(smart_init)
xue@0 36 #pragma resource "*.dfm"
xue@0 37 TForm1 *Form1;
xue@0 38 extern timestamp1;
xue@0 39 //---------------------------------------------------------------------------
xue@0 40 char ReturnKey=VK_RETURN;
xue@0 41 int BAR=2;
xue@0 42 #define ASMALLNEGATIVEVALUE -1.1e-24
xue@0 43
xue@0 44 __fastcall TForm1::TForm1(TComponent* Owner)
xue@0 45 : TForm(Owner)
xue@0 46 {
xue@0 47 Application->HintPause=0.1;
xue@0 48
xue@0 49 WaveAudio1=new TWaveAudio(NULL);
xue@0 50 WaveAudio1->AutoUseMemoryStream=true;
xue@0 51 WaveAudio1->OnLoad=WaveAudio1Load;
xue@0 52 WaveView1=new TWaveView(NULL, true, false);
xue@0 53 WaveView1->Parent=PanelWaveView;
xue@0 54 WaveView1->Align=alClient;
xue@0 55 WaveView1->ScrollBar=ScrollBar1;
xue@0 56 WaveView1->WaveAudio=WaveAudio1;
xue@0 57 WaveView1->ClickFocus=true;
xue@0 58 WaveView1->WaveBackColor=clWhite;
xue@0 59 WaveView1->WaveColor=clBlack;
xue@0 60 WaveView1->AxisColor=clGray;
xue@0 61 WaveView1->CustomInfo=WaveView1CustomInfo;
xue@0 62 WaveView1->CustomPaneInfo=WaveView1CustomPaneInfo;
xue@0 63 WaveView1->OnGetOpMode=WaveView1OpMode;
xue@0 64 WaveView1->OnGetPlaybackStartAndEndPos=WaveView1PlaybackStartAndEndPos;
xue@0 65 WaveView1->OnInfoDblClick=WaveView1InfoDblClick;
xue@0 66 WaveView1->OnPaint=WaveView1AfterPaint;
xue@0 67 WaveView1->OnPlaybackStart=WaveView1PlaybackStart;
xue@0 68 WaveView1->OnPlaybackDone=WaveView1PlaybackDone;
xue@0 69 WaveView1->OnKeyPress=WaveView1KeyPress;
xue@0 70 WaveView1->OnMouseDown=WaveView1MouseDown;
xue@0 71 WaveView1->OnMouseMove=WaveView1MouseMove;
xue@0 72 WaveView1->OnMousePointer=WaveView1MousePointer;
xue@0 73 WaveView1->OnMouseUp=WaveView1MouseUp;
xue@0 74 WaveView1->OnMouseWheel=WaveView1MouseWheel;
xue@0 75 WaveView1->SelectedFrameColorX=clGreen;
xue@0 76 WaveView1->SelectedAreaColorX=clGreen;
xue@0 77 WaveView1->BeforePlayback=WaveView1BeforePlayback;
xue@0 78 WaveView1->Hint=""; WaveView1->ShowHint=true;
xue@0 79 WaveView1->DefaultPopupMenu=false; WaveView1->PopupMenu=WaveView1PopupMenu;
xue@0 80 WaveView1->Tools<<wvtPlayNote;
xue@0 81 WaveView1->PlayNoteInSemitone=true;
xue@0 82
xue@0 83 WaveAudio2=0;
xue@0 84
xue@0 85 TWaveViewObject Obj; memset(&Obj, 0, sizeof(TWaveViewObject));
xue@0 86 Obj.DrawObject=WaveView1DrawObject; Obj.OnClick=WaveView1ObjectClick;
xue@0 87 for (int i=0; i<6; i++){Obj.Id=i; WaveView1->FObjects.Add(Obj);}
xue@0 88 WaveView1->FObjects.Items[5].OnClick=0; WaveView1->FObjects.Items[5].OnDblClick=WaveView1ObjectDblClick;
xue@0 89 WaveView1->FObjects.Items[5].OnMouseWheel=WaveView1ObjectMouseWheel;
xue@0 90
xue@0 91 Navigator1=new TNavigator(NULL);
xue@0 92 Navigator1->Parent=PanelNavigator;
xue@0 93 Navigator1->Align=alClient;
xue@0 94 Navigator1->AreaColorX=clYellow;
xue@0 95 Navigator1->OnAreaChange=Navigator1AreaChange;
xue@0 96 Navigator1->OnBackground=Navigator1Background;
xue@0 97 NavButton=new TSpeedButton(this); NavButton->Parent=Navigator1; NavButton->Left=0; NavButton->Top=0; NavButton->Width=24; NavButton->Height=16;
xue@0 98 NavButton->Transparent=true; NavButton->Font->Name="Ariel"; NavButton->Font->Height=12; NavButton->Font->Color=clBlack; NavButton->Caption="W/S";
xue@0 99 NavButton->Flat=true; NavButton->OnClick=NavButtonClick;
xue@0 100
xue@0 101 Initialize();
xue@0 102 SetWaveViewContents();
xue@0 103
xue@0 104 BitmapPlay=new Graphics::TBitmap; BitmapPlay->LoadFromResourceID((int)HInstance, 100);
xue@0 105 BitmapStop=new Graphics::TBitmap; BitmapStop->LoadFromResourceID((int)HInstance, 101);
xue@0 106 SpeedButtonPlay->Glyph=BitmapPlay;
xue@0 107 BitmapSpectrogram=new Graphics::TBitmap; BitmapSpectrogram->LoadFromResourceID((int)HInstance, 102);
xue@0 108 BitmapWaveform=new Graphics::TBitmap; BitmapWaveform->LoadFromResourceID((int)HInstance, 103);
xue@0 109 SpeedButtonS->Glyph=BitmapSpectrogram;
xue@0 110 BitmapRecord=new Graphics::TBitmap; BitmapRecord->LoadFromResourceID((int)HInstance, 104);
xue@0 111 BitmapRecording=new Graphics::TBitmap; BitmapRecording->LoadFromResourceID((int)HInstance, 105);
xue@0 112 SpeedButtonRecord->Glyph=BitmapRecord;
xue@0 113 BitmapTimeSelect=new Graphics::TBitmap; BitmapTimeSelect->LoadFromResourceID((int)HInstance, 106);
xue@0 114 SpeedButtonT->Glyph=BitmapTimeSelect;
xue@0 115 BitmapFreqSelect=new Graphics::TBitmap; BitmapFreqSelect->LoadFromResourceID((int)HInstance, 107);
xue@0 116 SpeedButtonF->Glyph=BitmapFreqSelect;
xue@0 117 BitmapMultiSelect=new Graphics::TBitmap; BitmapMultiSelect->LoadFromResourceID((int)HInstance, 108);
xue@0 118 SpeedButtonM->Glyph=BitmapMultiSelect;
xue@0 119 BitmapHSSelect=new Graphics::TBitmap; BitmapHSSelect->LoadFromResourceID((int)HInstance, 109);
xue@0 120 SpeedButtonSelect->Glyph=BitmapHSSelect;
xue@0 121 BitmapCursorText=new Graphics::TBitmap; BitmapCursorText->LoadFromResourceID((int)HInstance, 110);
xue@0 122 SpeedButtonCursorText->Glyph=BitmapCursorText;
xue@0 123 BitmapPaneInfo=new Graphics::TBitmap; BitmapPaneInfo->LoadFromResourceID((int)HInstance, 111);
xue@0 124 SpeedButtonPaneInfo->Glyph=BitmapPaneInfo;
xue@0 125
xue@0 126 SpectrogramView=false;
xue@0 127 HS=0;
xue@0 128 PartialSelectCombo->ItemIndex=0;
xue@0 129 ancps=0;
xue@0 130 ancfrs=0;
xue@0 131 ancfs=0;
xue@0 132 ancts=0;
xue@0 133 onset.f0s=0;
xue@0 134 onset.pitches=0;
xue@0 135 onset.xfr=0;
xue@0 136
xue@0 137 Application->OnIdle=ApplicationIdle;
xue@0 138
xue@0 139 for (int i=0; i<MaxRecents; i++)
xue@0 140 {
xue@0 141 int ind=File1->IndexOf(Recent00);
xue@0 142 TMenuItem* Item=new TMenuItem(this);
xue@0 143 Item->Tag=i;
xue@0 144 Item->Caption=i+1;
xue@0 145 Item->OnClick=Recent11Click;
xue@0 146 File1->Insert(ind, Item);
xue@0 147 Recents[i]=Item;
xue@0 148 }
xue@0 149
xue@0 150
xue@0 151 ExePath=ExtractFilePath(Application->ExeName);
xue@0 152 TmpInFileName=ExePath+"tvoin";
xue@0 153 TmpOutFileName=ExePath+"tvoout";
xue@0 154 IniFileName=ChangeFileExt(Application->ExeName, ".ini");
xue@0 155
xue@0 156 RecentFile("");
xue@0 157
xue@0 158 }
xue@0 159
xue@0 160 __fastcall TForm1::~TForm1()
xue@0 161 {
xue@0 162 TIniFile* Ini=0;
xue@0 163 try{
xue@0 164 Ini=new TIniFile(ChangeFileExt(Application->ExeName, ".ini"));
xue@0 165 Ini->WriteString("CurrentFile", "FileName", WaveAudio1->FileName);
xue@0 166 Ini->WriteInteger("CurrentView", "Start", WaveView1->StartPos);
xue@0 167 Ini->WriteInteger("CurrentView", "End", WaveView1->EndPos);
xue@0 168 Ini->WriteFloat("CurrentView", "StartF", WaveView1->StartDigiFreq);
xue@0 169 Ini->WriteFloat("CurrentView", "EndF", WaveView1->EndDigiFreq);
xue@0 170 Ini->WriteInteger("CurrentView", "SpecRes", WindowSizeCombo->ItemIndex);
xue@0 171 Ini->WriteInteger("CurrentView", "WindowType", WindowTypeCombo->ItemIndex);
xue@0 172 Ini->WriteString("HS", "delp", HSDelpEdit1->Text);
xue@0 173 Ini->WriteString("HS", "delm", HSDelmEdit1->Text);
xue@0 174 Ini->WriteInteger("Settings", "MouseWheelZoom", MouseWheelZoom->Checked);
xue@0 175 Ini->WriteInteger("Settings", "Mixer", false);
xue@0 176 } catch(...) {}
xue@0 177 delete Ini;
xue@0 178
xue@0 179 delete WaveAudio1;
xue@0 180 delete WaveView1;
xue@0 181 delete Navigator1;
xue@0 182 delete BitmapPlay;
xue@0 183 delete BitmapStop;
xue@0 184 delete BitmapSpectrogram;
xue@0 185 delete BitmapWaveform;
xue@0 186 delete BitmapRecord;
xue@0 187 delete BitmapRecording;
xue@0 188 delete BitmapTimeSelect;
xue@0 189 delete BitmapFreqSelect;
xue@0 190 delete BitmapMultiSelect;
xue@0 191 delete BitmapHSSelect;
xue@0 192 delete BitmapCursorText;
xue@0 193 delete BitmapPaneInfo;
xue@0 194
xue@0 195 free(ancps);
xue@0 196 free(ancfrs);
xue@0 197 free(ancfs);
xue@0 198 free(ancts);
xue@0 199 DeAlloc2(onset.f0s);
xue@0 200 DeAlloc2(onset.pitches);
xue@0 201 delete[] onset.xfr;
xue@0 202 }
xue@0 203 //---------------------------------------------------------------------------
xue@0 204 void __fastcall TForm1::ApplicationIdle(TObject* Sender, bool& Done)
xue@0 205 {
xue@0 206 if (FileExists(TmpInFileName)) VibratoDemoForm->ExternalInput();
xue@0 207 if (VibratoDemoForm->ForceUpdate) VibratoDemoForm->UpdateDisplay();
xue@0 208
xue@0 209 Done=true;
xue@0 210 }
xue@0 211
xue@0 212 //---------------------------------------------------------------------------
xue@0 213 void __fastcall TForm1::Backup1Click(TObject *Sender)
xue@0 214 {
xue@0 215 BackupForm1->ShowModal();
xue@0 216 }
xue@0 217 //---------------------------------------------------------------------------
xue@0 218
xue@0 219 void __fastcall TForm1::Exit1Click(TObject *Sender)
xue@0 220 {
xue@0 221 Close();
xue@0 222 }
xue@0 223 //---------------------------------------------------------------------------
xue@0 224 void __fastcall TForm1::ZoomToSelection1Click(TObject *Sender)
xue@0 225 {
xue@0 226 WaveView1->DoExtract(Sender);
xue@0 227 if (GetKeyState(VK_SHIFT)>=0) WaveView1->RemoveSelection(-1);
xue@0 228 }
xue@0 229 //---------------------------------------------------------------------------
xue@0 230 void TForm1::Initialize()
xue@0 231 {
xue@0 232 TIniFile* Ini=new TIniFile(ChangeFileExt(Application->ExeName, ".ini"));
xue@0 233 AnsiString FileName=Ini->ReadString("CurrentFile", "FileName", "");
xue@0 234 if (FileExists(FileName))
xue@0 235 {
xue@0 236 WaveAudio1->LoadFromFile(FileName);
xue@0 237 int Start=Ini->ReadInteger("CurrentView", "Start", 0);
xue@0 238 int End=Ini->ReadInteger("CurrentView", "End", WaveAudio1->Length);
xue@0 239 double StartDF=Ini->ReadFloat("CurrentView", "StartF", 0);
xue@0 240 double EndDF=Ini->ReadFloat("CurrentView", "EndF", 0.5);
xue@0 241 WaveView1->SetArea(Start, End, StartDF, EndDF);
xue@0 242 WindowTypeCombo->ItemIndex=Ini->ReadInteger("CurrentView", "WindowType", 2); WindowTypeComboChange(NULL);
xue@0 243 WindowSizeCombo->ItemIndex=Ini->ReadInteger("CurrentView", "SpecRes", 5); WindowSizeComboChange(NULL);
xue@0 244 HSDelpEdit1->Text=Ini->ReadString("HS", "delp", "1.0");
xue@0 245 HSDelmEdit1->Text=Ini->ReadString("HS", "delm", "1.0");
xue@0 246 MouseWheelZoom->Checked=Ini->ReadInteger("Settings", "MouseWheelZoom", true);
xue@0 247 WaveView1->DisableMouseWheelZoom=!MouseWheelZoom->Checked;
xue@0 248 }
xue@0 249 delete Ini;
xue@0 250 }
xue@0 251 //---------------------------------------------------------------------------
xue@0 252 void __fastcall TForm1::LogFreqCheckClick(TObject *Sender)
xue@0 253 {
xue@0 254 SetWaveViewContents();
xue@0 255 }
xue@0 256 //---------------------------------------------------------------------------
xue@0 257 void __fastcall TForm1::NavButtonClick(TObject*)
xue@0 258 {
xue@0 259 NavButton->Font->Color=(NavButton->Font->Color==clBlack)?clYellow:clBlack;
xue@0 260 Navigator1->Resize();
xue@0 261 }
xue@0 262 //---------------------------------------------------------------------------
xue@0 263 void __fastcall TForm1::Navigator1AreaChange(TObject*)
xue@0 264 {
xue@0 265 WaveView1->SetArea(WaveView1->Length*Navigator1->x1, WaveView1->Length*Navigator1->x2,
xue@0 266 (1-Navigator1->y2)*0.5, (1-Navigator1->y1)*0.5);
xue@0 267 }
xue@0 268 //---------------------------------------------------------------------------
xue@0 269 void __fastcall TForm1::Navigator1Background(TObject*)
xue@0 270 {
xue@0 271 if (WaveAudio1->Length<=0)
xue@0 272 Navigator1->BkgBmp->Canvas->FillRect(Navigator1->ClientRect);
xue@0 273 else if (NavButton->Font->Color==clYellow)
xue@0 274 {
xue@0 275 TWaveViewSelection Sel={0, WaveView1->Length, 0, 0.5};
xue@0 276 WaveView1->DrawSpectrogramX(0, Sel, 0, Navigator1->BkgBmp->Canvas, Navigator1->ClientRect, 10, false, false, 1);
xue@0 277 }
xue@0 278 else WaveView1->DrawWaveForm(0, Navigator1->BkgBmp->Canvas, Navigator1->ClientRect, 0, WaveView1->Length);
xue@0 279 }
xue@0 280 //---------------------------------------------------------------------------
xue@0 281 void __fastcall TForm1::Open1Click(TObject *Sender)
xue@0 282 {
xue@0 283 OpenDialog1->FilterIndex=1;
xue@0 284 if (OpenDialog1->Execute())
xue@0 285 {
xue@0 286 if (WaveAudio1->FileName!=OpenDialog1->FileName) RecentFile(WaveAudio1->FileName);
xue@0 287 WaveAudio1->LoadFromFile(OpenDialog1->FileName);
xue@0 288 }
xue@0 289 }
xue@0 290
xue@0 291 //---------------------------------------------------------------------------
xue@0 292 void __fastcall TForm1::PanelRightButtonMouseUp(TObject *Sender,
xue@0 293 TMouseButton Button, TShiftState Shift, int X, int Y)
xue@0 294 {
xue@0 295 TShape* Shape=(TShape*)Sender;
xue@0 296 if (Button==mbLeft && X>=0 && Y>=0 && X<Shape->Width && Y<Shape->Height)
xue@0 297 {
xue@0 298 TPanel* APanel; TSplitter* ASplitter;
xue@0 299 if (Shape==PanelRightButton) APanel=PanelRight, ASplitter=Splitter1;
xue@0 300 else if (Shape==PanelRightButton2) APanel=PanelGrid, ASplitter=Splitter3;
xue@0 301 ShowPanel(APanel, APanel->Visible);
xue@0 302 ASplitter->Visible=!ASplitter->Visible;
xue@0 303 }
xue@0 304 }
xue@0 305 //---------------------------------------------------------------------------
xue@0 306 void __fastcall TForm1::Play1Click(TObject *Sender)
xue@0 307 {
xue@0 308 WaveView1->StartPlayback(Sender);
xue@0 309 }
xue@0 310 //---------------------------------------------------------------------------
xue@0 311 void TForm1::PrepareNMSettings(NMSettings* settings)
xue@0 312 {
xue@0 313 memset(settings, 0, sizeof(NMSettings));
xue@0 314 int wid=WaveView1->SpecRes, sps=WaveView1->SamplesPerSec;
xue@0 315 windowspec(WaveView1->SpecWindowType, wid, &settings->M, settings->c, &settings->iH2);
xue@0 316 settings->hB=3;
xue@0 317 settings->maxp=HSMaxpEdit1->Text.ToInt();
xue@0 318 settings->maxB=HSMaxBEdit1->Text.ToDouble();
xue@0 319 settings->epf=2.0e-4;
xue@0 320 settings->epf0=2;
xue@0 321 settings->delm=HSDelmEdit1->Text.ToDouble();
xue@0 322 settings->delp=HSDelpEdit1->Text.ToDouble();
xue@0 323 settings->minf0=HSMinF0Edit1->Text.ToDouble()/sps*wid;
xue@0 324 settings->maxf0=HSMaxF0Edit1->Text.ToDouble()/sps*wid;
xue@0 325 settings->pin0=PartialSelectCombo->ItemIndex+1;
xue@0 326 settings->pcount=0;
xue@0 327 }
xue@0 328
xue@0 329 //---------------------------------------------------------------------------
xue@0 330 void TForm1::RecentFile(AnsiString FileName)
xue@0 331 {
xue@0 332 TIniFile* Ini=0;
xue@0 333 try{
xue@0 334 Ini=new TIniFile(IniFileName);
xue@0 335
xue@0 336 int newi=0, start[MaxRecents+1], end[MaxRecents+1];
xue@0 337 double fstart[MaxRecents+1], fend[MaxRecents+1];
xue@0 338 AnsiString Names[MaxRecents+1];
xue@0 339 if (FileExists(FileName))
xue@0 340 {
xue@0 341 Names[0]=FileName;
xue@0 342 start[0]=WaveView1->StartPos, end[0]=WaveView1->EndPos;
xue@0 343 fstart[0]=WaveView1->StartDigiFreq, fend[0]=WaveView1->EndDigiFreq;
xue@0 344 newi=1;
xue@0 345 }
xue@0 346
xue@0 347 AnsiString S0="RecentFile";
xue@0 348 for (int i=1; i<=MaxRecents; i++)
xue@0 349 {
xue@0 350 AnsiString S=S0+i;
xue@0 351 if (!Ini->SectionExists(S)) continue;
xue@0 352 AnsiString LName=Ini->ReadString(S, "FileName", "");
xue@0 353 if (FileExists(LName) && LName!=FileName)
xue@0 354 {
xue@0 355 Names[newi]=LName;
xue@0 356 start[newi]=Ini->ReadInteger(S, "Start", 0);
xue@0 357 end[newi]=Ini->ReadInteger(S, "End", -1);
xue@0 358 fstart[newi]=Ini->ReadFloat(S, "StartF", 0);
xue@0 359 fend[newi]=Ini->ReadFloat(S, "EndF", 0.5);
xue@0 360 newi++;
xue@0 361 }
xue@0 362 Ini->EraseSection(S);
xue@0 363 }
xue@0 364
xue@0 365 if (newi>MaxRecents) newi=MaxRecents;
xue@0 366 for (int i=0; i<newi; i++)
xue@0 367 {
xue@0 368 AnsiString S="RecentFile"; S=S+(i+1);
xue@0 369 Ini->WriteString(S, "FileName", Names[i]);
xue@0 370 Ini->WriteInteger(S, "Start", start[i]);
xue@0 371 Ini->WriteInteger(S, "End", end[i]);
xue@0 372 Ini->WriteFloat(S, "StartF", fstart[i]);
xue@0 373 Ini->WriteFloat(S, "EndF", fend[i]);
xue@0 374 }
xue@0 375
xue@0 376 for (int i=0; i<newi; i++)
xue@0 377 {
xue@0 378 Recents[i]->Caption=AnsiString(i+1)+". "+Names[i];
xue@0 379 Recents[i]->Visible=true;
xue@0 380 }
xue@0 381 for (int i=newi; i<MaxRecents; i++) Recents[i]->Visible=false;
xue@0 382 Recent00->Visible=(newi>0);
xue@0 383 }catch(...){}
xue@0 384 delete Ini;
xue@0 385 }
xue@0 386
xue@0 387 //---------------------------------------------------------------------------
xue@0 388
xue@0 389 void TForm1::SetGridContents()
xue@0 390 {
xue@0 391 if (!PanelGrid->Visible) return;
xue@0 392 if (WaveView1->CurrentPane<0) return;
xue@0 393 GridSourcePane=WaveView1->CurrentPane;
xue@0 394 int Wid=WaveView1->SpecRes, hWid=Wid/2, Offst=WaveView1->SpecOffst;
xue@0 395 double t=WaveView1->CurrentTime, f=WaveView1->CurrentDigiFreq, amp=sqrt(1.0/Wid), prange=100, i2pi=0.5*prange/M_PI;
xue@0 396 int Channel=WaveView1->FPanes.Channel[GridSourcePane];
xue@0 397 if (WaveView1->FPanes.HasFreqAxis[GridSourcePane] && (AmpTab->Visible || ArcTab->Visible))
xue@0 398 {
xue@0 399 TStringGrid* Grid;
xue@0 400 if (AmpTab->Visible) Grid=AmpGrid;
xue@0 401 else if (ArcTab->Visible) Grid=PhaseGrid;
xue@0 402 Grid->RowCount=Grid->Height/(Grid->DefaultRowHeight+1);
xue@0 403 Grid->ColCount=Grid->Width/(Grid->DefaultColWidth+1);
xue@0 404 int maxfr=(WaveView1->Length-Wid)/Offst+1;
xue@0 405 if (Grid->ColCount>maxfr+1) Grid->ColCount=maxfr+1;
xue@0 406 if (Grid->RowCount>hWid+1) Grid->ColCount=hWid+1;
xue@0 407
xue@0 408 int CurrentBin=floor(f*Wid+0.5), CurrentFr=floor((t-hWid)*1.0/Offst+0.5);
xue@0 409 if (CurrentFr<0) CurrentFr=0; else if (CurrentFr>maxfr-1) CurrentFr=maxfr-1;
xue@0 410 if (CurrentBin<0) CurrentBin=0; if (CurrentBin>hWid-1) CurrentBin=hWid-1;
xue@0 411 int frst=CurrentFr-Grid->ColCount/2; if (frst<0) frst=0;
xue@0 412 int fren=frst+Grid->ColCount-1; if (fren>maxfr) fren=maxfr, frst=maxfr-Grid->ColCount+1;
xue@0 413 int binst=CurrentBin-Grid->RowCount/2; if (binst<0) binst=0;
xue@0 414 int binen=binst+Grid->RowCount-1; if (binen>hWid) binen=hWid, binst=hWid-Grid->RowCount+1;
xue@0 415
xue@0 416 char format[128];
xue@0 417 memcpy(format, FormatEdit->Text.c_str(), FormatEdit->Text.Length()+1);
xue@0 418
xue@0 419 double *dw=0, *tw=0;
xue@0 420 cdouble *W, *X=0;
xue@0 421
xue@0 422 for (int fr=frst; fr<fren; fr++)
xue@0 423 {
xue@0 424 if (AmpTab->Visible)
xue@0 425 {
xue@0 426 QSPEC_FORMAT* data=WaveView1->A[Channel][fr];
xue@0 427 for (int bin=binst; bin<binen; bin++)
xue@0 428 Grid->Cells[fr-frst+1][binen-bin]=AnsiString().sprintf(format, data[bin]*amp);
xue@0 429 }
xue@0 430 else if (ArcTab->Visible)
xue@0 431 {
xue@0 432 cmplx<QSPEC_FORMAT>* data=WaveView1->Spec[Channel][fr];
xue@0 433 for (int bin=binst; bin<binen; bin++)
xue@0 434 {
xue@0 435 double pvalue=arg(data[bin])*i2pi;
xue@0 436 if (bin%2) pvalue+=prange/2;
xue@0 437 if (pvalue>prange/2) pvalue-=prange;
xue@0 438 Grid->Cells[fr-frst+1][binen-bin]=AnsiString().sprintf(format, pvalue);
xue@0 439 }
xue@0 440 }
xue@0 441
xue@0 442 Grid->Cells[fr-frst+1][0]=fr;
xue@0 443 for (int bin=binst; bin<binen; bin++) Grid->Cells[0][binen-bin]=bin;
xue@0 444 }
xue@0 445
xue@0 446 Grid->Row=binen-CurrentBin;
xue@0 447 Grid->Col=CurrentFr-frst+1;
xue@0 448
xue@0 449 delete[] dw;
xue@0 450 delete[] tw;
xue@0 451 delete[] X;
xue@0 452 }
xue@0 453 else if (WaveView1->FPanes.HasFreqAxis[GridSourcePane] && QPkTab->Visible)
xue@0 454 {
xue@0 455 TStringGrid* Grid=QPkGrid;
xue@0 456 Grid->RowCount=Grid->Height/(Grid->DefaultRowHeight+1);
xue@0 457 int maxfr=(WaveView1->Length-Wid)/Offst+1;
xue@0 458 if (Grid->RowCount>hWid+1) Grid->ColCount=hWid+1;
xue@0 459 TStringList* List=new TStringList;
xue@0 460 for (int c=0; c<Grid->ColCount; c++)
xue@0 461 for (int r=0; r<Grid->RowCount; r++) Grid->Cells[c][r]="";
xue@0 462 delete List;
xue@0 463
xue@0 464 int CurrentBin=floor(f*Wid+0.5), CurrentFr=floor((t-hWid)*1.0/Offst+0.5);
xue@0 465 if (CurrentFr<0) CurrentFr=0; else if (CurrentFr>maxfr-1) CurrentFr=maxfr-1;
xue@0 466 if (CurrentBin<0) CurrentBin=0; if (CurrentBin>hWid-1) CurrentBin=hWid-1;
xue@0 467 int binst=CurrentBin-Grid->RowCount/2; if (binst<0) binst=0;
xue@0 468 int binen=binst+Grid->RowCount-1; if (binen>hWid) binen=hWid, binst=hWid-Grid->RowCount+1;
xue@0 469
xue@0 470
xue@0 471 int frst=CurrentFr-Grid->ColCount/2; if (frst<0) frst=0;
xue@0 472 int fren=frst+Grid->ColCount-1; if (fren>maxfr) fren=maxfr, frst=maxfr-Grid->ColCount+1;
xue@0 473
xue@0 474 char format[128];
xue@0 475 memcpy(format, FormatEdit->Text.c_str(), FormatEdit->Text.Length()+1);
xue@0 476
xue@0 477 Grid->Cells[0][0]=AnsiString().sprintf("fr.%d", CurrentFr);
xue@0 478 for (int bin=binst; bin<binen; bin++) Grid->Cells[0][binen-bin]=bin;
xue@0 479 Grid->Cells[1][0]="f"; Grid->Cells[2][0]="a";
xue@0 480
xue@0 481 double *f=new double[(binen-binst)*3], *a=&f[binen-binst];
xue@0 482 cmplx<QSPEC_FORMAT>* spec=WaveView1->Spec[Channel][CurrentFr];
xue@0 483 cdouble *x=new cdouble[Wid/2+1]; memset(x, 0, sizeof(cdouble)*(Wid/2+1));
xue@0 484 int bnst=binst-2, bnen=binen+2; if (bnst<0) bnst=0; if (bnen>Wid/2) bnen=Wid/2;
xue@0 485 for (int i=bnst; i<bnen; i++) x[i]=spec[i];
xue@0 486 int M; double c[6], iH2;
xue@0 487 windowspec(WaveView1->SpecWindowType, Wid, &M, c, &iH2);
xue@0 488 int p=QuickPeaks(f, a, Wid, x, M, c, iH2, 0.0005, binst, binen);
xue@0 489
xue@0 490 MList* mlist=0;
xue@0 491 int M_, I, p0, q0, *p0s;
xue@0 492 double **h, *s;
xue@0 493 cdouble **u, **du;
xue@0 494 if (p>0)
xue@0 495 {
xue@0 496 mlist=new MList;
xue@0 497 s=new double[Wid]; mlist->Add(s, 1);
xue@0 498 __int16* data=&WaveView1->Data16[Channel][Offst*CurrentFr];
xue@0 499 for (int n=0; n<Wid; n++) s[n]=data[n];
xue@0 500 }
xue@0 501
xue@0 502
xue@0 503 for (int ip=0; ip<p; ip++)
xue@0 504 {
xue@0 505 int bin=floor(f[ip]+0.5);
xue@0 506 Grid->Cells[1][binen-bin]=AnsiString().sprintf(format, f[ip]);
xue@0 507 Grid->Cells[2][binen-bin]=AnsiString().sprintf(format, a[ip]);
xue@0 508 }
xue@0 509
xue@0 510 delete mlist;
xue@0 511
xue@0 512 delete[] x;
xue@0 513 delete[] f;
xue@0 514
xue@0 515 Grid->Row=binen-CurrentBin;
xue@0 516 }
xue@0 517 }
xue@0 518 //---------------------------------------------------------------------------
xue@0 519 void TForm1::SetWaveViewContents()
xue@0 520 {
xue@0 521 int rulers=(WaveView1->FPanes.Count>0)?WaveView1->FPanes.Rulers[0]:7;
xue@0 522 if (WaveView1->ShowInfo) WaveView1->FPanes.MarginOut=TRect(5, WaveView1->DefaultInfoFont->Height, 5, WaveView1->DefaultInfoFont->Height);
xue@0 523 else WaveView1->FPanes.MarginOut=TRect(5, 5, 5, WaveView1->DefaultInfoFont->Height);
xue@0 524 if (WaveView1->Channels>=2 && DisplayChannelRadio->ItemIndex==0)
xue@0 525 {
xue@0 526 int Columns=PanesRadio->ItemIndex+1;
xue@0 527 WaveView1->CreatePanes(Columns, 2);
xue@0 528 int type=SpectrogramView?(FreqLineCheck->Checked?2:1):0;
xue@0 529 WaveView1->SetContent(0, 0, 0, type);
xue@0 530 WaveView1->SetContent(0, 1, 1, type);
xue@0 531 if (Columns>1)
xue@0 532 {
xue@0 533 type=SpectrogramView?0:(FreqLineCheck->Checked?2:1);
xue@0 534 WaveView1->SetContent(1, 0, 0, type);
xue@0 535 WaveView1->SetContent(1, 1, 1, type);
xue@0 536 }
xue@0 537 }
xue@0 538 else
xue@0 539 {
xue@0 540 int Rows=PanesRadio->ItemIndex+1;
xue@0 541 WaveView1->CreatePanes(1, Rows);
xue@0 542 int type=SpectrogramView?(FreqLineCheck->Checked?2:1):0;
xue@0 543 int channel=(WaveView1->Channels>=2 && DisplayChannelRadio->ItemIndex==2)?1:0;
xue@0 544 WaveView1->SetContent(0, 0, channel, type);
xue@0 545 if (Rows>1)
xue@0 546 {
xue@0 547 type=SpectrogramView?0:(FreqLineCheck->Checked?2:1);
xue@0 548 WaveView1->SetContent(0, 1, channel, type);
xue@0 549 }
xue@0 550 }
xue@0 551
xue@0 552 int yscale=LogFreqCheck->Checked?1:0;
xue@0 553 for (int i=0; i<4; i++) WaveView1->SetYScale(i, yscale), WaveView1->SetRulers(i, rulers);
xue@0 554
xue@0 555 WaveView1->ShowCursorText=SpeedButtonCursorText->Down;
xue@0 556 WaveView1->ShowPaneInfo=SpeedButtonPaneInfo->Down;
xue@0 557 }
xue@0 558 //---------------------------------------------------------------------------
xue@0 559 void TForm1::ShowPanel(TPanel* APanel, bool Hide)
xue@0 560 {
xue@0 561 APanel->Visible=!Hide;
xue@0 562 if (APanel==PanelRight) PanelRightButton->Brush->Color=Hide?clTeal:clSilver;
xue@0 563 else if (APanel==PanelGrid) PanelRightButton2->Brush->Color=Hide?clTeal:clSilver;
xue@0 564 }
xue@0 565 //---------------------------------------------------------------------------
xue@0 566 void __fastcall TForm1::SpectrogramBrightness1Click(TObject *Sender)
xue@0 567 {
xue@0 568 WaveView1->SpecAmp=1;
xue@0 569 }
xue@0 570 //---------------------------------------------------------------------------
xue@0 571 //---------------------------------------------------------------------------
xue@0 572 void __fastcall TForm1::SpeedButtonFClick(TObject *Sender)
xue@0 573 {
xue@0 574 if (SpeedButtonF->Down)
xue@0 575 {
xue@0 576 WaveView1->SelectMode=WaveView1->SelectMode|WV2_VSELECT;
xue@0 577 if (GetKeyState(VK_SHIFT)>=0 && SpeedButtonT->Down)
xue@0 578 {
xue@0 579 SpeedButtonT->Down=false;
xue@0 580 WaveView1->SelectMode=WaveView1->SelectMode&(~WV2_HSELECT);
xue@0 581
xue@0 582 }
xue@0 583 }
xue@0 584 else WaveView1->SelectMode=WaveView1->SelectMode&(~WV2_VSELECT);
xue@0 585 }
xue@0 586 //---------------------------------------------------------------------------
xue@0 587
xue@0 588 void __fastcall TForm1::SpeedButtonMClick(TObject *Sender)
xue@0 589 {
xue@0 590 WaveView1->MultiSelect=(SpeedButtonM->Down);
xue@0 591 }
xue@0 592 //---------------------------------------------------------------------------
xue@0 593 void __fastcall TForm1::SpeedButtonTClick(TObject *Sender)
xue@0 594 {
xue@0 595 if (SpeedButtonT->Down)
xue@0 596 {
xue@0 597 WaveView1->SelectMode=WaveView1->SelectMode|WV2_HSELECT;
xue@0 598 if (GetKeyState(VK_SHIFT)>=0 && SpeedButtonF->Down)
xue@0 599 {
xue@0 600 SpeedButtonF->Down=false;
xue@0 601 WaveView1->SelectMode=WaveView1->SelectMode&(~WV2_VSELECT);
xue@0 602 }
xue@0 603 }
xue@0 604 else WaveView1->SelectMode=WaveView1->SelectMode&(~WV2_HSELECT);
xue@0 605 }
xue@0 606 //---------------------------------------------------------------------------
xue@0 607 void __fastcall TForm1::UndoZoom1Click(TObject *Sender)
xue@0 608 {
xue@0 609 WaveView1->UndoExtract(Sender);
xue@0 610 }
xue@0 611 //---------------------------------------------------------------------------
xue@0 612 void ClearObjectByShortTag0(TWaveView* WV, int tag0)
xue@0 613 {
xue@0 614 if (WV->ObjectAtPointer && WV->ObjectAtPointer->ShortTag[0]==tag0) WV->ObjectAtPointer=0;
xue@0 615 int ind=0; for (int i=0; i<WV->FObjects.Count; i++) if (WV->FObjects.Items[i].ShortTag[0]!=tag0) WV->FObjects.Items[ind++]=WV->FObjects.Items[i]; WV->FObjects.Count=ind;
xue@0 616 }
xue@0 617
xue@0 618 void __fastcall TForm1::WaveAudio1Load(TObject*)
xue@0 619 {
xue@0 620 DisplayChannelRadio->Enabled=(WaveAudio1->Channels>1);
xue@0 621 PlayChannelRadio->Enabled=(WaveAudio1->Channels>1);
xue@0 622 ClearObjectByShortTag0(WaveView1, stAtom);
xue@0 623 ClearObjectByShortTag0(WaveView1, stOnset);
xue@0 624 SetWaveViewContents();
xue@0 625 Caption="hv - "+WaveAudio1->FileName;
xue@0 626 if (EventBox) {EventBox->Load(NULL);}
xue@0 627 Navigator1->SetArea(0, 1, 1-WaveView1->EndDigiFreq*2, 1-WaveView1->StartDigiFreq*2);
xue@0 628 Navigator1->Resize();
xue@0 629 }
xue@0 630 //---------------------------------------------------------------------------
xue@0 631 void __fastcall TForm1::WaveView1AfterPaint(TObject*)
xue@0 632 {
xue@0 633 Navigator1->SetArea(WaveView1->StartPos*1.0/WaveView1->Length, WaveView1->EndPos*1.0/WaveView1->Length, 1-WaveView1->EndDigiFreq*2, 1-WaveView1->StartDigiFreq*2);
xue@0 634 fcalculatespcount=WaveView1->TimeStamp1;
xue@0 635 }
xue@0 636 //---------------------------------------------------------------------------
xue@0 637 void __fastcall TForm1::WaveView1BeforePlayback(TObject*)
xue@0 638 {
xue@0 639 if (WaveView1->Selections->Count)
xue@0 640 WaveView1->PlaybackFilter=(TWaveViewPlaybackFilter)PlayFilterCombo->ItemIndex;
xue@0 641 else
xue@0 642 WaveView1->PlaybackFilter=wvfNone;
xue@0 643 WaveView1->StereoMode=(TWaveViewStereoMode)PlayChannelRadio->ItemIndex;
xue@0 644 }
xue@0 645 //---------------------------------------------------------------------------
xue@0 646 int __fastcall TForm1::WaveView1CustomInfo(TObject* Sender)
xue@0 647 {
xue@0 648 TStringList* List=new TStringList;
xue@0 649 List->Add(AnsiString().sprintf(" %d-channel, %dhz, %dbit. ", WaveView1->Channels, WaveView1->SamplesPerSec, WaveView1->BytesPerSample*8));
xue@0 650 if (WaveView1->RulerUnitTime==0)
xue@0 651 List->Add(AnsiString().sprintf(" Time(%d): from %d to %d. ", WaveView1->EndPos-WaveView1->StartPos, WaveView1->StartPos, WaveView1->EndPos));
xue@0 652 else
xue@0 653 {
xue@0 654 double fs=WaveView1->StartPos*1.0/WaveView1->SamplesPerSec, fe=WaveView1->EndPos*1.0/WaveView1->SamplesPerSec;
xue@0 655 List->Add(AnsiString().sprintf(" Time(%.4gs): from %.4gs to %.4gs. ", fe-fs, fs, fe));
xue@0 656 }
xue@0 657 if (WaveView1->RulerUnitFreq==0)
xue@0 658 {
xue@0 659 double fs=WaveView1->StartDigiFreq*WaveView1->SamplesPerSec, fe=WaveView1->EndDigiFreq*WaveView1->SamplesPerSec;
xue@0 660 AnsiString as=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(fs)/C4)), ae=SemitoneToPitch(12*Log2(WV2_LOG_FREQ(fe)/C4));
xue@0 661 List->Add(AnsiString().sprintf(" Frequency: from %.1fhz(%s) to %.1fhz(%s). ", fs, as.c_str(), fe, ae.c_str()));
xue@0 662 }
xue@0 663 else
xue@0 664 List->Add(AnsiString().sprintf(" Frequency: from %.4gbin to %.4gbin. ", WaveView1->StartDigiFreq*WaveView1->SpecRes, WaveView1->EndDigiFreq*WaveView1->SpecRes));
xue@0 665 return (int)List;
xue@0 666 }
xue@0 667
xue@0 668 int __fastcall TForm1::WaveView1CustomPaneInfo(TObject* Sender)
xue@0 669 {
xue@0 670 TStringList* List=new TStringList;
xue@0 671
xue@0 672 if (WaveView1->Channels>1) List->Add(WaveView1->FPanes.Channel[WaveView1->CurrentPane]==0?"Channel: left":"Channel: right");
xue@0 673 if (WaveView1->Selections->Count>0 && WaveView1->Selections->Focus>=0)
xue@0 674 {
xue@0 675 List->Add("Current Selection");
xue@0 676 int st=WaveView1->Selections->StartPos, en=WaveView1->Selections->EndPos;
xue@0 677 List->Add(AnsiString().sprintf("Time(%d): from %d to %d", en-st, st, en));
xue@0 678 // List->Add(AnsiString().sprintf("Frequency: from %.1fhz to %.1fhz", WaveView1->Selections->StartDigiFreq*WaveView1->SamplesPerSec, WaveView1->Selections->EndDigiFreq*WaveView1->SamplesPerSec));
xue@0 679 }
xue@0 680 if (WaveView1->ObjectAtPointer && WaveView1->ObjectAtPointer->ShortTag[0]==stAtom)
xue@0 681 {
xue@0 682 atom* part=(atom*)WaveView1->ObjectAtPointer->Buffer;
xue@0 683 List->Add("Current Atom");
xue@0 684 List->Add(AnsiString().sprintf("Partial %d", WaveView1->ObjectAtPointer->ShortTag[2]));
xue@0 685 List->Add(AnsiString().sprintf("Frame %d", WaveView1->ObjectAtPointer->Tag[2]));
xue@0 686 if (WaveView1->RulerUnitTime==0) List->Add(AnsiString().sprintf("Time %d", int(part->t)));
xue@0 687 else List->Add(AnsiString().sprintf("Time %.4fs", part->t/WaveView1->SamplesPerSec));
xue@0 688 if (WaveView1->RulerUnitFreq==0) List->Add(AnsiString().sprintf("Freq %.2fhz", part->f*WaveView1->SamplesPerSec));
xue@0 689 else List->Add(AnsiString().sprintf("Freq %.2fbin", part->f*WaveView1->SpecRes));
xue@0 690 List->Add(AnsiString().sprintf("Phase%% %.2f", part->p*50/M_PI));
xue@0 691 List->Add(AnsiString().sprintf("Amplitude %.4g", part->a));
xue@0 692 List->Add(AnsiString().sprintf("Scale %d", int(part->s)));
xue@0 693 }
xue@0 694
xue@0 695 return (int)List;
xue@0 696 }
xue@0 697 //---------------------------------------------------------------------------
xue@0 698 void __fastcall TForm1::WaveView1DrawFreqLimiter(TObject* Sender, TWaveViewObject& Obj)
xue@0 699 {
xue@0 700 TCanvas* Canv=WaveView1->Canvas; Canv->Pen->Color=clGreen; Canv->Pen->Mode=pmCopy; Canv->Pen->Style=psDot;
xue@0 701 int X=Obj.Tag[1], Y=WaveView1->FromDigiFreqToPixel(WaveView1->StartPane, f1/WaveView1->SpecRes);
xue@0 702 Canv->MoveTo(X-10, Y); Canv->LineTo(X+10, Y);
xue@0 703 Y=WaveView1->FromDigiFreqToPixel(WaveView1->StartPane, f2/WaveView1->SpecRes);
xue@0 704 Canv->MoveTo(X-10, Y); Canv->LineTo(X+10, Y);
xue@0 705 Canv->Pen->Style=psSolid;
xue@0 706 double delm=HSDelmEdit1->Text.ToDouble();
xue@0 707 Y=WaveView1->FromDigiFreqToPixel(WaveView1->StartPane, (f1-delm)/WaveView1->SpecRes);
xue@0 708 Canv->MoveTo(X-10, Y); Canv->LineTo(X+10, Y);
xue@0 709 Y=WaveView1->FromDigiFreqToPixel(WaveView1->StartPane, (f2+delm)/WaveView1->SpecRes);
xue@0 710 Canv->MoveTo(X-10, Y); Canv->LineTo(X+10, Y);
xue@0 711 }
xue@0 712 //---------------------------------------------------------------------------
xue@0 713 void __fastcall TForm1::WaveView1DrawObject(TObject* Sender, TWaveViewObject& Obj)
xue@0 714 {
xue@0 715 TCanvas* Canv=WaveView1->Canvas;
xue@0 716 int Y=WaveView1->Height;
xue@0 717
xue@0 718 if (Obj.Id>=0)
xue@0 719 {
xue@0 720 if (WaveView1->ObjectAtPointer==&Obj)
xue@0 721 {
xue@0 722 Canv->Brush->Color=clRed; Canv->Brush->Style=bsSolid;
xue@0 723 Canv->Font=WaveView1->DefaultInfoFont; Canv->Font->Color=clWhite;
xue@0 724 }
xue@0 725 else
xue@0 726 {
xue@0 727 Canv->Brush->Color=clBlack; Canv->Brush->Style=bsSolid;
xue@0 728 Canv->Font=WaveView1->DefaultInfoFont; Canv->Font->Color=clWhite;
xue@0 729 }
xue@0 730 AnsiString text; int left, top;
xue@0 731 if (Obj.Id==0)
xue@0 732 {
xue@0 733 text=(WaveView1->RulerUnitTime==1)?AnsiString(" [seconds] "):AnsiString(" [samples] ");
xue@0 734 left=WaveView1->FPanes.MarginOut.left, top=Y-WaveView1->FPanes.MarginOut.bottom;
xue@0 735 }
xue@0 736 else if (Obj.Id==1)
xue@0 737 {
xue@0 738 if (WaveView1->RulerUnitFreq==1)
xue@0 739 {
xue@0 740 if (LogFreqCheck->Checked) text=" [pitch] ";
xue@0 741 else text= " [bin] ";
xue@0 742 }
xue@0 743 else text=" [hz] ";
xue@0 744 left=WaveView1->FObjects.Items[0].Rect.right, top=WaveView1->FObjects.Items[0].Rect.top;
xue@0 745 }
xue@0 746 else if (Obj.Id==2)
xue@0 747 {
xue@0 748 text=(WaveView1->RulerUnitAmp==1)?AnsiString(" [abs. amp] "):AnsiString(" [rel. amp] ");
xue@0 749 left=WaveView1->FObjects.Items[1].Rect.right, top=WaveView1->FObjects.Items[0].Rect.top;
xue@0 750 }
xue@0 751 else if (Obj.Id==3)
xue@0 752 {
xue@0 753 if (WaveView1->FPanes.Rulers[0] & WV2_HSELECT) text=(WaveView1->RulerAlignX==alTop)?AnsiString(" [X axis: top] "):AnsiString(" [X axis: bottom] ");
xue@0 754 else text=" [X axis: off] ";
xue@0 755 left=WaveView1->FObjects.Items[2].Rect.right, top=WaveView1->FObjects.Items[0].Rect.top;
xue@0 756 }
xue@0 757 else if (Obj.Id==4)
xue@0 758 {
xue@0 759 if (WaveView1->FPanes.Rulers[0] & WV2_VSELECT) text=(WaveView1->RulerAlignY==alLeft)?AnsiString(" [Y axis: left] "):AnsiString(" [Y axis: right] ");
xue@0 760 else text=" [Y axis: off] ";
xue@0 761 left=WaveView1->FObjects.Items[3].Rect.right, top=WaveView1->FObjects.Items[0].Rect.top;
xue@0 762 }
xue@0 763 else if (Obj.Id==5)
xue@0 764 {
xue@0 765 if (WaveView1->AutoSpecAmp) text=AnsiString().sprintf(" [spec. amp (auto): %.3g] ", log(WaveView1->SpecAmp)/log(2.0));
xue@0 766 else text=AnsiString().sprintf(" [spec. amp: %.3g] ", log(WaveView1->SpecAmp)/log(2.0));
xue@0 767 left=WaveView1->FObjects.Items[4].Rect.right, top=WaveView1->FObjects.Items[0].Rect.top;
xue@0 768 }
xue@0 769 Canv->TextOut(left, top, text);
xue@0 770 Obj.Rect.left=left, Obj.Rect.top=top, Obj.Rect.right=left+Canv->TextWidth(text), Obj.Rect.bottom=top+Canv->TextHeight(text);
xue@0 771 }
xue@0 772 }
xue@0 773
xue@0 774 //---------------------------------------------------------------------------
xue@0 775 void __fastcall TForm1::WaveView1DrawAtom(TObject* Sender, TWaveViewObject& Obj)
xue@0 776 {
xue@0 777 int pane=0;
xue@0 778 while (pane<WaveView1->FPanes.Count && (!WaveView1->FPanes.HasFreqAxis[pane]
xue@0 779 ||WaveView1->FPanes.Channel[pane]!=Obj.ShortTag[1])) pane++;
xue@0 780 if (pane>=WaveView1->FPanes.Count)
xue@0 781 {Obj.Rect.left=0, Obj.Rect.right=-1, Obj.Rect.top=0, Obj.Rect.bottom=-1; return;}
xue@0 782
xue@0 783 atom* par=(atom*)Obj.Buffer;
xue@0 784 if (par->t<WaveView1->StartPos || par->t>=WaveView1->EndPos || par->f<WaveView1->StartDigiFreq || par->f>WaveView1->EndDigiFreq || par->f<=0)
xue@0 785 {Obj.Rect.left=0, Obj.Rect.right=-1, Obj.Rect.top=0, Obj.Rect.bottom=-1; return;}
xue@0 786
xue@0 787 TCanvas* Canv=WaveView1->Canvas;
xue@0 788 TRect Rect=WaveView1->FPanes.Rect[pane];
xue@0 789 HRGN Rgn=CreateRectRgn(Rect.left, Rect.top, Rect.right, Rect.bottom);
xue@0 790 SelectClipRgn(Canv->Handle, Rgn);
xue@0 791
xue@0 792 int Wid=WaveView1->SpecRes, HOffst=WaveView1->SpecOffst/2; double df=1.0/Wid;
xue@0 793 int X=WaveView1->FromSampleToPixel(pane, par->t), X1=WaveView1->FromSampleToPixel(pane, par->t-HOffst), X2=WaveView1->FromSampleToPixel(pane, par->t+HOffst);
xue@0 794 int Y=WaveView1->FromDigiFreqToPixel(pane, par->f), Y1=WaveView1->FromDigiFreqToPixel(pane, par->f+df), Y2=WaveView1->FromDigiFreqToPixel(pane, par->f-df);
xue@0 795 if (X1>X-1) X1=X-1; if (X2<X+2) X2=X+2;
xue@0 796 if (Y1>Y-1) Y1=Y-1; if (Y2<Y+2) Y2=Y+2;
xue@0 797 Canv->Pen->Mode=pmCopy; Canv->Pen->Style=psSolid;
xue@0 798 bool shiftdown=(GetKeyState(VK_SHIFT)<0), ctrldown=(GetKeyState(VK_CONTROL)<0), onobj=(WaveView1->ObjectAtPointer && WaveView1->ObjectAtPointer->ShortTag[0]==stAtom);
xue@0 799 if (!shiftdown && !ctrldown && onobj
xue@0 800 || !shiftdown && ctrldown && onobj && Obj.ShortTag[2]==WaveView1->ObjectAtPointer->ShortTag[2]
xue@0 801 || shiftdown && !ctrldown && onobj && Obj.Tag[2]==WaveView1->ObjectAtPointer->Tag[2])
xue@0 802 {
xue@0 803 switch (par->type)
xue@0 804 {
xue@0 805 case atAnchor: case atPeak: Canv->Pen->Color=clWhite; break;
xue@0 806 case atInfered: Canv->Pen->Color=clLime; break;
xue@0 807 case atMuted:
xue@0 808 case atBuried: Canv->Pen->Color=clRed; break;
xue@0 809 }
xue@0 810 }
xue@0 811 else
xue@0 812 {
xue@0 813 switch (par->type)
xue@0 814 {
xue@0 815 case atAnchor: case atPeak: Canv->Pen->Color=clGray; break;
xue@0 816 case atInfered: Canv->Pen->Color=clGreen; break;
xue@0 817 case atMuted:
xue@0 818 case atBuried: Canv->Pen->Color=TColor(RGB(128, 0, 0)); break;
xue@0 819 }
xue@0 820 }
xue@0 821 Canv->MoveTo(X-1, Y); Canv->LineTo(X+2, Y); Canv->MoveTo(X, Y-1); Canv->LineTo(X, Y+2);
xue@0 822 if (par->type==atAnchor) {Canv->MoveTo(X, Y+3); Canv->LineTo(X-3, Y); Canv->LineTo(X, Y-3); Canv->LineTo(X+3, Y); Canv->LineTo(X, Y+3);}
xue@0 823 if (WaveView1->ObjectAtPointer==&Obj)
xue@0 824 {
xue@0 825 if (par->type==atAnchor) {Canv->MoveTo(X, Y+4); Canv->LineTo(X-4, Y); Canv->LineTo(X, Y-4); Canv->LineTo(X+4, Y); Canv->LineTo(X, Y+4);}
xue@0 826 else {Canv->Brush->Style=bsClear; Canv->Rectangle(X1, Y1, X2, Y2);}
xue@0 827 }
xue@0 828 Obj.Rect.left=X1, Obj.Rect.right=X2;
xue@0 829 Obj.Rect.top=(Y1<Y-5)?(Y-5):Y1, Obj.Rect.bottom=(Y2>Y+6)?(Y+6):Y2;
xue@0 830 SelectClipRgn(Canv->Handle, NULL);
xue@0 831 DeleteObject(Rgn);
xue@0 832 }
xue@0 833
xue@0 834 //---------------------------------------------------------------------------
xue@0 835 void __fastcall TForm1::WaveView1InfoDblClick(TObject* Sender)
xue@0 836 {
xue@0 837 if (WaveView1->InfoRectAtPointer==1) //time range
xue@0 838 {
xue@0 839 bool timeunit=(WaveView1->RulerUnitTime==0);
xue@0 840 RangeEdit->Caption="Edit time range";
xue@0 841 if (timeunit){RangeEdit->Edit1->Text=WaveView1->StartPos; RangeEdit->Edit2->Text=WaveView1->EndPos;}
xue@0 842 else {RangeEdit->Edit1->Text=WaveView1->StartPos*1.0/WaveView1->SamplesPerSec; RangeEdit->Edit2->Text=WaveView1->EndPos*1.0/WaveView1->SamplesPerSec;}
xue@0 843 if (RangeEdit->ShowModal())
xue@0 844 {
xue@0 845 int NewStartPos, NewEndPos;
xue@0 846 if (timeunit) NewStartPos=RangeEdit->Edit1->Text.ToInt(), NewEndPos=RangeEdit->Edit2->Text.ToInt();
xue@0 847 else NewStartPos=RangeEdit->Edit1->Text.ToDouble()*WaveView1->SamplesPerSec, NewEndPos=RangeEdit->Edit2->Text.ToDouble()*WaveView1->SamplesPerSec;
xue@0 848 if (NewStartPos>NewEndPos) {int tmp=NewStartPos; NewStartPos=NewEndPos; NewEndPos=tmp;}
xue@0 849 if (NewStartPos<0) NewStartPos=0; if (NewEndPos>WaveView1->Length) NewEndPos=WaveView1->Length;
xue@0 850 WaveView1->SetStartAndEndPos(NewStartPos, NewEndPos);
xue@0 851 }
xue@0 852 }
xue@0 853 else if (WaveView1->InfoRectAtPointer==2)
xue@0 854 {
xue@0 855 bool frequnit=(WaveView1->RulerUnitFreq==0);
xue@0 856 RangeEdit->Caption="Edit frequency range";
xue@0 857 if (frequnit){RangeEdit->Edit1->Text=WaveView1->StartDigiFreq*WaveView1->SamplesPerSec; RangeEdit->Edit2->Text=WaveView1->EndDigiFreq*WaveView1->SamplesPerSec;}
xue@0 858 else {RangeEdit->Edit1->Text=WaveView1->StartDigiFreq*WaveView1->SpecRes; RangeEdit->Edit2->Text=WaveView1->EndDigiFreq*WaveView1->SpecRes;}
xue@0 859 if (RangeEdit->ShowModal())
xue@0 860 {
xue@0 861 double NewStartDigiFreq, NewEndDigiFreq;
xue@0 862 if (frequnit) NewStartDigiFreq=RangeEdit->Edit1->Text.ToDouble()/WaveView1->SamplesPerSec, NewEndDigiFreq=RangeEdit->Edit2->Text.ToDouble()/WaveView1->SamplesPerSec;
xue@0 863 else NewStartDigiFreq=RangeEdit->Edit1->Text.ToDouble()/WaveView1->SpecRes, NewEndDigiFreq=RangeEdit->Edit2->Text.ToDouble()/WaveView1->SpecRes;
xue@0 864 if (NewStartDigiFreq>NewEndDigiFreq) {double tmp=NewStartDigiFreq; NewStartDigiFreq=NewEndDigiFreq; NewEndDigiFreq=tmp;}
xue@0 865 if (NewStartDigiFreq<0) NewStartDigiFreq=0; if (NewEndDigiFreq>0.5) NewEndDigiFreq=0.5;
xue@0 866 WaveView1->SetStartAndEndDigiFreq(NewStartDigiFreq, NewEndDigiFreq);
xue@0 867 }
xue@0 868 }
xue@0 869 }
xue@0 870
xue@0 871 //---------------------------------------------------------------------------
xue@0 872
xue@0 873 void __fastcall TForm1::WaveView1KeyPress(TObject* Sender, char &Key)
xue@0 874 {
xue@0 875 if (Key=='a')
xue@0 876 {
xue@0 877 if (PanelGrid->Visible)
xue@0 878 {
xue@0 879 PageControl2->SelectNextPage(true, true);
xue@0 880 }
xue@0 881 }
xue@0 882 else if (Key=='A')
xue@0 883 {
xue@0 884 if (PanelGrid->Visible)
xue@0 885 {
xue@0 886 PageControl2->SelectNextPage(false, true);
xue@0 887 }
xue@0 888 }
xue@0 889 else if (Key=='E')
xue@0 890 {
xue@0 891 if (GetKeyState(VK_SHIFT)<0)
xue@0 892 {
xue@0 893 if (EventBox->HSCount<1) return;
xue@0 894 int idx=-1;
xue@0 895 double delf;
xue@0 896 double f=WaveView1->CurrentDigiFreq;
xue@0 897 int t=WaveView1->CurrentTime, ch=WaveView1->FPanes.Channel[WaveView1->CurrentPane];
xue@0 898 for (int ev=0; ev<EventBox->HSCount; ev++)
xue@0 899 {
xue@0 900 THS* hs=EventBox->HS[ev];
xue@0 901 if (t<hs->StartPos() || t>hs->EndPos()) continue;
xue@0 902 int offst=hs->StdOffst();
xue@0 903 int fr=(t-hs->StartPos())/offst;
xue@0 904 int m=f/hs->Partials[0][fr].f-1;
xue@0 905 if (m<0) m=0;
xue@0 906 if (m>hs->M-1) m=hs->M-1;
xue@0 907 double ldelf=fabs(f-hs->Partials[m][fr].f);
xue@0 908 while (m>0 && ldelf>fabs(f-hs->Partials[m-1][fr].f))
xue@0 909 {
xue@0 910 ldelf=ldelf>fabs(f-hs->Partials[m-1][fr].f);
xue@0 911 m--;
xue@0 912 }
xue@0 913 while (m<hs->M-1 && ldelf>fabs(f-hs->Partials[m+1][fr].f))
xue@0 914 {
xue@0 915 ldelf=fabs(f-hs->Partials[m+1][fr].f);
xue@0 916 m++;
xue@0 917 }
xue@0 918 if (idx==-1 || delf>ldelf)
xue@0 919 {
xue@0 920 delf=ldelf;
xue@0 921 idx=ev;
xue@0 922 }
xue@0 923 }
xue@0 924 if (idx>=0) EventBox->SetItemIndex(idx);
xue@0 925 }}
xue@0 926 }
xue@0 927
xue@0 928
xue@0 929 void __fastcall TForm1::AddHSObject(THS* aHS)
xue@0 930 {
xue@0 931 for (int m=0; m<aHS->M; m++) for (int fr=0; fr<aHS->Fr; fr++)
xue@0 932 {
xue@0 933 if (aHS->Partials[m][fr].f>0)
xue@0 934 {
xue@0 935 TWaveViewObject Obj; memset(&Obj, 0, sizeof(TWaveViewObject));
xue@0 936 Obj.ShortTag[0]=stAtom; Obj.ShortTag[1]=aHS->Channel; Obj.ShortTag[2]=m+1; Obj.ShortTag[3]=0;
xue@0 937 Obj.Tag[2]=fr;
xue@0 938 Obj.DrawObject=WaveView1DrawAtom; Obj.Buffer=&aHS->Partials[m][fr]; Obj.OnKeyDown=WaveView1ParKeyDown;
xue@0 939 Obj.OnMouseDown=WaveView1ParMouseDown; Obj.OnMouseMove=WaveView1ParMouseMove; Obj.OnMouseUp=WaveView1ParMouseUp;
xue@0 940 Obj.OnMouseWheel=WaveView1ParMouseWheel;
xue@0 941 WaveView1->FObjects.Add(Obj);
xue@0 942 }
xue@0 943 }
xue@0 944 }
xue@0 945
xue@0 946 void __fastcall TForm1::WaveView1MouseDown(TObject* Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
xue@0 947 {
xue@0 948 if (WaveView1->OpMode!=wopCrop) WaveView1PopupMenu->AutoPopup=true;
xue@0 949 else WaveView1PopupMenu->AutoPopup=false;
xue@0 950 if (WaveView1->Playing && Shift.Contains(ssCtrl) && Button==mbRight) {WaveView1->PBPR=WaveView1->CurrentTime, WaveView1->ForceOLA=true; WaveView1PopupMenu->AutoPopup=false; return;}
xue@0 951
xue@0 952 if (WaveView1->OpMode==wopHS && WaveView1->FPanes.HasFreqAxis[WaveView1->CurrentPane] && Shift.Contains(ssLeft))
xue@0 953 {
xue@0 954 if (WaveView1->CurrentPane<0) return;
xue@0 955 if (WaveView1->ObjectAtPointer && WaveView1->ObjectAtPointer->ShortTag[0]==stAtom) PartialSelectCombo->ItemIndex=WaveView1->ObjectAtPointer->ShortTag[2]-1;
xue@0 956
xue@0 957 if (Shift.Contains(ssShift) || !(WaveView1->ObjectAtPointer && WaveView1->ObjectAtPointer->ShortTag[0]==stAtom))
xue@0 958 {
xue@0 959 double _f=WaveView1->CurrentDigiFreq;
xue@0 960 int _t=WaveView1->CurrentTime, SpecRes=WaveView1->SpecRes, SpecOffst=WaveView1->SpecOffst;
xue@0 961
xue@0 962 int frst=(WaveView1->StartPos-SpecRes/2)/SpecOffst, fren=(WaveView1->EndPos-SpecRes/2)/SpecOffst;
xue@0 963 if (frst<0) frst=0;
xue@0 964
xue@0 965 int M, Fr; atom** Partials;
xue@0 966 int Channel=WaveView1->FPanes.Channel[WaveView1->CurrentPane];
xue@0 967 NMSettings settings; PrepareNMSettings(&settings);
xue@0 968 int tag=FindNote(_t, _f, M, Fr, Partials, frst, fren, SpecRes, SpecOffst, WaveView1->Spectrogram[Channel], settings);
xue@0 969
xue@0 970 if (M>0)
xue@0 971 {
xue@0 972 if (!HS) HS=EventBox->NewHS(0, 0);
xue@0 973 else
xue@0 974 {
xue@0 975 ClearObjectByShortTag0(WaveView1, stAtom);
xue@0 976 if (HS->Partials) DeAlloc2(HS->Partials);
xue@0 977 if (HS->startamp) {DeAlloc2(HS->startamp); HS->st_count=0;}
xue@0 978 }
xue@0 979 HS->M=M, HS->Fr=Fr; HS->Partials=Partials;
xue@0 980 HS->Channel=Channel;
xue@0 981
xue@0 982 AddHSObject(HS);
xue@0 983 if (tag) HS->isconstf=1;
xue@0 984
xue@0 985 EventBox->ListBox1->Items->Strings[EventBox->ListBox1->ItemIndex]
xue@0 986 =((HS->Channel==0)?"left: ":"right: ")
xue@0 987 +AnsiString().sprintf("%.2fs, ", HS->Partials[0][0].t*1.0/WaveView1->SamplesPerSec)
xue@0 988 +SemitoneToPitch(Log2(HS->Partials[0][0].f*WaveView1->SamplesPerSec/C4)*12);
xue@0 989 if (!EventBox->Visible)
xue@0 990 {
xue@0 991 EventBox->Left=Left+Width;
xue@0 992 EventBox->Top=Top;
xue@0 993 EventBox->Height=Height;
xue@0 994 EventBox->Show();
xue@0 995 }
xue@0 996 }
xue@0 997 }
xue@0 998 }
xue@0 999 }
xue@0 1000 //---------------------------------------------------------------------------
xue@0 1001 void __fastcall TForm1::WaveView1MouseMove(TObject* Sender, TShiftState Shift, int X, int Y)
xue@0 1002 {
xue@0 1003 if (Shift.Contains(ssRight) && (X!=WaveView1->StartSelX || Y!=WaveView1->StartSelY))
xue@0 1004 if (WaveView1PopupMenu->AutoPopup) WaveView1PopupMenu->AutoPopup=false;
xue@0 1005 if (PanelGrid->Visible && (!MBCheck->Checked || Shift.Contains(ssShift))) SetGridContents();
xue@0 1006 if (Shift.Contains(ssLeft) && WaveView1->OpMode==wopSample)
xue@0 1007 {
xue@0 1008 int channel=WaveView1->FPanes.Channel[WaveView1->StartPane],
xue@0 1009 t=WaveView1->StartSel;
xue@0 1010 WaveView1->Data16[channel][t]=WaveView1->FromPixelToAmplitude(WaveView1->StartPane, Y);
xue@0 1011 WaveView1->ExtDataChange(Sender, channel, t, t);
xue@0 1012 }
xue@0 1013 }
xue@0 1014 //---------------------------------------------------------------------------
xue@0 1015 void __fastcall TForm1::WaveView1MousePointer(TObject* Sender, int Pane, int t, double f)
xue@0 1016 {
xue@0 1017 }
xue@0 1018 //---------------------------------------------------------------------------
xue@0 1019 void __fastcall TForm1::WaveView1MouseUp(TObject* Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
xue@0 1020 {
xue@0 1021 }
xue@0 1022
xue@0 1023 //---------------------------------------------------------------------------
xue@0 1024 void __fastcall TForm1::WaveView1MouseWheel(TObject* Sender, TShiftState Shift, int WheelDelta, const TPoint& MousePos, bool& Handled)
xue@0 1025 {
xue@0 1026 if (Shift.Contains(ssRight))
xue@0 1027 {
xue@0 1028 if (WaveView1PopupMenu->AutoPopup) WaveView1PopupMenu->AutoPopup=false;
xue@0 1029 if (WaveView1->OpMode==wopDrag) WaveView1->StartDrag(WaveView1->LastX, WaveView1->LastY); //dragmode=false;
xue@0 1030 }
xue@0 1031 }
xue@0 1032 //---------------------------------------------------------------------------
xue@0 1033 void __fastcall TForm1::WaveView1ObjectClick(TObject*)
xue@0 1034 {
xue@0 1035 if (WaveView1->ObjectAtPointer->Id==0) WaveView1->RulerUnitTime=1-WaveView1->RulerUnitTime;
xue@0 1036 else if (WaveView1->ObjectAtPointer->Id==1) WaveView1->RulerUnitFreq=1-WaveView1->RulerUnitFreq;
xue@0 1037 else if (WaveView1->ObjectAtPointer->Id==2) WaveView1->RulerUnitAmp=1-WaveView1->RulerUnitAmp;
xue@0 1038 else if (WaveView1->ObjectAtPointer->Id==3){
xue@0 1039 if (WaveView1->FPanes.Rulers[0] & WV2_HSELECT){if (WaveView1->RulerAlignX==alTop) WaveView1->RulerAlignX=alBottom; else {int rulers=WaveView1->FPanes.Rulers[0] & ~WV2_HSELECT; for (int i=0; i<WaveView1->FPanes.Count; i++) WaveView1->FPanes.Rulers[i]=rulers; WaveView1->InvalidateBasic(-1, 0); WaveView1->RulerAlignX=alTop;}}
xue@0 1040 else {int rulers=WaveView1->FPanes.Rulers[0] | WV2_HSELECT; for (int i=0; i<WaveView1->FPanes.Count; i++) WaveView1->FPanes.Rulers[i]=rulers; WaveView1->InvalidateBasic(-1, 0); WaveView1->RulerAlignX=alTop;}}
xue@0 1041 else if (WaveView1->ObjectAtPointer->Id==4){
xue@0 1042 if (WaveView1->FPanes.Rulers[0] & (WV2_VSELECT|WV2_AMP)){if (WaveView1->RulerAlignY==alLeft) WaveView1->RulerAlignY=alRight; else {int rulers=WaveView1->FPanes.Rulers[0] & ~WV2_VSELECT & ~WV2_AMP; for (int i=0; i<WaveView1->FPanes.Count; i++) WaveView1->FPanes.Rulers[i]=rulers; WaveView1->InvalidateBasic(-1, 0); WaveView1->RulerAlignY=alLeft;}}
xue@0 1043 else {int rulers=WaveView1->FPanes.Rulers[0] | WV2_VSELECT | WV2_AMP; for (int i=0; i<WaveView1->FPanes.Count; i++) WaveView1->FPanes.Rulers[i]=rulers; WaveView1->InvalidateBasic(-1, 0); WaveView1->RulerAlignY=alLeft;}}
xue@0 1044 }
xue@0 1045 //---------------------------------------------------------------------------
xue@0 1046 void __fastcall TForm1::WaveView1ObjectDblClick(TObject*)
xue@0 1047 {
xue@0 1048 if (WaveView1->ObjectAtPointer->Id==5)
xue@0 1049 {
xue@0 1050 if (GetKeyState(VK_CONTROL)<0) WaveView1->AutoSpecAmp=!WaveView1->AutoSpecAmp;
xue@0 1051 else WaveView1->SpecAmp=1;
xue@0 1052 }
xue@0 1053 }
xue@0 1054 //---------------------------------------------------------------------------
xue@0 1055 void __fastcall TForm1::WaveView1ObjectMouseWheel(TObject* Sender, TShiftState Shift, int WheelDelta, const TPoint& MousePos, bool& Handled)
xue@0 1056 {
xue@0 1057 if (WaveView1->ObjectAtPointer->Id==5)
xue@0 1058 {
xue@0 1059 double amp=(WheelDelta>0)?sqrt(2.0):sqrt(0.5);
xue@0 1060 if (WaveView1->AutoSpecAmp) WaveView1->maxv_specamp*=amp;
xue@0 1061 WaveView1->SpecAmp*=amp;
xue@0 1062 }
xue@0 1063 }
xue@0 1064 //---------------------------------------------------------------------------
xue@0 1065 void __fastcall TForm1::WaveView1OpMode(TObject* Sender, TShiftState Shift, int& OpMode)
xue@0 1066 {
xue@0 1067 AnsiString S="";
xue@0 1068 if (WaveView1->Length<=0) OpMode=wopIdle;
xue@0 1069 else if (GetKeyState('X')<0) {OpMode=wopCrop; S="Crop"; WaveView1PopupMenu->AutoPopup=false;} //crop mode
xue@0 1070 else if ((SpeedButtonSelect->Down || GetKeyState('S')<0) && !EditorPanel->Visible) {OpMode=wopHS; WaveView1->Cursor=crArrow, S="Sinusoid"; WaveView1PopupMenu->AutoPopup=false;}//special select mode
xue@0 1071 else if (WaveView1->ObjectAtPointer && WaveView1->ObjectAtPointer->ShortTag[0]==stAtom) {OpMode=wopEdit; WaveView1->Cursor=crHandPoint; S="Edit";} //Edit mode
xue@0 1072 else if (Shift.Contains(ssCtrl)) OpMode=wopReselect, S="Reselect"; //re-select mode
xue@0 1073 else if (Shift.Contains(ssRight)) OpMode=wopDrag, S="Drag"; //drag mode
xue@0 1074 else if (WaveView1->CurrentPane>=0
xue@0 1075 && WaveView1->FPanes.Type[WaveView1->CurrentPane]==0
xue@0 1076 && (WaveView1->EndPos-WaveView1->StartPos)*10<WaveView1->FPanes.Rect[WaveView1->CurrentPane].Width()
xue@0 1077 && abs(WaveView1->CurrentSampleInPixel-WaveView1->CurrentY)<5)
xue@0 1078 {
xue@0 1079 OpMode=wopSample, S="Edit";
xue@0 1080 if (WaveView1->Cursor!=crHandPoint){WaveView1->Cursor=crHandPoint; ::SetCursor(Screen->Cursors[crHandPoint]);}
xue@0 1081 }
xue@0 1082 else OpMode=wopSelect, S="Select"; //select mode
xue@0 1083 StatusBar1->Panels->Items[0]->Text=S;
xue@0 1084 }
xue@0 1085 //---------------------------------------------------------------------------
xue@0 1086 void __fastcall TForm1::CropEventStart(TObject*, TShiftState Shift)
xue@0 1087 {
xue@0 1088 int dfr=WaveView1->ObjectAtPointer->Tag[2];
xue@0 1089 if (Shift.Contains(ssShift))
xue@0 1090 {
xue@0 1091 int dm=WaveView1->ObjectAtPointer->ShortTag[2];
xue@0 1092 for (int i=0; i<WaveView1->FObjects.Count; i++)
xue@0 1093 {
xue@0 1094 TWaveViewObject Obj=WaveView1->FObjects.Items[i];
xue@0 1095 if (Obj.ShortTag[0]==stAtom && Obj.ShortTag[2]==dm && Obj.Tag[2]<dfr) ((atom*)Obj.Buffer)->type=atMuted;
xue@0 1096 }
xue@0 1097 }
xue@0 1098 else
xue@0 1099 {
xue@0 1100 for (int m=0; m<HS->M; m++) for (int fr=0; fr<HS->Fr-dfr; fr++)
xue@0 1101 HS->Partials[m][fr]=HS->Partials[m][fr+dfr];
xue@0 1102 HS->Fr-=dfr;
xue@0 1103 int ind=0;
xue@0 1104 for (int i=0; i<WaveView1->FObjects.Count; i++)
xue@0 1105 {
xue@0 1106 TWaveViewObject Obj=WaveView1->FObjects.Items[i];
xue@0 1107 if (Obj.ShortTag[0]==stAtom)
xue@0 1108 {
xue@0 1109 {
xue@0 1110 if (Obj.Tag[2]>=dfr)
xue@0 1111 {
xue@0 1112 Obj.Tag[2]-=dfr;
xue@0 1113 Obj.Buffer=&HS->Partials[Obj.ShortTag[2]-1][Obj.Tag[2]];
xue@0 1114 if (WaveView1->ObjectAtPointer==&WaveView1->FObjects.Items[i]) WaveView1->ObjectAtPointer=&WaveView1->FObjects.Items[ind];
xue@0 1115 if (WaveView1->StartObject==&WaveView1->FObjects.Items[i]) WaveView1->StartObject=&WaveView1->FObjects.Items[ind];
xue@0 1116 WaveView1->FObjects.Items[ind++]=Obj;
xue@0 1117 }
xue@0 1118 else {}
xue@0 1119 }
xue@0 1120 }
xue@0 1121 else WaveView1->FObjects.Items[ind++]=Obj;
xue@0 1122 }
xue@0 1123 WaveView1->FObjects.Count=ind;
xue@0 1124 int EBLI=EventBox->ListBox1->ItemIndex;
xue@0 1125 if (HS==EventBox->HS[EBLI])
xue@0 1126 {
xue@0 1127 EventBox->ListBox1->Items->Strings[EBLI]=(HS->Channel==0?"left: ":"right: ")
xue@0 1128 +AnsiString().sprintf("%.2fs, ", HS->Partials[0][0].t*1.0/WaveView1->SamplesPerSec)
xue@0 1129 +SemitoneToPitch(Log2(HS->Partials[0][0].f*WaveView1->SamplesPerSec/C4)*12);
xue@0 1130 }
xue@0 1131 }
xue@0 1132 }
xue@0 1133 void __fastcall TForm1::CropEventEnd(TObject*, TShiftState Shift)
xue@0 1134 {
xue@0 1135 int dfr=WaveView1->ObjectAtPointer->Tag[2];
xue@0 1136 if (Shift.Contains(ssShift))
xue@0 1137 {
xue@0 1138 int dm=WaveView1->ObjectAtPointer->ShortTag[2];
xue@0 1139 for (int i=0; i<WaveView1->FObjects.Count; i++)
xue@0 1140 {
xue@0 1141 TWaveViewObject Obj=WaveView1->FObjects.Items[i];
xue@0 1142 if (Obj.ShortTag[0]==stAtom && Obj.ShortTag[2]==dm && Obj.Tag[2]>dfr) ((atom*)Obj.Buffer)->type=atMuted;
xue@0 1143 }
xue@0 1144 return;
xue@0 1145 }
xue@0 1146 HS->Fr=dfr+1;
xue@0 1147 int ind=0;
xue@0 1148 for (int i=0; i<WaveView1->FObjects.Count; i++)
xue@0 1149 {
xue@0 1150 TWaveViewObject Obj=WaveView1->FObjects.Items[i];
xue@0 1151 if (Obj.ShortTag[0]==stAtom && Obj.Tag[2]>dfr) {}
xue@0 1152 else
xue@0 1153 {
xue@0 1154 if (WaveView1->ObjectAtPointer==&WaveView1->FObjects.Items[i]) WaveView1->ObjectAtPointer=&WaveView1->FObjects.Items[ind];
xue@0 1155 if (WaveView1->StartObject==&WaveView1->FObjects.Items[i]) WaveView1->StartObject=&WaveView1->FObjects.Items[ind];
xue@0 1156 WaveView1->FObjects.Items[ind++]=Obj;
xue@0 1157 }
xue@0 1158 }
xue@0 1159 WaveView1->FObjects.Count=ind;
xue@0 1160 }
xue@0 1161 void __fastcall TForm1::WaveView1ParKeyDown(TObject*, Word& Key, TShiftState Shift)
xue@0 1162 {
xue@0 1163 if ((WaveView1->OpMode==wopHS || WaveView1->OpMode==wopEdit) && WaveView1->ObjectAtPointer->ShortTag[0]==stAtom)
xue@0 1164 {
xue@0 1165 if (Key==VK_DELETE)
xue@0 1166 {
xue@0 1167 atom* par=(atom*)WaveView1->ObjectAtPointer->Buffer;
xue@0 1168 if (par->type==atAnchor)
xue@0 1169 {
xue@0 1170 if (Shift.Contains(ssShift) && Shift.Contains(ssCtrl))
xue@0 1171 {
xue@0 1172 atom** Partials=HS->Partials;
xue@0 1173 for (int m=0; m<HS->M; m++) for (int fr=0; fr<HS->Fr; fr++) if (Partials[m][fr].type==atAnchor) Partials[m][fr].type=atPeak;
xue@0 1174 }
xue@0 1175 else if (Shift.Contains(ssShift))
xue@0 1176 {
xue@0 1177 atom** Partials=HS->Partials; int fr=WaveView1->ObjectAtPointer->Tag[2];
xue@0 1178 for (int m=0; m<HS->M; m++) if (Partials[m][fr].type==atAnchor) Partials[m][fr].type=atPeak;
xue@0 1179 }
xue@0 1180 else {par->type=atPeak;}
xue@0 1181 WaveView1->Invalidate();
xue@0 1182 }
xue@0 1183 }
xue@0 1184 }
xue@0 1185 }
xue@0 1186 //---------------------------------------------------------------------------
xue@0 1187 #define ExFpStiff ExFmStiff
xue@0 1188 void __fastcall TForm1::WaveView1ParMouseDown(TObject* Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
xue@0 1189 {
xue@0 1190 if (WaveView1->OpMode==wopHS && Shift.Contains(ssShift)) return;
xue@0 1191 if (WaveView1->ObjectAtPointer->ShortTag[0]!=stAtom) return;
xue@0 1192 if (WaveView1->OpMode==wopHS)
xue@0 1193 {
xue@0 1194 if (!Shift.Contains(ssLeft)) return;
xue@0 1195 edfr=WaveView1->ObjectAtPointer->Tag[2]; int M=HS->M, Fr=HS->Fr, p=WaveView1->ObjectAtPointer->ShortTag[2];
xue@0 1196 anccount=0;
xue@0 1197 ancps=(int*)realloc(ancps, sizeof(int)*M); ancfs=(double*)realloc(ancfs, sizeof(double)*M);
xue@0 1198 ancfrs=(int*)realloc(ancfrs, sizeof(int)*M);
xue@0 1199 atom** Partials=HS->Partials;
xue@0 1200
xue@0 1201 int frst=edfr, fren=edfr+1;
xue@0 1202 if (HS->isconstf) frst=0, fren=HS->Fr;
xue@0 1203
xue@0 1204 int N=WaveView1->SpecRes;
xue@0 1205 for (int m=0; m<M; m++)
xue@0 1206 {
xue@0 1207 for (int fr=frst; fr<fren; fr++)
xue@0 1208 {
xue@0 1209 if (m+1==p) continue;
xue@0 1210 double f=Partials[m][fr].f;
xue@0 1211 if (f>0 && HS->Partials[m][fr].type==atAnchor)
xue@0 1212 {
xue@0 1213 ancps[anccount]=m+1, ancfs[anccount]=f*N;
xue@0 1214 ancfrs[anccount]=(HS->Partials[m][fr].tags&ATOM_LOCALANCHOR)?fr:(-1); //fr>=0: local anchor, used in constant-f tracking
xue@0 1215 anccount++;
xue@0 1216 break;
xue@0 1217 }
xue@0 1218 }
xue@0 1219 }
xue@0 1220 if (anccount>0)
xue@0 1221 {
xue@0 1222 double delm=HSDelmEdit1->Text.ToDouble(), maxB=HSMaxBEdit1->Text.ToDouble();
xue@0 1223 TPolygon* R=new TPolygon(4+anccount*2);
xue@0 1224 InitializeR(R, ancps[0], ancfs[0], delm, maxB);
xue@0 1225 for (int i=1; i<anccount; i++) CutR(R, ancps[i], ancfs[i], delm);
xue@0 1226 ExFpStiff(f1, f2, p, R->N, R->X, R->Y);
xue@0 1227
xue@0 1228 TWaveViewObject Obj; memset(&Obj, 0, sizeof(TWaveViewObject));
xue@0 1229 Obj.ShortTag[0]=stFreqDelimiter; Obj.Tag[1]=WaveView1->FromSampleToPixel(WaveView1->StartPane, Partials[p-1][edfr].t); Obj.DrawObject=WaveView1DrawFreqLimiter;
xue@0 1230 WaveView1->FObjects.Add(Obj);
xue@0 1231 delete R;
xue@0 1232 }
xue@0 1233 }
xue@0 1234 else if (WaveView1->OpMode==wopCrop)
xue@0 1235 {
xue@0 1236 bool refresh=false;
xue@0 1237 if (Button==mbLeft) CropEventStart(0, Shift), refresh=true;
xue@0 1238 else if (Button==mbRight) CropEventEnd(0, Shift), refresh=true;
xue@0 1239 if (refresh) WaveView1->Invalidate();
xue@0 1240 }
xue@0 1241 }
xue@0 1242
xue@0 1243 void __fastcall TForm1::WaveView1ParMouseMove(TObject* Sender, TShiftState Shift, int X, int Y)
xue@0 1244 {
xue@0 1245 if (Shift.Contains(ssLeft))
xue@0 1246 {
xue@0 1247 WaveView1->ObjectAtPointer=WaveView1->StartObject;
xue@0 1248 if (Y==WaveView1->LastY) return;
xue@0 1249 if (WaveView1->OpMode==wopHS) //harmonic sinusoid estimation mode
xue@0 1250 { //*
xue@0 1251 if (!WaveView1->StartObject) return;
xue@0 1252 atom* par=(atom*)WaveView1->StartObject->Buffer;
xue@0 1253 int t=par->t, wid=WaveView1->SpecRes, offst=WaveView1->SpecOffst;
xue@0 1254 int hwid=wid/2, fr=(t-hwid)/offst;
xue@0 1255 double f0=WaveView1->CurrentDigiFreq*wid, B;
xue@0 1256
xue@0 1257 int Channel=WaveView1->StartObject->ShortTag[1];
xue@0 1258
xue@0 1259 cdouble *x=new cdouble[hwid+1];
xue@0 1260 cmplx<QSPEC_FORMAT>* spec=WaveView1->Spec[Channel][fr];
xue@0 1261 for (int i=0; i<=hwid; i++) x[i]=spec[i];
xue@0 1262 TPolygon* R=new TPolygon(1024); R->N=0;
xue@0 1263
xue@0 1264 NMSettings settings; PrepareNMSettings(&settings);
xue@0 1265 settings.pcount=anccount; settings.pin=ancps; settings.pinf=ancfs; settings.pin0asanchor=true;
xue@0 1266 settings.pinfr=ancfrs;
xue@0 1267
xue@0 1268 if (!HS->isconstf)
xue@0 1269 {
xue@0 1270 double fpp[1024], *vfpp=&fpp[256], *pfpp=&fpp[512]; atomtype *ptype=(atomtype*)&fpp[768];
xue@0 1271 memset(fpp, 0, sizeof(double)*1024);
xue@0 1272 NMResults results={fpp, vfpp, pfpp, ptype};
xue@0 1273
xue@0 1274 NoteMatchStiff3(R, f0, B, 1, &x, wid, 0, &settings, &results, 0, 0, ds0);
xue@0 1275 atom part; part.t=par->t; part.s=par->s;
xue@0 1276 if (f0>0)
xue@0 1277 {
xue@0 1278 int Fr=WaveView1->StartObject->Tag[2];
xue@0 1279 for (int i=0; i<settings.maxp; i++)
xue@0 1280 {
xue@0 1281 if (fpp[i]>0)
xue@0 1282 {
xue@0 1283 if (i<HS->M)
xue@0 1284 {
xue@0 1285 part.f=fpp[i]/wid;
xue@0 1286 part.a=vfpp[i];
xue@0 1287 part.p=pfpp[i];
xue@0 1288 part.pin=i+1;
xue@0 1289 part.type=ptype[i];
xue@0 1290 HS->Partials[i][Fr]=part;
xue@0 1291 }
xue@0 1292 }
xue@0 1293 else
xue@0 1294 {
xue@0 1295 for (int j=i; j<HS->M; j++) HS->Partials[j][Fr].f=0;
xue@0 1296 break;
xue@0 1297 }
xue@0 1298 }
xue@0 1299 }
xue@0 1300 }
xue@0 1301 else //HS->isconstf==true
xue@0 1302 {
xue@0 1303 int Fr=HS->Fr, maxp=settings.maxp;
xue@0 1304 Alloc2(Fr*3, maxp+2, fpp); double **vfpp=&fpp[Fr], **pfpp=&fpp[Fr*2];
xue@0 1305 atomtype** Allocate2(atomtype, Fr, maxp+2, ptype);
xue@0 1306 NMResults* results=new NMResults[Fr];
xue@0 1307 for (int fr=0; fr<Fr; fr++) results[fr].fp=fpp[fr], results[fr].vfp=vfpp[fr], results[fr].pfp=pfpp[fr], results[fr].ptype=ptype[fr];
xue@0 1308 cdouble** Allocate2(cdouble, Fr, hwid+1, xx);
xue@0 1309 int frst=(HS->Partials[0][0].t-hwid)/offst;
xue@0 1310 for (int fr=0; fr<Fr; fr++)
xue@0 1311 {
xue@0 1312 cmplx<QSPEC_FORMAT>* spec=WaveView1->Spec[Channel][frst+fr];
xue@0 1313 for (int i=0; i<=hwid; i++) xx[fr][i]=spec[i];
xue@0 1314 }
xue@0 1315
xue@0 1316 if (Shift.Contains(ssCtrl)) NoteMatchStiff3(R, f0, B, Fr, xx, wid, offst, &settings, results, 0, 0, ds0, true, WaveView1->StartObject->Tag[2], 3);
xue@0 1317 else NoteMatchStiff3(R, f0, B, Fr, xx, wid, offst, &settings, results, 0, 0, ds0, false, WaveView1->StartObject->Tag[2], 3);
xue@0 1318 if (f0>0)
xue@0 1319 {
xue@0 1320 for (int fr=0; fr<Fr; fr++)
xue@0 1321 {
xue@0 1322 double *fppfr=fpp[fr], *vfppfr=vfpp[fr], *pfppfr=pfpp[fr];
xue@0 1323 atomtype *ptypefr=ptype[fr];
xue@0 1324 for (int i=0; i<HS->M; i++)
xue@0 1325 {
xue@0 1326 atom* part=&HS->Partials[i][fr];
xue@0 1327 if (fppfr[i]>0)
xue@0 1328 {
xue@0 1329 if (i<HS->M)
xue@0 1330 {
xue@0 1331 part->f=fppfr[i]/wid;
xue@0 1332 part->a=vfppfr[i];
xue@0 1333 part->p=pfppfr[i];
xue@0 1334 part->pin=i+1;
xue@0 1335 if (ptypefr[i]) part->type=ptypefr[i];
xue@0 1336 else if (i==settings.pin0-1) part->type=atPeak;
xue@0 1337 }
xue@0 1338 }
xue@0 1339 else
xue@0 1340 {
xue@0 1341 for (int j=i; j<HS->M; j++) HS->Partials[j][fr].f=0;
xue@0 1342 break;
xue@0 1343 }
xue@0 1344 }
xue@0 1345 }
xue@0 1346 atom* atm=&HS->Partials[settings.pin0-1][WaveView1->StartObject->Tag[2]];
xue@0 1347 atm->type=atAnchor;
xue@0 1348 if (Shift.Contains(ssCtrl)) atm->tags=atm->tags|ATOM_LOCALANCHOR;
xue@0 1349 else atm->tags=atm->tags&~ATOM_LOCALANCHOR;
xue@0 1350 }
xue@0 1351 DeAlloc2(xx); delete[] results; DeAlloc2(fpp); DeAlloc2(ptype);
xue@0 1352 }
xue@0 1353 delete R;
xue@0 1354 delete[] x;
xue@0 1355 }
xue@0 1356 else if (WaveView1->OpMode==wopCrop) //crop mode
xue@0 1357 {
xue@0 1358 }
xue@0 1359 else if (WaveView1->OpMode==wopEdit) //HS edit mode
xue@0 1360 {
xue@0 1361 if (GetKeyState('F')<0)
xue@0 1362 {
xue@0 1363 Amplify1Click(FM1);
xue@0 1364 }
xue@0 1365 else
xue@0 1366 {
xue@0 1367 Amplify1Click(Pitchshifting1);
xue@0 1368 double f1=WaveView1->FromPixelToDigiFreq(WaveView1->StartPane, WaveView1->StartSelY),
xue@0 1369 f2=WaveView1->FromPixelToDigiFreq(WaveView1->StartPane, Y);
xue@0 1370 double dp=12*Log2(f2/f1);
xue@0 1371 EditorPanel->PitchEdit1->Text=dp;
xue@0 1372 EditorPanel->AmpEdit1KeyPress(EditorPanel->PitchEdit1, ReturnKey);
xue@0 1373 }
xue@0 1374 }
xue@0 1375 }
xue@0 1376 }
xue@0 1377
xue@0 1378 TPolygon* RFromAtoms(int& startp, double* vfped, double starts, int M, int fr, atom** Partials, int wid, double delm, double maxB)
xue@0 1379 {
xue@0 1380 TPolygon* R=new TPolygon(M*2+4); R->N=0;
xue@0 1381 memset(vfped, 0, sizeof(double)*M);
xue@0 1382 startp=M;
xue@0 1383 for (int m=0; m<M; m++)
xue@0 1384 {
xue@0 1385 double lf=Partials[m][fr].f*wid, la=Partials[m][fr].a;
xue@0 1386 if (lf>0)
xue@0 1387 {
xue@0 1388 if (Partials[m][fr].type<=1)
xue@0 1389 {
xue@0 1390 if (R->N==0) InitializeR(R, m+1, lf, delm, maxB);
xue@0 1391 else if (la>1) CutR(R, m+1, lf, delm, true);
xue@0 1392 }
xue@0 1393 vfped[m]=la; starts+=la*la;
xue@0 1394 }
xue@0 1395 else {startp=m; break;}
xue@0 1396 }
xue@0 1397 return R;
xue@0 1398 }
xue@0 1399
xue@0 1400 void __fastcall TForm1::WaveView1ParMouseUp(TObject* Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
xue@0 1401 {
xue@0 1402 if (Button==mbRight) return;
xue@0 1403
xue@0 1404 if (WaveView1->OpMode==wopHS)
xue@0 1405 {
xue@0 1406 if (!WaveView1->StartObject) return;
xue@0 1407 ClearObjectByShortTag0(WaveView1, stFreqDelimiter); //erase the delimiter
xue@0 1408
xue@0 1409 int M=HS->M, Fr=HS->Fr; atom** Partials=HS->Partials;
xue@0 1410 //*
xue@0 1411 edfr=WaveView1->StartObject->Tag[2];
xue@0 1412 int channel=WaveView1->StartObject->ShortTag[1];
xue@0 1413 int wid=WaveView1->SpecRes, offst=WaveView1->SpecOffst, hwid=wid/2;
xue@0 1414 NMSettings settings; PrepareNMSettings(&settings);
xue@0 1415 int maxp=settings.maxp;
xue@0 1416
xue@0 1417 if (HS->isconstf)
xue@0 1418 {
xue@0 1419 double brake=0.1;
xue@0 1420 if (edfr==0 || edfr==Fr-1)
xue@0 1421 {
xue@0 1422 int frst, fren, edt=HS->Partials[0][edfr].t, startfr=(edt-hwid)/offst;
xue@0 1423 atom* part;
xue@0 1424 if (edfr==0)
xue@0 1425 {
xue@0 1426 frst=ceil((WaveView1->StartPos-hwid)*1.0/offst); if (frst<0) frst=0;
xue@0 1427 part=new atom[M*(Fr+startfr-frst+1)];
xue@0 1428 }
xue@0 1429 else //edfr==Fr-1
xue@0 1430 {
xue@0 1431 fren=floor((WaveView1->EndPos-hwid)*1.0/offst);
xue@0 1432 part=new atom[M*(Fr+fren-startfr+1)];
xue@0 1433 }
xue@0 1434 int k=0; for (int fr=0; fr<Fr; fr++) for (int m=0; m<M; m++) if (Partials[m][fr].f>0) part[k++]=Partials[m][fr];
xue@0 1435
xue@0 1436 double ene0=0;
xue@0 1437 for (int m=0; m<HS->M; m++)
xue@0 1438 {
xue@0 1439 if (HS->Partials[m][edfr].f>0)
xue@0 1440 {
xue@0 1441 double tmp=HS->Partials[m][edfr].a;
xue@0 1442 ene0+=tmp*tmp;
xue@0 1443 }
xue@0 1444 else break;
xue@0 1445 }
xue@0 1446
xue@0 1447 int t=edt, dt=(edfr==0)?(-offst):offst;
xue@0 1448 int channel=WaveView1->StartObject->ShortTag[1];
xue@0 1449 cdouble* x=new cdouble[hwid+1];
xue@0 1450 if (edfr==0)
xue@0 1451 {
xue@0 1452 for (int fr=startfr-1; fr>=frst; fr--)
xue@0 1453 {
xue@0 1454 t+=dt;
xue@0 1455 cmplx<QSPEC_FORMAT>* spec=WaveView1->Spec[channel][fr];
xue@0 1456 for (int i=0; i<=hwid; i++) x[i]=spec[i];
xue@0 1457 double ene=0;
xue@0 1458 for (int m=0; m<HS->M; m++)
xue@0 1459 {
xue@0 1460
xue@0 1461 double f=HS->Partials[m][edfr].f*wid;
xue@0 1462 cdouble r=IPWindowC(f, x, wid, settings.M, settings.c, settings.iH2, ceil(f-settings.hB), floor(f+settings.hB));
xue@0 1463 double la=abs(r); atomtype ltype=HS->Partials[m][edfr].type; if (!ltype) ltype=atPeak;
xue@0 1464 atom lpart={t, wid, f/wid, la, arg(r), m+1, ltype};
xue@0 1465 part[k++]=lpart;
xue@0 1466 ene+=la*la;
xue@0 1467 }
xue@0 1468 if (ene<ene0*brake) break;
xue@0 1469 if (ene>ene0) ene0=ene;
xue@0 1470 }
xue@0 1471 }
xue@0 1472 else //edfr==Fr-1
xue@0 1473 {
xue@0 1474 for (int fr=startfr+1; fr<=fren; fr++)
xue@0 1475 {
xue@0 1476 t+=dt;
xue@0 1477 cmplx<QSPEC_FORMAT>* spec=WaveView1->Spec[channel][fr];
xue@0 1478 for (int i=0; i<=hwid; i++) x[i]=spec[i];
xue@0 1479 double ene=0;
xue@0 1480 for (int m=0; m<HS->M; m++)
xue@0 1481 {
xue@0 1482
xue@0 1483 double f=HS->Partials[m][edfr].f*wid;
xue@0 1484 cdouble r=IPWindowC(f, x, wid, settings.M, settings.c, settings.iH2, ceil(f-settings.hB), floor(f+settings.hB));
xue@0 1485 double la=abs(r); atomtype ltype=HS->Partials[m][edfr].type; if (!ltype) ltype=atPeak;
xue@0 1486 atom lpart={t, wid, f/wid, la, arg(r), m+1, ltype};
xue@0 1487 part[k++]=lpart;
xue@0 1488 ene+=la*la;
xue@0 1489 }
xue@0 1490 if (ene<ene0*brake) break;
xue@0 1491 if (ene>ene0) ene0=ene;
xue@0 1492 }
xue@0 1493 }
xue@0 1494 delete[] x;
xue@0 1495
xue@0 1496 DeAlloc2(HS->Partials); AtomsToPartials(k, part, HS->M, HS->Fr, HS->Partials, offst);
xue@0 1497 ClearObjectByShortTag0(WaveView1, stAtom); AddHSObject(HS);
xue@0 1498 delete[] part;
xue@0 1499
xue@0 1500 if (edfr==0)
xue@0 1501 {
xue@0 1502 int EBLI=EventBox->ListBox1->ItemIndex;
xue@0 1503 if (HS==EventBox->HS[EBLI])
xue@0 1504 {
xue@0 1505 EventBox->ListBox1->Items->Strings[EBLI]=(HS->Channel==0?"left: ":"right: ")
xue@0 1506 +AnsiString().sprintf("%.2fs, ", HS->Partials[0][0].t*1.0/WaveView1->SamplesPerSec)
xue@0 1507 +SemitoneToPitch(Log2(HS->Partials[0][0].f*WaveView1->SamplesPerSec/C4)*12);
xue@0 1508 }
xue@0 1509 }
xue@0 1510 }
xue@0 1511 return;
xue@0 1512 }
xue@0 1513
xue@0 1514
xue@0 1515 double delm=settings.delm, maxB=settings.maxB;
xue@0 1516
xue@0 1517 double *vfped=new double[M], starts=0;
xue@0 1518
xue@0 1519 int startp;
xue@0 1520
xue@0 1521 TPolygon* R=RFromAtoms(startp, vfped, starts, M, edfr, Partials, wid, delm, maxB);
xue@0 1522 int fr1=edfr-1; while (fr1>=0){int m; for (m=0; m<M; m++) if (Partials[m][fr1].f>0 && Partials[m][fr1].type==atAnchor) break; if (m<M) break; fr1--;}
xue@0 1523 int fr2=edfr+1; while (fr2<Fr){int m; for (m=0; m<M; m++) if (Partials[m][fr2].f>0 && Partials[m][fr2].type==atAnchor) break; if (m<M) break; fr2++;}
xue@0 1524
xue@0 1525 int fred=(Partials[0][edfr].t-wid/2)/offst, frst=(WaveView1->StartPos-wid/2)/offst, fren=(WaveView1->EndPos-wid/2)/offst;
xue@0 1526
xue@0 1527 if (fr1>=0)
xue@0 1528 {
xue@0 1529 int startpst; double startsst, *vfpst=new double[M];
xue@0 1530 TPolygon* Rst=RFromAtoms(startpst, vfpst, startsst, M, fr1, Partials, wid, delm, maxB);
xue@0 1531 FindNoteFB(fr1, Rst, vfpst, edfr, R, vfped, M, Partials, wid, offst, WaveView1->Spectrogram[channel], settings);
xue@0 1532 delete Rst; delete[] vfpst;
xue@0 1533 if (fr2<Fr)
xue@0 1534 {
xue@0 1535 int startpen; double startsen, *vfpen=new double[M];
xue@0 1536 TPolygon* Ren=RFromAtoms(startpen, vfpen, startsen, M, fr2, Partials, wid, delm, maxB);
xue@0 1537 FindNoteFB(edfr, R, vfped, fr2, Ren, vfpen, M, Partials, wid, offst, WaveView1->Spectrogram[channel], settings);
xue@0 1538 delete Ren; delete[] vfpen;
xue@0 1539 }
xue@0 1540 else
xue@0 1541 {
xue@0 1542 atom* part=new atom[M*Fr+maxp*(fren-frst)];
xue@0 1543 int k=0; for (int fr=0; fr<=edfr; fr++) for (int m=0; m<M; m++) if (Partials[m][fr].f>0) part[k++]=Partials[m][fr];
xue@0 1544 k+=FindNoteF(&part[k], starts, R, startp, vfped, fred, fren, wid, offst, WaveView1->Spectrogram[channel], settings, 0.02);
xue@0 1545 DeAlloc2(HS->Partials); AtomsToPartials(k, part, HS->M, HS->Fr, HS->Partials, offst);
xue@0 1546 ClearObjectByShortTag0(WaveView1, stAtom); AddHSObject(HS);
xue@0 1547 delete[] part;
xue@0 1548 }
xue@0 1549 }
xue@0 1550 else //fr1<0
xue@0 1551 {
xue@0 1552 if (fr2<Fr)
xue@0 1553 {
xue@0 1554 int startpen; double startsen, *vfpen=new double[M];
xue@0 1555 TPolygon* Ren=RFromAtoms(startpen, vfpen, startsen, M, fr2, Partials, wid, delm, maxB);
xue@0 1556 FindNoteFB(edfr, R, vfped, fr2, Ren, vfpen, M, Partials, wid, offst, WaveView1->Spectrogram[channel], settings);
xue@0 1557 delete Ren; delete[] vfpen;
xue@0 1558 }
xue@0 1559 atom* part=new atom[M*Fr+maxp*(fren-frst)];
xue@0 1560 int k=0, keepst=edfr, keepen=(fr2>=Fr)?edfr:(Fr-1);
xue@0 1561 for (int fr=keepst; fr<=keepen; fr++) for (int m=0; m<M; m++) if (Partials[m][fr].f>0) part[k++]=Partials[m][fr];
xue@0 1562 k+=FindNoteF(&part[k], starts, R, startp, vfped, fred, (frst>=0)?(frst-1):-1, wid, offst, WaveView1->Spectrogram[channel], settings, 0.02);
xue@0 1563 if (fr2>=Fr) k+=FindNoteF(&part[k], starts, R, startp, vfped, fred, fren, wid, offst, WaveView1->Spectrogram[channel], settings, 0.02);
xue@0 1564 DeAlloc2(HS->Partials); AtomsToPartials(k, part, HS->M, HS->Fr, HS->Partials, offst);
xue@0 1565 ClearObjectByShortTag0(WaveView1, stAtom); AddHSObject(HS);
xue@0 1566 delete[] part;
xue@0 1567 }
xue@0 1568 delete R;
xue@0 1569 delete[] vfped;
xue@0 1570 }
xue@0 1571 }
xue@0 1572 //---------------------------------------------------------------------------
xue@0 1573 void __fastcall TForm1::WaveView1ParMouseWheel(TObject* Sender, TShiftState Shift, int WheelDelta, const TPoint& MousePos, bool& Handled)
xue@0 1574 {
xue@0 1575 if (WaveView1->OpMode==wopEdit)
xue@0 1576 {
xue@0 1577 if (GetKeyState('A')<0)
xue@0 1578 {
xue@0 1579 Amplify1Click(AM1);
xue@0 1580 EditorPanel->AMAEdit1MouseWheel(WheelDelta);
xue@0 1581 }
xue@0 1582 else if (GetKeyState('D')<0)
xue@0 1583 {
xue@0 1584 Amplify1Click(DeFM1);
xue@0 1585 EditorPanel->DeFMEdit1MouseWheel(WheelDelta);
xue@0 1586 }
xue@0 1587 else if (GetKeyState('F')<0)
xue@0 1588 {
xue@0 1589 Amplify1Click(FM1);
xue@0 1590 EditorPanel->FMAEdit1MouseWheel(WheelDelta);
xue@0 1591 }
xue@0 1592 else
xue@0 1593 {
xue@0 1594 Amplify1Click(Amplify1);
xue@0 1595 EditorPanel->AmpEdit1MouseWheel(WheelDelta);
xue@0 1596 }
xue@0 1597
xue@0 1598 }
xue@0 1599 }
xue@0 1600
xue@0 1601
xue@0 1602 //---------------------------------------------------------------------------
xue@0 1603 //---------------------------------------------------------------------------
xue@0 1604 void __fastcall TForm1::WaveView1PlaybackDone(TObject*)
xue@0 1605 {
xue@0 1606 SpeedButtonPlay->Glyph=BitmapPlay;
xue@0 1607 }
xue@0 1608 //---------------------------------------------------------------------------
xue@0 1609 void __fastcall TForm1::WaveView1PlaybackStart(TObject*)
xue@0 1610 {
xue@0 1611 SpeedButtonPlay->Glyph=BitmapStop;
xue@0 1612 }
xue@0 1613 //---------------------------------------------------------------------------
xue@0 1614 void __fastcall TForm1::WaveView1PopupMenuPopup(TObject *Sender)
xue@0 1615 {
xue@0 1616 ZoomToSelection1->Visible=(WaveView1->Selections->Count>0 && WaveView1->Selections->Focus>=0);
xue@0 1617 UndoZoom1->Visible=(WaveView1->UndoExtractSelection.EndPos>=0);
xue@0 1618 TimeZoom1->Visible=(WaveView1->StartPos!=0 || WaveView1->EndPos!=WaveView1->Length);
xue@0 1619 FrequencyZoom1->Visible=(WaveView1->StartDigiFreq!=0 || WaveView1->EndDigiFreq!=0.5);
xue@0 1620 AmplitudeZoom1->Visible=(WaveView1->YZoomRate!=1);
xue@0 1621 SpectrogramBrightness1->Visible=(WaveView1->SpecAmp!=1);
xue@0 1622 Restore1->Visible=TimeZoom1->Visible || FrequencyZoom1->Visible || AmplitudeZoom1->Visible || SpectrogramBrightness1->Visible;
xue@0 1623
xue@0 1624 Play1->Visible=(WaveView1->Length>0);
xue@0 1625 Play1->Caption=WaveView1->Playing?"Stop":"Play";
xue@0 1626
xue@0 1627 Cut1->Visible=(WaveView1->OpMode<=2 && WaveView1->Selections->Count>0 &&
xue@0 1628 WaveView1->FPanes.HasFreqAxis[WaveView1->CurrentPane]) ||
xue@0 1629 (WaveView1->ObjectAtPointer && WaveView1->ObjectAtPointer->ShortTag[0]==stAtom);
xue@0 1630 Extract1->Visible=Cut1->Visible;
xue@0 1631 Editorpanel1->Visible=(WaveView1->ObjectAtPointer && WaveView1->ObjectAtPointer->ShortTag[0]==stAtom);
xue@0 1632 }
xue@0 1633 //---------------------------------------------------------------------------
xue@0 1634 void __fastcall TForm1::WindowSizeComboChange(TObject *Sender)
xue@0 1635 {
xue@0 1636 WaveView1->SpecRes=WindowSizeCombo->Text.ToInt();
xue@0 1637 }
xue@0 1638 //---------------------------------------------------------------------------
xue@0 1639 void __fastcall TForm1::WindowTypeComboChange(TObject *Sender)
xue@0 1640 {
xue@0 1641 WindowType types[]={wtRectangle, wtHamming, wtHann, wtBlackman, wtGaussian};
xue@0 1642 WaveView1->SpecWindowType=types[WindowTypeCombo->ItemIndex];
xue@0 1643 }
xue@0 1644
xue@0 1645 //---------------------------------------------------------------------------
xue@0 1646
xue@0 1647 void __fastcall TForm1::SpeedButtonSClick(TObject *Sender)
xue@0 1648 {
xue@0 1649 SpectrogramView=!SpectrogramView;
xue@0 1650 SpeedButtonS->Glyph=SpectrogramView?BitmapWaveform:BitmapSpectrogram;
xue@0 1651 Spectrogram2->Caption=SpectrogramView?"Waveform":"Spectrogram";
xue@0 1652 SetWaveViewContents();
xue@0 1653 }
xue@0 1654 //---------------------------------------------------------------------------
xue@0 1655
xue@0 1656 void __fastcall TForm1::AmplitudeZoom1Click(TObject *Sender)
xue@0 1657 {
xue@0 1658 WaveView1->YZoomRate=1;
xue@0 1659 }
xue@0 1660 //---------------------------------------------------------------------------
xue@0 1661
xue@0 1662
xue@0 1663
xue@0 1664
xue@0 1665
xue@0 1666 void __fastcall TForm1::Extract1Click(TObject *Sender)
xue@0 1667 {
xue@0 1668 if (WaveView1->ObjectAtPointer && WaveView1->ObjectAtPointer->ShortTag[0]==stAtom
xue@0 1669 || Sender==EventBox->Extract1 && HS)
xue@0 1670 {
xue@0 1671 int dst, den;
xue@0 1672 double* xrec=SynthesisHSp(HS, dst, den);
xue@0 1673 memset(&WaveView1->Data8[HS->Channel][WaveView1->BytesPerSample*WaveView1->StartPos], 0, WaveView1->BytesPerSample*(WaveView1->EndPos-WaveView1->StartPos));
xue@0 1674 WaveView1->ExtDataChange(NULL, HS->Channel, WaveView1->StartPos, WaveView1->EndPos);
xue@0 1675 PostWaveViewData(xrec, HS->Channel, dst, den, FadeInCheck->Checked, FadeInCombo->Text.ToInt());
xue@0 1676 free8(xrec);
xue@0 1677 }
xue@0 1678 else if (WaveView1->OpMode<=2 && WaveView1->Selections->Count>0 && WaveView1->Selections->Focus>=0)
xue@0 1679 {
xue@0 1680 WaveView1->TFFilter(WaveView1->CurrentChannel, true);
xue@0 1681 WaveView1->ExtDataChange(Sender, WaveView1->CurrentChannel, WaveView1->StartPos-WaveView1->SpecRes, WaveView1->EndPos+WaveView1->SpecRes);
xue@0 1682 }
xue@0 1683 }
xue@0 1684 //---------------------------------------------------------------------------
xue@0 1685 void __fastcall TForm1::PostWaveViewData(double* data, int Channel, int StartPos, int EndPos, bool fadein, int W)
xue@0 1686 {
xue@0 1687 int bps=WaveView1->BytesPerSample, L=EndPos-StartPos;
xue@0 1688 if (fadein)
xue@0 1689 {
xue@0 1690 int hW=W/2;
xue@0 1691 double* leadin=new double[hW*2]; double* leadout=&leadin[hW];
xue@0 1692 IntToDouble(leadin, &WaveView1->Data8[Channel][StartPos*bps], bps, hW);
xue@0 1693 IntToDouble(leadout, &WaveView1->Data8[Channel][(EndPos-hW)*bps], bps, hW);
xue@0 1694 for (int i=0; i<hW; i++)
xue@0 1695 {
xue@0 1696 double w=0.5+0.5*cos(M_PI*i/hW);
xue@0 1697 leadin[i]=leadin[i]*w+data[i]*(1-w);
xue@0 1698 leadout[i]=leadout[i]*(1-w)+data[L-hW+i]*w;
xue@0 1699 }
xue@0 1700 if (L>hW*2)
xue@0 1701 {
xue@0 1702 DoubleToInt(&WaveView1->Data8[Channel][StartPos*bps], bps, leadin, hW);
xue@0 1703 DoubleToInt(&WaveView1->Data8[Channel][(StartPos+hW)*bps], bps, &data[hW], L-hW*2);
xue@0 1704 DoubleToInt(&WaveView1->Data8[Channel][(EndPos-hW)*bps], bps, leadout, hW);
xue@0 1705 }
xue@0 1706 else
xue@0 1707 {
xue@0 1708 DoubleToInt(&WaveView1->Data8[Channel][StartPos*bps], bps, leadin, L/2);
xue@0 1709 DoubleToInt(&WaveView1->Data8[Channel][(StartPos+L/2)*bps], bps, &leadout[hW-L/2], L-L/2);
xue@0 1710 }
xue@0 1711 delete[] leadin;
xue@0 1712 }
xue@0 1713 else
xue@0 1714 DoubleToInt(&WaveView1->Data8[Channel][StartPos*bps], bps, data, L);
xue@0 1715 WaveView1->ExtDataChange(this, Channel, StartPos, EndPos);
xue@0 1716 }
xue@0 1717
xue@0 1718 void __fastcall TForm1::PostWaveViewData(__int16* data, int Channel, int StartPos, int EndPos, bool fadein, int W)
xue@0 1719 {
xue@0 1720 int bps=WaveView1->BytesPerSample, L=EndPos-StartPos;
xue@0 1721 if (fadein)
xue@0 1722 {
xue@0 1723 int hW=W/2;
xue@0 1724 double* leadin=new double[hW*2]; double* leadout=&leadin[hW];
xue@0 1725 IntToDouble(leadin, &WaveView1->Data8[Channel][StartPos*bps], bps, hW);
xue@0 1726 IntToDouble(leadout, &WaveView1->Data8[Channel][(EndPos-hW)*bps], bps, hW);
xue@0 1727 for (int i=0; i<hW; i++)
xue@0 1728 {
xue@0 1729 double w=0.5+0.5*cos(M_PI*i/hW);
xue@0 1730 leadin[i]=leadin[i]*w+data[i]*(1-w);
xue@0 1731 leadout[i]=leadout[i]*(1-w)+data[L-hW+i]*w;
xue@0 1732 }
xue@0 1733 if (L>hW*2)
xue@0 1734 {
xue@0 1735 DoubleToInt(&WaveView1->Data8[Channel][StartPos*bps], bps, leadin, hW);
xue@0 1736 memcpy(&WaveView1->Data8[Channel][(StartPos+hW)*bps], &data[hW], 2*(L-hW*2));
xue@0 1737 DoubleToInt(&WaveView1->Data8[Channel][(EndPos-hW)*bps], bps, leadout, hW);
xue@0 1738 }
xue@0 1739 else
xue@0 1740 {
xue@0 1741 DoubleToInt(&WaveView1->Data8[Channel][StartPos*bps], bps, leadin, L/2);
xue@0 1742 DoubleToInt(&WaveView1->Data8[Channel][(StartPos+L/2)*bps], bps, &leadout[hW-L/2], L-L/2);
xue@0 1743 }
xue@0 1744 delete[] leadin;
xue@0 1745 }
xue@0 1746 else
xue@0 1747 memcpy(&WaveView1->Data8[Channel][StartPos*bps],data, 2*L);
xue@0 1748 WaveView1->ExtDataChange(this, Channel, StartPos, EndPos);
xue@0 1749 }
xue@0 1750
xue@0 1751 void __fastcall TForm1::PostWaveViewData(__int16* data, int Channel, int StartPos, int EndPos)
xue@0 1752 {
xue@0 1753 memcpy(&WaveView1->Data16[Channel][StartPos], data, 2*(EndPos-StartPos));
xue@0 1754 WaveView1->ExtDataChange(this, Channel, StartPos, EndPos);
xue@0 1755 }
xue@0 1756
xue@0 1757
xue@0 1758 void __fastcall TForm1::FadeInCheckClick(TObject *Sender)
xue@0 1759 {
xue@0 1760 FadeInLabel->Enabled=FadeInCheck->Checked;
xue@0 1761 FadeInCombo->Enabled=FadeInCheck->Checked;
xue@0 1762 }
xue@0 1763 //---------------------------------------------------------------------------
xue@0 1764
xue@0 1765 void FadeInOut(double* x, int N, int hWid)
xue@0 1766 {
xue@0 1767 x[0]=0; double iPI=M_PI/hWid;
xue@0 1768 for (int n=1; n<hWid; n++)
xue@0 1769 {
xue@0 1770 double tmp=0.5-0.5*cos(n*iPI);
xue@0 1771 x[n]*=tmp;
xue@0 1772 x[N-n]*=tmp;
xue@0 1773 }
xue@0 1774 }
xue@0 1775
xue@0 1776 void __fastcall TForm1::Cut1Click(TObject *Sender)
xue@0 1777 {
xue@0 1778 if (WaveView1->ObjectAtPointer && WaveView1->ObjectAtPointer->ShortTag[0]==stAtom
xue@0 1779 || Sender==EventBox->Cut1 && HS)
xue@0 1780 {
xue@0 1781 int s=HS->Partials[0][0].s, hs=s/2, dst=HS->Partials[0][0].t-hs,
xue@0 1782 den=HS->Partials[0][HS->Fr-1].t+hs, bps=WaveView1->BytesPerSample;
xue@0 1783
xue@0 1784 double* data=new double[den-dst];
xue@0 1785 IntToDouble(data, &WaveView1->Data8[HS->Channel][dst*bps], bps, den-dst);
xue@0 1786
xue@0 1787 if (GetKeyState(VK_SHIFT)<0)
xue@0 1788 {
xue@0 1789 int st_wid=s/2, st_offst=st_wid/2, st_len=s;
xue@0 1790 int st_count=(st_len-st_wid)/st_offst+1;
xue@0 1791 int st_start=st_len-st_offst*st_count-hs, Fr=HS->Fr;
xue@0 1792 HS->st_start=st_start, HS->st_offst=st_offst, HS->st_count=st_count;
xue@0 1793 DeAlloc2(HS->startamp); Allocate2(double, HS->M, st_count, HS->startamp); memset(HS->startamp[0], 0, sizeof(double)*st_count*HS->M);
xue@0 1794 double *f1=new double[Fr*15], *fa=&f1[Fr], *fb=&fa[Fr], *fc=&fb[Fr], *fd=&fc[Fr], *xs=&fd[Fr], *p1=&xs[Fr], *a1=&p1[Fr],
xue@0 1795 *aa=&a1[Fr], *ab=&aa[Fr], *ac=&ab[Fr], *ad=&ac[Fr];
xue@0 1796 int *ixs=(int*)&f1[Fr*14];
xue@0 1797 double* xrec=new double[st_len];
xue@0 1798 for (int m=0; m<HS->M; m++)
xue@0 1799 {
xue@0 1800 atom* part=HS->Partials[m];
xue@0 1801 bool fzero=false;
xue@0 1802 for (int fr=0; fr<Fr; fr++)
xue@0 1803 {
xue@0 1804 if (part[fr].f<=0){fzero=true; break;}
xue@0 1805 ixs[fr]=part[fr].t;
xue@0 1806 xs[fr]=part[fr].t;
xue@0 1807 f1[fr]=part[fr].f;
xue@0 1808 p1[fr]=part[fr].p;
xue@0 1809 a1[fr]=part[fr].a*2;
xue@0 1810 }
xue@0 1811 if (fzero) break;
xue@0 1812
xue@0 1813 CubicSpline(Fr-1, fa, fb, fc, fd, xs, f1, 1, 1);
xue@0 1814 CubicSpline(Fr-1, aa, ab, ac, ad, xs, a1, 1, 1);
xue@0 1815 for (int l=0; l<Fr && ixs[l]-dst<st_len; l++)
xue@0 1816 {
xue@0 1817 int llen=(ixs[l+1]-dst<st_len)?(ixs[l+1]-ixs[l]):(st_len+dst-ixs[l]);
xue@0 1818 Sinusoid(llen, &xrec[ixs[l]-dst], aa[l], ab[l], ac[l], ad[l], fa[l], fb[l], fc[l], fd[l], p1[l], p1[l+1], false);
xue@0 1819 }
xue@0 1820 double tmpph=p1[0]; Sinusoid(&xrec[ixs[0]-dst], -hs, 0, aa[0], ab[0], ac[0], ad[0], fa[0], fb[0], fc[0], fd[0], tmpph, false);
xue@0 1821
xue@0 1822 for (int l=0; l<st_count; l++)
xue@0 1823 {
xue@0 1824 double *ldata=&data[st_offst*l], *lxrec=&xrec[st_offst*l];
xue@0 1825 double tmp=0, tmp2=0; for (int n=0; n<st_wid; n++) tmp+=ldata[n]*lxrec[n], tmp2+=lxrec[n]*lxrec[n];
xue@0 1826 HS->startamp[m][l]=tmp/tmp2;
xue@0 1827 }
xue@0 1828 }
xue@0 1829 delete[] xrec;
xue@0 1830 delete[] f1;
xue@0 1831 }
xue@0 1832
xue@0 1833 double* xrec=SynthesisHSp(HS, dst, den);
xue@0 1834 FadeInOut(xrec, den-dst, s/2);
xue@0 1835
xue@0 1836 for (int i=0; i<den-dst; i++) data[i]-=xrec[i];
xue@0 1837 PostWaveViewData(data, HS->Channel, dst, den, false&&FadeInCheck->Checked, FadeInCombo->Text.ToInt());
xue@0 1838 free8(xrec);
xue@0 1839 delete[] data;
xue@0 1840 }
xue@0 1841 else if (WaveView1->OpMode<=2 && WaveView1->Selections->Count>0 && WaveView1->Selections->Focus>=0)
xue@0 1842 {
xue@0 1843 WaveView1->TFFilter(WaveView1->CurrentChannel, false);
xue@0 1844 WaveView1->ExtDataChange(Sender, WaveView1->CurrentChannel, WaveView1->StartPos-WaveView1->SpecRes, WaveView1->EndPos+WaveView1->SpecRes);
xue@0 1845 }
xue@0 1846 }
xue@0 1847 //---------------------------------------------------------------------------
xue@0 1848 void __fastcall TForm1::Amplify1Click(TObject *Sender)
xue@0 1849 {
xue@0 1850 if (!EditorPanel->Visible)
xue@0 1851 {
xue@0 1852 GetTargetAudio(EditorPanel->targettype, EditorPanel->Channel, EditorPanel->From, EditorPanel->To, EditorPanel->target, EditorPanel->Before);
xue@0 1853 if (EditorPanel->targettype==1) {delete EditorPanel->HS; EditorPanel->HS=new THS(HS);}
xue@0 1854
xue@0 1855 EditorPanel->AmpEdit1->Text="1";
xue@0 1856 EditorPanel->AmpDBEdit1->Text="0";
xue@0 1857 EditorPanel->PitchEdit1->Text="0";
xue@0 1858 EditorPanel->AMAEdit1->Text="0";
xue@0 1859 EditorPanel->AMFEdit1->Text="4";
xue@0 1860 EditorPanel->FMAEdit1->Text="0";
xue@0 1861 EditorPanel->FMFEdit1->Text="4";
xue@0 1862 EditorPanel->DeFMEdit1->Text="1";
xue@0 1863 EditorPanel->DeFMEdit2->Text="1";
xue@0 1864 }
xue@0 1865
xue@0 1866 if (Sender==Amplify1) EditorPanel->PageControl1->ActivePage=EditorPanel->AmplifySheet;
xue@0 1867 else if (Sender==Pitchshifting1) EditorPanel->PageControl1->ActivePage=EditorPanel->PitchSheet;
xue@0 1868 else if (Sender==AM1) EditorPanel->PageControl1->ActivePage=EditorPanel->AMSheet;
xue@0 1869 else if (Sender==FM1) EditorPanel->PageControl1->ActivePage=EditorPanel->FMSheet;
xue@0 1870 else if (Sender==DeFM1) EditorPanel->PageControl1->ActivePage=EditorPanel->DeFMSheet;
xue@0 1871
xue@0 1872 if (!EditorPanel->Visible) EditorPanel->Show();
xue@0 1873 }
xue@0 1874 //---------------------------------------------------------------------------
xue@0 1875 void __fastcall TForm1::GetTargetAudio(int& targettype, int& channel, int& from, int& to, double*& target, __int16*& before)
xue@0 1876 {
xue@0 1877 free8(target);
xue@0 1878 delete[] before;
xue@0 1879 if (WaveView1->ObjectAtPointer && WaveView1->ObjectAtPointer->ShortTag[0]==stAtom)
xue@0 1880 {
xue@0 1881 targettype=1;
xue@0 1882 channel=HS->Channel;
xue@0 1883 target=SynthesisHSp(HS, from, to);
xue@0 1884 before=new __int16[to-from];
xue@0 1885 memcpy(before, &WaveView1->Data16[channel][from], sizeof(__int16)*(to-from));
xue@0 1886 }
xue@0 1887 else
xue@0 1888 {
xue@0 1889 targettype=0;
xue@0 1890 channel=WaveView1->FPanes.Channel[WaveView1->StartPane];
xue@0 1891 to=WaveView1->EndPos;
xue@0 1892 from=WaveView1->StartPos;
xue@0 1893 target=(double*)malloc8(sizeof(double)*(to-from));
xue@0 1894 before=new __int16[to-from];
xue@0 1895 memcpy(before, &WaveView1->Data16[0][from], sizeof(__int16)*(to-from));
xue@0 1896 IntToDouble(target, before, 2, to-from);
xue@0 1897 }
xue@0 1898 }
xue@0 1899
xue@0 1900 //---------------------------------------------------------------------------
xue@0 1901 void __fastcall TForm1::Events1Click(TObject *Sender)
xue@0 1902 {
xue@0 1903 if (!EventBox->Visible)
xue@0 1904 {
xue@0 1905 EventBox->Left=Left+Width;
xue@0 1906 EventBox->Top=Top;
xue@0 1907 EventBox->Height=Height;
xue@0 1908 EventBox->Load(NULL);
xue@0 1909 EventBox->Show();
xue@0 1910 }
xue@0 1911 else
xue@0 1912 {
xue@0 1913 if (EventBox->Left>=Screen->Width) EventBox->Left=Left+Width;
xue@0 1914 EventBox->BringToFront();
xue@0 1915 }
xue@0 1916 }
xue@0 1917 //---------------------------------------------------------------------------
xue@0 1918
xue@0 1919 void __fastcall TForm1::SpeedButtonSaveClick(TObject *Sender)
xue@0 1920 {
xue@0 1921 SaveDialog1->FileName="waveview.waveview1.wav";
xue@0 1922 SaveDialog1->FilterIndex=1;
xue@0 1923 int bps=WaveView1->BytesPerSample, rfb=WaveView1->StartPos*bps, rlen=WaveView1->EndPos-WaveView1->StartPos;
xue@0 1924 if (SaveDialog1->Execute())
xue@0 1925 {
xue@0 1926 TWaveAudio* WA=new TWaveAudio(NULL);
xue@0 1927 WA->GetWaveProperties(WaveAudio1);
xue@0 1928 if (WA->Channels==1)
xue@0 1929 WA->Write(&WaveView1->Data8[0][rfb], rlen*bps);
xue@0 1930 else if (WA->Channels==2)
xue@0 1931 WA->WriteSamplesInterleave(&WaveView1->Data8[0][rfb], &WaveView1->Data8[1][rfb], rlen);
xue@0 1932 WA->SaveToFile(SaveDialog1->FileName);
xue@0 1933 delete WA;
xue@0 1934 }
xue@0 1935 }
xue@0 1936
xue@0 1937 void __fastcall TForm1::TimeZoom1Click(TObject *Sender)
xue@0 1938 {
xue@0 1939 WaveView1->SetStartAndEndPos(0, WaveView1->Length);
xue@0 1940 }
xue@0 1941 //---------------------------------------------------------------------------
xue@0 1942
xue@0 1943
xue@0 1944 void __fastcall TForm1::FrequencyZoom1Click(TObject *Sender)
xue@0 1945 {
xue@0 1946 WaveView1->SetStartAndEndDigiFreq(0, 0.5);
xue@0 1947 }
xue@0 1948 //---------------------------------------------------------------------------
xue@0 1949
xue@0 1950
xue@0 1951 void __fastcall TForm1::Vibratowizard1Click(TObject *Sender)
xue@0 1952 {
xue@0 1953 TVibratoDemoForm* VF=VibratoDemoForm;
xue@0 1954 VF->WaveView1->StartDigiFreq=WaveView1->StartDigiFreq;
xue@0 1955 VF->WaveView2->StartDigiFreq=WaveView1->StartDigiFreq;
xue@0 1956 VF->WaveView1->EndDigiFreq=WaveView1->EndDigiFreq;
xue@0 1957 VF->WaveView2->EndDigiFreq=WaveView1->EndDigiFreq;
xue@0 1958 VF->WaveView2->SpecAmp=WaveView1->SpecAmp;
xue@0 1959
xue@0 1960 int SpecRes, SpecOffst;
xue@0 1961 if (Sender==EventBox->Vibratowizard1)
xue@0 1962 {
xue@0 1963 SpecRes=HS->Partials[0][0].s;
xue@0 1964 SpecOffst=HS->Partials[0][1].t-HS->Partials[0][0].t;
xue@0 1965 }
xue@0 1966 else
xue@0 1967 {
xue@0 1968 SpecRes=WaveView1->SpecRes;
xue@0 1969 SpecOffst=WaveView1->SpecOffst;
xue@0 1970 }
xue@0 1971 VF->WaveView1->SpecRes=SpecRes;
xue@0 1972 VF->WaveView1->SpecOffst=SpecOffst;
xue@0 1973
xue@0 1974 VF->WaveAudio1->Clear(NULL);
xue@0 1975 VF->WaveAudio1->SamplesPerSec=WaveAudio1->SamplesPerSec;
xue@0 1976 VF->WaveAudio1->BitsPerSample=WaveAudio1->BitsPerSample;
xue@0 1977 int ch=WaveView1->FPanes.Channel[WaveView1->StartPane];
xue@0 1978 if (Sender==EventBox->Vibratowizard1) ch=HS->Channel;
xue@0 1979 int st=(WaveView1->StartPos-SpecRes/2)/SpecOffst*SpecOffst;
xue@0 1980 int en=(WaveView1->EndPos-SpecRes/2)/SpecOffst*SpecOffst+SpecRes;
xue@0 1981
xue@0 1982 if (Sender==EventBox->Vibratowizard1)
xue@0 1983 {
xue@0 1984 st=HS->Partials[0][0].t-SpecOffst;
xue@0 1985 en=HS->Partials[0][HS->Fr-1].t+SpecOffst;
xue@0 1986 }
xue@0 1987
xue@0 1988 if (st<0) st=0;
xue@0 1989 if (en>WaveView1->Length) en=WaveView1->Length;
xue@0 1990
xue@0 1991 VF->WaveAudio1->WriteSamples(&WaveView1->Data16[ch][st], en-st);
xue@0 1992 VF->StartPos=st;
xue@0 1993
xue@0 1994 {
xue@0 1995 delete VF->HS;
xue@0 1996 VF->HS=new THS(HS, st, en);
xue@0 1997 }
xue@0 1998
xue@0 1999 VF->StartPos=st;
xue@0 2000 VF->Copydata();
xue@0 2001 VF->Synthesize();
xue@0 2002 VF->Reset();
xue@0 2003 VF->Show();
xue@0 2004 }
xue@0 2005
xue@0 2006 //---------------------------------------------------------------------------
xue@0 2007
xue@0 2008 void __fastcall TForm1::Recent11Click(TObject *Sender)
xue@0 2009 {
xue@0 2010 TIniFile* Ini=new TIniFile(ChangeFileExt(Application->ExeName, ".ini"));
xue@0 2011 AnsiString S="RecentFile"; S=S+(((TMenuItem*)Sender)->Tag+1);
xue@0 2012 AnsiString FileName=Ini->ReadString(S, "FileName", "");
xue@0 2013 int start=Ini->ReadInteger(S, "Start", 0);
xue@0 2014 int end=Ini->ReadInteger(S, "End", -1);
xue@0 2015 double fstart=Ini->ReadFloat(S, "StartF", 0);
xue@0 2016 double fend=Ini->ReadFloat(S, "EndF", 0.5);
xue@0 2017 delete Ini;
xue@0 2018
xue@0 2019 if (FileExists(FileName) && WaveAudio1->FileName!=FileName)
xue@0 2020 {
xue@0 2021 RecentFile(WaveAudio1->FileName);
xue@0 2022 WaveAudio1->LoadFromFile(FileName);
xue@0 2023 WaveView1->SetArea(start, end, fstart, fend);
xue@0 2024 }
xue@0 2025 }
xue@0 2026 //---------------------------------------------------------------------------
xue@0 2027
xue@0 2028 void __fastcall TForm1::SpeedButtonRecordClick(TObject *Sender)
xue@0 2029 {
xue@0 2030 if (WaveAudio2 && WaveAudio2->Recording)
xue@0 2031 {
xue@0 2032 WaveAudio2->PauseRecording(0);
xue@0 2033
xue@0 2034 double second=1.0*WaveAudio2->WaveStream->Position/(WaveAudio2->SamplesPerSec*WaveAudio2->BitsPerSample/8*WaveAudio2->Channels);
xue@0 2035 int secr=(second-floor(second))*100; TDateTime dt=second/86400;
xue@0 2036 RecordingForm->Label1->Caption=dt.FormatString("'Recording finished:' h:mm:ss.")+AnsiString().sprintf("%02d", secr);
xue@0 2037
xue@0 2038 WaveAudio2->CloseFile(true);
xue@0 2039 SpeedButtonRecord->Glyph=BitmapRecord;
xue@0 2040 RecordingForm->SpeedButtonRecord->Glyph=BitmapRecord;
xue@0 2041 delete WaveAudio2;
xue@0 2042 WaveAudio2=0;
xue@0 2043
xue@0 2044 RecordingForm->SpeedButton1->Enabled=true; RecordingForm->SpeedButton2->Enabled=true;
xue@0 2045 RecordingForm->Show();
xue@0 2046 }
xue@0 2047 else
xue@0 2048 {
xue@0 2049 WaveAudio2=new TWaveAudio(NULL);
xue@0 2050 WaveAudio2->GetWaveProperties(WaveAudio1);
xue@0 2051 WaveAudio2->CreateFile(ExtractFilePath(Application->ExeName)+"noname.wav");
xue@0 2052 WaveAudio2->OnInAddBuffer=WaveAudio2InAddBuffer;
xue@0 2053 WaveAudio2->StartRecording(0);
xue@0 2054 SpeedButtonRecord->Glyph=BitmapRecording;
xue@0 2055 RecordingForm->SpeedButtonRecord->Glyph=BitmapRecording;
xue@0 2056 RecordingForm->Label1->Caption="Recording in progress: 0:00:00.00";
xue@0 2057 RecordingForm->SpeedButton1->Enabled=false; RecordingForm->SpeedButton2->Enabled=false;
xue@0 2058 RecordingForm->Show();
xue@0 2059 }
xue@0 2060 }
xue@0 2061 //---------------------------------------------------------------------------
xue@0 2062
xue@0 2063 void __fastcall TForm1::WaveAudio2InAddBuffer(TObject*)
xue@0 2064 {
xue@0 2065 double second=1.0*WaveAudio2->WaveStream->Position/(WaveAudio2->SamplesPerSec*WaveAudio2->BitsPerSample/8*WaveAudio2->Channels);
xue@0 2066 int secr=(second-floor(second))*100; TDateTime dt=second/86400;
xue@0 2067 RecordingForm->Label1->Caption=dt.FormatString("'Recording in progress:' h:mm:ss.")+AnsiString().sprintf("%02d", secr);
xue@0 2068 }
xue@0 2069
xue@0 2070 //---------------------------------------------------------------------------
xue@0 2071 void __fastcall TForm1::Close1Click(TObject *Sender)
xue@0 2072 {
xue@0 2073 RecentFile(WaveAudio1->FileName);
xue@0 2074 WaveAudio1->Clear(this);
xue@0 2075 Navigator1->Resize();
xue@0 2076 }
xue@0 2077 //---------------------------------------------------------------------------
xue@0 2078
xue@0 2079
xue@0 2080 void __fastcall TForm1::AutoScrollCheckClick(TObject *Sender)
xue@0 2081 {
xue@0 2082 WaveView1->AutoScroll=AutoScrollCheck->Checked;
xue@0 2083 }
xue@0 2084
xue@0 2085 //---------------------------------------------------------------------------
xue@0 2086 void __fastcall TForm1::WaveView1PlaybackStartAndEndPos(TObject* Sender, int& st, int& en, bool fromsel)
xue@0 2087 {
xue@0 2088 TWaveView* WV=(TWaveView*)Sender;
xue@0 2089 if (fromsel)
xue@0 2090 {
xue@0 2091 st=WV->Selections->StartPos; if (st<0) st=0;
xue@0 2092 en=WV->Selections->EndPos; if (en>WV->Length) en=WV->Length;
xue@0 2093 }
xue@0 2094 else
xue@0 2095 {
xue@0 2096 st=WV->StartPos;
xue@0 2097 if (PlayUntilRadio->ItemIndex==0) en=WV->Length;
xue@0 2098 else if (PlayUntilRadio->ItemIndex==1) en=WV->EndPos;
xue@0 2099 }
xue@0 2100 }
xue@0 2101
xue@0 2102 //---------------------------------------------------------------------------
xue@0 2103
xue@0 2104 void __fastcall TForm1::LoopCheckClick(TObject *Sender)
xue@0 2105 {
xue@0 2106 if (LoopCheck->Checked)
xue@0 2107 {
xue@0 2108 WaveView1->LoopPlay=true;
xue@0 2109 }
xue@0 2110 else
xue@0 2111 {
xue@0 2112 WaveView1->LoopPlay=false;
xue@0 2113 PlayUntilRadioClick(Sender);
xue@0 2114 }
xue@0 2115 }
xue@0 2116 //---------------------------------------------------------------------------
xue@0 2117
xue@0 2118 void __fastcall TForm1::PlayUntilRadioClick(TObject *Sender)
xue@0 2119 {
xue@0 2120 if (PlayUntilRadio->ItemIndex==0)
xue@0 2121 WaveView1->SectionEndPos=WaveView1->Length;
xue@0 2122 else if (WaveView1->LoopMode==2)
xue@0 2123 WaveView1->SectionEndPos=WaveView1->Selections->EndPos;
xue@0 2124 else
xue@0 2125 WaveView1->SectionEndPos=WaveView1->EndPos;
xue@0 2126 }
xue@0 2127 //---------------------------------------------------------------------------
xue@0 2128
xue@0 2129 void __fastcall TForm1::MouseWheelZoomClick(TObject *Sender)
xue@0 2130 {
xue@0 2131 WaveView1->DisableMouseWheelZoom=!MouseWheelZoom->Checked;
xue@0 2132 }
xue@0 2133 //---------------------------------------------------------------------------
xue@0 2134
xue@0 2135 void __fastcall TForm1::AmpGridDblClick(TObject *Sender)
xue@0 2136 {
xue@0 2137 if (GridSourcePane<0 || GridSourcePane>=WaveView1->FPanes.Count
xue@0 2138 || !WaveView1->FPanes.HasFreqAxis[GridSourcePane]) return;
xue@0 2139
xue@0 2140 TPoint P;
xue@0 2141 GetCursorPos(&P);
xue@0 2142 TStringGrid* Grid=(TStringGrid*)Sender;
xue@0 2143 P=Grid->ScreenToClient(P);
xue@0 2144 int col, row;
xue@0 2145 Grid->MouseToCell(P.x, P.y, col, row);
xue@0 2146
xue@0 2147 if (col<0 || row<0) return;
xue@0 2148 if (Grid->Cells[col][row].IsEmpty()) return;
xue@0 2149 int CurrentFr=Grid->Cells[col][0].ToInt(), CurrentBin=Grid->Cells[0][row].ToInt();
xue@0 2150 int t=WaveView1->SpecRes/2+WaveView1->SpecOffst*CurrentFr;
xue@0 2151 double f=(CurrentBin+0.5)/WaveView1->SpecRes;
xue@0 2152 WaveView1->SetCursorTF(GridSourcePane, t, f);
xue@0 2153 }
xue@0 2154 //---------------------------------------------------------------------------
xue@0 2155
xue@0 2156
xue@0 2157 void __fastcall TForm1::Sourcefilter1Click(TObject *Sender)
xue@0 2158 {
xue@0 2159 TSFDemoForm* VF=SFDemoForm;
xue@0 2160 VF->WaveView1->StartDigiFreq=WaveView1->StartDigiFreq;
xue@0 2161 VF->WaveView2->StartDigiFreq=WaveView1->StartDigiFreq;
xue@0 2162 VF->WaveView1->EndDigiFreq=WaveView1->EndDigiFreq;
xue@0 2163 VF->WaveView2->EndDigiFreq=WaveView1->EndDigiFreq;
xue@0 2164 VF->WaveView2->SpecAmp=WaveView1->SpecAmp;
xue@0 2165
xue@0 2166 int SpecRes, SpecOffst;
xue@0 2167 if (Sender==EventBox->Vibratowizard1)
xue@0 2168 {
xue@0 2169 SpecRes=HS->Partials[0][0].s;
xue@0 2170 SpecOffst=HS->Partials[0][1].t-HS->Partials[0][0].t;
xue@0 2171 }
xue@0 2172 else
xue@0 2173 {
xue@0 2174 SpecRes=WaveView1->SpecRes;
xue@0 2175 SpecOffst=WaveView1->SpecOffst;
xue@0 2176 }
xue@0 2177 VF->WaveView1->SpecRes=SpecRes;
xue@0 2178 VF->WaveView1->SpecOffst=SpecOffst;
xue@0 2179
xue@0 2180 VF->WaveAudio1->Clear(NULL);
xue@0 2181 VF->WaveAudio1->SamplesPerSec=WaveAudio1->SamplesPerSec;
xue@0 2182 VF->WaveAudio1->BitsPerSample=WaveAudio1->BitsPerSample;
xue@0 2183 int ch=WaveView1->FPanes.Channel[WaveView1->StartPane];
xue@0 2184 if (Sender==EventBox->Vibratowizard1) ch=HS->Channel;
xue@0 2185 int st=(WaveView1->StartPos-SpecRes/2)/SpecOffst*SpecOffst;
xue@0 2186 int en=(WaveView1->EndPos-SpecRes/2)/SpecOffst*SpecOffst+SpecRes;
xue@0 2187
xue@0 2188 if (Sender==EventBox->Vibratowizard1)
xue@0 2189 {
xue@0 2190 st=HS->Partials[0][0].t-SpecOffst;
xue@0 2191 en=HS->Partials[0][HS->Fr-1].t+SpecOffst;
xue@0 2192 }
xue@0 2193
xue@0 2194 if (st<0) st=0;
xue@0 2195 if (en>WaveView1->Length) en=WaveView1->Length;
xue@0 2196
xue@0 2197 VF->WaveAudio1->WriteSamples(&WaveView1->Data8[ch][st*WaveAudio1->BitsPerSample/8], en-st);
xue@0 2198 VF->StartPos=st;
xue@0 2199
xue@0 2200 {
xue@0 2201 delete VF->HS;
xue@0 2202 VF->HS=new THS(HS, st, en);
xue@0 2203 }
xue@0 2204
xue@0 2205 VF->StartPos=st;
xue@0 2206 VF->Copydata();
xue@0 2207 VF->Synthesize();
xue@0 2208 VF->Reset();
xue@0 2209 VF->Show();
xue@0 2210 }
xue@0 2211 //---------------------------------------------------------------------------
xue@0 2212
xue@0 2213
xue@0 2214
xue@0 2215
xue@0 2216 //---------------------------------------------------------------------------
xue@0 2217
xue@0 2218 void __fastcall TForm1::PlayFilterComboSelect(TObject *Sender)
xue@0 2219 {
xue@0 2220 WaveView1->PlaybackFilter=(TWaveViewPlaybackFilter)PlayFilterCombo->ItemIndex;
xue@0 2221 PlaybackFilterRadio->ItemIndex=PlayFilterCombo->ItemIndex;
xue@0 2222 }
xue@0 2223 //---------------------------------------------------------------------------
xue@0 2224
xue@0 2225 void __fastcall TForm1::PlaybackFilterRadioClick(TObject *Sender)
xue@0 2226 {
xue@0 2227 PlayFilterCombo->ItemIndex=PlaybackFilterRadio->ItemIndex;
xue@0 2228 }
xue@0 2229 //---------------------------------------------------------------------------
xue@0 2230
xue@0 2231
xue@0 2232
xue@0 2233
xue@0 2234 void __fastcall TForm1::Retrieve1Click(TObject *Sender)
xue@0 2235 {
xue@0 2236 WaveView1->Retrieve(1);
xue@0 2237 }
xue@0 2238 //---------------------------------------------------------------------------
xue@0 2239
xue@0 2240