changeset 13:22964a1dc292

Accurate EBU R128 / ITU-R BS.1770 loudness calculation; batch resample bash script
author Brecht De Man <b.deman@qmul.ac.uk>
date Tue, 26 Apr 2016 14:54:32 +0200
parents 866c5da4d357
children f187d96b6c81
files aux/clipfade.m aux/getLoudness.m aux/loudness.m aux/loudness_itu.m aux/loudness_match.m aux/loudnesstest.m aux/resample aux/stereo2mono.m
diffstat 8 files changed, 123 insertions(+), 508 deletions(-) [+]
line wrap: on
line diff
--- a/aux/clipfade.m	Fri Jun 26 20:56:42 2015 +0100
+++ b/aux/clipfade.m	Tue Apr 26 14:54:32 2016 +0200
@@ -26,7 +26,7 @@
 end
 
 for i = 1:length(list)
-        [audio,fsfile] = audioread([folder slash list(i).name], [starttime*fs+1 endtime*fs]); % read part of file
+        [audio,fsfile] = audioread([folder slash list(i).name], [floor(starttime*fs)+1 ceil(endtime*fs)]); % read part of file
         assert(fsfile == fs); % check file has expected sampling rate
 
         Nfade = fadetime*fs; % make fade vector (based on sampling rate)
--- a/aux/getLoudness.m	Fri Jun 26 20:56:42 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,344 +0,0 @@
-function result = getloudness( vector, Fs, timescale, plotBOOL )
-%GETLOUDNESS returns loudness levels according to EBU R 128 specification
-% Function getLoudness accepts an audio file vector (vector), a sampling
-% rate (Fs), a timescale ('M' - Momentary, 'S' - Short, 'I' - Integrated)
-% and a boolean of whether or not to plot the results, and returns either a
-% scalar for Integrated timescales, or a vector of loudnesses with a
-% refresh rate of 10 Hz.
-%
-% Calling sequence:
-%   result = getLoudness(vector, Fs, timescale, plotBOOL)
-
-% 	% Defining filter coefficients for the pre-filter, according to ITU-R BS.1770-1 
-%     % Modelling a spherical head
-%     prefilterBcoeffs = [1.53512485958697, -2.69169618940638, 1.19839281085285];
-%     prefilterAcoeffs = [1.0, -1.69065929318241, 0.73248077421585];
-%     
-%     % Defining filter coefficients for the RLB, according to ITU-R BS.1770-1
-%     rlbBcoeffs = [1.0, -2.0, 1.0];
-%     rlbAcoeffs = [1.0, -1.99004745483398, 0.99007225036621];
-    
- % MY 44.1kHZ Coefficients   
-    
-%     prefilterBcoeffs = [1.53093728623786, -2.65120001232265, 1.16732946528280];
-%     prefilterAcoeffs = [1.0, -1.66410930225081, 0.711176041448821];
-
-% by Pedro Pestana; modified by Brecht De Man
-
-    rlbBcoeffs = [[0.994975383507587;], [-1.98995076701517;], [0.994975383507587;]];
-    rlbAcoeffs = [1, -1.98992552008493, 0.989976013945421];
-
-    % loudness prefilter function below this one (see Pestana 2013)
-    [prefilterBcoeffs, prefilterAcoeffs] = getloudnessprefilter(10, Fs);
-
-   
-    % Weighting coefficients with channel format [L, R, C, Ls, Rs]
-    nrChannels = size(vector,2);
-    switch nrChannels
-        case 1,
-            G = [1.0];
-        case 2,
-            G = [1.0 1.0];
-        case 5,
-            G = [1.0 1.0 1.0 1.41 1.41];
-        case 6,
-            G = [1.0 1.0 1.0 1.41 1.41]; % double check... AES is L,R,C,LFE,Ls,Rs
-        otherwise,
-            fprintf('Unsuported number of channels\n');
-    end
-    
-    pfVector = filter(prefilterBcoeffs, prefilterAcoeffs, vector); %Apply pre-filter
-	rlbVector = filter(rlbBcoeffs, rlbAcoeffs, pfVector);% Apply RLB filter
-    vectorSquared = rlbVector.^2;
-    
-    switch timescale
-        case 'M'
-            % MODE: MOMENTARY
-            winDur = 400; % window time in miliseconds
-            winSize = Fs*winDur/1000; % window duration in samples
-            olapSize = Fs*100/1000; % not specified
-            maxI = floor( length(vector)/olapSize - winSize/olapSize + 1); % number of iterations
-            for i = 1:maxI
-                blockEnergy(i,:) = sum( vectorSquared( (i-1)*olapSize+1 : (i-1)*olapSize+winSize ,:) )./winSize;
-                time(i) = (i*olapSize)/Fs;
-            end
-            gTimesZ = bsxfun(@times, blockEnergy, G);
-            loudness = -0.691 + 10 .* log10(sum(gTimesZ,2));
-            
-            if(plotBOOL)
-                plot(time, loudness, 'b-', 'LineWidth', 2);
-                axis([0 length(vector)/Fs -70 0]);
-                xlabel('Time (s)');
-                ylabel('Momentary Loudness (dB)')
-                grid on;
-            end
-            
-            result = loudness;
-            
-        case 'S'
-            % MODE: SHORT
-            winDur = 3000; % window time in miliseconds
-            winSize = Fs*winDur/1000; % window duration in samples
-            olapSize = Fs*100/1000; % 10 Hz refresh rate as per spec
-            maxI = floor( length(vector)/olapSize - winSize/olapSize + 1); % number of iterations
-            for i = 1:maxI
-                blockEnergy(i,:) = sum( vectorSquared( (i-1)*olapSize+1 : (i-1)*olapSize+winSize ,:) )./winSize;
-                time(i) = (i*olapSize)/Fs;
-            end
-            gTimesZ = bsxfun(@times, blockEnergy, G);
-            loudness = -0.691 + 10 .* log10(sum(gTimesZ,2));
-            
-            if(plotBOOL)
-                plot(time, loudness, 'r-.', 'LineWidth', 2);
-                axis([0 length(vector)/Fs -70 0]);
-                xlabel('Time (s)');
-                ylabel('Short Term Loudness (dB)')
-                grid on;
-            end
-            
-            result = loudness;
-        
-        case 'I' 
-
-            % MODE: INTEGRATED
-            
-            % Gating block interval duration
-            winDur = 400; % in miliseconds
-            winSize = Fs*winDur/1000; % in samples
-            overlap = 0.5; % overlap. Specs: 1/(1-n) must be a natural number exc. 1
-            olapSize = overlap*winSize; % block start interval
-            maxI = floor( length(vector)/olapSize - winSize/olapSize + 1 ); % number of iterations
-    
-            for i = 1:maxI
-                % equation 3
-                blockEnergy(i,:) = sum(vectorSquared( (i-1)*olapSize+1 : (i-1)*olapSize+winSize,:))./winSize;
-            end
-            
-            % equation 4 - loudness
-            gTimesZ = bsxfun(@times, blockEnergy, G);  %element-by-elemnt array multiple of G and blockEnergy
-            loudness = -0.691 + 10 .* log10(sum(gTimesZ,2));
-    
-            % applying the absolute gate
-            absGate = loudness >= -70;
-            absgatedLoudness = loudness(absGate);
-            absgatedEnergy = blockEnergy(absGate,:);
-            overallAbsLoudness = -0.691 + 10 .* log10( sum((sum(absgatedEnergy)./size(absgatedEnergy,1)).*G) );
-    
-            % applying the relative gate 8 dB down from overallAbsLoudness
-            relGateLevel = overallAbsLoudness - 8;
-            relGate = loudness >= relGateLevel;
-            relgatedLoudness = loudness(relGate);
-            relgateEnergy = blockEnergy(relGate,:);
-            overallRelLoudness = -0.691 + 10 .* log10( sum((sum(relgateEnergy)./size(relgateEnergy,1)).*G) );
-    
-            result = overallRelLoudness;
-           
-            
-        case 'ITU' 
-
-            % MODE: ITU (brecht)
-            
-            % Gating block interval duration
-            winDur = 400; % in miliseconds
-            winSize = Fs*winDur/1000; % in samples
-            overlap = 0.75; % overlap. Specs: 1/(1-n) must be a natural number exc. 1
-            olapSize = overlap*winSize; % block start interval
-            maxI = floor( length(vector)/olapSize - winSize/olapSize + 1 ); % number of iterations
-    
-            for i = 1:maxI
-                % equation 3
-                blockEnergy(i,:) = sum(vectorSquared( (i-1)*olapSize+1 : (i-1)*olapSize+winSize,:))./winSize;
-            end
-            
-            % equation 4 - loudness
-            gTimesZ = bsxfun(@times, blockEnergy, G);  %element-by-elemnt array multiple of G and blockEnergy
-            loudness = -0.691 + 10 .* log10(sum(gTimesZ,2));
-    
-            % applying the absolute gate
-            absGate = loudness >= -70;
-            absgatedLoudness = loudness(absGate);
-            absgatedEnergy = blockEnergy(absGate,:);
-            overallAbsLoudness = -0.691 + 10 .* log10( sum((sum(absgatedEnergy)./size(absgatedEnergy,1)).*G) );
-    
-            % applying the relative gate 10 dB down from overallAbsLoudness
-            relGateLevel = overallAbsLoudness - 10;
-            relGate = loudness >= relGateLevel;
-            relgatedLoudness = loudness(relGate);
-            relgateEnergy = blockEnergy(relGate,:);
-            overallRelLoudness = -0.691 + 10 .* log10( sum((sum(relgateEnergy)./size(relgateEnergy,1)).*G) );
-    
-            result = overallRelLoudness;
-            
-        case 'B' 
-
-            % MODE: INTEGRATED - modified by Brecht De Man to follow ITU-R BS.1770-3
-            % and Pestana 2013
-            
-            % GAIN???
-            
-            % Gating block interval duration
-            winDur = 280; % in miliseconds (see Pestana 2013)
-            winSize = Fs*winDur/1000; % in samples
-            overlap = 0.75; %! % overlap. Specs: 1/(1-n) must be a natural number exc. 1
-            olapSize = overlap*winSize; % block start interval
-            maxI = floor( length(vector)/olapSize - winSize/olapSize + 1 ); % number of iterations
-    
-            for i = 1:maxI
-                % equation 3
-                blockEnergy(i,:) = sum(vectorSquared( (i-1)*olapSize+1 : (i-1)*olapSize+winSize,:))./winSize;
-            end
-            
-            % equation 4 - loudness
-            gTimesZ = bsxfun(@times, blockEnergy, G);  %element-by-elemnt array multiple of G and blockEnergy
-            loudness = -0.691 + 10 .* log10(sum(gTimesZ,2));
-    
-            % applying the absolute gate
-            absGate = loudness >= -70;
-            absgatedLoudness = loudness(absGate);
-            absgatedEnergy = blockEnergy(absGate,:);
-            overallAbsLoudness = -0.691 + 10 .* log10( sum((sum(absgatedEnergy)./size(absgatedEnergy,1)).*G) );
-    
-            % applying the relative gate 10 dB (!) down from overallAbsLoudness
-            relGateLevel = overallAbsLoudness - 10; % !
-            relGate = loudness >= relGateLevel;
-            relgatedLoudness = loudness(relGate);
-            relgateEnergy = blockEnergy(relGate,:);
-            overallRelLoudness = -0.691 + 10 .* log10( sum((sum(relgateEnergy)./size(relgateEnergy,1)).*G) );
-    
-            result = overallRelLoudness;
-            
-        otherwise  
-           
-            % MODE: My short-time measure
-            
-            winDur = 3000; % window time in miliseconds
-            winSize = Fs*winDur/1000; % window duration in samples
-            blockEnergy = sum(vectorSquared(:))./winSize;
-
-            % equation 4 - loudness
-            gTimesZ = bsxfun(@times, blockEnergy, G);  %element-by-elemnt array multiple of G and blockEnergy
-            loudness = -0.691 + 10 .* log10(sum(gTimesZ,2));
-            
-            winSize=0;
-            olapSize=0;
-            
-            result = loudness; 
-            
-    end
-end
-
-
-
-function [prefilterBcoeffs, prefilterAcoeffs] = getloudnessprefilter(gainIndB, fs)
-% GET LOUDNESS calculates coefficients for prefilter with arbitrary gain as 
-% specified in EBU R 128 and the modification proposed in Pestana 2013. 
-% 
-% by Brecht De Man at Centre for Digital Music on 24 April 2014
-
-if nargin < 2
-    fs = 44100; % standard 44.1kHz
-    if nargin < 1
-        gainIndB = 4.0; % as recommended in EBU R 128 / ITU-R BS.1770-3
-    end
-end
-
-f0      = 1681.9;
-%Q = ?
-%BW = ?
-S       = 1;
- 
-A       = sqrt(10^(gainIndB/20));
-w0      = 2*pi*f0/fs;
-alpha   = sin(w0/2) * sqrt( (A+1/A) * (1/S-1) + 2);
- 
-b0      = A*((A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha);
-b1      = -2*A*((A-1) + (A+1)*cos(w0));
-b2      = A*((A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha);
-a0      = (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha;
-a1      = 2*((A-1) - (A+1)*cos(w0));
-a2      = (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha;
- 
-% b0 =  (1 - cos(w0))/2;
-% b1 =   1 - cos(w0);
-% b2 =  (1 - cos(w0))/2;
-% a0 =   1 + alpha;
-% a1 =  -2*cos(w0);
-% a2 =   1 - alpha;
- 
-% b0      = b0/a0;
-% b1      = b1/a0;
-% b2      = b2/a0;
-% a0      = a0/a0;
-% a1      = a1/a0;
-% a2      = a2/a0;
- 
-prefilterBcoeffs    = [b0, b1, b2];
-prefilterAcoeffs    = [a0, a1, a2];
-
-
-% % DEBUG: comparison with ITU/EBU standard hard coded coefficients
-% [Hpf,Wpf] = freqz(prefilterBcoeffs, prefilterAcoeffs, 20000, fs); % response in radians per sample
-%  
-% subplot(2,1,1)
-% semilogx(20*log10(abs(Hpf)));
-% axis([0 20000 -10 15]);
-% grid on
-% set(gca, 'XTickMode','manual');
-% set(gca, 'XTickLabel',num2str(get(gca,'XTick')'));
-%  
-% 
-% % fs=48k, 4dB gain
-% prefilterBcoeffs = [1.53512485958697, -2.69169618940638, 1.19839281085285];
-% prefilterAcoeffs = [1.0, -1.69065929318241, 0.73248077421585];
-%  
-% [Hpf,Wpf] = freqz(prefilterBcoeffs, prefilterAcoeffs, 20000,48000); % response in radians per sample
-%  
-% subplot(2,1,2)
-% semilogx(20*log10(abs(Hpf)));
-% axis([0 20000 -10 10]);
-% grid on
-% set(gca, 'XTickMode','manual');
-% set(gca, 'XTickLabel',num2str(get(gca,'XTick')'));
-
-
-% see 
-% S. Mansbridge, S. Finn, and J. D. Reiss, "Implementation and Evaluation 
-% of Autonomous Multi-track Fader Control," 132nd Convention of the Audio 
-% Engineering Society, 2012. 
-% f_c = 1681.97;
-% Omega = tan(pi*f_c/fs);
-% V_H = 1.58; % probably gain (?+4dB)
-% V_L = 1.26; % switch with V_B?
-% V_B = 1; 
-% Q   = 0.71;
-% 
-% b(1) = V_L * Omega^2 + V_B*Omega/Q + V_H;
-% b(2) = 2*(V_L*Omega^2 - V_H);
-% b(3) = V_L*Omega^2 - V_B*Omega/Q + V_H;
-% a(1) = Omega^2 + Omega/Q + 1;
-% a(2) = 2*(Omega^2 - 1);
-% a(3) = Omega^2 - Omega/Q + 1;
-% 
-% b = b /a(1);
-% a = a /a(1);
-
-% f  = 1682; % Hz
-% S  = 1; % steep without noticeable notches/peaks
-% A  = 10^(gain/40);
-% w0 =2*pi*f/fs;
-% alpha = sin(w0)/2 * sqrt( (A+ 1/A)*(1/S - 1) + 2 );
-% 
-% % filter coefficients
-% b(1)=    A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha );
-% b(2) = -2*A*( (A-1) + (A+1)*cos(w0)                   );
-% b(3) =    A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha );
-% a(1) =        (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha;
-% a(2) =    2*( (A-1) - (A+1)*cos(w0)                   );
-% a(3) =        (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha;
-% 
-
-
-% DEBUG
-%fvtool(b,a,'Fs',fs);
-
-end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aux/loudness.m	Tue Apr 26 14:54:32 2016 +0200
@@ -0,0 +1,102 @@
+function integratedloudness = loudness(signal, fs)
+%INTEGRATEDLOUDNESS returns loudness level (scalar) according to EBU R 128 
+% specification and accepts an audio file vector (vector) and a sampling
+% rate (fs). 
+% 
+% by Brecht De Man on Monday 25 April 2016 
+
+    nrSamples  = size(signal,1);
+    nrChannels = size(signal,2);
+
+    % loudness prefilters (functions below this one)
+    [b1, a1] = loudnessprefilter1(fs);
+    [b2, a2] = loudnessprefilter2(fs);
+   
+    % Weighting coefficients with channel format [L, R, C, Ls, Rs]
+    G = [1.0 1.0 1.0 1.41 1.41 0.0 0.0]; % temporary
+    
+    % Apply pre-filter
+    signal_intermediate = filter(b1, a1, signal); 
+    signal_filtered = filter(b2, a2, signal_intermediate); 
+
+    % Gating block interval duration
+    T_g = .4; % seconds
+    Gamma_a = -70.0; % absolute threshold: -70 LKFS
+    overlap = 0.75; % relative overlap (0.0 - 1.0)
+    step = 1 - overlap;
+    
+    T = nrSamples/fs; % length of measurement interval in seconds
+    j_range = 1:floor((T-T_g)/(T_g*step)+1);
+    z = zeros(nrChannels, max(size(j_range)));
+    for i = 1:nrChannels % for each channel i
+        for j=j_range % for each window j
+            lbound = floor(fs*T_g*(j-1)*step+1); 
+            hbound = floor(fs*T_g*((j-1)*step+1)); 
+            z(i,j) = (1/(T_g*fs))*sum(signal_filtered(lbound:hbound, i).^2);
+        end
+    end  
+
+    G_current = G(1:nrChannels); % discard weighting coefficients G_i unused channels
+    l = zeros(size(j_range,1), 1);
+    for j=j_range % for each window j
+        l(j) = -.691 + 10.0*log10(sum(G_current*z(:,j)));
+    end
+        
+    % throw out anything below absolute threshold:
+    z_avg = mean(z(:,l>Gamma_a),2);
+    Gamma_r = -.691 + 10.0*log10(G_current*z_avg) - 10.0;
+    % throw out anything below relative threshold:
+    z_avg = mean(z(:,l>Gamma_r),2);
+    integratedloudness = -.691 + 10.0*log10(G_current*z_avg);
+            
+end
+
+function [b, a] = loudnessprefilter1(fs)
+% LOUDNESSPREFILTER1 calculates coefficients for the first prefilter 
+% specified in EBU R 128. 
+
+    % pre-filter 1 coefficients
+    f0 = 1681.9744509555319;
+    G  = 3.99984385397;
+    Q  = 0.7071752369554193;
+    K  = tan(pi * f0 / fs);
+    Vh = 10.0^(G / 20.0); % TODO: precompute
+    Vb = Vh^0.499666774155; % TODO: precompute
+    a0_ = 1.0 + K / Q + K * K;
+    b0 = (Vh + Vb * K / Q + K * K) / a0_;
+    b1 = 2.0 * (K * K -  Vh) / a0_;
+    b2 = (Vh - Vb * K / Q + K * K) / a0_;
+    a0 = 1.0;
+    a1 = 2.0 * (K * K - 1.0) / a0_;
+    a2 = (1.0 - K / Q + K * K) / a0_;
+    
+    b = [b0, b1, b2];
+    a = [a0, a1, a2];
+    
+    % DEBUG
+    %fvtool(b,a,'fs',fs);
+
+end
+
+function [b, a] = loudnessprefilter2(fs)
+% LOUDNESSPREFILTER2 calculates coefficients for the second prefilter 
+% specified in EBU R 128. 
+
+    % pre-filter 2 coefficients
+    f0 = 38.13547087613982;
+    Q  = 0.5003270373253953;
+    K  = tan(pi * f0 / fs);
+    a0 = 1.0;
+    a1 = 2.0 * (K * K - 1.0) / (1.0 + K / Q + K * K);
+    a2 = (1.0 - K / Q + K * K) / (1.0 + K / Q + K * K);
+    b0 = 1.0;
+    b1 = -2.0;
+    b2 = 1.0;
+    
+    b = [b0, b1, b2];
+    a = [a0, a1, a2];
+    
+    % DEBUG
+    %fvtool(b,a,'fs',fs);
+
+end
--- a/aux/loudness_itu.m	Fri Jun 26 20:56:42 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-function lkfs = loudness_itu(x, fs)
-%LOUDNESS_ITU   compute loudness (LKFS) based on ITU-R BS.1770-2
-%   LOUDNESS_ITU(x, fs, mode) compute loudness based on ITU-R BS.1770-2
-%   specification.  x is an input signal (mono/stereo/5.1ch) with sampling
-%   frequency fs.
-%
-%   Input signal has to be either in mono (M), stereo (L and R), or
-%   5.1ch(L, R, C, LFE, Ls, and Rs) in respective channel order.
-%
-%   Example: loudness calculation
-%   [x,fs] = wavread('soundfile.wav');
-%   lkfs = LOUDNESS_ITU(x, fs);
-%
-%   2012-01-06 MARUI Atsushi
-
-% constants
-blockSize = 400;   % in ms
-overlapSize = 0.75;   % in percentage
-channelWeights = [1 1 1 0 sqrt(2) sqrt(2)];   % in L, R, C, LFE, Ls, Rs order
-absoluteThreshold = -70;   % in dB
-relativeThreshold = -10;   % in dB
-
-% preparation
-if size(x,1)~=length(x)
-    x = x';
-end
-numch = size(x,2);
-
-if fs~=48000
-    x = resample(x, 48000, fs);
-    fs = 48000;
-end
-
-switch(numch)
-    case 5
-        chwat = channelWeights([1 2 3 5 6]);
-    otherwise
-        chwat = channelWeights(1:numch);
-end
-
-% K-filter
-B1 = [
-    1.53512485958697
-    -2.69169618940638
-    1.19839281085285
-    ];
-A1 = [
-    1.0
-    -1.69065929318241
-    0.73248077421585
-    ];
-B2 = [
-    1.0
-    -2.0
-    1.0
-    ];
-A2 = [
-    1.0
-    -1.99004745483398
-    0.99007225036621
-    ];
-y = filter(B2,A2,filter(B1,A1,x));
-
-% Mean square
-numBlock = ceil(length(y)/ blockSize) + 1;
-yy = zeros(numBlock * blockSize, numch);
-yy(1:length(y),:) = y;
-j = 0:(length(y) - blockSize)/(blockSize * (1-overlapSize));
-z = zeros(length(j), numch);
-for n1 = 1:length(j)
-    yyy = yy(blockSize*j(n1)*(1-overlapSize)+1:blockSize*(j(n1)*(1-overlapSize)+1)+1,:);
-    z(n1,:) = sum(yyy .^ 2) / blockSize;
-end
-l = -0.691 + 10*log10(sum(repmat(chwat,length(z),1) .* z, 2));
-
-% Gating (absolute)
-Jg = l > absoluteThreshold;
-zz = repmat(channelWeights(1:numch),length(z),1) .* z;
-L_KG = -0.691 + 10*log10(chwat * sum(zz(Jg,:), 1)' / sum(Jg));
-
-% Gating (relative)
-Gamma_r = L_KG + relativeThreshold;
-Jg = l > Gamma_r;
-L_KG = -0.691 + 10*log10(chwat * sum(zz(Jg,:), 1)' / sum(Jg));
-
-% OPTIONAL: draw pretty figure
-if false
-    t = (blockSize*(j*(1-overlapSize)+1)+1)/fs;
-    h = plot(t, l, 'color', [.5 .5 .5]);
-    hold on;
-    h = line([t(1) t(end)], [L_KG L_KG]);
-    set(h, 'Color', 'b');
-    set(h, 'LineStyle', '--');
-    set(h, 'LineWidth', 1);
-    h = line([t(1) t(end)], [Gamma_r Gamma_r]);
-    set(h, 'Color', 'b');
-    set(h, 'LineStyle', ':');
-    set(gca, 'Xlim', [t(1) t(end)]);
-    hold off;
-    legend({'momentary', 'integrated', 'relative gate'});
-end
-
-% output
-lkfs = L_KG;
\ No newline at end of file
--- a/aux/loudness_match.m	Fri Jun 26 20:56:42 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-function factor = loudness_match (X, fs, lkfs)
-%LOUDNESS_MATCH
-%   LOUDNESS_MATCH (X, fs, lkfs) calculates an amplitude multiplication factor
-%   which equalizes a sound to match the specified loudness (in LKFS).
-%
-%   2010-02-23 by MARUI Atsushi
-
-factor = 1.0;
-factorHigh = 10^(+60/20);
-factorLow = 10^(-60/20);
-i = 1;
-
-while i
-    s = loudness_itu(factor * X, fs);
-    k = (s - lkfs) / lkfs;
-    
-    fprintf('%3d:   Factor %7.5f   LKFS %7.3f   (%6.2f%% difference)\n', i, factor, s, k*100);
-    i = i + 1;
-    
-    if abs(k) < 0.001
-        return;
-    end
-    
-    if k < 0.0
-        factorOld = factor;
-        factor = (factorLow + factor) / 2.0;
-        factorHigh = factorOld;
-    elseif k > 0.0
-        factorOld = factor;
-        factor = (factorHigh + factor) / 2.0;
-        factorLow = factorOld;
-    end
-end
\ No newline at end of file
--- a/aux/loudnesstest.m	Fri Jun 26 20:56:42 2015 +0100
+++ b/aux/loudnesstest.m	Tue Apr 26 14:54:32 2016 +0200
@@ -1,27 +1,15 @@
-% test loudness mod
+% test loudness.m
 
-tic; 
+testfolder = '/Users/Brecht/Google Drive/Writings/ebur128-scripts/ebu-loudness-test-setv04/';
 
-% target loudness and test file
-target_loudness = -23;  % dBLU
-filename = 'W.wav';
+files = dir([testfolder '*.wav']);
 
-% import sound file
-[audio, fs] = audioread(filename); 
-
-% measure and display loudness
-initial_loudness = getloudness(audio, fs, 'ITU', 0);
-disp(['Initial loudness: ' num2str(initial_loudness)]);
-
-% apply gain
-difference_loudness = target_loudness - initial_loudness;
-disp(['Difference in loudness: ' num2str(difference_loudness)]);
-audio = 10^(difference_loudness/20) .* audio;
-disp(['Gain: ' num2str(10^(difference_loudness/20))]);
-
-% measure and display loudness (should be equal to target loudness)
-resulting_loudness = getloudness(audio, fs, 'ITU', 0);
-disp(['Resulting loudness: ' num2str(resulting_loudness)]);
-
-elapsed_time = toc;
-disp(['Elapsed time: ' num2str(elapsed_time)]);
\ No newline at end of file
+tTotal = tic;
+for file = files'
+    [signal, fs] = audioread([testfolder file.name]);
+    tic;
+    IL = loudness(signal,fs); % calculate integrated loudness
+    tCurrent = toc;
+    fprintf('%s:\t%4.10f\t%d\t(%4.2f s)\n', file.name, IL, fs, tCurrent);
+end
+fprintf('Testing completed: %4.2f seconds elapsed\n', toc(tTotal));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aux/resample	Tue Apr 26 14:54:32 2016 +0200
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+for i in *.wav; do
+    sox -G $i -b 24 temp.wav rate -v 96k;
+    mv temp.wav $i;
+done
\ No newline at end of file
--- a/aux/stereo2mono.m	Fri Jun 26 20:56:42 2015 +0100
+++ b/aux/stereo2mono.m	Tue Apr 26 14:54:32 2016 +0200
@@ -25,8 +25,8 @@
         [audio,fs] = audioread(files(k).name); % read audio
         % check if stereo; if so, get channels and save as separate wavfile
         if size(audio,2)==2
-            audiowrite([files(k).name(1:end-4) '_L.wav'],audio(:,1),fs, 'BitsPerSample', 24);
-            audiowrite([files(k).name(1:end-4) '_R.wav'],audio(:,2),fs, 'BitsPerSample', 24);
+            audiowrite([files(k).name(1:end-4) '.L.wav'],audio(:,1),fs, 'BitsPerSample', 24);
+            audiowrite([files(k).name(1:end-4) '.R.wav'],audio(:,2),fs, 'BitsPerSample', 24);
         end
 end
 cd(currentfolder); % go back to original folder