module Sound.MED.Generic.Tempo (
MEDTempo(..),
Mode(..),
song0Tempo,
song2Tempo,
update,
toTime,
) where
import Sound.MED.Generic.Block(Cmd,Val)
import qualified Sound.MED.Raw.MMD0Song as MMD0Song
import qualified Sound.MED.Raw.MMD2Song as MMD2Song
import Sound.MED.Basic.Amiga
import Data.Bits (testBit, (.&.))
import Data.Bool.HT (if')
data MEDTempo = MEDTempo
{ MEDTempo -> Mode
mode :: Mode,
MEDTempo -> Cmd
primary, MEDTempo -> Cmd
secondary :: Int
}
data Mode = Speed | Octa | BPM {Mode -> Cmd
linesPerBeat :: Int}
tempoMode :: UBYTE -> UBYTE -> Mode
tempoMode :: UBYTE -> UBYTE -> Mode
tempoMode UBYTE
flags UBYTE
flags2 =
forall a. Bool -> a -> a -> a
if' (forall a. Bits a => a -> Cmd -> Bool
testBit UBYTE
flags Cmd
6) Mode
Octa forall a b. (a -> b) -> a -> b
$
forall a. Bool -> a -> a -> a
if' (forall a. Bits a => a -> Cmd -> Bool
testBit UBYTE
flags2 Cmd
5) (Cmd -> Mode
BPM forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral (UBYTE
flags2 forall a. Bits a => a -> a -> a
.&. UBYTE
0x1F) forall a. Num a => a -> a -> a
+ Cmd
1)
Mode
Speed
song0Tempo :: MMD0Song.MMD0Song -> MEDTempo
song0Tempo :: MMD0Song -> MEDTempo
song0Tempo MMD0Song
song =
MEDTempo
{ mode :: Mode
mode = UBYTE -> UBYTE -> Mode
tempoMode (MMD0Song -> UBYTE
MMD0Song.flags MMD0Song
song) (MMD0Song -> UBYTE
MMD0Song.flags2 MMD0Song
song)
, primary :: Cmd
primary = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ MMD0Song -> UWORD
MMD0Song.deftempo MMD0Song
song
, secondary :: Cmd
secondary = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ MMD0Song -> UBYTE
MMD0Song.tempo2 MMD0Song
song
}
song2Tempo :: MMD2Song.MMD2Song -> MEDTempo
song2Tempo :: MMD2Song -> MEDTempo
song2Tempo MMD2Song
song =
MEDTempo
{ mode :: Mode
mode = UBYTE -> UBYTE -> Mode
tempoMode (MMD2Song -> UBYTE
MMD2Song.flags MMD2Song
song) (MMD2Song -> UBYTE
MMD2Song.flags2 MMD2Song
song)
, primary :: Cmd
primary = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ MMD2Song -> UWORD
MMD2Song.deftempo MMD2Song
song
, secondary :: Cmd
secondary = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ MMD2Song -> UBYTE
MMD2Song.tempo2 MMD2Song
song
}
update :: MEDTempo -> (Cmd, Val) -> MEDTempo
update :: MEDTempo -> (Cmd, Cmd) -> MEDTempo
update MEDTempo
tempo (Cmd
cmd,Cmd
val) =
case Cmd
cmd of
Cmd
0x09 -> MEDTempo
tempo{secondary :: Cmd
secondary = forall a. Integral a => a -> a -> a
mod (Cmd
valforall a. Num a => a -> a -> a
-Cmd
1) Cmd
0x20 forall a. Num a => a -> a -> a
+ Cmd
1}
Cmd
0x0F ->
if Cmd
0 forall a. Ord a => a -> a -> Bool
< Cmd
val Bool -> Bool -> Bool
&& Cmd
val forall a. Ord a => a -> a -> Bool
< Cmd
0xF0
then MEDTempo
tempo{primary :: Cmd
primary = forall a b. (Integral a, Num b) => a -> b
fromIntegral Cmd
val}
else MEDTempo
tempo
Cmd
_ -> MEDTempo
tempo
toTime :: Fractional a => MEDTempo -> a
toTime :: forall a. Fractional a => MEDTempo -> a
toTime (MEDTempo Mode
mode_ Cmd
tempo1 Cmd
tempo2) =
forall a. Fractional a => Mode -> Cmd -> a
timeFromPrimary Mode
mode_ Cmd
tempo1 forall a. Num a => a -> a -> a
* forall a b. (Integral a, Num b) => a -> b
fromIntegral Cmd
tempo2
ciabFreq :: Fractional a => a
ciabFreq :: forall a. Fractional a => a
ciabFreq = a
715909
timerDiv :: Fractional a => a
timerDiv :: forall a. Fractional a => a
timerDiv = a
474326
_sttempo :: Fractional a => a
_sttempo :: forall a. Fractional a => a
_sttempo = a
2416.3
sttempoMeasured :: Fractional a => a
sttempoMeasured :: forall a. Fractional a => a
sttempoMeasured = a
293.70
octaTempo :: Fractional a => a
octaTempo :: forall a. Fractional a => a
octaTempo = a
390.70
timeFromPrimary :: Fractional a => Mode -> Int -> a
timeFromPrimary :: forall a. Fractional a => Mode -> Cmd -> a
timeFromPrimary Mode
mode_ Cmd
tempo =
case Mode
mode_ of
BPM Cmd
lpb -> a
60 forall a. Fractional a => a -> a -> a
/ (forall a b. (Integral a, Num b) => a -> b
fromIntegral Cmd
tempo forall a. Num a => a -> a -> a
* a
6 forall a. Num a => a -> a -> a
* forall a b. (Integral a, Num b) => a -> b
fromIntegral Cmd
lpb)
Mode
Octa -> forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Ord a => a -> a -> a
min Cmd
10 Cmd
tempo) forall a. Fractional a => a -> a -> a
/ forall a. Fractional a => a
octaTempo
Mode
Speed ->
if Cmd
tempoforall a. Ord a => a -> a -> Bool
<=Cmd
10
then forall a b. (Integral a, Num b) => a -> b
fromIntegral Cmd
tempo forall a. Fractional a => a -> a -> a
/ forall a. Fractional a => a
sttempoMeasured
else forall a. Fractional a => a
timerDiv forall a. Fractional a => a -> a -> a
/ (forall a. Fractional a => a
ciabFreq forall a. Num a => a -> a -> a
* forall a b. (Integral a, Num b) => a -> b
fromIntegral Cmd
tempo)