0
$\begingroup$

i'm writing a batch script in MATLAB to flange.

i'm getting some periodic noise, and i'm having trouble tracking down the source. it's definitely in the algorithm, because soundsc() will scale values larger than 1. and theres no memory or computing time issue, because it's running as a batch process.

any mp3 or wave file should do the trick

current script, with interpolation (sounds worse so far than non-interpolating, because i am probably using the wrong X for the interpolation.)


function result = dLinTerp(x1,x2,y1,y2,x)

% calculate decimal position of x
dx = (x - x1)/(x2 - x1);

% use weighted sum method of interpolating
result = dx*y2 + (1-dx)*y1;

and

    cur_frac=cur_sin*max_samp_delay;

    if (readIdx + cur_frac >= (max_samp_delay)) 
        fetchIdx = cur_frac - (max_samp_delay - readIdx) + 1;
    else
        fetchIdx = readIdx + cur_frac;       
    end

    if (floor(fetchIdx) = max_samp_delay)
        fetchNext = 1;
    else
        fetchNext = ceil(fetchIdx);
    end
     integ = fix(cur_frac); 
     frac = abs(cur_frac - integ);
    interp = dLinTerp(0.0, 1.0, delayBuff(fetchPrev), delayBuff(fetchNext),frac);
    out(i) = (amp*input(i)) + (amp*interp);


here is the original script, no interpolation

%flanger

[input,fs] = audioread('pianoriff_s.mp3');
input = input(:,1);
len = length(input);
out = zeros(len,1);

max_time_delay=0.007; % 7ms max delay in seconds
rate=0.2; %rate of flange in Hz
max_samp_delay= floor(max_time_delay*fs);
delayBuff = zeros(max_samp_delay,1);
amp=0.7;
readIdx = 1;

for i = 1:len,
    delayBuff(readIdx) = input(i);

    sin_ref = sin(2*pi*i*(rate/fs));
    cur_sin=abs(sin_ref); %abs of current sin val 0-1
    cur_delay=ceil(cur_sin*max_samp_delay);

    if (readIdx + cur_delay >= max_samp_delay)
        fetchIdx = cur_delay - (max_samp_delay - readIdx) + 1;
    else
        fetchIdx = readIdx + cur_delay;
    end

    out(i) = (amp*input(i)) + (amp*(delayBuff(fetchIdx)));


    if (readIdx+1 >= max_samp_delay)
        readIdx = 1;
    else
        readIdx = readIdx + 1;
    end
end

soundsc(out,fs);
$\endgroup$
  • $\begingroup$ scaling my sine wave by some amplitude less than 1 seems to help, without the need for interpolation, but still not perfect $\endgroup$ – panthyon Feb 7 '15 at 22:29
  • $\begingroup$ so this is as good as it will get without interpolation, just need to figure out how to do that :p $\endgroup$ – panthyon Feb 8 '15 at 5:30
1
$\begingroup$

ok so it turns out setting indices is tricky in MATLAB (who knew :p)

first, a less needlessly complicated interpolator:

function result = dLinTerp(y1,y2,x)

% use weighted sum method of interpolating
result = x*y2 + (1-x)*y1;

and the flanger

% flanger
clear all;
% Creates a single FIR delay with the delay time oscillating from
% Either 0-3 ms or 0-15 ms at 0.1 - 5 Hz
[input,fs] = audioread('pianoriff_s.mp3');
input = input(:,1);
len = length(input);
out = zeros(len,1);

% parameters to vary the effect %
max_time_delay=0.005; % 7ms max delay in seconds
rate=0.3; %rate of flange in Hz

% convert delay in ms to max delay in samples
max_samp_delay= floor(max_time_delay*fs);
delayBuff = zeros(max_samp_delay,1);
amp=0.7;
readIdx = 1;

fetchPrev = 1;

% delaybase = .010;
% new_d_base = delaybase*fs;
% d_base = LIN_INTERP(0,1,0, new_d_base,frac);
%
% dp = (float)(delay_pos - d_base) - (delay_depth * law);
% %     // Get the integer part
% dp_idx = f_round(dp - 0.5f);
% %     // Get the fractional part
% dp_frac = dp - dp_idx;

% for each sample
for i = 1:len,
    delayBuff(readIdx) = input(i);
    sin_ref = 0.97*sin(2*pi*i*(rate/fs));
    sin_next = 0.97*sin(2*pi*(i+1)*(rate/fs));
    cur_sin=abs(sin_ref); %abs of current sin val 0-1
    cur_delay=ceil(cur_sin*max_samp_delay);

    cur_frac=cur_sin*max_samp_delay;

    if (readIdx + cur_frac >= (max_samp_delay))
        fetchIdx = cur_frac - (max_samp_delay - readIdx) + 1;
    else
        fetchIdx = readIdx + cur_frac;
    end

    if (floor(fetchIdx) = max_samp_delay)
        fetchNext = 1;
    else
        fetchNext = ceil(fetchIdx);
    end

    integ = fix(cur_frac);
    frac = abs(cur_frac - integ);
    interp = dLinTerp(delayBuff(fetchPrev), delayBuff(fetchNext),frac);
    out(i) = (amp*input(i)) + (amp*interp);

    if (readIdx+1 >= max_samp_delay)
        readIdx = 1;
    else
        readIdx = readIdx + 1;
    end


end
% write output

soundsc(out,fs);
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.