xue@0
|
1 /*
|
xue@0
|
2 Harmonic Visualiser
|
xue@0
|
3
|
xue@0
|
4 An audio file viewer and editor.
|
xue@0
|
5 Centre for Digital Music, Queen Mary, University of London.
|
xue@0
|
6 This file copyright 2011 Wen Xue.
|
xue@0
|
7
|
xue@0
|
8 This program is free software; you can redistribute it and/or
|
xue@0
|
9 modify it under the terms of the GNU General Public License as
|
xue@0
|
10 published by the Free Software Foundation; either version 2 of the
|
xue@0
|
11 License, or (at your option) any later version.
|
xue@0
|
12 */
|
xue@0
|
13 //---------------------------------------------------------------------------
|
xue@0
|
14
|
xue@0
|
15 #include <vcl.h>
|
xue@0
|
16 #include <math.h>
|
xue@0
|
17 #include <Math.hpp>
|
xue@0
|
18 #pragma hdrstop
|
xue@0
|
19
|
xue@0
|
20 #include "EditorPanelUnit.h"
|
xue@0
|
21 #include "Unit1.h"
|
xue@0
|
22 #include "VibratoDemoUnit.h"
|
xue@0
|
23 #include "SFDemoUnit.h"
|
xue@0
|
24 #include "splines.h"
|
xue@0
|
25 #include "hsedit.h"
|
xue@0
|
26
|
xue@0
|
27 //---------------------------------------------------------------------------
|
xue@0
|
28 #pragma package(smart_init)
|
xue@0
|
29 #pragma resource "*.dfm"
|
xue@0
|
30 TEditorPanel *EditorPanel;
|
xue@0
|
31 //---------------------------------------------------------------------------
|
xue@0
|
32 __fastcall TEditorPanel::TEditorPanel(TComponent* Owner)
|
xue@0
|
33 : TForm(Owner)
|
xue@0
|
34 {
|
xue@0
|
35 target=0;
|
xue@0
|
36 Before=0;
|
xue@0
|
37 HS=0;
|
xue@0
|
38 }
|
xue@0
|
39
|
xue@0
|
40 __fastcall TEditorPanel::~TEditorPanel()
|
xue@0
|
41 {
|
xue@0
|
42 free8(target);
|
xue@0
|
43 delete[] Before;
|
xue@0
|
44 delete HS;
|
xue@0
|
45 }
|
xue@0
|
46 //---------------------------------------------------------------------------
|
xue@0
|
47 void __fastcall TEditorPanel::AmpEdit1MouseWheel(int zDelta)
|
xue@0
|
48 {
|
xue@0
|
49 double a, db;
|
xue@0
|
50 a=AmpEdit1->Text.ToDouble()*pow((zDelta>0)?2:0.5, 0.1); db=Log10(a)*20;
|
xue@0
|
51 AmpEdit1->Text=a;
|
xue@0
|
52 AmpDBEdit1->Text=db;
|
xue@0
|
53 EditAmplify(a);
|
xue@0
|
54 }
|
xue@0
|
55 void __fastcall TEditorPanel::AMAEdit1MouseWheel(int zDelta)
|
xue@0
|
56 {
|
xue@0
|
57 double dep=AMAEdit1->Text.ToDouble()+((zDelta>0)?0.05:-0.05);
|
xue@0
|
58 if (dep<0) dep=0;
|
xue@0
|
59 AMAEdit1->Text=dep;
|
xue@0
|
60 EditAM(dep, AMFEdit1->Text.ToDouble(), AMPhEdit1->Text.ToDouble());
|
xue@0
|
61 }
|
xue@0
|
62 void __fastcall TEditorPanel::DeFMEdit1MouseWheel(int zDelta)
|
xue@0
|
63 {
|
xue@0
|
64 double a=DeFMEdit1->Text.ToDouble()+((zDelta>0)?0.2:-0.2);
|
xue@0
|
65 if (a<0) a=0;
|
xue@0
|
66 DeFMEdit1->Text=a;
|
xue@0
|
67 EditReFM(a, DeFMEdit2->Text.ToDouble());
|
xue@0
|
68 }
|
xue@0
|
69 void __fastcall TEditorPanel::FMAEdit1MouseWheel(int zDelta)
|
xue@0
|
70 {
|
xue@0
|
71 double a=FMAEdit1->Text.ToDouble()+((zDelta>0)?0.2:-0.2);
|
xue@0
|
72 if (a<0) a=0;
|
xue@0
|
73 FMAEdit1->Text=a;
|
xue@0
|
74 EditFM(a, FMFEdit1->Text.ToDouble(), FMPhEdit1->Text.ToDouble());
|
xue@0
|
75 }
|
xue@0
|
76 void __fastcall TEditorPanel::FMFEdit1MouseWheel(int zDelta)
|
xue@0
|
77 {
|
xue@0
|
78 double fre=FMFEdit1->Text.ToDouble()+((zDelta>0)?0.5:-0.5);
|
xue@0
|
79 if (fre<0) fre=0;
|
xue@0
|
80 FMFEdit1->Text=fre;
|
xue@0
|
81 EditFM(FMAEdit1->Text.ToDouble(), fre, FMPhEdit1->Text.ToDouble());
|
xue@0
|
82 }
|
xue@0
|
83 void __fastcall TEditorPanel::WMMouseWheel(TWMMouseWheel Message)
|
xue@0
|
84 {
|
xue@0
|
85 int zDelta=Message.WheelDelta; // wheel rotation
|
xue@0
|
86 if (AmpEdit1->Focused()) AmpEdit1MouseWheel(zDelta);
|
xue@0
|
87 else if (AmpDBEdit1->Focused())
|
xue@0
|
88 {
|
xue@0
|
89 double a, db;
|
xue@0
|
90 db=AmpDBEdit1->Text.ToDouble()+((zDelta>0)?0.5:-0.5); a=pow(10, db/20);
|
xue@0
|
91 AmpEdit1->Text=a;
|
xue@0
|
92 AmpDBEdit1->Text=db;
|
xue@0
|
93 EditAmplify(a);
|
xue@0
|
94 }
|
xue@0
|
95 else if (PitchEdit1->Focused())
|
xue@0
|
96 {
|
xue@0
|
97 double ps=PitchEdit1->Text.ToDouble()+((zDelta>0)?1:-1);
|
xue@0
|
98 PitchEdit1->Text=ps;
|
xue@0
|
99 EditPitchShifting(ps);
|
xue@0
|
100 }
|
xue@0
|
101 else if (AMAEdit1->Focused()) AMAEdit1MouseWheel(zDelta);
|
xue@0
|
102 else if (AMFEdit1->Focused())
|
xue@0
|
103 {
|
xue@0
|
104 double fre=AMFEdit1->Text.ToDouble()+((zDelta>0)?0.5:-0.5);
|
xue@0
|
105 if (fre<0) fre=0;
|
xue@0
|
106 AMFEdit1->Text=fre;
|
xue@0
|
107 EditAM(AMAEdit1->Text.ToDouble(), fre, AMPhEdit1->Text.ToDouble());
|
xue@0
|
108 }
|
xue@0
|
109 else if (AMPhEdit1->Focused())
|
xue@0
|
110 {
|
xue@0
|
111 double ph=AMPhEdit1->Text.ToDouble()+((zDelta>0)?0.1:-0.1);
|
xue@0
|
112 AMPhEdit1->Text=ph;
|
xue@0
|
113 EditAM(AMAEdit1->Text.ToDouble(), AMFEdit1->Text.ToDouble(), ph);
|
xue@0
|
114 }
|
xue@0
|
115 else if (FMAEdit1->Focused()) FMAEdit1MouseWheel(zDelta);
|
xue@0
|
116 else if (FMFEdit1->Focused()) FMFEdit1MouseWheel(zDelta);
|
xue@0
|
117 else if (FMPhEdit1->Focused())
|
xue@0
|
118 {
|
xue@0
|
119 double ph=FMPhEdit1->Text.ToDouble()+((zDelta>0)?0.1:-0.1);
|
xue@0
|
120 FMPhEdit1->Text=ph;
|
xue@0
|
121 EditFM(FMAEdit1->Text.ToDouble(), FMFEdit1->Text.ToDouble(), ph);
|
xue@0
|
122 }
|
xue@0
|
123 else if (DeFMEdit1->Focused()) DeFMEdit1MouseWheel(zDelta);
|
xue@0
|
124 else if (DeFMEdit2->Focused())
|
xue@0
|
125 {
|
xue@0
|
126 double r=DeFMEdit2->Text.ToDouble()+((zDelta>0)?0.1:-0.1);
|
xue@0
|
127 if (r<0.2) r=0.2;
|
xue@0
|
128 DeFMEdit2->Text=r;
|
xue@0
|
129 EditReFM(DeFMEdit1->Text.ToDouble(), r);
|
xue@0
|
130 }
|
xue@0
|
131 }
|
xue@0
|
132 //---------------------------------------------------------------------------
|
xue@0
|
133
|
xue@0
|
134
|
xue@0
|
135 void __fastcall TEditorPanel::AmpEdit1MouseMove(TObject *Sender,
|
xue@0
|
136 TShiftState Shift, int X, int Y)
|
xue@0
|
137 {
|
xue@0
|
138 ((TWinControl*)Sender)->SetFocus();
|
xue@0
|
139 }
|
xue@0
|
140 //---------------------------------------------------------------------------
|
xue@0
|
141
|
xue@0
|
142
|
xue@0
|
143
|
xue@0
|
144 void __fastcall TEditorPanel::AmpEdit1KeyPress(TObject *Sender, char &Key)
|
xue@0
|
145 {
|
xue@0
|
146 if (Key==VK_RETURN)
|
xue@0
|
147 {
|
xue@0
|
148 if (Sender==AmpEdit1) {double a=AmpEdit1->Text.ToDouble(); AmpDBEdit1->Text=double(Log10(a)*20); EditAmplify(a);}
|
xue@0
|
149 else if (Sender==AmpDBEdit1) {double a=pow(10, AmpDBEdit1->Text.ToDouble()/20); AmpEdit1->Text=a; EditAmplify(a);}
|
xue@0
|
150 else if (Sender==PitchEdit1) EditPitchShifting(PitchEdit1->Text.ToDouble());
|
xue@0
|
151 else if (Sender==AMAEdit1 || Sender==AMFEdit1 || Sender==AMPhEdit1) EditAM(AMAEdit1->Text.ToDouble(), AMFEdit1->Text.ToDouble(), AMPhEdit1->Text.ToDouble());
|
xue@0
|
152 else if (Sender==FMAEdit1 || Sender==FMFEdit1 || Sender==FMPhEdit1) EditFM(FMAEdit1->Text.ToDouble(), FMFEdit1->Text.ToDouble(), FMPhEdit1->Text.ToDouble());
|
xue@0
|
153 else if (Sender==DeFMEdit1 || Sender==DeFMEdit2) EditReFM(DeFMEdit1->Text.ToDouble(), DeFMEdit2->Text.ToDouble());
|
xue@0
|
154 }
|
xue@0
|
155 else if ((Key<'0' || Key>'9') && Key!='.' && Key!='-' && Key!=VK_BACK) Key=NULL;
|
xue@0
|
156 }
|
xue@0
|
157 //---------------------------------------------------------------------------
|
xue@0
|
158
|
xue@0
|
159
|
xue@0
|
160
|
xue@0
|
161 double* SynthesisHSp(THS* HS, int& dst, int& den);
|
xue@0
|
162 void __fastcall TEditorPanel::EditAmplify(double a)
|
xue@0
|
163 {
|
xue@0
|
164 for (int m=0; m<HS->M; m++) for (int fr=0; fr<HS->Fr; fr++) HS->Partials[m][fr].a=Form1->HS->Partials[m][fr].a*a;
|
xue@0
|
165
|
xue@0
|
166 double* data=SynthesisHSp(HS, dst, den);
|
xue@0
|
167 int L=To-From;
|
xue@0
|
168 for (int i=0; i<L; i++) data[i]=Before[i]-target[i]+data[i];
|
xue@0
|
169 Form1->PostWaveViewData(data, Channel, From, To, Form1->FadeInCheck->Checked, Form1->FadeInCombo->Text.ToInt());
|
xue@0
|
170 free8(data);
|
xue@0
|
171 }
|
xue@0
|
172
|
xue@0
|
173 void __fastcall TEditorPanel::EditAM(double dep, double fre, double ph_00)
|
xue@0
|
174 {
|
xue@0
|
175 HSAM(HS, Form1->HS, dep, fre/Form1->WaveView1->SamplesPerSec, ph_00*2*M_PI);
|
xue@0
|
176 double* data=SynthesisHS(HS, dst, den);
|
xue@0
|
177 int L=To-From; for (int i=0; i<L; i++) data[i]=Before[i]-target[i]+data[i];
|
xue@0
|
178 Form1->PostWaveViewData(data, Channel, From, To, Form1->FadeInCheck->Checked, Form1->FadeInCombo->Text.ToInt());
|
xue@0
|
179 free8(data);
|
xue@0
|
180 }
|
xue@0
|
181
|
xue@0
|
182 void __fastcall TEditorPanel::EditFM(double a, double fre, double ph_00)
|
xue@0
|
183 {
|
xue@0
|
184 HSFM(HS, Form1->HS, a, fre/Form1->WaveView1->SamplesPerSec, ph_00*2*M_PI);
|
xue@0
|
185
|
xue@0
|
186 double* data=SynthesisHS(HS, dst, den);
|
xue@0
|
187 int L=To-From; for (int i=0; i<L; i++) data[i]=Before[i]-target[i]+data[i];
|
xue@0
|
188 Form1->PostWaveViewData(data, Channel, From, To, Form1->FadeInCheck->Checked, Form1->FadeInCombo->Text.ToInt());
|
xue@0
|
189 free8(data);
|
xue@0
|
190 }
|
xue@0
|
191
|
xue@0
|
192 void __fastcall TEditorPanel::EditPitchShifting(double ps12)
|
xue@0
|
193 {
|
xue@0
|
194 HSPitchShift(HS, Form1->HS, ps12);
|
xue@0
|
195
|
xue@0
|
196 double* data=SynthesisHS(HS, dst, den);
|
xue@0
|
197 int L=To-From;
|
xue@0
|
198 if (PitchCheck1->Checked) for (int i=0; i<L; i++) data[i]=Before[i]+data[i];
|
xue@0
|
199 else for (int i=0; i<L; i++) data[i]=Before[i]-target[i]+data[i];
|
xue@0
|
200 Form1->PostWaveViewData(data, Channel, From, To, Form1->FadeInCheck->Checked, Form1->FadeInCombo->Text.ToInt());
|
xue@0
|
201 free8(data);
|
xue@0
|
202 }
|
xue@0
|
203
|
xue@0
|
204 void __fastcall TEditorPanel::EditReFM(double amp, double rate)
|
xue@0
|
205 {
|
xue@0
|
206 ReFM(Form1->HS->M, Form1->HS->Fr, Form1->HS->Partials, HS->Partials, amp, rate);
|
xue@0
|
207 double* data=SynthesisHS(HS, dst, den);
|
xue@0
|
208
|
xue@0
|
209 int L=To-From;
|
xue@0
|
210
|
xue@0
|
211 for (int i=0; i<L; i++) data[i]=Before[i]-target[i]+data[i];
|
xue@0
|
212 Form1->PostWaveViewData(data, Channel, From, To, Form1->FadeInCheck->Checked, Form1->FadeInCombo->Text.ToInt());
|
xue@0
|
213 free8(data);
|
xue@0
|
214 }
|
xue@0
|
215
|
xue@0
|
216 void ClearObjectByShortTag0(TWaveView* WV, int tag0);
|
xue@0
|
217 void __fastcall TEditorPanel::FormClose(TObject *Sender, TCloseAction &Action)
|
xue@0
|
218 {
|
xue@0
|
219 if (ModalResult==mrCancel) Form1->PostWaveViewData(Before, Channel, From, To);
|
xue@0
|
220 else
|
xue@0
|
221 {
|
xue@0
|
222 DeAlloc2(Form1->HS->Partials);
|
xue@0
|
223 Form1->HS->Channel=HS->Channel; Form1->HS->M=HS->M; Form1->HS->Fr=HS->Fr; Allocate2(atom, HS->M, HS->Fr, Form1->HS->Partials);
|
xue@0
|
224 for (int m=0; m<HS->M; m++) memcpy(Form1->HS->Partials[m], HS->Partials[m], sizeof(atom)*HS->Fr);
|
xue@0
|
225 ClearObjectByShortTag0(Form1->WaveView1, 1);
|
xue@0
|
226 Form1->AddHSObject(Form1->HS);
|
xue@0
|
227 }
|
xue@0
|
228 }
|
xue@0
|
229 //---------------------------------------------------------------------------
|
xue@0
|
230
|
xue@0
|
231
|
xue@0
|
232 void __fastcall TEditorPanel::SpeedButton1Click(TObject *Sender)
|
xue@0
|
233 {
|
xue@0
|
234 ModalResult=mrOk;
|
xue@0
|
235 Close();
|
xue@0
|
236 }
|
xue@0
|
237 //---------------------------------------------------------------------------
|
xue@0
|
238
|
xue@0
|
239 void __fastcall TEditorPanel::SpeedButton2Click(TObject *Sender)
|
xue@0
|
240 {
|
xue@0
|
241 ModalResult=mrCancel;
|
xue@0
|
242 Close();
|
xue@0
|
243 }
|
xue@0
|
244 //---------------------------------------------------------------------------
|
xue@0
|
245
|
xue@0
|
246 void __fastcall TEditorPanel::SpeedButton4Click(TObject *Sender)
|
xue@0
|
247 {
|
xue@0
|
248 for (int m=0; m<HS->M; m++) memcpy(HS->Partials[m], Form1->HS->Partials[m], sizeof(atom)*HS->Fr);
|
xue@0
|
249 Form1->PostWaveViewData(Before, Channel, From, To);
|
xue@0
|
250 }
|
xue@0
|
251 //---------------------------------------------------------------------------
|
xue@0
|
252
|