Comp 346/488: Intro to Telecommunications

Tuesdays 7:00-9:30, Lewis Towers 412

Class 8: Oct 26

Chapter readings (7th-9th editions):
    8.1, 8.2
    10.1-10.5

(4/π)2*[1 + 1/32 + 1/52 + 1/72] = 0.94959...
So the power level from the first four frequencies in problem 3.22 is~95% of the total.


Strowger switch

cascaded selectors (three shown here)

     o----o-> o
| o
| o
| o----o-> o
| o | o
| o--------o-> o
| o | o-------------
| o | o
| o
| o
See also http://people.seas.harvard.edu/~jones/cscie129/nu_lectures/lecture11/switching/strowger/strowger.html


Signal processing

Compression

Here's a simple algorithm: take 20 ms samples. Standard PCM 8-bit encoding would take 160 bytes. Instead, just report the frequencies used; 20 frequencies at 10 bits each would take 200 bits, or 25 bytes. Another 15-20 bytes would give amplitudes.

One way to find the presence of a tone of a certain frequency is to form a running average the original signal (in an array samples[]) with a sine wave of the desired frequency. One starts with the following running sum (note that freq has to be expressed in terms of the sampling rate):
    double sum = 0;
    for (i=0; i<samples.length; i++) sum += samples[i]*sin(2*pi*freq*i);
If the samples represent a sine wave of a different frequency, then over a long enough interval this will average to zero, and the sum will be small. If the samples represent a sine wave of the same frequency, then samples[i] ≃ K* sin(2*pi*freq*i), for some constant K, and so the sum is of K*sin2(2*pi*freq*i), and over several wavelengths the average of sin2(t) is 1/2 and the sum will not be small.

Of course, running the above sum over your entire sample is a lot of number crunching, and in particular you often want to do this in real time (rather than waiting for the entire sample to be collected). So instead of a "complete" average, one often uses a running average over a set interval. This operation is known as convolution.



Convolution

Specifically, convolution of an array samples[] by a second array K, a shorter array of double of length len, means to set result[n] as follows:

	double sum = 0;
for (int i = 0; i<len; i++) sum += samples[i+n]*K[len-i-1];
result[n] = (short) sum;
Sometimes you might divide by len; more often, K has been adjusted so that the K[i] add up to 1.0 (or 0.0). Purists do the reversed indexing of K, as above, but if you replace K[len-i-1] with K[i], all you have to do is make sure that K itself is created in the reversed order. If K is symmetrical, you won't even have to do that. This reversed form means taking the sum of samples[i+n]*K[i], for i<len.

You can do two things when you reach the upper end of the array samples[]: quit at n = samples.length - len, or else use 0.0 wherever you need a value samples[n] for n ≥ samples.length.

In the literature, K is often said to be a kernel, though this is a very different usage than in the OS sense.

Mathematically, convolving with a kernel K(t) involves taking the integral ∫ signal(t)×K(x-t)dt, over an appropriate interval such as [0,len]. Convolution is the time-domain version of pointwise mulitiplication in the frequency domain; if the frequencies are, say, ⟨f0, f1, f2, f3, f4, f5, f6, f7⟩ and we multiply pointwise by ⟨0,0,0,1,0,0,0,0⟩ we get f3; that is, we have isolated a particular frequency. If we multiply pointwise by ⟨0,0,0,0,1,1,1,1⟩ we get ⟨0,0,0,0,f4,f5,f6,f7⟩; that is, we have implemented a high-pass filter. Both frequency isolation (above) and lo/hi/bandpass filters are indeed implemented as convolutions in the time domain.

A kernel to implement an echo is the following [this is in nonreversed form]:
	1 0 0 0 0 0 ... (length depends on delay) ... 0 0 A

If the length here is len+1, this has the effect of setting result[n] = samples[n] + A*samples[n-len]; that is, adding back into the samples the result from len units ago, reduced by factor A.