tixonome 0.2.1

An extremely simple CLI metronome in Rust
/*  Copyright (c) 2021, Momozor <momozor4@gmail.com>
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree.
 */

use rodio::source::{SineWave, Source};
use rodio::{OutputStream, OutputStreamHandle, Sink};
use simple_logger::SimpleLogger;
use std::process;
use std::time::Duration;
use structopt::StructOpt;

#[derive(Debug, StructOpt)]
struct Opt {
    #[structopt(short, default_value = "80")]
    beats_per_minute: u32,
    #[structopt(short = "a", default_value = "4")]
    beats_per_bar: u8,
}

fn main() {
    SimpleLogger::new().init().unwrap();

    let (_stream, stream_handle) = OutputStream::try_default().unwrap_or_else(|error| {
        log::error!("Cannot open output stream.\n More info: {}", error);
        process::exit(1);
    });

    run(Opt::from_args(), &stream_handle);
}

fn play_sound(stream_handle: &OutputStreamHandle, is_accent: bool) {
    let low_pitch = 440;
    let amplification = 0.20;
    let beep_duration = 0.40;

    let sink = Sink::try_new(stream_handle).unwrap_or_else(|error| {
        log::error!("Cannot open sink stream!\n More info: {}", error);
        process::exit(1);
    });

    let small_hertz_leap = 40;
    let medium_pitch = low_pitch + small_hertz_leap;
    let source = SineWave::new(match is_accent {
        true => medium_pitch,
        _ => low_pitch,
    })
    .take_duration(Duration::from_secs_f32(beep_duration))
    .amplify(amplification);

    sink.append(source);
    sink.sleep_until_end();
}

fn run(opt: Opt, stream_handle: &OutputStreamHandle) {
    let minute = 60.0;
    let duration = minute / opt.beats_per_minute as f32;
    let mut counter: u32 = 0;

    loop {
        counter += 1;
        if counter % opt.beats_per_bar as u32 != 0 {
            play_sound(stream_handle, false);
        } else {
            play_sound(stream_handle, true);
            counter = 0;
        }
        std::thread::sleep(Duration::from_secs_f32(duration));
    }
}