I am in the process of creating a synthesiser for iOS. After playing around and attempting to learn core audio, I have encountered a problem that I cannot get my head around. My sine wave makes a clicking noise on regular intervals, which Im guessing is related to the phase. I have looked at several guides and books on the subject, and all suggest that I am doing it correctly.
If anybody would be so kind to look at my code for me it would be greatly appreciated.
static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
{
// Get a reference to the object that was passed with the callback
// In this case, the AudioController passed itself so
// that you can access its data.
AudioController *THIS = (AudioController*)inRefCon;
// Get a pointer to the dataBuffer of the AudioBufferList
AudioSampleType *outA = (AudioSampleType *)ioData->mBuffers[0].mData;
float freq = THIS->Frequency;
float phase = THIS->sinPhase;
float envValue;
float sinSignal;
// The amount the phase changes in single sample
double phaseIncrement = 2 * M_PI * freq / kGraphSampleRate;
// Loop through the callback buffer, generating samples
for (UInt32 i = 0; i < inNumberFrames; ++i) {
sinSignal = sin(phase);
envValue = THIS->env.tick();
// Put the sample into the buffer
// Scale the -1 to 1 values float to
// -32767 to 32767 and then cast to an integer
outA[i] = (SInt16)(((sinSignal * 32767.0f) / 2) * envValue);
phase = phase + phaseIncrement;
if (phase >= (2 * M_PI * freq)) {
phase = phase - (2 * M_PI * freq);
}
}
// Store the phase for the next callback.
THIS->sinPhase = phase;
return noErr;
}
The phase can overflow on wrong point
Replace this:
if (phase >= (2 * M_PI * freq)) {
phase = phase - (2 * M_PI * freq);
}
with
if (phase >= (2 * M_PI)) {
phase = phase - (2 * M_PI);
}
If your frequency is not exactly an integer value, then this line:
phase = phase - (2 * M_PI * freq);
will adjust and rotate the phase by an amount not equal to 2pi, thus producing a discontinuity.
A great debugging technique for these types of problems is to look at your audio in an oscilloscope or wave editor. Seeing exactly when and how often a click occurs will usually provide a few clues as to why the click is happening.
The same technique can be used with signals that aren't 'audio' signals such as envelope generators etc. Just make sure you turn down your speakers!