0
$\begingroup$

I have been reading papers related to adding echos into digital audio signals recently. I guess I understood the logic behind, yet I guess I am still having lack of DSP knowledge to figure out everything.

In order to add a single echo delay $\Delta$ into audio signal $S$ using convolution operator, echo kernel $k(n)$ is defined as:

$$ k(n)= \delta [n] + \alpha \cdot \delta [n-\Delta]$$

where $\delta [n]$ is Kronecker Delta Function, and $ 0 < \alpha \ll 1.$

Echoed sound signal $S'$ calculated using convolution operator "$*$" as:

$$S'=S \ * k(n)$$

I have no problems until this part. My question is based on this publication, [Ko, Nishimura, Suzuki - 2005]. It is based on echo data hiding for audio watermarking (steganography), but a very good source to understand sound echos. Authors say that multiple echos provide better quality for HAS than single echos (see Fig. 1.)

enter image description here

A pseudorandom sequence is generated to spread multiple echos in time. I generate it in MATLAB with the following code:

rand('seed', key);         % set seed of random sequence
a = rand(length, 1);       
prseq = (a > 0.5)*2-1;     % convert into -1 and +1  

In next step, time-spread echo kernel is defined using PN Sequence as: (see Fig. 2.)

$$ k(n)= \delta [n] + \alpha \cdot P[n-\Delta], 0 < \alpha \ll 1 $$

enter image description here

Schemetic explanation is made in Fig. 3. below:

enter image description here

I tried this tecnique in MATLAB and I actually have two questions:

  1. Audio signal is being corrupted when the number of echos increases no matter how small $\alpha$ value is chosen. In the same article length of PN Sequence is chosen as $1023$, and delay = 1 ms which is about 44 samples in 44.1 kHz audio signal. So how is it possible to provide "a real room" echos as it is said in the article? Do I miss anything?

I am adding my summarized MATLAB codes:

delta = 44;
alpha = 0.02;

% Single echo kernel
for n=1:delta+1
    k_single(n) = kdelta(n-1) + alpha*kdelta(n-delta-1);
end

% Time-spread echo kernel without using kronecker delta:
kernel = [1 zeros(1,delta-1) alpha*prseq'];

echoed = conv(audio_data, kernel);

function [ out ] = kdelta( x )
    out = double((x==0));
end

Alternatively:

single_echo = signal + alpha*[zeros(1,delta) signal(1:length(signal)-delta)];
  1. I was adding echos in an audio signal by shifting and adding as I mentioned above "alternatively". I figured out that it would take so much time to use it for multiple echos, so I thought I had to use convolution. But conv(x,y) function in matlab changing data size up to length(x)+length(y)-1 according to definition of convolution. Is it a good idea to just to crop it like echoed(1:length(audio_data)) to keep the length fixed? What is best option to accomplish multiple echoing as fast as possible and using less memory?

Excuse me for such a long question. I wanted to explain my problem in details, so it made my question longer.

Thanks in advance.

$\endgroup$
2
  • $\begingroup$ What are you actually trying to achieve, an acoustic effect or a watermarking technique as outlined in that paper? For an acoustic effect what you are really describing is known as reverb, which is related to echo but also deals with sound reflections in a more generalised sense. $\endgroup$
    – PAK-9
    Mar 3, 2017 at 14:23
  • $\begingroup$ @PAK-9 thanks for the comment. I actually wanted to achive watermarking technique, but I have no problems with watermarking using echo-hiding technique. Few echos look fine in audio signal, almost imperceptible, and I am able to extract watermarks back. So my question was about using convolution operator and how so many echos give a better sound quality according to article. Sound gets corrupted when I try to add that many echos in matlab... $\endgroup$
    – kdrtkl
    Mar 3, 2017 at 15:34

1 Answer 1

1
$\begingroup$

I'm not that familiar with the technique but reading up it looks like you basically just want an echoic convolution kernel of some sort which you can apply. I don't think the kernel you are building there is correct - if you want, for example, a single echo then the convolution kernel would need to contain two impulses, one at zero offset and one offset into the kernel by the time delay of the echo. For further echoes you would want further impulses, again offset into the kernel by their delay amount. You can have more sophisticated echo kernels but I would suggest this as a starting point

enter image description here

In response to question 2 I would not crop your signal unless it is particularly important to keep the length the same. Keeping the tail will make the deconvolution more accurate and unless your kernal is huge it won't be a very noticeable extension of the signal.

$\endgroup$
5
  • $\begingroup$ Thank you for your response. My question was not about "how to hide bits via echos". In echo-hiding I do split up cover audio into frames as the number of message bits desired to embed. I create two echo kernels with different time delays, one offset and zero offset, to represent bit0 and bit1. I window each frame to provide a smoother transition. It works well. I am able to decode hidden bits using cepstral correlation. $\endgroup$
    – kdrtkl
    Mar 3, 2017 at 19:49
  • $\begingroup$ So about what I actually wanted to learn: I was using "alternate" code line to add up echos into sounds as I mentioned in my question. But as you can guess it sucks when there are tousands of echos to spread. So I had to use convolution operator to let the progress work faster. I am new to this DSP notation of echo kernel. When I tried to apply it, it worked fine with few echos, but when the number of echos increases, it is becoming noissy, and at some point is being corrupted. I wondered if I miss anything to cause this corruption myself, or is it the usual case? $\endgroup$
    – kdrtkl
    Mar 3, 2017 at 19:55
  • $\begingroup$ About second question: Tail from echo kernel is very small, but what is the best method to keep original signal and echoed signal same sized? Is it fine to convolve them like: x1 = conv(signal,kernel) and then crop it like x2 = x1(1:length(signal)) ?? It just seems like amateurish, that's why I asked this question. There may be another smarter way to do same process. $\endgroup$
    – kdrtkl
    Mar 3, 2017 at 20:02
  • $\begingroup$ When you add more echos you will need to decrease the amplitude of all of the echos to keep the same signal to noise ratio (the ratio of kernel sample zero to all other samples in the kernel). Are you doing that? $\endgroup$
    – PAK-9
    Mar 6, 2017 at 10:40
  • $\begingroup$ I am doing that, but I guess I need to decrase amplitudes a bit more. I tried that also, it feels like there is no echos, yet in this case I am not able to catch peaks of echos via cepstrum analysis which i need to decide wheter it is bit0 or bit1. Thanks anyway. $\endgroup$
    – kdrtkl
    Mar 6, 2017 at 11:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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