Trying to modulate audio with OFDM data.

My fs = 44.1khz, i'm using 64 sub-carriers, but i'm only using 5 sub-carriers for data, so my bandwidth is about 3.445khz. I'm not sure how to properly write the all real data to a wav file and then reconstruct the complex signal when I read it back. Can someone point me where I'm messing up?

Matlab code:

 close all
clear all

%fft length

%carrier frequency
fc = 15000; 

%create the data to send
qpsk1 = (floor(2*rand(1,2))-.5)/.5 + 1j*(floor(2*rand(1,2))-.5)/.5;
qpsk2 = (floor(2*rand(1,3))-.5)/.5 + 1j*(floor(2*rand(1,3))-.5)/.5;

inputiFFT = [zeros(1,29) qpsk1, 0, qpsk2 zeros(1,29)];
outputiFFT = ifft(inputiFFT,N);

%spin data to carrier
y3 = outputiFFT.*exp(1j*2*pi*15000/44100*(0:length(outputiFFT)-1));
%despin to baseband for sanity check
y4 = y3.*exp(-1j*2*pi*15000/44100*(0:length(y3)-1));

hold on
plot((-0.5:1/NN:.5-1/NN)*44100, ((abs(fft(outputiFFT,NN)))))
plot((-0.5:1/NN:.5-1/NN)*44100, ((abs(fft(y3,NN)))))
hold off
title('Data - blue, Data at carrier - r')
plot((-0.5:1/NN:.5-1/NN)*44100, ((abs(fft(y4,NN)))))
title('sanity check down mix')

%upconvert to 15khz and write to wav (all 'real')
towav = real(outputiFFT).*cos(-2*pi*fc/44100*(0:length(outputiFFT)-1)) + imag(outputiFFT).*sin(-2*pi*fc/44100*(0:length(outputiFFT)-1));

%write to wav then read from wave
wavwrite(towav, 44100, 'ofdmTest.wav');
[y_wav,FS] = wavread('ofdmTest.wav');

hold on
plot((-0.5:1/NN:.5-1/NN)*44100, ((abs(fft(towav,NN)))),'color','b')
plot((-0.5:1/NN:.5-1/NN)*44100, ((abs(fft(y3,NN)))),'color','r')
hold off
title('Theoretical data up converted to carrier -r , data written to wav - b')

%convert to I-Q
yRx = (y_wav.*cos(-2*pi*fc/44100*(0:length(outputiFFT)-1)).'+ 1j*y_wav.*sin(-2*pi*fc/44100*(0:length(outputiFFT)-1)).');

hold on
plot((-0.5:1/NN:.5-1/NN)*44100, ((abs(fft(yRx.',NN)))),'color','b')
plot((-0.5:1/NN:.5-1/NN)*44100, ((abs(fft(y_wav,NN)))),'color','r')
plot((-0.5:1/NN:.5-1/NN)*44100, ((abs(fft(y3,NN)))),'color','g')

hold off
title('yRx -b, data written to wav -r, theoretical - g')

1 Answer 1


Typically you use Orthogonal Frequency Division Multiplexing (OFDM) with communications. In this context having complex data in the time domain makes sense because the real and imaginary parts of the number represent the inphase and quadrature parts of the signal.

In an audio signal which is what a wav file is used for is only real. As sound is a naturally occurring signal.

I am not sure why you'd want to store the inverse of an FFT in a wav file (listening to it would sound awful). As you've discovered there's no way of guaranteeing that this data is real. You seem to get around this by taking the real part of the output and only writing that to your file.

However, if I assume you need this data stored in a wav file you could store the real and imaginary part in the wav file by interleaving them. You could write something like:

towav = zeros(length(outputiFFT)*2);
towav(1:2:end-1) = real(outputiFFT).*cos(-2*pi*fc/44100*(0:length(outputiFFT)-1));
towav(2:2:end) = imag(outputiFFT).*sin(-2*pi*fc/44100*(0:length(outputiFFT)-1));

in your code above.

Bear in mind this "halves” your sample rate when you write the 'towav' variable to your wav file. Although I am assuming you don't need to listen to the file, so this is unlikely to matter.

EDIT: as the comment below points out if you weren’t generating random QPSK signals and you ensured that the input sequence in the frequency domain was conjugate symmetric you would have a real sequence in the time domain and you would not need to store the imaginary part.

  • $\begingroup$ Thanks! I don't care what it sounds like, im trying to upconvert it to 15khz so its almost inaudible and play it to a wave so i can send it over aux cable to demodulate it-basically trying to build a software defined radio in the audio spectrum. But it seems the line: towav = real(outputiFFT).*cos(-2*pifc/44100*(0:length(outputiFFT)-1)) + imag(outputiFFT).*sin(-2*pifc/44100*(0:length(outputiFFT)-1)); might have somehting inherently theoretically wrong with it, but this is how diagrams for carrier frequency modulators are always written I & Q are just modulated onto cos(fc) and sin(fc) $\endgroup$ Dec 1, 2018 at 0:08
  • $\begingroup$ Actually, there is a way to make sure the output of a IFFT is real, just make sure the complex input is conjugate symmetric. And just because humans can’t hear the diff between inphase and quadrature audio doesn’t mean it can’t describe the actual sound spectrum in synchronized mono channels. $\endgroup$
    – hotpaw2
    Dec 1, 2018 at 1:03
  • $\begingroup$ Yes this is true. Although in the code a random qpsk signal is being generated. Hence my response. $\endgroup$
    – bluefocs
    Dec 1, 2018 at 3:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.