ACM11 Homework 4 Solutions
Contents
Problem 1(a)
Write a function that converts the row and column of a keypad entry to the corresponding number. See freq2num.html. We can test it:
fprintf('The entries of the keypad look like:\n'); for k = 1:4 for j = 1:3 fprintf('%s ', freq2num(k,j) ); end fprintf('\n'); end
The entries of the keypad look like: 1 2 3 4 5 6 7 8 9 * 0 #
Problem 1(b)
Load the data and put it in a useable form
fr = [697 770 852 941]; % row frequencies, in Hz fc = [1209 1336 1477]; % column frequencies, in Hz % See what variables are in the file: who -file touchtone.mat % We could load all variables with this line: % load touchtone % Or, just load variable "y": load touchtone y % Extract the data: Fs = y.fs; Y = double(y.sig)/128; % convert to a floating point number n = length(Y); t = (0:(n-1) ) / Fs; % plot(t,Y) % plots the signal in the time-domain % sound(Y,Fs) % plays the sound on speakers % break Y up into pieces: % use data cursor to make the index "by hand" indx = [0,.6,1.5,2.1,2.8,3.5,4.1,4.8,5.5,6.1,6.8,7.4]*1e4 + 1; for chunk = 1:11 Time{chunk} = t(indx(chunk):indx(chunk+1)); Sig{chunk} = Y(indx(chunk):indx(chunk+1)); end
Your variables are: D y z
make a plot:
for chunk = 1:11, plot(Time{chunk},Sig{chunk} ); hold all; end title('Amplitude of dialed phone number; each color represents a number',... 'fontsize',12); xlabel('time, in seconds','fontsize',12);

Problem 1(c)
Number = []; for chunk = 1:11 % loop through each number separately [P,F] = pwelch(Sig{chunk},[],[],[],Fs); % take fourier transform f = F( find( P > .3*1e-3 ) ); % find dominant frequencies % we want to combine neighboring frequencies. Here's one method: tones = f(1); for fi = f(2:end).' % all frequencies within 50 Hz are lumped together. This is OK % because the touch-tone frequencies (in fr and fc) are all % separated by at least 70 Hz. if abs(fi - tones(end)) > 50 tones = [tones, fi]; end end if length(tones) ~= 2 disp('error! found more than two tones (or less)'); end % because the row frequencies (fr) are always less than the column % frequencies (fc), we know tones(1) is a row frequency and tones(2) % is a column frequency. Now, we look for the best match: x = abs( fr - tones(1) ); [temp,i] = min(x); % "temp" is the max, and "i" is the index % where the max occurred tone1 = fr(i); % repeat for column frequency now: x = abs( fc - tones(2) ); [temp,j] = min(x); tone2 = fc(j); % call our function from part (a) to get the number: Number = [Number, freq2num(i,j)] ; end fprintf('Dialed phone number is %s-%s-%s-%s\n',Number(1),... Number(2:4),Number(5:7),Number(8:end));
Dialed phone number is 1-508-647-7001
The problem further asked for a function that takes a signal as input and returns the phone number. Modifying the above to a function is straightforward.
Here are some plots of what's happening (for a single chunk)
[P,F] = pwelch(Sig{chunk},[],[],[],Fs); % take fourier transform f = F( find( P > .3*1e-3 ) ); % find dominant frequencies % make a plot, to show what's going on figure(1); subplot(1,2,1); pwelch( Sig{1},[],[],Fs); subplot(1,2,2); plot( F, P, 'o:' ); title('Power vs Frequency, linear axes'); xlabel('Frequency, Hz'); ylabel('power'); line( [F(1),F(end)],.3e-3*[1,1],'color','red'); text( 2000, .4e-3,'cutoff line','color','red');

if we wanted to do a Fourier Transform (i.e. w/o pwelch), here's how:
l = length( Sig{1} ); p = fft( Sig{1} )/sqrt(l); p = abs( p(1: round(l/2)+1 ) ).^2; % only take part of the output % because for a Real input, the fft % had redundancies. Take the % square to convert to power. % Here's the appropriate scaling for frequency: F2 = (0:round(l/2) )* Fs/l; figure(2); plot(F2,p); title('Power vs Frequency, linear axes, via "DIY" fft');
