xue@0
|
1 /*
|
xue@0
|
2 Harmonic Visualiser
|
xue@0
|
3
|
xue@0
|
4 An audio file viewer and editor.
|
xue@0
|
5 Centre for Digital Music, Queen Mary, University of London.
|
xue@0
|
6 This file copyright 2011 Wen Xue.
|
xue@0
|
7
|
xue@0
|
8 This program is free software; you can redistribute it and/or
|
xue@0
|
9 modify it under the terms of the GNU General Public License as
|
xue@0
|
10 published by the Free Software Foundation; either version 2 of the
|
xue@0
|
11 License, or (at your option) any later version.
|
xue@0
|
12 */
|
xue@0
|
13 //---------------------------------------------------------------------------
|
xue@0
|
14
|
xue@0
|
15 #include <vcl.h>
|
xue@0
|
16 #pragma hdrstop
|
xue@0
|
17
|
xue@0
|
18 #include "EventBoxUnit.h"
|
xue@0
|
19 #include "WaveView.h"
|
xue@0
|
20 #include "Unit1.h"
|
xue@0
|
21 #include "EditorPanelUnit.h"
|
xue@0
|
22 #include <Math.hpp>
|
xue@0
|
23 #include <math.h>
|
xue@0
|
24 //---------------------------------------------------------------------------
|
xue@0
|
25 #pragma package(smart_init)
|
xue@0
|
26 #pragma resource "*.dfm"
|
xue@0
|
27 TEventBox *EventBox;
|
xue@0
|
28 //---------------------------------------------------------------------------
|
xue@0
|
29 __fastcall TEventBox::TEventBox(TComponent* Owner)
|
xue@0
|
30 : TForm(Owner)
|
xue@0
|
31 {
|
xue@0
|
32 HSCapacity=100;
|
xue@0
|
33 HSCount=0;
|
xue@0
|
34 HS=(THS**)malloc(sizeof(THS*)*HSCapacity);
|
xue@0
|
35 memset(HS, 0, sizeof(THS*)*HSCapacity);
|
xue@0
|
36 }
|
xue@0
|
37
|
xue@0
|
38 __fastcall TEventBox::~TEventBox()
|
xue@0
|
39 {
|
xue@0
|
40 Clear();
|
xue@0
|
41 free(HS);
|
xue@0
|
42 }
|
xue@0
|
43
|
xue@0
|
44 void __fastcall TEventBox::Clear()
|
xue@0
|
45 {
|
xue@0
|
46 ListBox1->Clear();
|
xue@0
|
47 for(int i=0; i<HSCount; i++) delete HS[i];
|
xue@0
|
48 HSCount=0;
|
xue@0
|
49 }
|
xue@0
|
50 //---------------------------------------------------------------------------
|
xue@0
|
51 THS* __fastcall TEventBox::NewHS(int M, int Fr)
|
xue@0
|
52 {
|
xue@0
|
53 if (HSCount>=HSCapacity)
|
xue@0
|
54 {
|
xue@0
|
55 HSCapacity+=100;
|
xue@0
|
56 HS=(THS**)realloc(HS, sizeof(THS*)*HSCapacity);
|
xue@0
|
57 memset(&HS[HSCount], 0, sizeof(THS*)*(HSCapacity-HSCount));
|
xue@0
|
58 }
|
xue@0
|
59 THS* newhs;
|
xue@0
|
60 if (M>0 && Fr>0) newhs=new THS(M, Fr);
|
xue@0
|
61 else newhs=new THS;
|
xue@0
|
62 HS[HSCount++]=newhs;
|
xue@0
|
63 if (ListBox1->Enabled)
|
xue@0
|
64 {
|
xue@0
|
65 ListBox1->Items->Add("");
|
xue@0
|
66 ListBox1->ItemIndex=ListBox1->Count-1;
|
xue@0
|
67 }
|
xue@0
|
68 return newhs;
|
xue@0
|
69 }
|
xue@0
|
70
|
xue@0
|
71 //---------------------------------------------------------------------------
|
xue@0
|
72 void __fastcall TEventBox::ListBox1MouseDown(TObject *Sender,
|
xue@0
|
73 TMouseButton Button, TShiftState Shift, int X, int Y)
|
xue@0
|
74 {
|
xue@0
|
75 int c=ListBox1->ItemAtPos(TPoint(X, Y), true);
|
xue@0
|
76 SetItemIndex(c);
|
xue@0
|
77 }
|
xue@0
|
78 //---------------------------------------------------------------------------
|
xue@0
|
79 void ClearObjectByShortTag0(TWaveView* WV, int tag0);
|
xue@0
|
80 void __fastcall TEventBox::SetItemIndex(int index)
|
xue@0
|
81 {
|
xue@0
|
82 ListBox1->ItemIndex=index;
|
xue@0
|
83 ClearObjectByShortTag0(Form1->WaveView1, 1);
|
xue@0
|
84 if (index>=0)
|
xue@0
|
85 {
|
xue@0
|
86 Form1->HS=HS[index];
|
xue@0
|
87 Form1->AddHSObject(Form1->HS);
|
xue@0
|
88 }
|
xue@0
|
89 else
|
xue@0
|
90 {
|
xue@0
|
91 Form1->HS=0;
|
xue@0
|
92 }
|
xue@0
|
93
|
xue@0
|
94 bool alreadyinvalidated=false;
|
xue@0
|
95 if (CheckBox1->Checked && Form1->HS)
|
xue@0
|
96 {
|
xue@0
|
97 TWaveView* WaveView1=Form1->WaveView1;
|
xue@0
|
98 int eventst=Form1->HS->Partials[0][0].t, eventen=Form1->HS->Partials[0][Form1->HS->Fr-1].t,
|
xue@0
|
99 wvlen=WaveView1->EndPos-WaveView1->StartPos;
|
xue@0
|
100 if (eventst>WaveView1->EndPos || eventen<WaveView1->StartPos)
|
xue@0
|
101 {
|
xue@0
|
102 int newst=(eventst+eventen)/2-wvlen/2, newen=newst+wvlen;
|
xue@0
|
103 if (newst<0) newst=0, newen=wvlen;
|
xue@0
|
104 else if (newen>WaveView1->Length) newen=WaveView1->Length, newst=WaveView1->Length-wvlen;
|
xue@0
|
105 WaveView1->SetStartAndEndPos(newst, newen);
|
xue@0
|
106 alreadyinvalidated=true;
|
xue@0
|
107 }
|
xue@0
|
108 }
|
xue@0
|
109 if (!alreadyinvalidated) Form1->WaveView1->Invalidate();
|
xue@0
|
110 }
|
xue@0
|
111 //---------------------------------------------------------------------------
|
xue@0
|
112 void __fastcall TEventBox::Save(TObject *Sender)
|
xue@0
|
113 {
|
xue@0
|
114 Sort();
|
xue@0
|
115 AnsiString FileName=ChangeFileExt(Form1->WaveAudio1->FileName, ".evt");
|
xue@0
|
116 if (FileExists(FileName))
|
xue@0
|
117 {
|
xue@0
|
118 AnsiString BakName=ChangeFileExt(FileName, ".evt.bak."+Now().FormatString("yymmddhhnnss"));
|
xue@0
|
119 RenameFile(FileName, BakName);
|
xue@0
|
120 }
|
xue@0
|
121 SaveToFile(FileName);
|
xue@0
|
122 }
|
xue@0
|
123 //---------------------------------------------------------------------------
|
xue@0
|
124 void __fastcall TEventBox::Load(TObject *Sender)
|
xue@0
|
125 {
|
xue@0
|
126 LoadFromFile(ChangeFileExt(Form1->WaveAudio1->FileName, ".evt"));
|
xue@0
|
127 }
|
xue@0
|
128 //---------------------------------------------------------------------------
|
xue@0
|
129 void __fastcall TEventBox::Sort()
|
xue@0
|
130 {
|
xue@0
|
131 for (int i=0; i<HSCount-1; i++)
|
xue@0
|
132 {
|
xue@0
|
133 int indmint=i;
|
xue@0
|
134 for (int j=i+1; j<HSCount; j++) if (HS[j]->Partials[0][0].t<HS[indmint]->Partials[0][0].t) indmint=j;
|
xue@0
|
135
|
xue@0
|
136 if (indmint!=i)
|
xue@0
|
137 {
|
xue@0
|
138 THS* tmphs=HS[i];
|
xue@0
|
139 HS[i]=HS[indmint];
|
xue@0
|
140 HS[indmint]=tmphs;
|
xue@0
|
141 AnsiString tmpstr=ListBox1->Items->Strings[i];
|
xue@0
|
142 ListBox1->Items->Strings[i]=ListBox1->Items->Strings[indmint];
|
xue@0
|
143 ListBox1->Items->Strings[indmint]=tmpstr;
|
xue@0
|
144 }
|
xue@0
|
145 }
|
xue@0
|
146 }
|
xue@0
|
147
|
xue@0
|
148 void __fastcall TEventBox::SaveToFile(AnsiString FileName)
|
xue@0
|
149 {
|
xue@0
|
150 TFileStream* File=new TFileStream(FileName, fmCreate);
|
xue@0
|
151 File->Write(&HSCount, sizeof(int));
|
xue@0
|
152 for (int i=0; i<HSCount; i++) HS[i]->WriteToStream(File);
|
xue@0
|
153 delete File;
|
xue@0
|
154 }
|
xue@0
|
155
|
xue@0
|
156 void __fastcall TEventBox::LoadFromFile(AnsiString FileName)
|
xue@0
|
157 {
|
xue@0
|
158 Clear(); SetItemIndex(-1);
|
xue@0
|
159 if (!FileExists(FileName)) return;
|
xue@0
|
160 TFileStream* File=new TFileStream(FileName, fmOpenRead);
|
xue@0
|
161 __int32 hsc; File->Read(&hsc, sizeof(__int32));
|
xue@0
|
162 bool counted=memcmp(&hsc, "EVT", 4);
|
xue@0
|
163 if (!counted) File->Seek(-4, soFromCurrent);
|
xue@0
|
164 ListBox1->Enabled=false;
|
xue@0
|
165
|
xue@0
|
166 int i=0;
|
xue@0
|
167 while (!counted || i<hsc)
|
xue@0
|
168 {
|
xue@0
|
169 THS* hs=NewHS(0, 0);
|
xue@0
|
170 if (!hs->ReadFromStream(File))
|
xue@0
|
171 {
|
xue@0
|
172 if (!counted)
|
xue@0
|
173 {
|
xue@0
|
174 delete HS[i];
|
xue@0
|
175 HSCount--;
|
xue@0
|
176 break;
|
xue@0
|
177 }
|
xue@0
|
178 else
|
xue@0
|
179 { //load old format file
|
xue@0
|
180 char c[5]; c[4]=0;
|
xue@0
|
181 int Channel, M, Fr;
|
xue@0
|
182 File->Read(c, 4);
|
xue@0
|
183 File->Read(&Channel, sizeof(int));
|
xue@0
|
184 File->Read(&M, sizeof(int));
|
xue@0
|
185 File->Read(&Fr, sizeof(int));
|
xue@0
|
186 hs->Resize(M, Fr);
|
xue@0
|
187 hs->Channel=Channel;
|
xue@0
|
188 File->Read(hs->Partials[0], sizeof(atom)*M*Fr);
|
xue@0
|
189 File->Read(c, 4);
|
xue@0
|
190 if (strcmp(c, "EVT ")) hs->isconstf=*(int*)c;
|
xue@0
|
191 else File->Seek(-4, soFromCurrent);
|
xue@0
|
192 }
|
xue@0
|
193 }
|
xue@0
|
194 i++;
|
xue@0
|
195 }
|
xue@0
|
196 delete File;
|
xue@0
|
197 TStringList* List=new TStringList;
|
xue@0
|
198
|
xue@0
|
199 for (int i=0; i<HSCount; i++)
|
xue@0
|
200 {
|
xue@0
|
201 List->Add(AnsiString(i)+" "+
|
xue@0
|
202 (HS[i]->Channel==0?"left: ":"right: ")
|
xue@0
|
203 +AnsiString().sprintf("%.2fs, ", HS[i]->Partials[0][0].t*1.0/Form1->WaveView1->SamplesPerSec)
|
xue@0
|
204 +SemitoneToPitch(Log2(HS[i]->Partials[0][0].f*Form1->WaveView1->SamplesPerSec/C4)*12)
|
xue@0
|
205 );
|
xue@0
|
206 }
|
xue@0
|
207 ListBox1->Items=List;
|
xue@0
|
208 delete List;
|
xue@0
|
209 ListBox1->Enabled=true;
|
xue@0
|
210 SetItemIndex(-1);
|
xue@0
|
211 }
|
xue@0
|
212 //---------------------------------------------------------------------------
|
xue@0
|
213
|
xue@0
|
214
|
xue@0
|
215 void __fastcall TEventBox::ListBox1KeyUp(TObject *Sender, WORD &Key,
|
xue@0
|
216 TShiftState Shift)
|
xue@0
|
217 {
|
xue@0
|
218 int LII=ListBox1->ItemIndex;
|
xue@0
|
219 if (Key==VK_DELETE)
|
xue@0
|
220 {
|
xue@0
|
221 if (LII>=0)
|
xue@0
|
222 {
|
xue@0
|
223 delete HS[LII];
|
xue@0
|
224 HSCount-=1;
|
xue@0
|
225 memcpy(&HS[LII], &HS[LII+1], sizeof(THS*)*(HSCount-LII));
|
xue@0
|
226 ListBox1->Items->Delete(LII);
|
xue@0
|
227 ClearObjectByShortTag0(Form1->WaveView1, 1);
|
xue@0
|
228 Form1->HS=0;
|
xue@0
|
229 Form1->WaveView1->Invalidate();
|
xue@0
|
230 }
|
xue@0
|
231 }
|
xue@0
|
232 else if (Key=='L') Load(NULL);
|
xue@0
|
233 else if (Key=='S') Save(NULL);
|
xue@0
|
234 else
|
xue@0
|
235 {
|
xue@0
|
236 }
|
xue@0
|
237 LII=ListBox1->ItemIndex;
|
xue@0
|
238 if (LII>=0 && Form1->HS!=HS[LII]) SetItemIndex(LII);
|
xue@0
|
239 else if (LII<0 && Form1->HS!=0) SetItemIndex(LII);
|
xue@0
|
240 }
|
xue@0
|
241 //---------------------------------------------------------------------------
|
xue@0
|
242
|
xue@0
|
243
|
xue@0
|
244 void __fastcall TEventBox::Vibratowizard1Click(TObject *Sender)
|
xue@0
|
245 {
|
xue@0
|
246 if (Form1->Vibratowizard1->Enabled) Form1->Vibratowizard1Click(Sender);
|
xue@0
|
247 }
|
xue@0
|
248 //---------------------------------------------------------------------------
|
xue@0
|
249
|
xue@0
|
250 void __fastcall TEventBox::ListBox1DblClick(TObject *Sender)
|
xue@0
|
251 {
|
xue@0
|
252 if (Form1->Vibratowizard1->Enabled)
|
xue@0
|
253 {
|
xue@0
|
254 if (GetKeyState(VK_SHIFT)>=0)
|
xue@0
|
255 Form1->Sourcefilter1Click(Vibratowizard1);
|
xue@0
|
256 else
|
xue@0
|
257 Form1->Vibratowizard1Click(Vibratowizard1);
|
xue@0
|
258 }
|
xue@0
|
259 }
|
xue@0
|
260 //---------------------------------------------------------------------------
|
xue@0
|
261
|
xue@0
|
262 //---------------------------------------------------------------------------
|
xue@0
|
263
|
xue@0
|
264 void __fastcall TEventBox::FormClick(TObject *Sender)
|
xue@0
|
265 {
|
xue@0
|
266 SetItemIndex(-1);
|
xue@0
|
267 }
|
xue@0
|
268 //---------------------------------------------------------------------------
|
xue@0
|
269
|
xue@0
|
270
|
xue@0
|
271 void __fastcall TEventBox::Cut1Click(TObject *Sender)
|
xue@0
|
272 {
|
xue@0
|
273 if (Form1->Cut1->Enabled) Form1->Cut1Click(Sender);
|
xue@0
|
274 }
|
xue@0
|
275 //---------------------------------------------------------------------------
|
xue@0
|
276
|
xue@0
|
277
|
xue@0
|
278 void __fastcall TEventBox::PopupMenu1Popup(TObject *Sender)
|
xue@0
|
279 {
|
xue@0
|
280 bool hasselection=ListBox1->ItemIndex>=0;
|
xue@0
|
281 Vibratowizard1->Visible=hasselection;
|
xue@0
|
282 Sourcefilter1->Visible=hasselection;
|
xue@0
|
283 Extract1->Visible=hasselection;
|
xue@0
|
284 Cut1->Visible=hasselection;;
|
xue@0
|
285 }
|
xue@0
|
286 //---------------------------------------------------------------------------
|
xue@0
|
287
|
xue@0
|
288 void __fastcall TEventBox::Extract1Click(TObject *Sender)
|
xue@0
|
289 {
|
xue@0
|
290 if (Form1->Extract1->Enabled) Form1->Extract1Click(Sender);
|
xue@0
|
291 }
|
xue@0
|
292 //---------------------------------------------------------------------------
|
xue@0
|
293
|
xue@0
|
294
|
xue@0
|
295 void __fastcall TEventBox::Sourcefilter1Click(TObject *Sender)
|
xue@0
|
296 {
|
xue@0
|
297 if (Form1->Vibratowizard1->Enabled)
|
xue@0
|
298 Form1->Sourcefilter1Click(Vibratowizard1);
|
xue@0
|
299 }
|
xue@0
|
300 //---------------------------------------------------------------------------
|
xue@0
|
301
|