YampaSynth-0.1.1: src/Main/OpenAL.hs
module Main where
import MidiSynth
import qualified Codec.SoundFont as SF
import qualified Codec.Midi as Midi
import Player.OpenAL
import SynthParams
import FRP.Yampa
import Numeric
import System.IO
import System.Environment
import System.Console.GetOpt
import Control.Monad
import Control.Applicative
data Flag =
SampleRate String
| SoundFontFile FilePath
| MidiFile FilePath
deriving Show
options :: [OptDescr Flag]
options =
[ Option ['r'] ["samplerate"] (ReqArg SampleRate "SAMPLERATE")
"synthesizer sampling rate"
, Option ['s'] ["soundfont"] (ReqArg SoundFontFile "FILE")
"SoundFont FILE"
, Option ['m'] ["midi"] (ReqArg MidiFile "FILE")
"midi FILE to synthesize"
]
main :: IO ()
main = do
argv <- getArgs
let (opts,nopts,errs) = getOpt Permute options argv
printErrs "not valid options" nopts
mapM_ putStrLn errs
when (not $ null errs) . ioError . userError $ concat errs ++ usageInfo "aborting" options
go . concat $ [getSampleRate, getSoundFontFile, getMidiFile] <*> opts
printErrs :: String -> [String] -> IO ()
printErrs s x = when (not $ null x) . putStrLn $ s ++ ": " ++ show x
-- the record transformer approach described here is probably a better way to achieve option order insensitivity
-- http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/System-Console-GetOpt.html#4
getSampleRate :: MonadPlus m => Flag -> m String
getSampleRate (SampleRate x) = return x
getSampleRate _ = mzero
getSoundFontFile :: MonadPlus m => Flag -> m FilePath
getSoundFontFile (SoundFontFile x) = return x
getSoundFontFile _ = mzero
getMidiFile :: MonadPlus m => Flag -> m FilePath
getMidiFile (MidiFile x) = return x
getMidiFile _ = mzero
go :: [String] -> IO ()
go [srs, soundFontFile, midiFile] = do
sampleRate' <- case (readDec srs) of
[] -> fail "SAMPLERATE must be a positive decimal integer number"
(i,_) : _ -> (putStrLn $ show i) >> return i
hPutStrLn stderr "Importing MIDI File ..."
eMidi <- Midi.importFile midiFile
midi <- case eMidi of
Left err -> fail err
Right midi -> return midi
hPutStrLn stderr "Done."
hPutStrLn stderr "Importing SoundFontFile ... This may take a while ..."
eSoundFont <- SF.importFile soundFontFile
soundFont <- case eSoundFont of
Left err -> fail err
Right sf -> return sf
hPutStrLn stderr "Done."
hPutStrLn stderr "Now you should hear something ..."
hPutStrLn stderr "If you are getting interruptions decrase sampling rate."
let paramsGen = soundFontToSynthParams soundFont
signalFunction = midiToEventSource midi >>> midiSynth paramsGen
Player.OpenAL.play sampleRate' (1 * 1024) 2 signalFunction
putStrLn "Done."
go _ = fail $ usageInfo "all options are mandatory\n" options