moduleReactive.Banana.ALSA.TimewhereimportqualifiedSound.ALSA.Sequencer.EventasEventimportqualifiedSound.ALSA.Sequencer.RealTimeasRealTimeimportqualifiedSound.ALSA.Sequencer.TimeasATimeimportqualifiedNumeric.NonNegative.ClassasNonNegimportqualifiedData.MonoidasMnimportData.Ratio((%),)importPreludehiding(div,){- |
The 'T' types are used instead of floating point types,
because the latter ones caused unpredictable 'negative number' errors.
The denominator must always be a power of 10,
this way we can prevent unlimited grow of denominators.
-}typeAbs=RationalnewtypeT=Cons{decons::Rational}deriving(Show,Eq,Ord)cons::String->Rational->Tconsmsgx=ifx>=0thenConsxelseerror$msg++": negative number"inc::T->Abs->Absincdtt=t+deconsdtsubSat::Abs->Abs->TsubSatt1t0=cons"Time.sub"$max0$t1-t0scale::Double->T->Tscalek(Const)=cons"Time.scale"$round(toRationalk*t*nano)%nanoscaleCeiling::Double->T->TscaleCeilingk(Const)=cons"Time.scaleCeiling"$ceiling(toRationalk*t*nano)%nanoscaleInt::Integrali=>i->T->TscaleIntk(Const)=cons"Time.scaleInt"$t*fromIntegralkdiv::T->T->Doubledivdt1dt0=fromRational(deconsdt1/deconsdt0)nano::Numa=>anano=1000^(3::Int)instanceMn.MonoidTwheremempty=Cons0mappend(Consx)(Consy)=Cons(x+y)instanceNonNeg.CTwheresplit=NonNeg.splitDefaultdeconsConsfromStamp::ATime.Stamp->AbsfromStampt=casetofATime.Realrt->RealTime.toIntegerrt%nano-- _ -> 0,_->error"unsupported time stamp type"toStamp::Abs->ATime.StamptoStampt=ATime.Real(RealTime.fromInteger(round(t*nano)))fromEvent::Event.T->AbsfromEventev=caseEvent.timeevofATime.ConsATime.Absolutestamp->fromStampstamp_->error"timeFromEvent: we can only handle absolute time stamps"