ivan@138
|
1 function [SNRx, PSM, PSMt, PESQ_MOS, EAQUAL_ODG, EAQUAL_DIX] = ...
|
ivan@138
|
2 audioQualityMeasures(xRef,xTest,fs,options)
|
ivan@138
|
3 %
|
ivan@138
|
4 %
|
ivan@138
|
5 % Usage:
|
ivan@138
|
6 %
|
ivan@138
|
7 %
|
ivan@138
|
8 % Inputs:
|
ivan@138
|
9 % -
|
ivan@138
|
10 % -
|
ivan@138
|
11 % -
|
ivan@138
|
12 % -
|
ivan@138
|
13 % -
|
ivan@138
|
14 % -
|
ivan@138
|
15 % -
|
ivan@138
|
16 % -
|
ivan@138
|
17 %
|
ivan@138
|
18 % Outputs:
|
ivan@138
|
19 % -
|
ivan@138
|
20 % -
|
ivan@138
|
21 % -
|
ivan@138
|
22 % -
|
ivan@138
|
23 %
|
ivan@138
|
24 % Note that the CVX library is needed.
|
ivan@138
|
25 %
|
ivan@138
|
26 % -------------------
|
ivan@138
|
27 %
|
ivan@138
|
28 % Audio Inpainting toolbox
|
ivan@138
|
29 % Date: June 28, 2011
|
ivan@138
|
30 % By Valentin Emiya, Amir Adler, Maria Jafari
|
ivan@138
|
31 % This code is distributed under the terms of the GNU Public License version 3 (http://www.gnu.org/licenses/gpl.txt).
|
ivan@138
|
32 % Computes a series of audio quality measures
|
ivan@138
|
33 %
|
ivan@138
|
34 % Usage:
|
ivan@138
|
35 % [PSM,PSMt] = ...
|
ivan@138
|
36 % audioQualityMeasures(xRef,xTest,fs,options)
|
ivan@138
|
37 %
|
ivan@138
|
38 % Inputs:
|
ivan@138
|
39 % - xRef: reference signal
|
ivan@138
|
40 % - xTest: test signal (to be compared to xRef)
|
ivan@138
|
41 % - fs: sampling frequency
|
ivan@138
|
42 % - optional parameters [default]:
|
ivan@138
|
43 % - options.ENABLE_PEMOQ: flag to use PEMO-Q or not [true]
|
ivan@138
|
44 % - options.pemoQExec: name of PEMO-Q executable ['"./PEMO-Q v1.1.2 demo/audioqual_demo.exe"']
|
ivan@138
|
45 % - options.PESQExec: name of PESQ executable [''./PESQ/pesq'']
|
ivan@138
|
46 % - options.EAQUALExec: name of EAQUAL (PEAQ) executable ['./EAQUAL/eaqual.exe']
|
ivan@138
|
47 %
|
ivan@138
|
48 % Note that PEMO-Q and EAQUAL programs are Windows executable and that
|
ivan@138
|
49 % under unix, they can be used by means of wine (Windows Emulator). One
|
ivan@138
|
50 % just have to have wine installed.
|
ivan@138
|
51 %
|
ivan@138
|
52 % Valentin Emiya, INRIA, 2010.
|
ivan@138
|
53
|
ivan@138
|
54
|
ivan@138
|
55 %% default options
|
ivan@138
|
56 defaultOptions.pemoQExec = '"C:/Program Files/PEMO-Q v1.2/audioqual.exe"'; % Full licensed version
|
ivan@138
|
57 if isempty(dir(defaultOptions.pemoQExec))
|
ivan@138
|
58 defaultOptions.pemoQExec = '"./PEMO-Q v1.1.2 demo/audioqual_demo.exe"'; % Demo version
|
ivan@138
|
59 end
|
ivan@138
|
60 defaultOptions.ENABLE_PEMOQ = true;
|
ivan@138
|
61 defaultOptions.PESQExec = './PESQ/pesq';
|
ivan@138
|
62
|
ivan@138
|
63 if ispc
|
ivan@138
|
64 defaultOptions.EAQUALExec = './EAQUAL/eaqual.exe';
|
ivan@138
|
65 else % if unix, use wine
|
ivan@138
|
66 defaultOptions.EAQUALExec = 'wine ./EAQUAL/eaqual.exe';
|
ivan@138
|
67 defaultOptions.pemoQExec = ['wine ' defaultOptions.pemoQExec];
|
ivan@138
|
68 end
|
ivan@138
|
69
|
ivan@138
|
70 if nargin<4
|
ivan@138
|
71 options = defaultOptions;
|
ivan@138
|
72 else
|
ivan@138
|
73 names = fieldnames(defaultOptions);
|
ivan@138
|
74 for k=1:length(names)
|
ivan@138
|
75 if ~isfield(options,names{k}) || isempty(options.(names{k}))
|
ivan@138
|
76 options.(names{k}) = defaultOptions.(names{k});
|
ivan@138
|
77 end
|
ivan@138
|
78 end
|
ivan@138
|
79 end
|
ivan@138
|
80
|
ivan@138
|
81 if ~ischar(xRef) && ~ischar(xTest) && length(xRef)~=length(xTest)
|
ivan@138
|
82 warning('EVAL:LENGTH','Different lengths');
|
ivan@138
|
83 L = min(length(xRef),length(xTest));
|
ivan@138
|
84 xRef = xRef(1:L);
|
ivan@138
|
85 xTest = xTest(1:L);
|
ivan@138
|
86 end
|
ivan@138
|
87
|
ivan@138
|
88 if ischar(xRef)
|
ivan@138
|
89 refFile = xRef;
|
ivan@138
|
90 sRef = wavread(refFile);
|
ivan@138
|
91 else
|
ivan@138
|
92 refFile = [tempname '.wav'];
|
ivan@138
|
93 sRef = xRef;
|
ivan@138
|
94 wavwrite(xRef,fs,refFile);
|
ivan@138
|
95 end
|
ivan@138
|
96 if ischar(xTest)
|
ivan@138
|
97 testFile = xTest;
|
ivan@138
|
98 sTest = wavread(testFile);
|
ivan@138
|
99 else
|
ivan@138
|
100 testFile = [tempname '.wav'];
|
ivan@138
|
101 sTest = xTest;
|
ivan@138
|
102 wavwrite(xTest,fs,testFile);
|
ivan@138
|
103 end
|
ivan@138
|
104
|
ivan@138
|
105
|
ivan@138
|
106 SNRx = SNR(sRef,sTest);
|
ivan@138
|
107
|
ivan@138
|
108 try
|
ivan@138
|
109 % if ispc && options.ENABLE_PEMOQ
|
ivan@138
|
110 if options.ENABLE_PEMOQ
|
ivan@138
|
111 %% PEMO-Q
|
ivan@138
|
112 [PSM,PSMt] = aux_pemoq(refFile,testFile,options);
|
ivan@138
|
113 else
|
ivan@138
|
114 warning('audioQualityMeasures:noPQ','PEMO-Q is not available (requires Windows plateform)')
|
ivan@138
|
115 PSM = NaN;
|
ivan@138
|
116 PSMt = NaN;
|
ivan@138
|
117 end
|
ivan@138
|
118
|
ivan@138
|
119 %% PESQ
|
ivan@138
|
120 PESQ_MOS = aux_pesq(refFile,testFile,options);
|
ivan@138
|
121
|
ivan@138
|
122 %% EAQUAL (PEAQ)
|
ivan@138
|
123 [EAQUAL_ODG, EAQUAL_DIX] = aux_eaqual(refFile,testFile,options);
|
ivan@138
|
124
|
ivan@138
|
125 if ~ischar(xRef)
|
ivan@138
|
126 %% Delete temporary files
|
ivan@138
|
127 delete(refFile);
|
ivan@138
|
128 end
|
ivan@138
|
129 if ~ischar(xTest)
|
ivan@138
|
130 delete(testFile);
|
ivan@138
|
131 end
|
ivan@138
|
132
|
ivan@138
|
133 catch
|
ivan@138
|
134 if ~ischar(xRef)
|
ivan@138
|
135 %% In case of error, delete the temporary files
|
ivan@138
|
136 delete(refFile);
|
ivan@138
|
137 end
|
ivan@138
|
138 if ~ischar(xTest)
|
ivan@138
|
139 delete(testFile);
|
ivan@138
|
140 end
|
ivan@138
|
141 rethrow;
|
ivan@138
|
142 end
|
ivan@138
|
143
|
ivan@138
|
144
|
ivan@138
|
145 return
|
ivan@138
|
146
|
ivan@138
|
147 function [PSM,PSMt] = aux_pemoq(refFile,testFile,options)
|
ivan@138
|
148 if ~isempty(findstr(options.pemoQExec, 'demo'))
|
ivan@138
|
149 fprintf('To unlock PEMO-Q demo, please enter the PIN shown in the new window\n');
|
ivan@138
|
150 end
|
ivan@138
|
151 [dum, pemo] = system(sprintf('%s %s %s [] [] 0 0 0', options.pemoQExec, refFile, testFile));
|
ivan@138
|
152 pemo = regexp(pemo, 'PSM.? = \d*.\d*', 'match');
|
ivan@138
|
153 PSM = str2double(cell2mat(regexp(pemo{1},'\d+.?\d*', 'match')));
|
ivan@138
|
154 PSMt = str2double(cell2mat(regexp(pemo{2},'\d+.?\d*', 'match')));
|
ivan@138
|
155
|
ivan@138
|
156 return
|
ivan@138
|
157
|
ivan@138
|
158 function PESQ_MOS = aux_pesq(refFile,testFile,options)
|
ivan@138
|
159 [dum fs] = wavread(refFile,'size');
|
ivan@138
|
160 if ~ismember(fs,[8000 16000])
|
ivan@138
|
161 error('audioQualityMeasures:badFs',...
|
ivan@138
|
162 '8kHz or 16 kHz sampling frequency required for PESQ');
|
ivan@138
|
163 end
|
ivan@138
|
164 [dum,s] = system(sprintf('%s +%d %s %s',options.PESQExec,fs,refFile,testFile));
|
ivan@138
|
165 PESQ_MOS = regexp(s, 'Prediction : PESQ_MOS = \d*.\d*', 'match');
|
ivan@138
|
166 PESQ_MOS = str2double(PESQ_MOS{end}(length('Prediction : PESQ_MOS = ')+1:end));
|
ivan@138
|
167 return
|
ivan@138
|
168
|
ivan@138
|
169 function [EAQUAL_ODG, EAQUAL_DIX] = aux_eaqual(refFile,testFile,options)
|
ivan@138
|
170 [dum fs] = wavread(refFile,'size');
|
ivan@138
|
171 DELETE_FLAG = false;
|
ivan@138
|
172 if fs<44100
|
ivan@138
|
173 warning('EAQUAL:BAD_FS',...
|
ivan@138
|
174 'Sampling frequency is too low for Eaqual (<44.1kHz).\nResampling first (result not relevant)');
|
ivan@138
|
175 DELETE_FLAG = true;
|
ivan@138
|
176
|
ivan@138
|
177 x = wavread(refFile);
|
ivan@138
|
178 fsEaqual = 48000;
|
ivan@138
|
179 x = resample(x,fsEaqual,fs);
|
ivan@138
|
180 refFile = [tempname '.wav'];
|
ivan@138
|
181 wavwrite(x,fsEaqual,refFile);
|
ivan@138
|
182
|
ivan@138
|
183 x = wavread(testFile);
|
ivan@138
|
184 fsEaqual = 48000;
|
ivan@138
|
185 x = resample(x,fsEaqual,fs);
|
ivan@138
|
186 testFile = [tempname '.wav'];
|
ivan@138
|
187 wavwrite(x,fsEaqual,testFile);
|
ivan@138
|
188
|
ivan@138
|
189 fs = fsEaqual;
|
ivan@138
|
190 end
|
ivan@138
|
191
|
ivan@138
|
192 [dum,s] = system(sprintf('%s -fref %s -ftest %s -srate %d',options.EAQUALExec,refFile,testFile,fs));
|
ivan@138
|
193
|
ivan@138
|
194 EAQUAL_ODG = regexp(s, 'Resulting ODG:\t.?\d*(\.\d*)?', 'match');
|
ivan@138
|
195 EAQUAL_ODG = str2double(EAQUAL_ODG{end}(length('Resulting ODG: ')+1:end));
|
ivan@138
|
196 EAQUAL_DIX = regexp(s, 'Resulting DIX:\t.?\d*(\.\d*)?', 'match');
|
ivan@138
|
197 EAQUAL_DIX = str2double(EAQUAL_DIX{end}(length('Resulting DIX: ')+1:end));
|
ivan@138
|
198
|
ivan@138
|
199 if DELETE_FLAG
|
ivan@138
|
200 delete(refFile);
|
ivan@138
|
201 delete(testFile);
|
ivan@138
|
202 end
|
ivan@138
|
203 return
|