You can just have a variable that remembers whether the alarm is
supposed to be on or off. Let's call it alarm_on. Then:
bool alarm_on;
static void start_alarm() { alarm_on = true; }
static void stop_alarm() { noTone(); alarm_on = false; }
void loop()
{
if (alarm_on) alarm();
if (some_condition()) start_alarm();
if (some_other_condition()) stop_alarm();
}
For a better approach that allows you to sound the alarm without blocking the whole program, see the Blink Without Delay Arduino tutorial.
Edit: I just wrote (but did not test) a non-blocking version of this alarm, based on a state machine and the timing technique from the Blink Without Delay tutorial. Here it is, as a class:
class TwoToneAlarm {
public:
static const uint16_t HIGH_FREQ = 3300;
static const uint16_t LOW_FREQ = 3000;
static const uint16_t TONE_DURATION = 200;
TwoToneAlarm(uint8_t output_pin)
: state(OFF), pin(output_pin) {}
// Start the alarm.
void start()
{
tone(pin, HIGH_FREQ);
state = HIGH_TONE;
last_tone_change = millis();
}
// Stop the alarm.
void stop()
{
noTone(pin);
state = OFF;
}
// Call this periodically to handle the tone changes.
void update()
{
if (state == OFF) return;
if (millis() - last_tone_change >= TONE_DURATION) {
switch (state) {
case HIGH_TONE:
tone(pin, LOW_FREQ);
state = LOW_TONE;
break;
case LOW_TONE:
tone(pin, HIGH_FREQ);
state = HIGH_TONE;
break;
default:
break;
}
last_tone_change += TONE_DURATION;
}
}
private:
enum { OFF, HIGH_TONE, LOW_TONE } state;
uint16_t last_tone_change;
uint8_t pin;
};
It could be used like this:
TwoToneAlarm alarm(8);
void loop()
{
if (some_scary_condition()) alarm.start();
if (some_other_condition()) alarm.stop();
alarm.update();
}
Note that the whole program must be non-blocking (delay()-free),
otherwise the tone changes will not be done on time.