annotate AudioDegradationToolbox/degradationUnit_applyWowResampling.m @ 11:2d0ed50c547f version 0.11

Removed tag version 0.11
author matthiasm
date Wed, 21 Aug 2013 19:18:43 +0100
parents 9d682f5e3927
children
rev   line source
matthiasm@0 1 function [f_audio_out,timepositions_afterDegr] = degradationUnit_applyWowResampling(f_audio, samplingFreq, timepositions_beforeDegr, parameter)
matthiasm@0 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
matthiasm@0 3 % Name: degradation_applyWowResampling
matthiasm@0 4 % Date of Revision: 2013-03
matthiasm@0 5 % Programmer: Sebastian Ewert
matthiasm@0 6 %
matthiasm@0 7 % Description:
matthiasm@0 8 % - This is useful for wow and flutter simulations.
matthiasm@0 9 % - a playback speed of 1 is modulated by a cos signal via
matthiasm@0 10 % f(x) = a_m * cos(2*pi*f_m*x)+1
matthiasm@0 11 % - the function mapping a position in the original recording
matthiasm@0 12 % to a position in the generated recording:
matthiasm@0 13 % F(x) = x + a_m * sin(2*pi*f_m*x) / (2*pi*f_m)
matthiasm@0 14 % - an optimal solution now would employ a sinc reconstruction of f_audio,
matthiasm@0 15 % sinc_fa, and sampling sinc_fa(F^-1(y)) equidistantly.
matthiasm@0 16 % - This implementation employs only an approximation by first upsampling
matthiasm@0 17 % f_audio and then sampling that using nearest neighbors
matthiasm@0 18 %
matthiasm@0 19 % Input:
matthiasm@0 20 % f_audio - audio signal \in [-1,1]^{NxC} with C being the number of
matthiasm@0 21 % channels
matthiasm@0 22 % samplingFreq - sampling frequency of f_audio
matthiasm@0 23 % timepositions_beforeDegr - some degradations delay the input signal. If
matthiasm@0 24 % some points in time are given via this
matthiasm@0 25 % parameter, timepositions_afterDegr will
matthiasm@0 26 % return the corresponding positions in the
matthiasm@0 27 % output. Set to [] if unavailable. Set f_audio
matthiasm@0 28 % and samplingFreq to [] to compute only
matthiasm@0 29 % timepositions_afterDegr.
matthiasm@0 30 %
matthiasm@0 31 % Input (optional): parameter
matthiasm@0 32 % .intensityOfChange = 1.5 - a_m = parameter.intensityOfChange/100; stay below 100
matthiasm@0 33 % .frequencyOfChange = 0.5 - f_m
matthiasm@0 34 % .upsamplingFactor = 5 - the higher the better the quality (and the more memory)
matthiasm@0 35 % .normalizeOutputAudio = 0 - normalize audio
matthiasm@0 36 %
matthiasm@0 37 % Output:
matthiasm@0 38 % f_audio_out - audio signal \in [-1,1]^{NxC} with C being the number
matthiasm@0 39 % of channels
matthiasm@0 40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
matthiasm@0 41
matthiasm@0 42 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
matthiasm@0 43 % Audio Degradation Toolbox
matthiasm@0 44 %
matthiasm@0 45 % Centre for Digital Music, Queen Mary University of London.
matthiasm@0 46 % This file copyright 2013 Sebastian Ewert, Matthias Mauch and QMUL.
matthiasm@0 47 %
matthiasm@0 48 % This program is free software; you can redistribute it and/or
matthiasm@0 49 % modify it under the terms of the GNU General Public License as
matthiasm@0 50 % published by the Free Software Foundation; either version 2 of the
matthiasm@0 51 % License, or (at your option) any later version. See the file
matthiasm@0 52 % COPYING included with this distribution for more information.
matthiasm@0 53 %
matthiasm@0 54 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
matthiasm@0 55
matthiasm@0 56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
matthiasm@0 57 % Check parameters
matthiasm@0 58 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
matthiasm@0 59 if nargin<4
matthiasm@0 60 parameter=[];
matthiasm@0 61 end
matthiasm@0 62 if nargin<3
matthiasm@0 63 timepositions_beforeDegr=[];
matthiasm@0 64 end
matthiasm@0 65 if nargin<2
matthiasm@0 66 error('Please specify input data');
matthiasm@0 67 end
matthiasm@0 68
matthiasm@0 69 if isfield(parameter,'intensityOfChange')==0
matthiasm@0 70 parameter.intensityOfChange = 1.5; % a_m = parameter.intensityOfChange/100; %stay below 100
matthiasm@0 71 end
matthiasm@0 72 if isfield(parameter,'frequencyOfChange')==0
matthiasm@0 73 parameter.frequencyOfChange = 0.5; % f_m
matthiasm@0 74 end
matthiasm@0 75 if isfield(parameter,'upsamplingFactor')==0
matthiasm@0 76 parameter.upsamplingFactor = 5; % the higher the better the quality (and the more memory)
matthiasm@0 77 end
matthiasm@0 78 if isfield(parameter,'normalizeOutputAudio')==0
matthiasm@0 79 parameter.normalizeOutputAudio = 0;
matthiasm@0 80 end
matthiasm@0 81
matthiasm@0 82 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
matthiasm@0 83 % Main program
matthiasm@0 84 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
matthiasm@0 85 fs = samplingFreq;
matthiasm@0 86 fsOverSampled = fs * parameter.upsamplingFactor;
matthiasm@0 87 a_m = parameter.intensityOfChange / 100;
matthiasm@0 88 f_m = parameter.frequencyOfChange;
matthiasm@0 89
matthiasm@0 90 f_audio_out = f_audio;
matthiasm@0 91 if ~isempty(f_audio)
matthiasm@0 92 numSamples = size(f_audio,1);
matthiasm@0 93 numChannels = size(f_audio,2);
matthiasm@0 94 length_sec = numSamples/fs;
matthiasm@0 95 numFullPeriods = floor(length_sec * f_m);
matthiasm@0 96 numSamplesToWarp = round(numFullPeriods *fs / f_m);
matthiasm@0 97
matthiasm@0 98 oldSamplePositions_to_newOversampledPositions = round(timeAssignment_newToOld([1:numSamplesToWarp]/fs,a_m,f_m)*fsOverSampled);
matthiasm@0 99
matthiasm@0 100 for ch=1:numChannels
matthiasm@0 101 audioUpsampled = resample(f_audio(:,ch),parameter.upsamplingFactor,1);
matthiasm@0 102
matthiasm@0 103 f_audio_out(1:numSamplesToWarp,ch) = audioUpsampled(oldSamplePositions_to_newOversampledPositions);
matthiasm@0 104
matthiasm@0 105 clear audioUpsampled
matthiasm@0 106 end
matthiasm@0 107
matthiasm@0 108 if parameter.normalizeOutputAudio
matthiasm@0 109 f_audio_out = adthelper_normalizeAudio(f_audio_out, samplingFreq);
matthiasm@0 110 end
matthiasm@0 111
matthiasm@0 112 end
matthiasm@0 113
matthiasm@0 114 %pitchShifted_semitones = getPitchShiftAtPositionsInNewFile([0:0.1:length_sec],a_m,f_m); % not used yet but might be useful later on
matthiasm@0 115
matthiasm@0 116 %selftest(length_sec,a_m,f_m);
matthiasm@0 117
matthiasm@0 118 % This degradation does impose a complex temporal distortion
matthiasm@0 119 timepositions_afterDegr = [];
matthiasm@0 120 if ~isempty(timepositions_beforeDegr)
matthiasm@0 121 timepositions_afterDegr = timeAssignment_oldToNew(timepositions_beforeDegr,a_m,f_m);
matthiasm@0 122 end
matthiasm@0 123
matthiasm@0 124 end
matthiasm@0 125
matthiasm@0 126
matthiasm@0 127 function timeAssigned = timeAssignment_oldToNew(x,a_m,f_m)
matthiasm@0 128 % vectorized
matthiasm@0 129
matthiasm@0 130 timeAssigned = x + a_m * sin(2*pi*f_m*x) / (2*pi*f_m);
matthiasm@0 131
matthiasm@0 132 end
matthiasm@0 133
matthiasm@0 134 function timeAssigned = timeAssignment_newToOld(y,a_m,f_m)
matthiasm@0 135 % vectorized
matthiasm@0 136 % SE: non linear equation: solved numerically (we are lucky:
matthiasm@0 137 % As G(x) := x - (F(x)-y) is a contraction for a_m<1 we can simply employ the Banach fixpoint theorem)
matthiasm@0 138
matthiasm@0 139 timeAssigned = y;
matthiasm@0 140 for k=1:40
matthiasm@0 141 timeAssigned = y - a_m * sin(2*pi*f_m*timeAssigned) / (2*pi*f_m);
matthiasm@0 142 end
matthiasm@0 143
matthiasm@0 144 end
matthiasm@0 145
matthiasm@0 146 function pitchShifted_semitones = getPitchShiftAtPositionsInNewFile(y,a_m,f_m)
matthiasm@0 147 % vectorized
matthiasm@0 148
matthiasm@0 149 % maps times from new to old and takes a look at the value of the derivative
matthiasm@0 150 % there
matthiasm@0 151
matthiasm@0 152 timeAssigned = timeAssignment_newToOld(y,a_m,f_m);
matthiasm@0 153
matthiasm@0 154 derivative = 1 + a_m * cos(2*pi*f_m*timeAssigned);
matthiasm@0 155
matthiasm@0 156 pitchShifted_semitones = log2(1./derivative)*12;
matthiasm@0 157
matthiasm@0 158 end
matthiasm@0 159
matthiasm@0 160 function selftest(length_sec,a_m,f_m)
matthiasm@0 161
matthiasm@0 162 x0 = rand(10000,1) * length_sec;
matthiasm@0 163
matthiasm@0 164 timeAssigned1 = timeAssignment_oldToNew(x0,a_m,f_m);
matthiasm@0 165 timeAssigned2 = timeAssignment_newToOld(timeAssigned1,a_m,f_m);
matthiasm@0 166
matthiasm@0 167 figure;
matthiasm@0 168 plot(x0 - timeAssigned2);
matthiasm@0 169
matthiasm@0 170 end
matthiasm@0 171
matthiasm@0 172
matthiasm@0 173
matthiasm@0 174
matthiasm@0 175
matthiasm@0 176