import Control.Concurrent import Control.Concurrent.MVar import System.Process (runCommand) -- This program works only on the GHC compiler because of the use of -- threadDelay data Beep = Stop | Hi | Low type Pattern = [Beep] type BeatsPerMinute = Int minute = 60000000 -- 1 minute = 60,000,000 microseconds -- give one of the following example patterns to the metronome function pattern4_4 = [Hi, Low, Low, Low] pattern2_4 = [Hi, Low] pattern3_4 = [Hi, Low, Low] pattern6_8 = [Hi, Low, Low, Low, Low, Low] -- use this version if you can't play audio, use Windows or don't -- have audio files to play -- beep :: Beep -> IO () -- beep Stop = return () -- beep Hi = putChar 'H' -- beep Low = putChar 'L' -- use this version if you can and want to play audio on Linux using -- Alsa. Change the name of the files to those of your choice beep Stop = return () beep Hi = putChar 'H' >> runCommand "aplay hi.wav &> /dev/null" >> return () beep Low = putChar 'L' >> runCommand "aplay low.wav &> /dev/null" >> return () tick :: MVar Pattern -> BeatsPerMinute -> IO () tick b i = do t <- readMVar b case t of [Stop] -> return () x -> do mapM_ (\v -> forkIO (beep v) >> threadDelay (minute `div` i)) t tick b i metronome :: Pattern -> BeatsPerMinute -> IO () metronome p i = do putStrLn "Press any key to stop the metronome." b <- newMVar p _ <- forkIO $ tick b i _ <- getChar putMVar b [Stop]