I'm trying out the code in this example and basically I want to limit the number of samples that are played.
Right now once you hit the play button the app plays a tone at the frequency that was set but it doesn't stop until you hit stop. I would like to only play a sound for a second long.
Any idea how to do that? I already tried changing inNumberFrames to 44100 but all that does is make my tone unstable.
// Generate the samples
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;
}
}
EDIT
Kurt Revis says that CoreAudio calls your RenderTone() function repeatedly. I didn't think of this but I guess that makes sense. It does lead me to another question though: what happens if i want to send like a 4 minute song to the buffer? (44100 * 60 * 4 samples)
If the RenderTone method gets called repeatedly I'm guessing it will each time start playing the samples from the start. How can I play a long set of samples?
Two possibilities.
High-level: When you start playing, make an NSTimer that calls a method to call -stop
after one second. Or use -[NSObject performSelector:withObject:afterDelay:]
.
Low-level: In RenderTone()
, keep track of how many samples have been played already. Across calls to RenderTone()
, keep that value in an ivar in the view controller, exactly the same way as it does with theta
. In the sample-generation loop, if the sample count is >= 44100, set buffer[frame]
to 0.
The fundamental thing to understand is: CoreAudio calls your RenderTone()
function repeatedly, whenever it needs more audio data to play. It asks you for a certain amount of data (inSampleCount
), and you need to provide exactly that much, no more, no less. If you want it to play silence, then you need to fill the buffer with zeros.