Generate echo to an audio

299 views (last 30 days)
pepperlisbon
pepperlisbon on 13 Jul 2019
Edited: DGM on 18 Mar 2023
I have to write a function called echo_gen that adds an echo effect to an audio recording. The function is to be called like this:
output = echo_gen(input, fs, delay, amp);
where input is a column vector with values between -1 and 1 representing a time series of digitized sound data. The input argument fs is the sampling rate. The sampling rate specifies how many samples we have in the data each second. For example, an audio CD uses 44,100 samples per second. The input argument delay represent the delay of the echo in seconds. That is, the echo should start after delay seconds have passed from the start of the audio signal. Finally, amp specifies the amplification of the echo which normally should be a value less than 1, since the echo is typically not as loud as the original signal.
The output of the function is a column vector containing the original sound with the echo superimposed. The output vector will be longer than the input vector if the delay is not zero (round to the nearest number of points needed to get the delay, as opposed to floor or ceil). A sound recording has values between -1 and 1, so if the echo causes some values to be outside of this range, you will need to normalize the entire vector, so that all values adhere to this requirement.
I got blocked on the following code:
function output = echo_gen(input, fs, delay, amp);
samples_echo = round(fs*delay);
input_sound = zeros(length(input)+fs,1);
input = (input_sound(1:length(input)))';
echo = zeros(length(input)+samples_echo,1);
echo_sound = echo(delay+(1:length(input*amp)));
output = input + echo_sound;
max_output = max(abs(output));
if max_output > 1;
for i = i:length (output);
output2 (i) = output2(i)/max_output;
end
output = output2
else
output = output
end
  4 Comments
Omkar Gharat
Omkar Gharat on 18 Aug 2020
function out = blur(img,w)
% convert to double for doing calculations
imgD = double(img);
[row, col] = size(img);
out = zeros(row, col);
for ii = 1:row
for jj = 1:col
% Get the indices for a submatrix
r1 = ii-w;
r2 = ii+w;
c1 = jj-w;
c2 = jj+w;
% Test that indices are valid
% If not, set to min/max that is valid
if r1 < 1
r1 = 1;
end
if r2 > row
r2 = row;
end
if c1 < 1
c1 = 1;
end
if c2 > col
c2 = col;
end
% Get the submatrix and assign the mean to the output pixel
m = imgD(r1:r2, c1:c2);
out(ii,jj) = mean(m(:));
end
end
% convert back to uint8
out = uint8(out);
end
Michelle Zheng
Michelle Zheng on 11 Dec 2020
@omkar, wrong problem

Sign in to comment.

Answers (10)

dhouimir salem
dhouimir salem on 1 Jan 2020
Edited: Walter Roberson on 1 Jan 2020
valid code :
function output = echo_gen(in,fs,delay,gain)
samples = round(fs*delay) ;
ds = floor(samples);
signal = zeros(length(in)+ds,1);
signal(1:length(in))=in;
echo_signal =zeros(length(in)+ds,1);
echo_signal(ds+(1:length(in*gain)))=in*gain;
output= signal + echo_signal;
p= max(abs(output));
if p>1
output=output ./ p;
else
output = output;
end
end
another valid code :
function output = echo_gen(s, Fs, delay, amp)
% Find the time between points using Fs
dt = 1/Fs;
% Calculate the number of points for the given delay
N = round(delay/dt);
% Pad the original signal with zeros to make room for the echo
s1 = [s; zeros(N, 1)];
% Create an echo signal that starts with 0's
s2 = [zeros(N, 1); s.*amp];
% Add the echo to the original signal
output = s1 + s2;
% the abs of all values must be < 1. Rescale if necessary
if max(abs(output)) > 1
output = output./max(abs(output));
end
% Note: This only works with column vectors - can you make the
% function more robust so that it works with column or row vectors?
end
enjoy
  10 Comments
Sachin Patare
Sachin Patare on 30 Sep 2020
Good coding. Even if you don't use the "abs", the code will work.
Walter Roberson
Walter Roberson on 30 Sep 2020
No, you need the abs(). When you have echo, negative values can reinforce each other just like positive values can reinforce each other.
Remember, the human ear does not directly hear whether a speaker is fully extended or fully pulled back: the human ear perceives the changes.
load handel
sound(-y,Fs)
is going to sound exactly like sound(y,Fs) .
So if the processesing can produce values > 1 that have to be scaled back due to reinforcement, then it follows that if the exact negative of the signal had been given, the values would be < -1 instead. It would therefore be a mistake to only test for > 1 instead of abs() > 1.

Sign in to comment.


Arafat Roney
Arafat Roney on 11 May 2020
Edited: Arafat Roney on 11 May 2020
function output = echo_gen(input, fs, delay, amp)
ds = round((delay)*fs); %%CALCULATING DELAY SAMPLE NUMBERS
if ds==0 %%THIS APPENDS TO THE INPUT TO EQUAL THE SIZE WITH OUTPUT
append=[]; %%APPENDS EMPTY MATRIX WHILE 'ds' IS ZERO
else
append=zeros(ds,1); %%APPENDS ZERO VECTOR FOR THE DELAY
end
ain = [append;input]; %%APPENDED INPUT
dmwa = amp*ain; %%AMPLIFIED SIGNAL
outd = [input; append]; %%APPENDED OUTPUT
out = (dmwa+outd); %%OUTPUT WITHOUT SCALLING
%%% SCALLING (IF NEEDED)
mx = max(out);
mn = min(out);
if max(abs(out))>1
if(abs(mx)>abs(mn))
output = out/abs(mx);
else
output = out/abs(mn);
end
else
output=out; %%OUTPUT WITH SCALLING(IF NEEDED)
end
end
  3 Comments
Francesco Tortora
Francesco Tortora on 23 Apr 2022
Hello, thanks for the help! Can you explain better the 'SCALLING' code part?
Thanks!
Walter Roberson
Walter Roberson on 23 Apr 2022
Suppose that you have a sine wave at full volume and suppose that you have a 2% echo. Then your signal value 1.0 would increase to 1.02 with the echo. But the maximum value that can be recorded is 1.0.

Sign in to comment.


David Gonzalez
David Gonzalez on 25 May 2020
function echo_sound = echo_gen(input, fs, delay, amp)
new_sr = round(fs*delay);
no_echo = [input; zeros(new_sr,1)];
echo_effect = [zeros(new_sr,1); input*amp];
echo_sound = no_echo + echo_effect;
norm_factor = max(abs(echo_sound));
if norm_factor > 1
echo_sound = echo_sound./norm_factor;
end

Nisarg Dalal
Nisarg Dalal on 15 May 2020
I wrote the following code, and I am getting errors. Can you help me with it?
function output = echo_gen(input, fs, delay, amp)
[a b] = size(input);
input1 = input*amp;
c = round(fs*delay);
d = length(input1);
x = zeros(a+c,1);
x(1:a) = input;
y = zeros(a+c,1);
y(c:d+c-1) = input1;
output = x+y;
maxi = max(abs(output));
if(maxi > 1)
output = output./maxi;
else
output = output;
end
end

Ajijul Mridol
Ajijul Mridol on 27 Jun 2020
function output=echo_gen(input,fs,delay,amp)
%here calculating the delay points after which echo will be added
c=round(delay*fs);
s1=[input;zeros(c,1)];
s2=[zeros(c,1);input.*amp];
output=s1+s2;
if max(abs(output)) > 1
output = output./max(abs(output)); %scaling the invalid values
end
end
end

Kazi Hafizur Rahman
Kazi Hafizur Rahman on 19 Aug 2020
Edited: Kazi Hafizur Rahman on 19 Aug 2020
this one is a little detailed but works like a charm
function output=echo_gen(input,fs,delay,amp)
N=round(fs*delay);%Number of additional points needed for delay
sz=length(input);
output=zeros(N+sz,1);%if delay is not equal to zero output size will be N greater
for i=1:length(output)
if N<sz%in this case superposition will occur
if i<=N
output(i)=input(i);%first N points will only contain original sound
elseif i<=sz
output(i)=input(i)+amp*input(i-N);%points ranging from N+1 to sz will contain original Sound +amplified sound of a previous time
else
output(i)=amp*input(i-N);%Last N points will only contain amplified data points
end
else
if i<=sz%no superposition in this case
output(i)=input(i);%first sz points will get only original signal data
%points ranging from sz+1 to N will contain nothing
elseif i>N
output(i)=amp*input(i-N);%points after N will contain amplified signal only
end
end
end
maxi=max(abs(output));
if maxi>1
output=output/maxi;%scaling if values fall outside the range [-1,1]
end
end

Mati Somp
Mati Somp on 7 Oct 2020
Ok, it works. In my opinion, the round should be the floor, because the echo signal never reaches the last point in real life.
function out = echo_gen(in, fs, del, amp);
if del==0
a=0;
else
a=round(fs*del);
end
z=zeros(a,1);
out=[in;z]+[z;in*amp];
m=max(abs(out))
if m>1
out=out/m;
end

Kushagra Mehrotra
Kushagra Mehrotra on 23 Feb 2021
function output = echo_gen (y,Fs,delay,amp)
additionalsamples = round (Fs*delay);
delay_vector = zeros(additionalsamples,1);
inputD = [y ; delay_vector];
newy = zeros((length(y)+additionalsamples),1);
amplified = y.*amp;
M = size(y);
newy(end-M+1:end) = amplified(1:end);
outF = newy;
out = (outF + inputD);
Max = max(out);
Min = min(out);
if max(abs(out))>1
if(abs(Max)>abs(Min))
output = out/abs(Max);
else
output = out/abs(Min);
end
else
output=out;
end
end

绵辉 翁
绵辉 翁 on 31 Jul 2021
function output = echo_gen(input,fs,delay,amp)
rawecho = zeros(length(input)+round(fs*delay),1);%creat a vector to storge "pure" echo
v = zeros(round(fs*delay),1);
rawoutput = [input;v];%creat a vector to storge the mixtrue of "pure" echo and input
for ii = 1:length(input)
rawecho(round(fs*delay) + ii) = amp*input(ii);
end
v2 = rawecho + rawoutput;%get the mixtrue of "pure" echo and input
if isempty(v2(v2<-1|v2>1))%check whether to scale obtained output
output = v2;
else
v3 = abs(v2);%scale the output maintaining the relative amplitude of the elements
Maxnum = max(v3);
output = v2/Maxnum;
end

昱安 朱
昱安 朱 on 18 Mar 2023
Edited: DGM on 18 Mar 2023
function output = echo_gen(input, fs, delay, amp)
%input : signal,fs : sample rate,dalay : time of dalay,amp : amplitude
num_delay=round(fs*delay); %延後幾個開始放
echo0=zeros(num_delay,1);
echo_dalay=input*amp;
echo_final=[echo0;echo_dalay]; %最後echo=echo_dalay前面加上delay的數字
org_input=[input;echo0]; %在原來的聲音加上0,匹配成echo的長度
output=echo_final+org_input; %output=原來的聲音加上回音
if max(abs(output))>1
output=output/max(abs(output)); %讓echo在1~-1
end

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!