Octave: How to attenuate all frequencies except one?

I am implementing a morse code decoder in Octave. It already works, but not on very noisy signals, like the following:

I had the following idea to reduce the noise:

1. Perform fft to find the "beep" frequency of the morse tone
2. Use a bandpass filter to attenuate all other frequencies.

Unfortunately, I apparently can't do step 2. After filtering, my signal looks like this:

This shows about the first two milliseconds of the signal.

My code looks like the following. Please tell me:

• whether my basic idea is promising

• how to improve my code in a way that it actually does what I want

[x, f_sampling]  = wavread(filename);
t = fft(x);
l = length(t);
magnitudes = (abs(t/l))(1:l/2+1);
f = f_sampling*(0:(l/2))/l;
[peaks, locations] = findpeaks(magnitudes);
[maximum,index] = max(peaks);
f_main = f(locations(index))

f_cutoff = [0.1 0.9]*2*f_main/(f_sampling)
[b, a] = cheby1(20, 1, f_cutoff);
y = x / max(x);

y = filter(b, a, x);

• This is a repost of a questiion I already posted on stackoverflow. I hope that's o.k. stackoverflow.com/questions/40267017 – spilot Oct 30 '16 at 19:14
• I would suggest that the question is better placed here, therefore you can probably erase its copy from stackoverflow if you like (?). Can I please ask you what is the "beep" frequency? – A_A Oct 30 '16 at 19:22
• Well, the frequency of the tone in the Morse signal. Morse code could be played on any frequency to be valid, e.g. 440 Hz or 4400 Hz. Finding that frequency works very well already. – spilot Oct 30 '16 at 19:25
• I am sorry, I did not pay attention to the findpeaks part. I was initially wondering if you were interested in filtering out a specific "beep" frequency. Since you are already doing the FFT, why not set everything except the two "highest peaks" (the f and its symmetric) to zero and then IFFT? – A_A Oct 30 '16 at 22:29
• I would start by using freqz to visualize the filter's frequency response and see if it actually matches what you expected to get. – MBaz Oct 30 '16 at 22:33

Think of the morse code as an OOK (on-off keying) modulated signal corrupted by additive noise. The optimal linear receiver that can maximize the SNR is matched filter. So "the best" filter you can choose is a filter matched to the frequency of $1$s. After doing that, you have a hypothesis test problem. So you need to choose a threshold (again, the optimal threshold is something known).

If you decided to go that way, I can give you the details.

Before any details, your code appears to be just a pseudo code. It is really not clear what specific waveform you assume. So I try to give you a general answer.

How to do it:

1 - Find the frequency of the $1$s, using FFT or any other scheme. Let's say it is $f_0$.

2 - You should know the bit duration (i.e. the time each $1$ or $0$ takes). Assume it is $T$.

3 - If the waveform of $1$'s is $s(t)$, then your matched filter is $h(t)=s(T-t)$.

4 - Calculate $y(t)=\int_{0}^{t}r(\tau)h(t-\tau)d\tau$, where $r(t)$ is your noisy signal at each interval $T$. This will give you the output of matched filter. We will look at this output at $t=T$ in each timeslot. In other words, you will have discrete values $y_k$ corresponding to each timeslot.

5 - Now you need a threshold $\gamma$ to decide which part of $y_k$ corresponds to a $0$ and which one is $1$. There are a bunch of options, depending on what you want to achieve, the statistics of noise, and the prior probabilities of $0$s and $1$s. If you are not so strict about optimality, assume equiprobable bits. In AWGN you can assume you will expect equally likely $0$s and $1$s which simplifies your choice. So an option would be just $\gamma$ equal to half of the magnitude difference between $0$s and $1$s.

• I'm trying to do exactly that, apply a matched filter. I find out the frequency of 1s by ffr, just assuming that its the highest peak in the spectrum. But the filtering itself fails. – spilot Oct 30 '16 at 22:27
• That's good, but you are doing a completely different thing. I added some details, hope you will find it useful. – msm Oct 30 '16 at 23:36
• Thank you for the details. In your point 4., what is τ? Also, what about my initial approach, finding out the frequency of the 1s by fft and then taking an interval around this frequency as passband for cheby1-filter? Wouldn't that work, if done correctly? And why? – spilot Oct 31 '16 at 9:12
• $T$ is duration of each $0$ or $1$ (or timeslot). Note that you need to ultimately translate the bits to symbols in the morse code (and morse code uses variable length codes). Your initial approach has some serious problems. Most notably your filter does not care about noise. So it allows all passband frequencies in, regardless if they are due to noise or signal (so it is useless against noise). Another major problem is that filtering like that will cause what we refer to as ISI (inter-symbol interference) since your signal has sharp edges. – msm Oct 31 '16 at 9:56
• Thank you, two further questions: 1. How is $f_0$ important after step 1? 2. Can I just assume that my waveform is a sinewave? – spilot Oct 31 '16 at 13:56