Reputation: 675
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
Reputation: 9341
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.
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 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