Begum
Begum

Reputation: 675

iOS Generate Square Sound

I want to generate a square wave sound on iPhone, I found a sine wave code on Web (sorry forgotten the link), but i want to generate Square wave format. Could you help me please?

    const double amplitude = 0.25;

ViewController *viewController =
(__bridge ViewController *)inRefCon;
double theta = viewController->theta;
double theta_increment = 2.0 * M_PI * viewController->frequency / viewController->sampleRate;

const int channel = 0;
Float32 *buffer = (Float32 *)ioData->mBuffers[channel].mData;

for (UInt32 frame = 0; frame < inNumberFrames; frame++)
{
    buffer[frame] = sin(theta) * amplitude;

    theta += theta_increment;
    if (theta > 2.0 * M_PI)
    {
        theta -= 2.0 * M_PI;
    }
}
   viewController->theta = theta;

Upvotes: 0

Views: 153

Answers (1)

jaket
jaket

Reputation: 9341

Sum of the odd harmonics

A perfect square wave is the sum of all the odd harmonics divided by the harmonic number up to infinity. In the real world you have to stop of course - specifically at the nyquist frequency in digital. Below is a picture of the fundamental plus the first 3 odd harmonics. You can see how the square begins to take shape.

Square of the first 9 harmonics

In your code sample, this would mean wrapping the sine generation in another loop. Something like this:

double harmNum = 1.0;
while (true)
{
    double freq = viewController->frequency * harmNum;
    if (freq > viewController->sampleRate / 2.0)
        break;

    double theta_increment = 2.0 * M_PI * freq / viewController->sampleRate;

    double ampl = amplitude / harmNum;

    // and then the rest of your code.
    for (UInt32 frame = ....

The main problem you'll have is that you need to track theta for each of the harmonics.

A cheater solution

A cheat would be to draw a square like you would on paper. Divide the sample rate by the frequency by 2 and then produce that number of -1 and that number of +1.

For example, for a 1kHz sine at 48kHz. 48000/1000/2 = 24 so you need to output [-1,-1,-1,....,1,1,1,.....] where there are 24 of each.

A major disadvantage is that you'll have poor frequency resolution. Like if your sample rate were 44100 you can't produce exactly 1kHz. because that would require 22.05 samples at -1 and 22.05 samples at 1 so you have to round down.

Depending on your requirements this might an easier way to go since you can implement it with a counter and the last count between invocations (as you're tracking theta now)

Upvotes: 1

Related Questions