×
INTELLIGENT WORK FORUMS
FOR ENGINEERING PROFESSIONALS

Contact US

Log In

Come Join Us!

Are you an
Engineering professional?
Join Eng-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Eng-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Sampling and Reproduction of an audio signal

Sampling and Reproduction of an audio signal

Sampling and Reproduction of an audio signal

(OP)
Hi all,

I'm trying to go about the task of samping a small piece of an audio signal and then reproducing that piece an arbitrary amount of times (repeating the same audio over and over I suppose you could say).  I'm working in C++.

The way I'm going about doing it is like so (using an example):

1. I have a sinusoidal signal with a period of 765.62Hz (a tricky frequency), sampled at 32000Hz. I grab approx. 33 ms of it, which corresponds to approx. 2^10 or 1024 samples. I perform a 1024 point FFT of it. This gives me 1024 real values which make an even spectrum and 1024 imaginary values which make an odd spectrum (this is consistent with fourier transform properties).

2. I then go through each sample in the fft and perform a phase shifting of that sample. I'm following the theory that a time shift of m samples in the time domain corresponds to a phase shift of exp^-j*w*m in the frequency domain. So my equations are like this:

CODE

(remember A*exp^j*w*m = A*cos(w*m) + A*j*sin(w*m))

for (i = 0; i < 1024; i++) { // 1024 samples in the fft

  frequency = (i* sampleRate) / 1024
  totalTimeShift = timeShift / sampleRate     (for reproducing the original signal just once the timeShift in this case is 1024 samples)
  phaseShiftAngle = 2 * pi * frequency * totalTimeShift

  realValue[i] = (realValue[i] * cos(phaseShiftAngle)) + (imaginaryValue[i] * sin(phaseShiftAngle))

  imaginaryValue[i] = (imaginaryValue[i] * cos(phaseShiftAngle)) - (realValue[i] * sin(phaseShiftAngle))
}
3. Next, I do an ifft of my phase shifted fft signal, and then stick the resulting 1024 sample time domain signal next to the original 1024 samples.

The problem I am having is that, for some strange reason, the phase of the signal is always perfect but the amplitudes are always flipped. For example, if the original sinusoid sample goes up-down-up-down, then the phase-shifted signal will always go down-up-down-up. And I can't figure out why!

The problem is not my fft or ifft, because I have done a straight fft and ifft of a signal and always got the original signal back. It most likely has something to do with my phase shifting calculations and also the fact that the period of the sinusoid is quite tricky to work with.

Any ideas? Thanks in advance.

RE: Sampling and Reproduction of an audio signal

Hello tj80
Let's look at the circular time shift property of the DFT transform.
x(n-l) (modulo N) <--DFT--> X(k)*exp(-j*2*pi*k*l/N)

Where:
x (small) is the signal in the time doamin,
n is the index of samples in the time domain
l is the circular time shift (number of samples)
N is the number of samples, 1024 in your case
X (big) is the signal is the frequency doamin
k is the index of samples in the frequency domain

Note that the time shift is circular of modulo N. Than means it repeats itself every 1024 delay samples.

As I understood (correct me if I am wrong), you wanted to perform a circular timeshift on your signal, by doing the following steps:
applying a DFT transform (using FFT) on your signal, phase shifting the signal in the frequency domain (constant phase), and then to perform an inverse DFT to have the signal back in the time domain.

From your code I see that you multiplied by
exp(j*2*pi*k*l/N) , instead of exp(-j*2*pi*k*l/N). that means you circularly advancedes your samples in the time domain instead of circularly delay it. Maybe this is your problem. Check the minus sign before the -j*2*pi*k*l/N

Try to circularly advance it in the time domain and compare the results.

RE: Sampling and Reproduction of an audio signal

Allow me to suggest another rhing. As a test, enter a sequence of numbers 1, 2, 3 up to 1024 (instead of your sinosoid), and apply your routine on this squence. Verify that your routine actually performs the circular shifting property on this sequence.

RE: Sampling and Reproduction of an audio signal

Chatman is correct.
Another way to look at it would be in vector form the resulting vector would rotate clockwise instead of anti-clockwise if you use j*2PI.K/N instead of -j 2PI.K/N.

Simple way to fix this without changing too much code would be to change your imaginary coeff's , multiply all of them by -1.

RE: Sampling and Reproduction of an audio signal

(OP)
thank you both for your great replies, and yes you are both correct in understanding what I am trying to do.

Thanks for the suggestion to multiply the imaginary coeffs by -1, I'll try this, but in the meantime my question is:

for the code line:

CODE

imaginaryValue[i] = (imaginaryValue[i] * cos(phaseShiftAngle)) - (realValue[i] * sin(phaseShiftAngle))

if the phase shift angle was zero and we were multiplying the imaginary coeffs by -1, is it correct or not correct to deduce that the imaginary value would end up changing sign (+ve to -ve or vice versa)? is that how is it supposed to work for no phase shift?

RE: Sampling and Reproduction of an audio signal

First of all I see that I was wrong, and that you do multiply by exp(-j*2*pi*k*l/N), instead of exp(j*2*pi*k*l/N) (as I said in my previous answer).

If the phase shift angle is zero, it doesn't matter if you multiply the imaginary coefficient by +1 or -1. In both cases your samples won't change. That is because there was no circular delay or circular advance to the input samples.

Do a test. Try to enter a sequence from 1 to 1024, apply your routine, and see what's happened.

If the variable 'timeShift' is 2, you should get:
1023, 1024, 1, 2 ... , 1022
That is becuase you circularly delayed the input samples

If the 'timeShift' variable is -2 you should get 3, 4, ... , 1024, 1, 2
In this case you circularly advances your samples.

If timeShift is zero, the result is then: 1, 2, .. , 1024. No change in the samples.

Also, make sure that all the numbers after inverse FFT, have zero imaginary part.

Hope it helps

RE: Sampling and Reproduction of an audio signal

(OP)
ok I did try this:

setting the 'timeShift' to +2 produced numbers of

1023, 1024, 1, ... , 1021, 1022

setting the 'timeShift' to 0 produced numbers of

1, 2, 3, ..., 1023, 1024

setting the 'timeShift' to -2 produced numbers of

2, 3, 4, ... , 1022, 1023, 0, 1

The -2 shift appears to be wrong (rounding error?), but the others are okay.


RE: Sampling and Reproduction of an audio signal

Did you use the electrical engineers Fourier transform or the mathematicians or physicists Fourier transform (FT)?  Chatman mentions that you used the EE version, however, I think that is based on seeing your phase shifting code done in the frequency domain.  You shifted by negative phase, not positive phase.  That could be an issue.
The EE and other FT differ in the assumption of what the signal is therefore what the kernel must be.  We EE's like to have our signals as exp ^ jwt, thus leaving the kernel to be exp ^ -jwt.  In doing so, a time shift is a negative phase shift.  Group delay for a EE is groupDelay = -dPhi / dw, where w is frequency, and Phi is the phase shift.  This may be involved in having to use an arbitrary sign reversal.
If you are using C++ then you could use the built in std:complex and the sign error would not occur and you might get better performance, especially if you use a std:valarray and operate on the entire array, instead of element by element.  Also prefix notation could give you a MIPS improvement, depending on your compiler and optimization setting.  Try for( iFft = 0; iFft != 1024; ++i ) instead.
In conclusion:
1)  A time delay is a shift to the right.  A sine wave, say:
 sin(wt),
 shifted to the right be 10 degrees would be:
 sin(wt-10).  
So you need to subtract 10 degrees in the frequency domain.  You code hard coded a multiplication by a negative phaseShiftAngle.
2)You may have used the original (non EE) FT.
3) Your FT may put the first element as the most negative frequency.  This would put your DC at your 513th point, not at your first point.  When you calculated your intended phase shift, you assumed i = 0 meant DC.  That is probably incorrect, depending on your FT code.

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Eng-Tips Forums free from inappropriate posts.
The Eng-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Eng-Tips forums is a member-only feature.

Click Here to join Eng-Tips and talk with other members! Already a Member? Login


Resources

Low-Volume Rapid Injection Molding With 3D Printed Molds
Learn methods and guidelines for using stereolithography (SLA) 3D printed molds in the injection molding process to lower costs and lead time. Discover how this hybrid manufacturing process enables on-demand mold fabrication to quickly produce small batches of thermoplastic parts. Download Now
Design for Additive Manufacturing (DfAM)
Examine how the principles of DfAM upend many of the long-standing rules around manufacturability - allowing engineers and designers to place a part’s function at the center of their design considerations. Download Now
Taking Control of Engineering Documents
This ebook covers tips for creating and managing workflows, security best practices and protection of intellectual property, Cloud vs. on-premise software solutions, CAD file management, compliance, and more. Download Now

Close Box

Join Eng-Tips® Today!

Join your peers on the Internet's largest technical engineering professional community.
It's easy to join and it's free.

Here's Why Members Love Eng-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close