I am trying to make an acoustic modem with matlab. It records sound an stores it in an array, modulates it using 64-QAM and adds then demodulates it. But the demodulated sound and recorded sound are not the same.
Here is the code:
clear;
clc;
M = 64; % Modulation order (alphabet size or number of points in signal constellation)
k = log2(M);
Fs=44100;
Nbits=8;
nChannels=1;
SNR=250;
%audio recording
recObj=audiorecorder(Fs,Nbits,nChannels);
recDuration=3;
disp("Begin speaking.")s
recordblocking(recObj,recDuration);
disp("2 sec pause")
pause(2)
disp("End of recording")
y=getaudiodata(recObj);
plot(y);
% playObj=audioplayer(y,Fs);
% play(playObj);
Ts=-(1/Fs)/2:1:(1/Fs)/2;
figure
subplot(1,2,1);
plottf(y,Ts,'t');
subplot(1,2,2);
plottf(y,Ts,'f');
%MODULATION QAM
y_int = abs(round(y*1000/16));
constdiag = comm.ConstellationDiagram('XLimits',[-sqrt(M) sqrt(M)],'YLimits',[-sqrt(M) sqrt(M)]);
qamData = qammod(y_int,M);
constdiag(qamData)
%DEMODULATION QAM
demodData = qamdemod(noisySound,M);
demodData = demodData*16/1000;
isequal(y_int,demodData);
playObjn=audioplayer(demodData,Fs);
play(playObjn);
%LOWPASS FILTER
Fn = Fs/2; % Nyquist Frequency (Hz)
Wp = 1000/Fn; % Passband Frequency (Normalised)
Ws = 1010/Fn; % Stopband Frequency (Normalised)
Rp = 1; % Passband Ripple (dB)
Rs = 150; % Stopband Ripple (dB)
[n,Ws] = cheb2ord(Wp,Ws,Rp,Rs); % Filter Order
[z,p,k] = cheby2(n,Rs,Ws,'low'); % Filter Design
[soslp,glp] = zp2sos(z,p,k); % Convert To Second-Order-Section For Stability
figure(3)
freqz(soslp, 2^16, Fs) % Filter Bode Plot
filtered_sound = filtfilt(soslp, glp, demodData);
%sound(filtered_sound, 44100)
where am i doing wrong?
I tried 16QAM and 32QAM but result is the same.
Related
I designed the following filter and would like to find the zero phase delay between input[x] and filtered signal[Filtsig]. I know how to use y = filtfilt(d,x) but my matlab only suppports the following case only: Case1 Filtsig=filtfilt(sos,g,x)
Case2 Filtsig=filtfilt(b,a,x)
function Hd = untitled0
%UNTITLED0 Returns a discrete-time filter object.
% MATLAB Code
% Generated by MATLAB(R) 9.0 and the Signal Processing Toolbox 7.2.
% Generated on: 02-Apr-2019 20:28:37
% Butterworth Lowpass filter designed using FDESIGN.LOWPASS.
% All frequency values are in Hz.
Fs = 350; % Sampling Frequency
Fpass = 60; % Passband Frequency
Fstop = 70; % Stopband Frequency
Apass = 1; % Passband Ripple (dB)
Astop = 80; % Stopband Attenuation (dB)
match = 'stopband'; % Band to match exactly
% Construct an FDESIGN object and call its BUTTER method.
h = fdesign.lowpass(Fpass, Fstop, Apass, Astop, Fs);
Hd = design(h, 'butter', 'MatchExactly', match);
Filtsig=filtfilt(sos,g,x)
Filtsig=filtfilt(b,a,x)
% Construct an FDESIGN object and call its BUTTER method.
h = fdesign.lowpass(Fpass, Fstop, Apass, Astop, Fs);
Hd = design(h, 'butter', 'MatchExactly', match);
Filtsig=filtfilt(sos,g,x)
Filtsig=filtfilt(b,a,x)
How can i use filtfilt function in the following filter created by matlab filter analysis toolbox.My matlab is 2012.
Below is the syntax but i don't know the variables inside the parentheses y = filtfilt(b,a,x) y = filtfilt(sos,g,x) y = filtfilt(d,x)
% MATLAB Code
% Generated by MATLAB(R) 8.2 and the Signal Processing Toolbox 6.20.
% Generated on: 18-Mar-2019 12:11:31
% Equiripple Lowpass filter designed using the FIRPM function.
% All frequency values are in Hz.
data = xlsread('Smoothendata2.xlsx',1);% read csv content
d1 = data(:,1); % Original Time Vector
d2 = data(:,2); % Original Data Vector
L = length(d1);
tv = linspace(min(d1), max(d1), L); % Time Vector For Interpolation
dv = interp1(d1, d2, tv, 'linear'); % Interpolated Data Vector
Ts = mean(diff(tv)); % Sampling Time Interval
t_stats = [Ts std(tv)];
Fs = 1/Ts; % Sampling Frequency
Fn = Fs/2; % Nyquist Frequency
FTD = fft(dv)/L; % Fourier Transform
Fv = linspace(0, 1, fix(L/2)+1)*Fn; % Frequency Vector
Iv = 1:length(Fv); % Index Vector
figure(1)
semilogy(Fv, abs(FTD(Iv))*2) % Plot Fourier Transform
grid
xlabel('Frequency (Hz)')
ylabel('Amplitude')
%
Fpass = 50; % Passband Frequency
Fstop = 60; % Stopband Frequency
Dpass = 0.17099735734; % Passband Ripple
Dstop = 1; % Stopband Attenuation
dens = 20; % Density Factor
% Calculate the order from the parameters using FIRPMORD.
[N, Fo, Ao, W] = firpmord([Fpass, Fstop]/(Fs/2), [1 0], [Dpass, Dstop]);
% Calculate the coefficients using the FIRPM function.
b = firpm(N, Fo, Ao, W, {dens});
Hd = dfilt.dffir(b);
The filtfilt command is not only made to apply FIR but also IIR filters.
As the FIR has no feedback, in contrast to the IIR filter, it only depends on the feedforward filter coefficients which are defined by b. (the feedback coefficients are represented by a)
As you are interested in applying it for a FIR filter you can set a=1;
So the answer to your question is:
b = firpm(N, Fo, Ao, W, {dens});
a=1;
y = filtfilt(b,a,x)
I have been trying to modulate and demodulate the default audio signal speech_dft.mp3 in MATLAB using various modulation methods with no luck so far. Here is the code I have written up till this point
clear;
close;
clc;
%% Constants and Initialization
Ac = 1; % Carrier Amplitude
Fc = 5.0e6; % Carrier Frequency
Fs = 20e6; % Sampling Frequency
Kf = 50; % Frequency Deviation
Kp = 75; % Phase Deviation
Beg = 1500; % Sample to begin song from
SongStr = 'speech_dft.mp3'; % Name of the File
Song = audioinfo(SongStr); % Getting Audio Info
L = 100; % Length or number of samples
audio = audioread(SongStr); % Reading the Song
audio = audio(Beg:Beg+L-1,:);
%% Modulating
Wave(:,:,1) = (ammod(audio,Fc,Fs)); % DSB-SC AM Modulation
Wave(:,:,3) = (ammod(audio,Fc,Fs,0,Ac)); % DSB-FC AM Modulation
Wave(:,:,5) = (ssbmod(audio,Fc,Fs)); % SSB-SC Lower Sideband AM Modulation
Wave(:,:,7) = (ssbmod(audio,Fc,Fs,0,'upper')); % SSB-SC Upper Sideband AM Modulation
Wave(:,:,9) = (fmmod(audio,Fc,Fs,Kf)); % FM Modulation
Wave(:,:,11) = (pmmod(audio,Fc,Fs,Kp)); % PM Modulation
%% Demodulating
Wave(:,:,2) = (amdemod(audio,Fc,Fs)); % DSB-SC AM Demodulation
Wave(:,:,4) = (amdemod(audio,Fc,Fs,0,Ac)); % DSB-FC AM Demodulation
Wave(:,:,6) = (ssbdemod(audio,Fc,Fs)); % SSB-SC Lower Sideband AM Demodulation
Wave(:,:,8) = (ssbdemod(audio,Fc,Fs)); % SSB-SC Upper Sideband AM Demodulation
Wave(:,:,10) = (fmdemod(audio,Fc,Fs,Kf)); % FM Demodulation
Wave(:,:,12) = (pmdemod(audio,Fc,Fs,Kp)); % PM Demodulation
%% Output
figure(1);
title('Demodulated')
subplot(3,2,1);
hold on;
plot(Wave(:,1,2));
plot(audio(:,1));
legend('DSB-SC','Original')
title('DSB-SC Demod');
subplot(3,2,2);
hold on;
plot(Wave(:,1,4));
plot(audio(:,1));
legend('DSB-FC','Original')
title('DSB-FC Demod');
subplot(3,2,3);
hold on;
plot(Wave(:,1,6));
plot(audio(:,1));
legend('SSB-Lower','Original')
title('SSB-Lower Demod');
subplot(3,2,4);
hold on;
plot(Wave(:,1,8));
plot(audio(:,1));
legend('SSB-Upper','Original')
title('SSB-Upper Demod');
subplot(3,2,5);
hold on;
plot(Wave(:,1,10));
plot(audio(:,1));
legend('FM','Original')
title('FM Demod');
subplot(3,2,6);
hold on;
plot(Wave(:,1,12));
plot(audio(:,1));
legend('PM','Original')
title('PM Demod');
I have kept the Wave(:,1,2) since I also tried working with audio files having two channels and plotting a single channel is much simpler.
This is the output that I get :
As pretty much obvious from the image, the demodulated output is nowhere close to the original message signal but in some cases looks more like modulated signals. Can somebody tell where my mistake is? Thanks in advance.
I'm trying to better understand upsampling and downsampling, and am using an audio signal to do so. I start with a base sampling rate of 66.15kHz, upsample by 2, run it through an LPF (sample rate of 66.15kHz, cutoff frequency of half that), then downsample by 2.
To visualize the differences between the initial and final signal, I created two spectrograms, with different sampling frequencies. There's lots of clear similarities, as well as a tighter band around the signals in the lower frequency version (as a result of the upsampling?), but I think the best thing to do is just take some sort of subtraction of the images. The problem is that the matrices are different sizes, so I can't use approaches found here or here.
Should I just upsample both of them to be the same size? Will the differences still be there?
The spectrograms in question:
Here's the code I used, some parts are commented out that may help to visualize things along the way:
%clc, clear all, close all;
NFFT = 1:10:4000; % used like F in the spectrogram fxn
WINDOW = 2000;
NOVERLAP = 0;
preupsample = audioread('audioclip.wav');
Fo = 66150;
orig_nyq = Fo/2;
U = 2;
D = 3;
postupsample = upsample(preupsample, U);
[preLPF, ~, W] = myfft(postupsample,U*Fo,length(postupsample));
% figure, plot(W,mag2db(abs(preLPF))), xlabel('Frequency (Hz)'), ylabel('Magnitude Response (dB)');
% title('Magnitude Response after upsampling');
filterorder = 100;
Fpass = orig_nyq;
Fs = U*Fo;
Rpass = 0.00057565; % .1dB passband ripple
Rstop = 1e-4; % -80dB stopband attenuation
LPF = firceqrip(filterorder,Fpass/(Fs/2),[Rpass Rstop],'passedge');
% fvtool(LPF,'Fs',Fs,'Color','White');
filtered_upsample = filter(LPF,1,postupsample);
[postLPF, ~, W] = myfft(filtered_upsample,U*Fo,length(filtered_upsample));
% figure, plot(W,mag2db(abs(postLPF))), xlabel('Frequency (Hz)'), ylabel('Magnitude Response (dB)');
% title('Magnitude Response after applying LPF');
postdownsample = downsample(filtered_upsample,D);
[postDS, w, W] = myfft(postdownsample,U*Fo/D,length(postdownsample));
% figure, plot(W,mag2db(abs(postDS))), xlabel('Frequency (Hz)'), ylabel('Magnitude Response (dB)');
% title('Magnitude Response after downsampling');
%[~,F1,T1,P1]=
figure, spectrogram(preupsample(:,1),WINDOW,NOVERLAP,NFFT,Fo,'yaxis');
%[~,F2,T2,P2]=
figure, spectrogram(postdownsample(:,1),WINDOW,NOVERLAP,NFFT,Fo*U/D,'yaxis');
% surf(T2,F2,10*(log10(abs(P2))-log10(abs(P1))),'edgecolor','none');
% view(90,-90);
% axis tight;
The contents of myfft.m:
function [X, w, W] = myfft(x, F, N)
X = fftshift(fft(x, N));
w = fftshift((0:N-1)/N*2*pi);
w(1:N/2) = w(1:N/2) - 2*pi;
W = F*w;
end
I'm making a bandpass filter and I've created a signal with some unwanted frequencies based on sinusoids:
Fs = 8e3; % Sampling Rate
fn = Fs/2; % Nyquist frequency
L = 1e3; % Length of signal
T = 1/Fs; % Sampling period
t = T*linspace(0,L,Fs); % Time domain
% Frequencies in Hz
f1 = 1500;
f2 = 700;
f3 = 2500;
f4 = 3500;
% Signal
x = 6*sin(2*pi*f1*t);
% Noise
noise = 3*sin(2*pi*f2*t)...
+ 2*sin(2*pi*f3*t)...
+ 1*sin(2*pi*f4*t);
x_noise = x + noise;
I then create a Butterworth bandpass filter:
[b,a] = butter(10,[1000 2000]/fn,'bandpass');
The signal in time and frequency space, with the bandpass response (with freqz) looks like this:
Fig. 1 Signal with corruption | Fig. 2 Frequency with bandpass response
I would've figured from here on, simply doing
xf = filter(b,a,x_noise);
would've yielded something very similar to the original signal, but alas, what I get is really far from the filtered signal with a high response far from the bandpass.
What am I doing wrong here?
Here's the full code:
clear all
Fs = 8e3; % Sampling Rate
fn = Fs/2; % Nyquist frequency
L = 1e3; % Length of signal
T = 1/Fs; % Sampling period
t = T*linspace(0,L,Fs); % Time domain
% Frequencies in Hz
f1 = 1500;
f2 = 700;
f3 = 2500;
f4 = 3500;
% Signal
x = 6*sin(2*pi*f1*t);
% Noise
noise = 3*sin(2*pi*f2*t)...
+ 2*sin(2*pi*f3*t)...
+ 1*sin(2*pi*f4*t);
x_noise = x + noise;
subplot(221);
idx = 1:round(length(t)/30);
plot(t(idx),x(idx),t(idx),x_noise(idx));
xlabel('Time (s)'); ylabel('Signal Amplitudes');
legend('Original signal','Noisy signal');
% Frequency space
f = fn*linspace(0,1,L/2+1);
X = fft(x_noise)/L;
[b,a] = butter(10,[1000 2000]/fn,'bandpass');
h = abs(freqz(b,a,floor(L/2+1)));
subplot(222);
plot(f,abs(X(1:L/2+1)),f,h*max(abs(X)));
xlabel('Freq (Hz)'); ylabel('Frequency amplitudes');
legend('Fourier Transform of signal','Filter amplitude response');
% Filtered signal
xf = filter(b,a,x_noise);
subplot(223)
plot(t(idx),xf(idx));
xlabel('Time (s)'); ylabel('Signal Amplitudes');
legend('Filtered signal');
% Filtered in frequency space
Xf = abs(fft(xf)/L);
subplot(224);
plot(f,Xf(1:L/2+1),f,h*5e-6);
xlabel('Freq (Hz)'); ylabel('Frequency amplitudes');
legend('Fourier Transform of filtered signal','Bandpass');
Your time variable t is wrong, e.g 1/(t(2)-t(1)) should give Fs but it doesn't.
Try instead:
t = T*(0:L-1);