holger@0
|
1 % This is an example script to illustrate the use of the CAdaptInstrSpec
|
holger@0
|
2 % class. The script loads the spectra extracted two recordings of two
|
holger@0
|
3 % different violins. It then applied the CAdaptInstrSpec class to adapt the
|
holger@0
|
4 % spectra of the first violin to those of the second.
|
holger@0
|
5
|
holger@0
|
6 clearvars;
|
holger@0
|
7 close all;
|
holger@0
|
8
|
holger@0
|
9 addpath('./functions/');
|
holger@0
|
10
|
holger@0
|
11
|
holger@0
|
12 %% constants
|
holger@0
|
13
|
holger@0
|
14 % file paths of instrument spectra
|
holger@0
|
15 noteSpectraFilePaths = {'./instrSpectra/Violin.CQT.mat'; ...
|
holger@0
|
16 './instrSpectra/Violin2.CQT.mat'};
|
holger@0
|
17 numInstr = length(noteSpectraFilePaths);
|
holger@0
|
18
|
holger@0
|
19 % analysis
|
holger@0
|
20 tuningFreqInHz = 440;
|
holger@0
|
21 costFctName = 'LS';
|
holger@0
|
22 beta = 2; % only needed for plotting. should match the cost function above
|
holger@0
|
23 numIter = 5;
|
holger@0
|
24
|
holger@0
|
25
|
holger@0
|
26
|
holger@0
|
27
|
holger@0
|
28 %% load instrument spectra
|
holger@0
|
29 instrSpec = cell(numInstr,1);
|
holger@0
|
30 f0Idcs = cell(numInstr,1);
|
holger@0
|
31
|
holger@0
|
32 for instrIdx = 1:numInstr
|
holger@0
|
33 load(noteSpectraFilePaths{instrIdx}); % loads variables: noteSpectra, midiPitches, freqsInHz
|
holger@0
|
34 instrSpec{instrIdx} = noteSpectra;
|
holger@0
|
35 f0Idcs{instrIdx} = midiPitch2Shift(midiPitches, tuningFreqInHz, freqsInHz)+1;
|
holger@0
|
36 end
|
holger@0
|
37 numBinsPerSemitone = getNumBinsPerSemitoneFromFreqVec(freqsInHz);
|
holger@0
|
38
|
holger@0
|
39
|
holger@0
|
40 %% estimate filter curve
|
holger@0
|
41
|
holger@0
|
42 % create instrSpecFilter object
|
holger@0
|
43 instrFiltObj = CAdaptInstrSpec(instrSpec{1}, instrSpec{2}, f0Idcs{1}, f0Idcs{2}, numBinsPerSemitone, costFctName);
|
holger@0
|
44
|
holger@0
|
45 % apply update function for h
|
holger@0
|
46 for iterIdx = 1:numIter;
|
holger@0
|
47 instrFiltObj = instrFiltObj.updateH;
|
holger@0
|
48 end
|
holger@0
|
49
|
holger@0
|
50 h = instrFiltObj.getH;
|
holger@0
|
51 h_smooth = instrFiltObj.getSmoothedH;
|
holger@0
|
52
|
holger@0
|
53
|
holger@0
|
54 %% estimate spectra with given filter curve
|
holger@0
|
55 estSpectra = instrFiltObj.estimateSpectra(f0Idcs{1});
|
holger@0
|
56
|
holger@0
|
57
|
holger@0
|
58
|
holger@0
|
59
|
holger@0
|
60 %% plot results
|
holger@0
|
61
|
holger@0
|
62 % plot original spectra and estimated spectra
|
holger@0
|
63 yticks = [250 500 1000 2000 4000];
|
holger@0
|
64 yticklabel = {'250'; '500'; '1k'; '2k'; '4k'};
|
holger@0
|
65
|
holger@0
|
66 figure;
|
holger@0
|
67 subplot(311);
|
holger@0
|
68 imagesc(f0Idcs{1}, freqsInHz, instrSpec{1});
|
holger@0
|
69 axis xy;
|
holger@0
|
70 set(gca, 'YScale', 'log', 'YTick', yticks, 'YTickLabel', yticklabel);
|
holger@0
|
71 xlabel('pitch index');
|
holger@0
|
72 ylabel('frequency [Hz]');
|
holger@0
|
73 title('spectra of instrument 1');
|
holger@0
|
74
|
holger@0
|
75
|
holger@0
|
76 subplot(312);
|
holger@0
|
77 imagesc(f0Idcs{1}, freqsInHz, instrSpec{2});
|
holger@0
|
78 axis xy;
|
holger@0
|
79 set(gca, 'YScale', 'log', 'YTick', yticks, 'YTickLabel', yticklabel);
|
holger@0
|
80 xlabel('pitch index');
|
holger@0
|
81 ylabel('frequency [Hz]');
|
holger@0
|
82 title('spectra of instrument 2');
|
holger@0
|
83
|
holger@0
|
84 subplot(313);
|
holger@0
|
85 imagesc(f0Idcs{1}, freqsInHz, estSpectra);
|
holger@0
|
86 axis xy;
|
holger@0
|
87 set(gca, 'YScale', 'log', 'YTick', yticks, 'YTickLabel', yticklabel);
|
holger@0
|
88 xlabel('pitch index');
|
holger@0
|
89 ylabel('frequency [Hz]');
|
holger@0
|
90 title('spectra of instrument 2 adapted to instrument 1')
|
holger@0
|
91
|
holger@0
|
92
|
holger@0
|
93 % plot filter curve and errors
|
holger@0
|
94 xticks = [125 250 500 1000 2000 4000];
|
holger@0
|
95 xticklabel = {'125'; '250'; '500'; '1k'; '2k'; '4k'};
|
holger@0
|
96
|
holger@0
|
97 % compute beta divergence for each element
|
holger@0
|
98 betaDivsOriginal = betaDivergencePerElement(instrSpec{1}, instrSpec{2}, beta);
|
holger@0
|
99 betaDivsEstimate = betaDivergencePerElement(instrSpec{1}, estSpectra, beta);
|
holger@0
|
100
|
holger@0
|
101 % scale per-element beta divergence for image plot
|
holger@0
|
102 numColors = size(colormap,1);
|
holger@0
|
103 maxDist = max([betaDivsOriginal(:); betaDivsEstimate(:)]);
|
holger@0
|
104 betaDivsOriginal = betaDivsOriginal / maxDist * numColors;
|
holger@0
|
105 betaDivsEstimate = betaDivsEstimate / maxDist * numColors;
|
holger@0
|
106
|
holger@0
|
107
|
holger@0
|
108
|
holger@0
|
109 figure;
|
holger@0
|
110 subplot(311)
|
holger@0
|
111 %stem(freqsInHz(h ~= 0), h(h ~= 0), 'k', 'filled');
|
holger@0
|
112 plot(freqsInHz(h ~= 0), h(h ~= 0), 'k.');
|
holger@0
|
113 hold on;
|
holger@0
|
114 plot(freqsInHz, h_smooth, 'k');
|
holger@0
|
115 hold off;
|
holger@0
|
116 axis tight;
|
holger@0
|
117 set(gca, 'XScale', 'log', 'XTick', xticks, 'XTickLabel', xticklabel);
|
holger@0
|
118 title('estimated filter curve ''h''');
|
holger@0
|
119 legend('original', 'smoothed', 'Location', 'NorthWest');
|
holger@0
|
120
|
holger@0
|
121 subplot(312);
|
holger@0
|
122 image(f0Idcs{1}, freqsInHz, betaDivsOriginal);
|
holger@0
|
123 axis xy;
|
holger@0
|
124 set(gca, 'YScale', 'log', 'YTick', yticks, 'YTickLabel', yticklabel);
|
holger@0
|
125 xlabel('pitch index');
|
holger@0
|
126 ylabel('frequency [Hz]');
|
holger@0
|
127 title('elementwise differences between original sets of spectra');
|
holger@0
|
128
|
holger@0
|
129 subplot(313);
|
holger@0
|
130 image(f0Idcs{1}, freqsInHz, betaDivsEstimate);
|
holger@0
|
131 axis xy;
|
holger@0
|
132 set(gca, 'YScale', 'log', 'YTick', yticks, 'YTickLabel', yticklabel);
|
holger@0
|
133 xlabel('pitch index');
|
holger@0
|
134 ylabel('frequency [Hz]');
|
holger@0
|
135 title('differences between original and adapted set of spectra'); |