Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DSP - Converting a sampled signal from real samples to complex samples and vice versa

How can I convert baseband sampled signal from real-valued samples to complex-valued samples (real,imaginary) and vice-versa.

My samples are integers, and I'm looking for a fast (but accurate) conversion algorithms.

A C++ sample code (real, not complex ;-) would be more than welcome.

Edit: IPP code will be much welcome.

Edit: I'm looking for a method that will convert n real-samples to n/2 complex-samples and vice-versa, without affecting the bandwidth.

like image 201
Lior Kogan Avatar asked Dec 05 '22 01:12

Lior Kogan


2 Answers

Adding zeros as the imaginary is conceptually the first step in what you want to do. Initially you have a real only signal that looks like this in the frequency domain:

           [r0, r1, r2, r3, ...]

                           /-~--------\
                         DC            +Fs/2

If you stuff it with zeros for the imaginary value, you'll see that you really have both positive and negative frequencies as mirror images:

           [r0 + 0i, r1 + 0i, r2 + 0i, r3 + 0i, ...]

             /--------~-\  /-~--------\
          -Fs/2          DC            +Fs/2

Next, you multiply that signal in the time domain by a complex tone at -Fs/4 (tuning the signal). Your signal will look like

           ----~-\ /-~--------\ /------
                        DC

So now, you filter out the center half and you get:

           ________/-~--------\________
                        DC

Then you decimate by two and you end up with:

                   /-~--------\

Which is what you want.

All of these steps can be performed efficiently in the time domain. If you pay attention to all of the intermediate steps, you'll notice that there are many places where you're multiplying by 0, +1, -1, +i, or -i. Furthermore, the half band low pass filter will have a lot of zeros and some symmetry to exploit. Since you know you're going to decimate by 2, you only have to calculate the samples you intend to keep. If you work through the algebra, you'll find a lot of places to simplify it for a clean and fast implementation.

Ultimately, this is all equivalent to a Hilbert transform, but I think it's much easier to understand when you decompose it into pieces like this.

Converting back to real from complex is similar. You'll stuff it with zeroes for every other sample to undo the decimation. You'll filter the complex signal to remove an alias you just introduced. You'll tune it up by Fs/4, and then throw away the imaginary component. (Sorry, I'm all ascii-arted out... :-)

Note that this conversion is lossy near the boundaries. You'd have to use an infinite length filter to do it perfectly.

like image 112
xscott Avatar answered Jan 11 '23 22:01

xscott


If you want to create a complex vector with a strictly real spectrum, just add an imaginary component of 0.0 to every sample. Depending on your data format, this may be as easy as creating a double length memory array, zeroing it, and copying from every element of the source into every other element of the destination.

If you want to convert a complex vector containing complex data (non-zero imaginary components above your required minimum noise floor) into a real vector, you will need to double your bandwidth in order to not lose information, which may or may not make sense, unless you are modulating, demodulating or filtering the signal.

If you want to produce a one-sided signal with a complex spectrum from a real vector, you can use a Hilbert transform (or filter) to create an imaginary component with the same spectrum but conjugate phase (except for DC). This would probably not be both fast and accurate.

like image 33
hotpaw2 Avatar answered Jan 11 '23 23:01

hotpaw2