I think the bit in which you stop the audio output between notes is the culprit:
if (self.toneUnit) { AudioOutputUnitStop(self.toneUnit); AudioUnitUninitialize(self.toneUnit); AudioComponentInstanceDispose(self.toneUnit); self.toneUnit = nil; }
Just leave the tone block active and you will have less twittering. You will need another way to generate silence, perhaps if the RenderTone continues to work, but will generate zero amplitude.
I was able to eliminate the minor tweets that remained if he, with a change in frequency, faded out the amplitude to zero, updated the frequency and disappeared again. This, of course, is something that the old PC speaker could not do (with the exception of a few people who quickly turned it on again), but with very fast fading, you can probably get the effect of the old school without tweets.
Here is my fading RenderTone function (currently using evil global variables):
double currentFrequency=0; double currentSampleRate=0; double currentAmplitude=0; OSStatus RenderTone( void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { // Fixed amplitude is good enough for our purposes const double amplitude = 0.5; // Get the tone parameters out of the view controller ToneGen *toneGen = (__bridge ToneGen *)inRefCon; double theta = toneGen.theta; BOOL fadingOut = NO; if ((currentFrequency != toneGen.frequency) || (currentSampleRate != toneGen.sampleRate)) { if (currentAmplitude > DBL_EPSILON) { fadingOut = YES; } else { currentFrequency = toneGen.frequency; currentSampleRate = toneGen.sampleRate; } } double theta_increment = 2.0 * M_PI * currentFrequency /currentSampleRate; // This is a mono tone generator so we only need the first buffer const int channel = 0; Float32 *buffer = (Float32 *)ioData->mBuffers[channel].mData; // Generate the samples for (UInt32 frame = 0; frame < inNumberFrames; frame++) { buffer[frame] = sin(theta) * currentAmplitude; //NSLog(@"amplitude = %f", currentAmplitude); theta += theta_increment; if (theta > 2.0 * M_PI) { theta -= 2.0 * M_PI; } if (fadingOut) { if (currentAmplitude > 0) { currentAmplitude -= 0.001; if (currentAmplitude < 0) currentAmplitude = 0; } } else { if (currentAmplitude < amplitude) { currentAmplitude += 0.001; if (currentAmplitude > amplitude) currentAmplitude = amplitude; } } } // Store the theta back in the view controller toneGen.theta = theta; return noErr; }
source share