Naveen
Naveen

Reputation: 43

Sine wave generation using phase

I'm generating a sine wave using the following method -

sampling rate = 22050;
theta = 0;

for (i = 0; i < N; i++)  
{  
 theta = phase * 2 * PI;  
 signal[i] = amplitude * sin(theta);  
 phase = phase + frequency/sampling rate;  
}

When I generate a signal with a frequency of 8000 Hz, there is distortion in the output. Frequencies below this (e.g. 6000 Hz) are generated correctly. The 8000 Hz signal is generated correctly if I place a check on the phase like so -

if (phase > 1)  
{  
  float temp = phase - 1;  
  phase = temp;  
}  

I think it has something to do with the sine function in Xcode, probably a range of values it can accept? The same code with and without the phase wrapping has no difference in Matlab. Can someone explain what's happening here?

Upvotes: 1

Views: 1199

Answers (3)

Scott Stensland
Scott Stensland

Reputation: 28285

@cixelsyd has the correct formula ... here is the code to create a set of samples of a given frequency based on a sample rate and a starting phase offset ... this code is written in go language

incr_theta := (2.0 * math.Pi * given_freq) / samples_per_second

phase := -1.74   // given phase ... typically 0 note its a constant
theta := 0.0

for curr_sample := 0; curr_sample < number_of_samples; curr_sample++ {

    source_buffer[curr_sample] = math.Sin(theta + phase)

    theta += incr_theta
}

for efficiency its best to move the calculation of delta theta outside of the loop ... notice phase is a constant as it just gives us an initial offset

Upvotes: 2

Peter K.
Peter K.

Reputation: 8108

I'm not certain, but I believe the problem might be:

theta = phase * 2 * PI;  

I think Xcode will change the result to an integer. You might want to try:

theta = phase * 2.0 * PI;  

instead, and make sure your PI variable is a double.

All of which makes this off-topic for DSP.SE. :-)

Upvotes: 0

cixelsyd
cixelsyd

Reputation: 31

I believe the calculation should be (2.0 * PI) * Frequency/Samplerate

This will give you the next phase increment in radians. this value can then be fed into the Sin function to calculate the phase. Note you need to accumulate the radian values.

Technically, your first statement is incorrect as it is worded. FS/2 is the nyquist value. You can produce frequencies above this but they will alias.

In terms of phase wrapping there are different ways to manage this.

My understanding of Radians is that it is 'linear' representation of the phase that doesn't repeat while phase revolves around 2 pi values. So you may not have a wrap issue if you manage phase by managing the radians.

Happy to corrected by more knowledgable folks.

Upvotes: 1

Related Questions