Hey thanks Bruno,
I think threads was mentioned as the most accurate method of timing but there are only examples of the other two approaches.
Yesterday I got a metronome working on the iPhone using ofxiPhoneSoundStream.mm as the clock.
It works fine but I did need to update to the latest ofxiPhoneSoundStream.mm file to get it to work.
I haven’t analyzed it but it sounds pretty solid so I am not sure if there would be a benefit to using a thread but maybe when I start to add more functionality the timing might slip.
Do share your results if you do try to do a threaded version.
But this (example below) should work on an iPhone.
Cheers
Simon
// in testApp.cc
//--------------------------------------------------------------
void testApp::setup(){
SAMPLE_RATE = 44100;
pos = 0; // running sample count
bpm = 120;
setBPM(bpm*2);
ofSoundStreamSetup(1,0,this);
}
// timing mechanism
void testApp::audioRequested(float *output, int bufferSize, int numChannels) {
bool startBeatDetected=false;
int i;
for(i = 0; i < bufferSize; i++) {
pos++; // this gets incremented with every sample
// when lengthOfOneBeatInSamples goes into
// pos a whole number of times, we’ve entered a new quarter beat
if(fmod(pos,lengthOfOneBeatInSamples)==0) {
startBeatDetected=true;
}
}
// was a new beat region entered during the last frame?
if(startBeatDetected){
tt.play();
}
}
void testApp::setBPM(float targetBPM){
// NB. Currently the target BPM might not actually be achieved,
// because permitted BPMs are limited to divisible by a whole number of samples.
lengthOfOneBeatInSamples = (int)((SAMPLE_RATE*60.0f)/targetBPM);
BPM=(SAMPLE_RATE*60.0f)/lengthOfOneBeatInSamples;
}
// in the header file you need to declare these
int pos;
float BPM;
int SAMPLE_RATE;
float lengthOfOneBeatInSamples;
int bpm;
void setBPM(float targetBPM);
void audioRequested(float *output, int bufferSize, int numChannels);
void playSound();