LAB 8 F. A. Q.
LAB 8 F. A. Q.
0. Some of these questions don’t seem to make sense with respect to this semester’s lab.
ANSWER: Correct. The FAQs are based on the labs from Fall-99. Refer to that lab description when certain section numbers are cited.
4.1 Simple Bandpass Filter Design
1. I am a little lost on the big picture for lab 8. Is the idea that we are writing a program that decodes a dialed (input) touch tone number and breaks it down in to its two frequencies? Also, in selecting beta so that the max value of the frequency response is 1, can we limit our formula to the DTMF frequencies? There would be no need for this to be a working application for any possible frequency, correct?
ANSWER: YES, and then you can decide which number was pressed. I don’t think the limitation you ask about would make it any easier or harder.
2. I am confused about how to get beta equal to one.
ANSWER: For the function freqz, remember how you can input a numerator, then make the denominator = 1 so that the requirement for the fraction doesn’t matter? So, the fact
that this is a cosine doesn’t matter either; we know it is real because it is a cosine, therefore it is like a vector of real numbers and can be used as filter coefficients in the function freqz.
3. Should we pick a beta value so that the maximum value of the frequency response will exactly equal one, or will approach one as L approaches infinity?
ANSWER: If you try to derive a mathematical formula, you may have to settle for something that is only EXACT for n–> infinity. If you let MATLAB do it, you can make it exact for any L.
4. Do we want the entire h[n] to equal 1, after summation, and if so, how do we get MATLAB to do this?
ANSWER: You have to make the peak of the FREQUENCY RESPONSE be equal to one; not h[n]. i.e., you determine beta based on scaling the frequency response to 1, then apply the beta that you got to the impulse response.
5. I am confused about the scaling of beta. Do we need to scale h[n] so that it is 1, or do we need to figure out H(w) from h[n], where H(w) needs to be scaled to 1. If it is the later, I have no idea how I would get H(w) from h[n] since it is a cosine signal.
ANSWER: Use freqz to figure out H(w) from h[n]. Beta should be calculated from H(w) but applied to h[n] once it is found. (Since what you want is to scale the FREQUENCY response so that the max is 1, but you use beta for impulse response as well.)
6. How do you get coefficients from h[n] to put into the vector bb to get the H(w) from freqz?
ANSWER: Recall the relationship between the impulse response and filter coefficients for an FIR filter. This was also done in Lab #7.
7. Are we scaling the maximum value for each frequency, or are we scaling just the maximum value overall? In other words, are we supposed to have one max value equal to 1 or seven max values equal to 1?
8. To find beta, we have to get the frequency response and then scale the highest value to one, correct? To do this, do we use some variation of find()? Also, should we have one Beta or 7? Since there are 7 filters with 7 different h[n] and 7 different H(w), should we get 7 different betas?
ANSWER: First of all, max() is the function you want to use. You should get SEVEN betas.
9. Is it valid to divide h[n] by its max value to scale it to an amplitude of 1, or is that too easy?
ANSWER: You apply beta to h[n], but you determine the value of beta from H(w). You need to make the max of |H(w)| equal to one.
10. This is my understanding of the lab: we take the formula given in the beginning of 4.1 and use that for h[n]. We normalize it so that the max output is 1, then take the output of dtmfdial and each of the normalized h[n]’s and firfilt it to get y[n]. Is this correct?
ANSWER: Not exactly correct. You filter what you get from dtmfdial() against your 7 filters you made with dtmfdesign(), and you score them with dtmfscore(). (Actually, you should be doing the filtering from within dtmfscore()). Now you’ve got 7 scores, telling you which filters this particular piece of your entire “phone number” signal has passed. This should give you two elements in the score vector as 1 and the other elements should be zeros. The ones correspond to the two frequencies of the key number. At this point, you just need to come up with an algorithm to associate matched filter scores (i.e., return values of 1 from dtmfscore()) to phone digits.
11. I have two questions related to this lab:
1) Do you want us to determine the exact value of L, such that it satisfies the stopband and passband specifications mentioned in section 4.1? I am confused because after finishing the lab, I find that even for very small values of L , e.g. L = 50, my program works fine. Is there something I have done wrong?
2) Secondly, although my program runs fine, it gives me a lot of warnings of the kind
Warning: Imaginary parts of complex X and/or Y arguments ignored.
> In C:MATLABR11workdtmfscore.m at line 20
In C:MATLABR11workdtmfrun.m at line 25
In C:MATLABR11workdtmf.m at line 5
ANSWER: Initially you design the filters for passband and stopband. At the end you optimize L so that the system works. As for the errors, some quantity is complex and you are treating it as real. It usually indicates a problem, unless the imaginary part is 10^(-15). Often this happens when you plot something: plot(ww,HH)will give that warning when HH is complex. It tells you the line numbers so look them up.
12. I have completed my lab; however, someone has informed me that I will not receive credit for my scaling of “beta” in part 4.1(a). I used the scaling from lab 7, and my filter worked perfectly. My graphs came out correctly and my filters will always find the correct telephone number or return an error for insufficient filter length.
ANSWER: You have discovered that the 2/L scaling works, and the reason is that it’s pretty close. Did you check the value for your maximum gain? Each of the 7 filters is probably a little different. However, 2/L is not the correct scaling to make the maximum gain be EQUAL to one, and usually filters have to be designed with a very strict control on the gain at certain frequencies. You shouldn’t get credit for Part 4.1(a), because you side-stepped a tough issue; on the other hand, it is only one step in the overall lab so it’s not like it invalidates your working system.
4.1 (b) Simple Bandpass Filter Design (dtmfdesign.m)
1. Is the hh that comes out of the dtmfdesign.m H(w) or is just h[n]?
ANSWER: it should be h[n]. It is in the discrete time domain.
2. The help comments for dtmfdesign says that the function will return a matrix hh that has dimensions (L, length(fcent)). For part (b) it says the function should produce all seven bandpass filters needed. I am confused by these two seemingly different instructions.
ANSWER: Aren’t these the same? What is length(fcent) ? Where are you going to store the 7 BPFs ? Every column of hh must be a bandpass filter that correspond to one of the seven frequencies.
3. Doesn’t the size of the matrix hh[n] have to be L * 7n instead of L*7, since each center frequency (fb) has n corresponding impulse responses, and since there are 7 frequencies, there have to be 7*n impulse responses?
ANSWER: The matrix hh has the columns corresponding to the impulse response of the 7 frequencies, therefore you have 7 columns. The length of each column is determined by n, which ranges from 0:L-1
4. If dtmfdesign is supposed to return a matrix that is L x length(fcent) then isn’t it true that we cannot use freekz because it makes a matrix fs x L?
ANSWER: Take a closer look at the code for dtmfdesign and reevaluate exactly what it returns. (Is it the frequency response?) Be careful about where and when you are using freqz. Use it one column at a time with a ‘for’ loop to scale each column (each filter). The bb vector into freekz can be a row or a column.
5. How do we find the bb vector?
ANSWER: Think column wise. Your bb vector is comprised of coefficients for your UNSCALED filter, check out h[n]!
6.When we used vectors in the dtmfdial in the warmup, we just concatenated to the end of the vector dtmfdial=[dtmfdial,xx]. For this portion, how do you concatenate to the end of hh, so that it forms new rows after it gets to the end of the previous row?
ANSWER: The following code will put “col_vector” into the i-th column of hh:
hh(:,i) = col_vector;
(f) Simple Bandpass Filter Design (dtmfdesign.m)
1. I don’t know if I’m using the right technique for determining L. I used the function in the lab report without beta, and calculated the impulse response. Then I used freqz to find the frequency response. I divided the magnitude of the frequency response by the largest value to scale it. I’ve changed L approximately 20 times and I have never noticed a difference. Shouldn’t I be dividing by L somewhere ?
ANSWER: NO, your scaling is taking care of L. If you looked at your scale factor closely you’d see that it depends on L. The bandwidth should change. The peak value should stay the same. If the bandwidth does not change, then you have a bug.
2. Given that the passband is where |h| is above .707, and the stopband is where |h| is below .2, I am measuring these values off the y axis. To get a value for L so that they are all below .2 is where I’m having trouble. Even with large values of L, I get little spikes above .2. Do these matter? What range should our L be in? What is the region between the passband and the stopband? As long as our spikes don’t go above .707 are we okay?
ANSWER: Just define the stopband to start outside the location where you have peaks above 0.2. The region between is called the TRANSITION ZONE. Every filter has that region because the frequency response is a continuous function. There has to be some region where the frequency response gets from the passband to the stopband. As long as you have a narrow passband you’re OK. You want to get one DTMF frequency in the passband and all the others in the stopband for each BPF for the value of L.
3. This part asks us to pick L so that “only one frequency lies with in the passband…..”. I am confused because there seem to be two ways to interpret this. (1) the curve is so narrow that it looks like a straight line, therefore only “one” frequency gets passed. (2) the curves above 0.707 don’t overlap, so one frequency component lies in the passband. Which one is right?
ANSWER: Either one might be right. In this case it is more like (1) because you have to get all the other DTMF frequencies in the stopband, which is defined to be the region where |H|<0.2
4. I am assuming that L has to be larger than 100 to get the rest of them in the stopband. Is this accurate?
ANSWER: Probably. That is one reason the lab suggests trying L=100.
5. In section 4.1(f), we are supposed to find ‘L’ that allows only one frequency response in the passband, and all others in stopband. I did this by graphing all frequency responses together and looking at graph to pick which L did this best, and got a rather large L. Later in the lab, we are supposed to test dtmfrun with various values of L and choose the smallest one that returns the correct key numbers. I got a relatively small value of L here. So my question is: are we supposed to get different values of L?
ANSWER: YES. you are using different criteria to find L. In one case, the separation vs. frequency; in the other, detection capability.
6. No matter what L I choose, I always get a magnitude above 0.2. I’ve gotten all the peaks to equal 1, but there are still values above .2, the designated stop band. Any ideas on how to correct this? It’s not much higher than the stopband, but I’m not sure if this will make a big difference.
ANSWER: There is a region when |H(w)| is below 0.2, and that is what is defined to be the stopband. And the size of that stopband region depends on L.
7. Are we still plotting all 7 frequencies but trying to achieve a certain L so that at .707 and above they don’t overlap, and so that all but the 7 frequencies are below the stopband? I keep getting a few values just above .2 .
ANSWER: If you have values above 0.2, then the stopband is defined to be outside that region. Plot one |H(w)| for one frequency. Locate all the 7 frequencies. Show that one is in the passband and the other 6 are in the stopband (i.e., have gain less than 0.2). Do this for each BPF (for each frequency).
4.2 A Scoring Function (dtmfscore.m)
1. I understand that we are supposed to use the dtmfcut function to break up the signal, but where do we get the signal? Also, how should we use the outputs nstart/nstop? Finally, in dtmfscore, how do we know which bandpass filter to use?
ANSWER: First, the dtmfdial function is used to generate the DTMF signal, so create an xx vector containing the DTMF tones for 1-800. You can play this through your speakers by using soundsc(). Note that dtmfscore is a function that takes in this xx vector and the filter coefficients for ONE of the seven impulse responses that you created. Each impulse response will allow only ONE frequency to “pass” while nulling other frequencies. So, in the decoding portion, (this is where you find out WHICH keys on the keypad are contained in the xx vector (in our example, we used 1-8-0-0 (note 0 = 11) so
1,8,11,and 11 are the keys that need to be found in xx). To find these keys, you write the dtmfscore function. You will need to call dtmfscore from your dtmfrun function that you write. When fed an xx vector containing the DTMF tones, dtmfrun will return a vector containing all the keys that are present in the xx vector. This call should return [1, 8, 11, 11] in our specific example. Also note that dtmfcut is already created for you. Additionally, dtmfscore will return a 1 or a 0. If the function returns a 1, then you know that for this particular impulse response filter, the frequency that this impulse response is suppose to isolate is present in the signal. If it returns 0, then the frequency is not present. You need to do this for all seven of your filters to find out which frequencies are present in the signal.
2. In the lab manual, it states that the input signal is normalized to the range [-2,+2], and we know that the range of the impulse response is between zero and one. Of course after the convolution, we will have most of the outputs that are in the range 1-2. For what reason would the threshold value be 0.95 ? Using this condition, my dtmfscore always fired 1 as the output.
ANSWER: Something’s wrong. After the signal goes through a BPF, it will be big if in the passband, but small if not. Make some plots of the outputs of your BPFs and look at the typical size of the output signal. Time for debugging—look at the signals inside your
1. Make L real long, so the filter is guaranteed to work.
2. Generate signal for one key only (as a test).
3. Make a plot of the output signals from each of the 7 BPFs.
Only two of them should be big, and you should know which two. Also, the two big ones should be very sinusoidal because with a large L the passbands are very narrow. Then you can determine if your filters are working correctly, OR if your detection/decoding logic has a bug.
4. The longer I make L the smaller my values get. My max values never reach .95. What could cause this?
ANSWER: Perhaps you have not scaled H(w) properly. Check the signal size at the input and the gain of the filter at the peak. If the signal has frequency equal to the passband center frequency, then you can compute (mathematically) the output. MATLAB should behave accordingly.
5. For the dtmfcut function, when I run it on my entire signal comprised of the tones generated in dtmfdial, I get a vector of 12 numbers. Is this what the function is supposed to return? If so, can you further define nstart and nstop?
ANSWER: Make sure you get both outputs from dtmfcut. It returns two vectors. In your case you should get two vectors, each with 12 elements. One is the starting indices, one is the ending indices. The first element from the first vector tells where the first signal starts in xx while the first element from the second vector tells where the first signal ends. Similarly, the second two elements in both vectors tell the start and the end of the second signal, respectively, and so on…
6. Is the purpose of dtmfscore to convolve the input tones from dtmfcut with their appropriate impulse response? If so, then is nstart the starting point of the tones from dtmfdial, and nstop the stopping point of the tones filtering out the pauses between numbers?
ANSWER: YES, both to convolve and then also test versus a threshold.
7. No matter what input I try, nstart is always a vector with length one. As a result the loop in dtmfrun only runs one time!
ANSWER: Does your dtmfdial function put silence in between the tones? The function dtmfcut needs silence to break them apart. How many numbers you are dialing as input to the dtmfdial.m.
8. In dtmfscore, we’re supposed to find the signal that has a max value above .95. If the maximum value of one sinusoid in xx was 1, and the frequency response had a maximum value of 1 at the same frequency of the sinusoid, then the maximum value of the output signal would be 1. Why do we need to choose an L in 4.1(f) that is so large (passband = .707 and stopband = .2) and then get a smaller L later when we say max(yy)> =.95? In this lab, it appears to me that max(yy) could be > =1. This would make the L smaller still. With the large L from 4.1(f), we could actually say max(yy)>=.707, couldn’t we?
ANSWER: YES, but the lab is imposing a certain detection threshold on your implementation. That dictates the value of L. In a real system there would be noise added to the tones, then detection would be harder. The basic idea (of real system design) is that you need frequency separation first, so you pick L to get that. Then you try to reduce L knowing that frequency interference will start to cause problems, as will noise. Eventually you can reduce L somewhat depending on how strict your threshold is.
9. I don’t understand what we are supposed to do with the vector hh. Do we have to traverse the matrix hh, and find the output for each column that is filtered with the vector xx?
ANSWER: The vector xx has to be filtered with each of the 7 bandpass filters. Recall that hh contains the 7 filters: one per column.
10. The skeleton says hh = the impulse response of ONE bandpass filter. If this is so, aren’t we only dealing with one column and therefore convolving xx with hh, not hh(:,column)?
ANSWER: The dtmfscore function does deal with one bandpass filter at a time, i.e., one column at a time; so dtmfscore deals with one segment of xx and one column of hh at a time. But hh contains seven columns each corresponds to one BPF.
11. I’m having trouble with the index exceeding matrix dimensions using this function. What form must the input of the xx vector be? I’ve tried different inputs, but I keep getting the error. For example, the following code gives me the error:
>> dtmfcut([697 770 852 941 1209 1336 1477],8000);
What am I doing wrong?
ANSWER: Your xx vector is the vector generated by dtmfdial.m; you apply the dtmfcut to that vector from the dtmfrun file, then process each segment returned from dtmfcut through dtmfscore. So, the input to dtmfcut should be your dtmfdial generated signal.
12. For this section, do we take in the signal produced from dtmfdial and split it up using the cut, then find the peaks with dtmfscore and recall the key values for the signal? If so, I can’t seem to figure out how to use dtmfscore to locate the correct spot in the signal to get the points to make the keys.
ANSWER: You need bandpass filters before you score it. Put the signal through 7 different BPFs. If the BPF is narrow enough, then it should pass one sinusoid only. Plot the output–it should look sinusoidal. Ignore the first L-1 points, because they are transient values.
4.3 DTMF Decode Function (dtmfrun.m)
1. Should the output of dtmfrun be in the form of telephone digits: 123456789*0# or should it be as it says in the lab: 1 2 3 4 5 6 7 8 9 10 11 12?
ANSWER: Either. But I must admit that 123456789*0# looks a lot more professional.
2. How can I make my program output a ‘*’ or ‘#’? Currently I have something like this:
This returns a value of 42 instead of ‘*’ when I look at the output. Do I need to convert keys to a string or something?
ANSWER: You need to make them all strings, even ‘1’, ‘2’ etc. MATLAB has "mat2str" and "num2str" for converting to strings. Try help to know how to deal with these two functions.
3. Since dtmfrun takes 3 inputs, should xx be only one signal or a vector of multiple signals? If it is only one signal, does that mean we can only enter one key at a time?
ANSWER: Has to be all of them. Then call dtmfcut to break them apart. Read the skeleton—it already has that information in it!
4. I am testing nstart and nstop with different keys, but they always give same output if the number of keys are the same. For example if I plug in 4 keys, then
nstart =[ 801 3601 6401 9201]
nstop= [2875 5677 8477 11200]
always. Is it suppose to be this way?
ANSWER: Yes, because your dtmfdial function is (probably) always making tones of the same length.
5. For dtmfrun, I am having trouble turning the frequencies that I found in to their corresponding numbers. Any suggestions?
ANSWER: Make a table and index into the table. Take the idea from dtmfdial and reverse it. One frequency is the row frequency, the other is the column frequency, so build a formula that takes the row index and the column index and computes the key ID. Something like:
3*row + column
This is not the exact formula but maybe it portrays the idea.
6. For last step, printing out the numbers found, I’m confused. For example, for an input of 3, I get 1,0,0,0,0,0,1 from dtmfscore. This makes sense because number 3 is in the first row, third column. How do I turn this into a number? Also, this is in a loop, so I get as many vector scores as there are numbers.
ANSWER: To turn that into a number, look at what you did in section 3 of the lab to go from matrix “coordinates” to phone pad numbers. Apply somewhat the same principle here. As for the loop, you should only use scores unique to each signal you test. That is, for pass through the loop, you should have 7 scores specific to the part of the signal tested in that loop.
7. In an earlier post, it was suggested that the ‘*’ and ‘#’ keys should be in their original form instead of 10 and 12. How do you do this? I tried setting them up as strings in my table with (‘*’) and (‘#’), but this doesn’t work. What am I missing here?
ANSWER: If you are trying to use ‘*’ and ‘#’ as strings, then the numbers from 0 to 9 should also be strings. In other words, instead of having keymap = [1 2 … ‘*’ ‘#’], you should have keymap = [‘1’ ‘2’ … ‘*’ ‘#’].
1. I do not quite understand the type of “error” they described here. I know key # can’t be negative and must be 1:12, but if key # = -1, for example, why does the filter length L get too small? Why do I need to test the minimum value for L?
ANSWER: In a realistic system design you would want to minimize the complexity of the system. The shorter you can make L, the less complicated the FIR filters will be. An FIR requires L multiplies per output, so longer L means you need a faster multiplier in your DSP.
2. Wouldn’t an error be indicated by —2 rather than -1 since we were to scale the input signal to [-2,+2] in 4.2 (c)?
ANSWER: You can indicate an error with any number that is not a legitimate output. Any negative number would be fine, as long as you know what the convention is. You don’t have to tie it to the signal size.
3. Instead of putting -1 in the key, wouldn’t it be easier to use the error() function in MATLAB?
ANSWER: Maybe, but you might want to know how many decodes were “in error” and not just bail on the first one.
4. I have been trying to test my program, and for some reason when I output the keys, I get the following arrangement when I dial 1 through 12: 1 1 1 4 4 4 7 7 7 10 10 10. My outputs from dtmfscore are the same for the first three, and then the next three, etc. I know the signals are different, am I missing something?
ANSWER: It looks as though you don’t have the column OFFSET implemented correctly when you access the keypad.
5. What is column offset, and where exactly should I have applied it? What is happening is that my vector that contains the s’s are the same for the first three and then the next three etc. Where should I focus my investigation? I am getting 11114444777710101010 for any values put in.
ANSWER: If you do your debugging by looking at signals, then you should plot the outputs of all the bandpass filters. Make the input have just one key. Pick one that isn’t working. Keep it simple and trace through all the BPF output signals and also trace through the logic that decides which signal is present.
4.4 Telephone Numbers
1. I have a question about how we are to demonstrate that our programs work by running them on the given telephone number. How can we show that our dtmfrun function works correctly? The only output is a matrix containing the keys that are present in the signal.
ANSWER: Might be hard, but one main point of the lab is to DESIGN the filters that will make the system work and to minimize the order of the filters. So, I would guess that you might show that it fails for a smaller L than the one you find to be the best. And it will only fail some of the time. The given phone number is just a suitable test case.
2. When I try to test my system by getting values from dtmfdial and using them in my dtmfrun function, I get values back, but there are wrong numbers in between the right ones – in particular, zeros. I’m thinking this could be caused from putting an improper amount of space in between my tone pairs in dtmfdial, but I can’t figure out how to change it- increasing and decreasing the space changes the numbers and the amount of them, but it doesn’t make them go away.
ANSWER: The space between the tone pairs should not matter. The function dtmfcut() detects that space and separates the tones. And, dtmfcut() just detects the zeros; it doesn’t care how many zeros there are. Try testing with one number, and then two numbers, so that the spacing isn’t the issue. Also you should plot the output of the bandpass filters to verify that the outputs are nearly sinusoidal. This might help to find a bug.