-- Copyright 2018 Evan Laforge
-- This program is distributed under the terms of the GNU General Public
-- License 3.0, see COPYING or http://www.gnu.org/licenses/gpl-3.0.txt

module Synth.Sampler.Patch.Rambat (patches, getVariations) where
import qualified Data.Char as Char
import qualified Data.List as List
import qualified Data.Map as Map
import qualified Data.Maybe as Maybe
import qualified Data.Set as Set
import qualified Data.Text as Text

import qualified Sound.File.Sndfile as Sndfile
import qualified System.FilePath as FilePath
import           System.FilePath ((</>))
import qualified Text.Read as Read

import qualified Util.Audio.Audio as Audio
import qualified Util.Audio.File as Audio.File
import qualified Util.Files as Files
import qualified Util.Lists as Lists
import qualified Util.Maps as Maps
import qualified Util.Num as Num

import qualified Cmd.Instrument.Bali as Bali
import qualified Cmd.Instrument.ImInst as ImInst
import qualified Derive.Attrs as Attrs
import qualified Derive.C.Prelude.Note as Prelude.Note
import qualified Derive.Call as Call
import qualified Derive.EnvKey as EnvKey
import qualified Derive.Instrument.DUtil as DUtil
import           Derive.Scale.BaliScales (Tuning(..))
import qualified Derive.Scale.Legong as Legong

import qualified Instrument.Common as Common
import qualified Perform.Im.Patch as Im.Patch
import qualified Perform.Pitch as Pitch
import qualified Perform.RealTime as RealTime

import qualified Synth.Lib.AUtil as AUtil
import qualified Synth.Sampler.Calibrate as Calibrate
import qualified Synth.Sampler.Patch as Patch
import qualified Synth.Sampler.Patch.Lib.Bali as Lib.Bali
import           Synth.Sampler.Patch.Lib.Bali (Pitch(..), PitchClass(..))
import qualified Synth.Sampler.Patch.Lib.Code as Code
import qualified Synth.Sampler.Patch.Lib.Util as Util
import           Synth.Sampler.Patch.Lib.Util (Dynamic(..))
import qualified Synth.Sampler.Sample as Sample
import qualified Synth.Shared.Config as Config
import qualified Synth.Shared.Control as Control
import qualified Synth.Shared.Note as Note
import qualified Synth.Shared.Signal as Signal

import           Global
import           Synth.Types


-- Like Wayang, but support short notes.

sampleFormat :: Util.SampleFormat
sampleFormat :: SampleFormat
sampleFormat = SampleFormat
Util.Flac

patches :: [Patch.Patch]
patches :: [Patch]
patches = Patch
pasang forall a. a -> [a] -> [a]
: forall a b. (a -> b) -> [a] -> [b]
map Tuning -> Patch
make [Tuning
Umbang, Tuning
Isep]
    where
    pasang :: Patch
pasang = Text -> (Patch -> Patch) -> Patch
Patch.patchKarya Text
"rambat" forall a b. (a -> b) -> a -> b
$
        Text -> Patch -> Patch
ImInst.dummy Text
Bali.pasang_msg forall b c a. (b -> c) -> (a -> b) -> a -> c
. Patch -> Patch
setRange
    make :: Tuning -> Patch
make Tuning
tuning =
        (Text -> Patch
Patch.patch forall a b. (a -> b) -> a -> b
$ Text -> [Text] -> Text
Text.intercalate Text
"-" [Text
"rambat", forall a. Show a => a -> Text
Util.showtLower Tuning
tuning])
        { _dir :: NonNull Char
Patch._dir = NonNull Char
dir
        , _convert :: Note -> ConvertM Sample
Patch._convert = Tuning -> Note -> ConvertM Sample
convert Tuning
tuning
        , _karyaPatch :: Patch
Patch._karyaPatch = Lens Patch Code
ImInst.code forall f a. Lens f a -> a -> f -> f
#= Tuning -> Code
code Tuning
tuning forall a b. (a -> b) -> a -> b
$
            Patch -> Patch
setRange forall a b. (a -> b) -> a -> b
$ Tuning -> Patch -> Patch
setTuning Tuning
tuning forall a b. (a -> b) -> a -> b
$
            Patch -> Patch
ImInst.make_patch forall a b. (a -> b) -> a -> b
$ Patch
Im.Patch.patch
                { patch_controls :: Map Control Text
Im.Patch.patch_controls = forall a. Monoid a => [a] -> a
mconcat
                    [ Map Control Text
Control.supportPitch
                    , Map Control Text
Control.supportDyn
                    , Map Control Text
Control.supportVariation
                    , forall k a. k -> a -> Map k a
Map.singleton Control
Control.mute
                        Text
"Amount of mute. This becomes a shortened envelope."
                    ]
                , patch_attribute_map :: AttributeMap
Im.Patch.patch_attribute_map = forall a b. a -> b -> a
const () forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> AttributeMap Articulation
attributeMap
                }
        , _allFilenames :: Set (NonNull Char)
Patch._allFilenames = Tuning -> Set (NonNull Char)
allFilenames Tuning
tuning
        }
        where
        dir :: NonNull Char
dir = NonNull Char
"rambat" NonNull Char -> NonNull Char -> NonNull Char
</> forall a. Show a => a -> NonNull Char
Util.showLower Tuning
tuning
        code :: Tuning -> Code
code Tuning
tuning = Code
note
            forall a. Semigroup a => a -> a -> a
<> NonNull Char -> (Note -> ConvertM Sample) -> Code
Util.thru NonNull Char
dir (Tuning -> Note -> ConvertM Sample
convert Tuning
tuning)
            forall a. Semigroup a => a -> a -> a
<> InstrumentPostproc -> Code
ImInst.postproc InstrumentPostproc
DUtil.with_symbolic_pitch
    setRange :: Patch -> Patch
setRange = Range -> Patch -> Patch
ImInst.range Range
Legong.rambat_range
    setTuning :: Tuning -> Patch -> Patch
setTuning Tuning
tuning = forall a. ToVal a => Text -> a -> Patch -> Patch
ImInst.environ Text
EnvKey.tuning (forall {a}. IsString a => Tuning -> a
tuningVal Tuning
tuning :: Text)

    tuningVal :: Tuning -> a
tuningVal Tuning
Umbang = a
"umbang"
    tuningVal Tuning
Isep = a
"isep"
    note :: Code
note = Doc
-> (NoteArgs -> NoteDeriver -> NoteDeriver)
-> (NoteArgs -> NoteDeriver)
-> Code
Bali.zero_dur_mute_with Doc
""
        (\NoteArgs
_args -> forall {a}. Deriver a -> Deriver a
transform forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Y -> Deriver a -> Deriver a
Call.multiply_dynamic Y
0.65)
        (\NoteArgs
args -> forall {a}. Deriver a -> Deriver a
transform forall a b. (a -> b) -> a -> b
$
            Config -> NoteArgs -> NoteDeriver
Prelude.Note.default_note Config
Prelude.Note.use_attributes NoteArgs
args)
        where transform :: Deriver a -> Deriver a
transform = forall {a}. Deriver a -> Deriver a
Code.withVariation

attributeMap :: Common.AttributeMap Articulation
attributeMap :: AttributeMap Articulation
attributeMap = forall a. [(Attributes, a)] -> AttributeMap a
Common.attribute_map
    [ (Attributes
calung forall a. Semigroup a => a -> a -> a
<> Attributes
mute, Articulation
MuteCalung)
    , (Attributes
calung, Articulation
Calung)
    , (Attributes
mute forall a. Semigroup a => a -> a -> a
<> Attributes
gangsa, Articulation
MuteGangsa)
    , (Attributes
mute forall a. Semigroup a => a -> a -> a
<> Attributes
Attrs.tight, Articulation
MuteGenderTight)
    , (Attributes
mute forall a. Semigroup a => a -> a -> a
<> Attributes
Attrs.loose, Articulation
MuteGenderLoose)
    , (Attributes
mute, Articulation
MuteGenderLoose)
    , (forall a. Monoid a => a
mempty, Articulation
Open)
    -- OpenShort is intentionally not in here, since it's supposed to be an
    -- implementation detail.
    ]
    where
    mute :: Attributes
mute = Attributes
Attrs.mute
    calung :: Attributes
calung = Text -> Attributes
Attrs.attr Text
"calung"
    gangsa :: Attributes
gangsa = Text -> Attributes
Attrs.attr Text
"gangsa"

convert :: Tuning -> Note.Note -> Patch.ConvertM Sample.Sample
convert :: Tuning -> Note -> ConvertM Sample
convert Tuning
tuning Note
note = do
    let art :: Articulation
art = forall a. a -> AttributeMap a -> Attributes -> a
Util.articulationDefault Articulation
Open AttributeMap Articulation
attributeMap forall a b. (a -> b) -> a -> b
$ Note -> Attributes
Note.attributes Note
note
    let (Dynamic
dyn, Y
dynVal) = forall dyn.
(Bounded dyn, Enum dyn) =>
(dyn -> (Int, Int)) -> Y -> Note -> (dyn, Y)
Util.dynamic Dynamic -> (Int, Int)
dynamicRange Y
minDyn Note
note
    Either Note NoteNumber
symPitch <- forall (m :: * -> *).
MonadError Text m =>
Note -> m (Either Note NoteNumber)
Util.symbolicPitch Note
note
    let variableMute :: RealTime
variableMute = Y -> RealTime
RealTime.seconds forall a b. (a -> b) -> a -> b
$ Control -> Note -> Y
Note.initial0 Control
Control.mute Note
note
    (Pitch
pitch, (NoteNumber
noteNn, NoteNumber
sampleNn)) <- forall e (m :: * -> *) a. MonadError e m => Either e a -> m a
tryRight forall a b. (a -> b) -> a -> b
$ Tuning
-> Either Note NoteNumber
-> Either Text (Pitch, (NoteNumber, NoteNumber))
findPitch Tuning
tuning Either Note NoteNumber
symPitch
    let filenames :: [NonNull Char]
filenames = Tuning
-> Articulation -> Pitch -> Dynamic -> RealTime -> [NonNull Char]
toFilenames Tuning
tuning Articulation
art Pitch
pitch Dynamic
dyn (Note -> RealTime
Note.duration Note
note)
    Y
dynVal <- forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Y
dynVal forall a. Num a => a -> a -> a
* Tuning -> Articulation -> Pitch -> Dynamic -> Y
tweakDynamic Tuning
tuning Articulation
art Pitch
pitch Dynamic
dyn
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ (NonNull Char -> Sample
Sample.make (forall a. [a] -> Note -> a
Util.chooseVariation [NonNull Char]
filenames Note
note))
        -- TODO duplicate from Wayang
        { envelope :: Signal
Sample.envelope = if
            | Articulation -> Bool
isMute Articulation
art -> forall {k} (kind :: k). Y -> Signal kind
Signal.constant Y
dynVal
            | RealTime
variableMute forall a. Ord a => a -> a -> Bool
> RealTime
0 -> forall {k} (kind :: k). [(RealTime, Y)] -> Signal kind
Signal.from_pairs
                [ (Note -> RealTime
Note.start Note
note, Y
dynVal)
                , (Note -> RealTime
Note.start Note
note
                    forall a. Num a => a -> a -> a
+ forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall a. (Eq a, Num a) => a -> a -> a -> a
Num.scale (RealTime, RealTime)
variableMuteRange (RealTime
1forall a. Num a => a -> a -> a
-RealTime
variableMute), Y
0)
                ]
            | Bool
otherwise -> forall {k} (kind :: k). [(RealTime, Y)] -> Signal kind
Signal.from_pairs
                [ (Note -> RealTime
Note.start Note
note, Y
dynVal), (Note -> RealTime
Note.end Note
note, Y
dynVal)
                , (Note -> RealTime
Note.end Note
note forall a. Num a => a -> a -> a
+ RealTime
muteTime, Y
0)
                ]
        , ratios :: Signal
Sample.ratios = forall {k} (kind :: k). Y -> Signal kind
Signal.constant forall a b. (a -> b) -> a -> b
$ NoteNumber -> NoteNumber -> Y
Sample.pitchToRatio NoteNumber
sampleNn NoteNumber
noteNn
        }

toFilenames :: Tuning -> Articulation -> Pitch -> Dynamic -> RealTime
    -> [Sample.SamplePath]
toFilenames :: Tuning
-> Articulation -> Pitch -> Dynamic -> RealTime -> [NonNull Char]
toFilenames Tuning
tuning Articulation
art Pitch
pitch Dynamic
dyn RealTime
dur =
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Tuning -> Pitch -> Dynamic -> Articulation -> [NonNull Char]
filenamesOf Tuning
tuning Pitch
pitch Dynamic
dyn) forall a b. (a -> b) -> a -> b
$
        Tuning
-> Pitch -> Dynamic -> RealTime -> Articulation -> [Articulation]
possibleArticulations Tuning
tuning Pitch
pitch Dynamic
dyn RealTime
dur Articulation
art

allFilenames :: Tuning -> Set FilePath
allFilenames :: Tuning -> Set (NonNull Char)
allFilenames Tuning
tuning = forall (t :: * -> *) a.
(HasCallStack, Foldable t) =>
Int -> t a -> t a
Util.assertLength (forall {a}. Num a => Tuning -> a
len Tuning
tuning) forall a b. (a -> b) -> a -> b
$ forall a. Ord a => [a] -> Set a
Set.fromList
    [ NonNull Char
fname
    | Articulation
art <- forall a. (Enum a, Bounded a) => [a]
Util.enumAll
    , Pitch
pitch <- forall k a. Map k a -> [k]
Map.keys Map Pitch (NoteNumber, NoteNumber)
rambatTuning
    , Dynamic
dyn <- forall a. (Enum a, Bounded a) => [a]
Util.enumAll
    , NonNull Char
fname <- Tuning
-> Articulation -> Pitch -> Dynamic -> RealTime -> [NonNull Char]
toFilenames Tuning
tuning Articulation
art Pitch
pitch Dynamic
dyn RealTime
1
        -- dur is irrelevant because I'm already picking OpenShort explicitly
    ]
    where
    len :: Tuning -> a
len Tuning
Umbang = a
1319
    len Tuning
Isep = a
1351

-- | Reign in some samples that stick out.
tweakDynamic :: Tuning -> Articulation -> Pitch -> Dynamic -> Signal.Y
tweakDynamic :: Tuning -> Articulation -> Pitch -> Dynamic -> Y
tweakDynamic Tuning
Umbang Articulation
Calung (Pitch Int
3 PitchClass
A) Dynamic
dyn
    | Dynamic
dyn forall a. Ord a => a -> a -> Bool
<= Dynamic
MP = Y
0.75
    | Dynamic
dyn forall a. Ord a => a -> a -> Bool
<= Dynamic
MF = Y
0.85
    | Bool
otherwise = Y
0.9
tweakDynamic Tuning
_ Articulation
_ Pitch
_ Dynamic
_ = Y
1

-- If the dur is under the min dur, then I can choose OpenShort in addition to
-- Open.
possibleArticulations :: Tuning -> Pitch -> Dynamic -> RealTime
    -> Articulation -> [Articulation]
possibleArticulations :: Tuning
-> Pitch -> Dynamic -> RealTime -> Articulation -> [Articulation]
possibleArticulations Tuning
tuning Pitch
pitch Dynamic
dyn RealTime
dur Articulation
art
    | Articulation
art forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Articulation
Open, Articulation
OpenShort] = case (Tuning, Pitch, Dynamic) -> Maybe Frames
minDurationOf (Tuning
tuning, Pitch
pitch, Dynamic
dyn) of
        Just Frames
sampleDur | RealTime -> Frames
AUtil.toFrames RealTime
dur forall a. Ord a => a -> a -> Bool
< Frames
sampleDur -> [Articulation
Open, Articulation
OpenShort]
        Maybe Frames
_ -> [Articulation
Open]
    | Bool
otherwise = [Articulation
art]

filenamesOf :: Tuning -> Pitch -> Dynamic -> Articulation -> [FilePath]
filenamesOf :: Tuning -> Pitch -> Dynamic -> Articulation -> [NonNull Char]
filenamesOf Tuning
tuning Pitch
pitch Dynamic
dyn Articulation
art = forall a b. (a -> b) -> [a] -> [b]
map (Pitch -> Articulation -> Dynamic -> Int -> NonNull Char
unparseFilename Pitch
pitch Articulation
art Dynamic
dyn) [Int
1..Int
vars]
    where vars :: Int
vars = Tuning -> Pitch -> Dynamic -> Articulation -> Int
variationsOf Tuning
tuning Pitch
pitch Dynamic
dyn Articulation
art

-- if there's a min dur, then Open -> 1, OpenShort -> 4
-- otherwise all 4
variationsOf :: Tuning -> Pitch -> Dynamic -> Articulation -> Int
variationsOf :: Tuning -> Pitch -> Dynamic -> Articulation -> Int
variationsOf Tuning
tuning Pitch
pitch Dynamic
dyn Articulation
art = case Articulation
art of
    Articulation
Open -> if Bool
hasShort then Int
1 else Int
4
    Articulation
OpenShort -> if Bool
hasShort then Int
4 else Int
0
    Articulation
Calung -> case Tuning
tuning of
        -- I started with 4 open vars.
        Tuning
Isep | Pitch
pitch forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Int -> PitchClass -> Pitch
Pitch Int
3 PitchClass
E, Int -> PitchClass -> Pitch
Pitch Int
3 PitchClass
U] -> Int
4
        -- var3 sample has a click and clunk.
        Tuning
Umbang | Pitch
pitch forall a. Eq a => a -> a -> Bool
== Int -> PitchClass -> Pitch
Pitch Int
3 PitchClass
A, Dynamic
dyn forall a. Eq a => a -> a -> Bool
== Dynamic
PP -> Int
2
        Tuning
_ -> Int
3
    Articulation
MuteCalung -> case Tuning
tuning of
        -- Forgot this sample.
        Tuning
Isep | Pitch
pitch forall a. Eq a => a -> a -> Bool
== Int -> PitchClass -> Pitch
Pitch Int
4 PitchClass
I Bool -> Bool -> Bool
&& Dynamic
dyn forall a. Eq a => a -> a -> Bool
== Dynamic
FF -> Int
3
        Tuning
_ -> Int
4
    Articulation
_ -> Int
4
    where
    hasShort :: Bool
hasShort = forall a. Maybe a -> Bool
Maybe.isJust forall a b. (a -> b) -> a -> b
$ (Tuning, Pitch, Dynamic) -> Maybe Frames
minDurationOf (Tuning
tuning, Pitch
pitch, Dynamic
dyn)

-- ** envelope, TODO same as wayang

dynamicRange :: Dynamic -> (Int, Int)
dynamicRange :: Dynamic -> (Int, Int)
dynamicRange = \case
    Dynamic
PP -> (Int
1, Int
31)
    Dynamic
MP -> (Int
32, Int
64)
    Dynamic
MF -> (Int
65, Int
108)
    Dynamic
FF -> (Int
109, Int
127)

-- | The samples are normalized, so it just scales by Control.dynamic, where
-- 0 gets this value.
minDyn :: Signal.Y
minDyn :: Y
minDyn = Y
0.5

variableMuteRange :: (RealTime, RealTime)
variableMuteRange :: (RealTime, RealTime)
variableMuteRange = (RealTime
0.85, RealTime
4)

-- | Time to mute at the end of a note.
muteTime :: RealTime
muteTime :: RealTime
muteTime = RealTime
0.35

-- * tuning

-- TODO this is similar to Wayang.findPitch and Reyong.findPitch
findPitch :: Tuning -> Either Pitch.Note Pitch.NoteNumber
    -> Either Text (Pitch, (Pitch.NoteNumber, Pitch.NoteNumber))
findPitch :: Tuning
-> Either Note NoteNumber
-> Either Text (Pitch, (NoteNumber, NoteNumber))
findPitch Tuning
tuning = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Tuning -> Note -> Either Text (Pitch, (NoteNumber, NoteNumber))
findSymPitch Tuning
tuning) (Tuning
-> NoteNumber -> Either Text (Pitch, (NoteNumber, NoteNumber))
findNnPitch Tuning
tuning)

findSymPitch :: Tuning -> Pitch.Note
    -> Either Text (Pitch, (Pitch.NoteNumber, Pitch.NoteNumber))
findSymPitch :: Tuning -> Note -> Either Text (Pitch, (NoteNumber, NoteNumber))
findSymPitch Tuning
tuning (Pitch.Note Text
pitch) = do
    Pitch
pitch <- forall e (m :: * -> *) a. MonadError e m => e -> Maybe a -> m a
tryJust (Text
"can't parse symbolic pitch: " forall a. Semigroup a => a -> a -> a
<> Text
pitch) forall a b. (a -> b) -> a -> b
$
        NonNull Char -> Maybe Pitch
Lib.Bali.parsePitch (Text -> NonNull Char
untxt Text
pitch)
    (NoteNumber
umbang, NoteNumber
isep) <- forall e (m :: * -> *) a. MonadError e m => e -> Maybe a -> m a
tryJust (Text
"pitch out of range: " forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty Pitch
pitch) forall a b. (a -> b) -> a -> b
$
        forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Pitch
pitch Map Pitch (NoteNumber, NoteNumber)
rambatTuning
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ case Tuning
tuning of
        Tuning
Umbang -> (Pitch
pitch, (NoteNumber
umbang, NoteNumber
umbang))
        Tuning
Isep -> (Pitch
pitch, (NoteNumber
isep, NoteNumber
isep))

findNnPitch :: Tuning -> Pitch.NoteNumber
    -> Either Text (Pitch, (Pitch.NoteNumber, Pitch.NoteNumber))
findNnPitch :: Tuning
-> NoteNumber -> Either Text (Pitch, (NoteNumber, NoteNumber))
findNnPitch Tuning
tuning NoteNumber
nn = do
    (NoteNumber
sampleNn, Pitch
pitch) <- forall e (m :: * -> *) a. MonadError e m => e -> Maybe a -> m a
tryJust Text
"no pitches" forall a b. (a -> b) -> a -> b
$ forall k v. (Ord k, Num k) => k -> Map k v -> Maybe (k, v)
Maps.lookupClosest NoteNumber
nn forall a b. (a -> b) -> a -> b
$
        case Tuning
tuning of
            Tuning
Umbang -> Map NoteNumber Pitch
umbangs
            Tuning
Isep -> Map NoteNumber Pitch
iseps
    forall (m :: * -> *) a. Monad m => a -> m a
return (Pitch
pitch, (NoteNumber
nn, NoteNumber
sampleNn))
    where
    umbangs :: Map NoteNumber Pitch
umbangs = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
        [(NoteNumber
umbang, Pitch
p) | (Pitch
p, (NoteNumber
umbang, NoteNumber
_)) <- forall k a. Map k a -> [(k, a)]
Map.toList Map Pitch (NoteNumber, NoteNumber)
rambatTuning]
    iseps :: Map NoteNumber Pitch
iseps = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
        [(NoteNumber
isep, Pitch
p) | (Pitch
p, (NoteNumber
_, NoteNumber
isep)) <- forall k a. Map k a -> [(k, a)]
Map.toList Map Pitch (NoteNumber, NoteNumber)
rambatTuning]

rambatTuning :: Map Pitch (Pitch.NoteNumber, Pitch.NoteNumber)
rambatTuning :: Map Pitch (NoteNumber, NoteNumber)
rambatTuning = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList forall a b. (a -> b) -> a -> b
$ forall a b. [a] -> [b] -> [(a, b)]
zip [Int -> PitchClass -> Pitch
Pitch Int
3 PitchClass
E ..]
    [ (NoteNumber
51.03,   NoteNumber
51.85)  -- 3e
    , (NoteNumber
55.05,   NoteNumber
55.67)
    , (NoteNumber
56.10,   NoteNumber
56.50)

    , (NoteNumber
59.91,   NoteNumber
60.40)  -- 4i
    , (NoteNumber
61.80,   NoteNumber
62.41)
    , (NoteNumber
62.90,   NoteNumber
63.27)
    , (NoteNumber
67.15,   NoteNumber
67.47)
    , (NoteNumber
68.06,   NoteNumber
68.33)
    , (NoteNumber
71.88,   NoteNumber
72.15)  -- 5i
    , (NoteNumber
73.60,   NoteNumber
73.80)
    , (NoteNumber
75.13,   NoteNumber
75.38)
    , (NoteNumber
79.12,   NoteNumber
79.28)
    , (NoteNumber
80.27,   NoteNumber
80.26)
    , (NoteNumber
84.09,   NoteNumber
84.24)  -- 6i
    ]

-- * implementation

data Articulation =
    Open | OpenShort | MuteGenderLoose | MuteGenderTight | MuteGangsa
    | Calung | MuteCalung
    deriving (Articulation -> Articulation -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Articulation -> Articulation -> Bool
$c/= :: Articulation -> Articulation -> Bool
== :: Articulation -> Articulation -> Bool
$c== :: Articulation -> Articulation -> Bool
Eq, Eq Articulation
Articulation -> Articulation -> Bool
Articulation -> Articulation -> Ordering
Articulation -> Articulation -> Articulation
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Articulation -> Articulation -> Articulation
$cmin :: Articulation -> Articulation -> Articulation
max :: Articulation -> Articulation -> Articulation
$cmax :: Articulation -> Articulation -> Articulation
>= :: Articulation -> Articulation -> Bool
$c>= :: Articulation -> Articulation -> Bool
> :: Articulation -> Articulation -> Bool
$c> :: Articulation -> Articulation -> Bool
<= :: Articulation -> Articulation -> Bool
$c<= :: Articulation -> Articulation -> Bool
< :: Articulation -> Articulation -> Bool
$c< :: Articulation -> Articulation -> Bool
compare :: Articulation -> Articulation -> Ordering
$ccompare :: Articulation -> Articulation -> Ordering
Ord, Int -> Articulation -> NonNull Char -> NonNull Char
[Articulation] -> NonNull Char -> NonNull Char
Articulation -> NonNull Char
forall a.
(Int -> a -> NonNull Char -> NonNull Char)
-> (a -> NonNull Char)
-> ([a] -> NonNull Char -> NonNull Char)
-> Show a
showList :: [Articulation] -> NonNull Char -> NonNull Char
$cshowList :: [Articulation] -> NonNull Char -> NonNull Char
show :: Articulation -> NonNull Char
$cshow :: Articulation -> NonNull Char
showsPrec :: Int -> Articulation -> NonNull Char -> NonNull Char
$cshowsPrec :: Int -> Articulation -> NonNull Char -> NonNull Char
Show, Int -> Articulation
Articulation -> Int
Articulation -> [Articulation]
Articulation -> Articulation
Articulation -> Articulation -> [Articulation]
Articulation -> Articulation -> Articulation -> [Articulation]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Articulation -> Articulation -> Articulation -> [Articulation]
$cenumFromThenTo :: Articulation -> Articulation -> Articulation -> [Articulation]
enumFromTo :: Articulation -> Articulation -> [Articulation]
$cenumFromTo :: Articulation -> Articulation -> [Articulation]
enumFromThen :: Articulation -> Articulation -> [Articulation]
$cenumFromThen :: Articulation -> Articulation -> [Articulation]
enumFrom :: Articulation -> [Articulation]
$cenumFrom :: Articulation -> [Articulation]
fromEnum :: Articulation -> Int
$cfromEnum :: Articulation -> Int
toEnum :: Int -> Articulation
$ctoEnum :: Int -> Articulation
pred :: Articulation -> Articulation
$cpred :: Articulation -> Articulation
succ :: Articulation -> Articulation
$csucc :: Articulation -> Articulation
Enum, Articulation
forall a. a -> a -> Bounded a
maxBound :: Articulation
$cmaxBound :: Articulation
minBound :: Articulation
$cminBound :: Articulation
Bounded)

isMute :: Articulation -> Bool
isMute :: Articulation -> Bool
isMute = \case
    Articulation
MuteGenderLoose -> Bool
True
    Articulation
MuteGenderTight -> Bool
True
    Articulation
MuteGangsa -> Bool
True
    Articulation
MuteCalung -> Bool
True
    Articulation
_ -> Bool
False

parseFilename :: FilePath
    -> Maybe (Pitch, Articulation, Dynamic, Util.Variation)
parseFilename :: NonNull Char -> Maybe (Pitch, Articulation, Dynamic, Int)
parseFilename NonNull Char
fname = case forall a. Eq a => NonNull a -> NonNull a -> NonNull (NonNull a)
Lists.split NonNull Char
"-" (NonNull Char -> NonNull Char
FilePath.dropExtension NonNull Char
fname) of
    [NonNull Char
pitch, NonNull Char
art, NonNull Char
dyn, Char
'v':NonNull Char
var] ->
        (,,,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonNull Char -> Maybe Pitch
Lib.Bali.parsePitch NonNull Char
pitch forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> NonNull Char -> Maybe Articulation
pArt NonNull Char
art forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> NonNull Char -> Maybe Dynamic
pDyn NonNull Char
dyn
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Read a => NonNull Char -> Maybe a
Read.readMaybe NonNull Char
var
    [NonNull Char]
_ -> forall a. Maybe a
Nothing
    where
    pArt :: NonNull Char -> Maybe Articulation
pArt = (forall k a. Ord k => k -> Map k a -> Maybe a
`Map.lookup` Map (NonNull Char) Articulation
filenameToArt)
    filenameToArt :: Map (NonNull Char) Articulation
filenameToArt = forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList forall a b. (a -> b) -> a -> b
$ forall a k. (a -> k) -> [a] -> [(k, a)]
Lists.keyOn Articulation -> NonNull Char
articulationFile forall a. (Enum a, Bounded a) => [a]
Util.enumAll
    pDyn :: NonNull Char -> Maybe Dynamic
pDyn = forall a. Read a => NonNull Char -> Maybe a
Read.readMaybe forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
Char.toUpper

unparseFilename :: Pitch -> Articulation -> Dynamic -> Util.Variation
    -> FilePath
unparseFilename :: Pitch -> Articulation -> Dynamic -> Int -> NonNull Char
unparseFilename Pitch
pitch Articulation
art Dynamic
dyn Int
var = forall a. Monoid a => a -> [a] -> a
Lists.join NonNull Char
"-"
    [ forall a. Pretty a => a -> NonNull Char
prettys Pitch
pitch, Articulation -> NonNull Char
articulationFile Articulation
art, forall a. Show a => a -> NonNull Char
Util.showLower Dynamic
dyn
    , Char
'v' forall a. a -> [a] -> [a]
: forall a. Show a => a -> NonNull Char
show Int
var
    ]
    forall a. [a] -> [a] -> [a]
++ SampleFormat -> NonNull Char
Util.extension SampleFormat
sampleFormat

articulationFile :: Articulation -> String
articulationFile :: Articulation -> NonNull Char
articulationFile = \case
    Articulation
Open -> NonNull Char
"open"
    Articulation
OpenShort -> NonNull Char
"open+short"
    Articulation
MuteGenderLoose -> NonNull Char
"mute+gender+loose"
    Articulation
MuteGenderTight -> NonNull Char
"mute+gender+tight"
    Articulation
MuteGangsa -> NonNull Char
"mute+gangsa"
    Articulation
Calung -> NonNull Char
"calung"
    Articulation
MuteCalung -> NonNull Char
"calung+mute"

-- * util

getVariations :: IO [(FilePath, Map Calibrate.Axis Text)]
getVariations :: IO [(NonNull Char, Map Text Text)]
getVariations = do
    [(Tuning, (Pitch, Articulation, Dynamic, Int))]
samples <- forall a. [a] -> [a] -> [a]
(++)
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (forall {t}.
t -> NonNull Char -> Maybe (t, (Pitch, Articulation, Dynamic, Int))
get Tuning
Umbang) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonNull Char -> IO [NonNull Char]
Files.list (NonNull Char
dir NonNull Char -> NonNull Char -> NonNull Char
</> NonNull Char
"umbang"))
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (forall {t}.
t -> NonNull Char -> Maybe (t, (Pitch, Articulation, Dynamic, Int))
get Tuning
Isep) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonNull Char -> IO [NonNull Char]
Files.list (NonNull Char
dir NonNull Char -> NonNull Char -> NonNull Char
</> NonNull Char
"isep"))
    forall (m :: * -> *) a. Monad m => a -> m a
return
        [ ( NonNull Char
dir NonNull Char -> NonNull Char -> NonNull Char
</> forall {a}. IsString a => Tuning -> a
tuningDir Tuning
tuning NonNull Char -> NonNull Char -> NonNull Char
</> Pitch -> Articulation -> Dynamic -> Int -> NonNull Char
unparseFilename Pitch
pitch Articulation
art Dynamic
dyn Int
var
          , forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
            [ (Text
Calibrate.tuning, forall a. Show a => a -> Text
showt Tuning
tuning), (Text
Calibrate.pitch, forall a. Pretty a => a -> Text
pretty Pitch
pitch)
            , (Text
Calibrate.art, forall a. Show a => a -> Text
showt Articulation
art), (Text
Calibrate.dyn, forall a. Show a => a -> Text
showt Dynamic
dyn)
            , (Text
Calibrate.var, forall a. Show a => a -> Text
showt Int
var)
            ]
          )
        | (Tuning
tuning, (Pitch
pitch, Articulation
art, Dynamic
dyn, Int
var)) <- forall a. Ord a => [a] -> [a]
List.sort [(Tuning, (Pitch, Articulation, Dynamic, Int))]
samples
        ]
    where
    tuningDir :: Tuning -> a
tuningDir Tuning
Umbang = a
"umbang"
    tuningDir Tuning
Isep = a
"isep"
    dir :: NonNull Char
dir = NonNull Char
Config.unsafeSamplerRoot NonNull Char -> NonNull Char -> NonNull Char
</> NonNull Char
"rambat"
    get :: t -> NonNull Char -> Maybe (t, (Pitch, Articulation, Dynamic, Int))
get t
tuning NonNull Char
fname = (t
tuning,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NonNull Char -> Maybe (Pitch, Articulation, Dynamic, Int)
parseFilename (NonNull Char -> NonNull Char
FilePath.takeFileName NonNull Char
fname)

getDurations :: IO [((Tuning, Pitch, Dynamic), Audio.Frames)]
getDurations :: IO [((Tuning, Pitch, Dynamic), Frames)]
getDurations = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [((Tuning, Pitch, Dynamic), Frames)]
-> [((Tuning, Pitch, Dynamic), Frames)]
group forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [a] -> [a]
(++)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall (m :: * -> *) a b.
Monad m =>
(a -> m (Maybe b)) -> [a] -> m [b]
mapMaybeM (forall {a}.
a -> NonNull Char -> IO (Maybe ((a, Pitch, Dynamic), Frames))
get Tuning
Umbang) forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< NonNull Char -> IO [NonNull Char]
Files.list (NonNull Char
dir NonNull Char -> NonNull Char -> NonNull Char
</> NonNull Char
"umbang"))
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (forall (m :: * -> *) a b.
Monad m =>
(a -> m (Maybe b)) -> [a] -> m [b]
mapMaybeM (forall {a}.
a -> NonNull Char -> IO (Maybe ((a, Pitch, Dynamic), Frames))
get Tuning
Isep) forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< NonNull Char -> IO [NonNull Char]
Files.list (NonNull Char
dir NonNull Char -> NonNull Char -> NonNull Char
</> NonNull Char
"isep"))
    where
    dir :: NonNull Char
dir = NonNull Char
Config.unsafeSamplerRoot NonNull Char -> NonNull Char -> NonNull Char
</> NonNull Char
"rambat"
    group :: [((Tuning, Pitch, Dynamic), Frames)]
-> [((Tuning, Pitch, Dynamic), Frames)]
group = forall a b. (a -> b) -> [a] -> [b]
map (forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Ord a => [(a, b)] -> [(a, NonNull b)]
Lists.groupFst
    get :: a -> NonNull Char -> IO (Maybe ((a, Pitch, Dynamic), Frames))
get a
tuning NonNull Char
fname = case NonNull Char -> Maybe (Pitch, Articulation, Dynamic, Int)
parseFilename (NonNull Char -> NonNull Char
FilePath.takeFileName NonNull Char
fname) of
        Just (Pitch
pitch, Articulation
OpenShort, Dynamic
dyn, Int
_var) -> do
            Frames
frames <- Int -> Frames
Audio.Frames forall b c a. (b -> c) -> (a -> b) -> a -> c
. Info -> Int
Sndfile.frames forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
                (forall a. NonNull Char -> Maybe a -> IO a
Audio.File.throwEnoent NonNull Char
fname forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< NonNull Char -> IO (Maybe Info)
Audio.File.getInfo NonNull Char
fname)
            forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just ((a
tuning, Pitch
pitch, Dynamic
dyn), Frames
frames)
        Maybe (Pitch, Articulation, Dynamic, Int)
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing

makeDurationOf :: IO ()
makeDurationOf :: IO ()
makeDurationOf = do
    [((Tuning, Pitch, Dynamic), Frames)]
durs <- IO [((Tuning, Pitch, Dynamic), Frames)]
getDurations
    NonNull Char -> IO ()
putStrLn NonNull Char
"-- Generated by 'makeDurationOf'."
    NonNull Char -> IO ()
putStrLn NonNull Char
"minDurationOf :: (Tuning, Pitch, Dynamic) -> Maybe Audio.Frames"
    NonNull Char -> IO ()
putStrLn NonNull Char
"minDurationOf = \\case"
    forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [((Tuning, Pitch, Dynamic), Frames)]
durs forall a b. (a -> b) -> a -> b
$ \((Tuning, Pitch, Dynamic)
pattern, Audio.Frames Int
dur) ->
        NonNull Char -> IO ()
putStrLn forall a b. (a -> b) -> a -> b
$ NonNull Char
"    " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> NonNull Char
show (Tuning, Pitch, Dynamic)
pattern forall a. Semigroup a => a -> a -> a
<> NonNull Char
" -> Just " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> NonNull Char
show Int
dur
    NonNull Char -> IO ()
putStrLn NonNull Char
"    _ -> Nothing"

-- * generated

-- Generated by 'makeDurationOf'.
minDurationOf :: (Tuning, Pitch, Dynamic) -> Maybe Audio.Frames
minDurationOf :: (Tuning, Pitch, Dynamic) -> Maybe Frames
minDurationOf = \case
    (Tuning
Umbang,Pitch Int
4 PitchClass
U,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
112417
    (Tuning
Umbang,Pitch Int
4 PitchClass
U,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
89104
    (Tuning
Umbang,Pitch Int
4 PitchClass
U,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
98465
    (Tuning
Umbang,Pitch Int
4 PitchClass
U,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
98032
    (Tuning
Umbang,Pitch Int
4 PitchClass
A,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
98944
    (Tuning
Umbang,Pitch Int
4 PitchClass
A,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
128828
    (Tuning
Umbang,Pitch Int
4 PitchClass
A,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
120046
    (Tuning
Umbang,Pitch Int
4 PitchClass
A,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
121991
    (Tuning
Umbang,Pitch Int
5 PitchClass
I,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
117717
    (Tuning
Umbang,Pitch Int
5 PitchClass
I,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
113140
    (Tuning
Umbang,Pitch Int
5 PitchClass
I,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
131214
    (Tuning
Umbang,Pitch Int
5 PitchClass
I,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
148473
    (Tuning
Umbang,Pitch Int
5 PitchClass
O,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
118262
    (Tuning
Umbang,Pitch Int
5 PitchClass
O,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
123510
    (Tuning
Umbang,Pitch Int
5 PitchClass
O,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
137182
    (Tuning
Umbang,Pitch Int
5 PitchClass
O,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
142009
    (Tuning
Umbang,Pitch Int
5 PitchClass
E,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
154636
    (Tuning
Umbang,Pitch Int
5 PitchClass
E,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
127746
    (Tuning
Umbang,Pitch Int
5 PitchClass
E,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
134054
    (Tuning
Umbang,Pitch Int
5 PitchClass
E,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
145411
    (Tuning
Umbang,Pitch Int
5 PitchClass
U,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
122106
    (Tuning
Umbang,Pitch Int
5 PitchClass
U,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
146435
    (Tuning
Umbang,Pitch Int
5 PitchClass
U,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
124714
    (Tuning
Umbang,Pitch Int
5 PitchClass
U,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
142971
    (Tuning
Umbang,Pitch Int
5 PitchClass
A,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
104942
    (Tuning
Umbang,Pitch Int
5 PitchClass
A,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
138559
    (Tuning
Umbang,Pitch Int
5 PitchClass
A,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
143342
    (Tuning
Umbang,Pitch Int
5 PitchClass
A,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
132916
    (Tuning
Umbang,Pitch Int
6 PitchClass
I,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
159177
    (Tuning
Umbang,Pitch Int
6 PitchClass
I,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
130106
    (Tuning
Umbang,Pitch Int
6 PitchClass
I,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
123345
    (Tuning
Umbang,Pitch Int
6 PitchClass
I,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
123045
    (Tuning
Isep,Pitch Int
3 PitchClass
E,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
162080
    (Tuning
Isep,Pitch Int
3 PitchClass
E,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
159529
    (Tuning
Isep,Pitch Int
3 PitchClass
E,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
158300
    (Tuning
Isep,Pitch Int
3 PitchClass
E,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
146243
    (Tuning
Isep,Pitch Int
3 PitchClass
U,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
153505
    (Tuning
Isep,Pitch Int
3 PitchClass
U,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
173756
    (Tuning
Isep,Pitch Int
3 PitchClass
U,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
142989
    (Tuning
Isep,Pitch Int
3 PitchClass
U,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
144636
    (Tuning
Isep,Pitch Int
3 PitchClass
A,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
144275
    (Tuning
Isep,Pitch Int
3 PitchClass
A,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
162957
    (Tuning
Isep,Pitch Int
3 PitchClass
A,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
172313
    (Tuning
Isep,Pitch Int
3 PitchClass
A,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
177877
    (Tuning
Isep,Pitch Int
4 PitchClass
I,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
133248
    (Tuning
Isep,Pitch Int
4 PitchClass
I,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
163591
    (Tuning
Isep,Pitch Int
4 PitchClass
I,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
193262
    (Tuning
Isep,Pitch Int
4 PitchClass
I,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
171032
    (Tuning
Isep,Pitch Int
4 PitchClass
O,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
129181
    (Tuning
Isep,Pitch Int
4 PitchClass
O,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
181993
    (Tuning
Isep,Pitch Int
4 PitchClass
O,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
169347
    (Tuning
Isep,Pitch Int
4 PitchClass
O,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
182898
    (Tuning
Isep,Pitch Int
4 PitchClass
E,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
133960
    (Tuning
Isep,Pitch Int
4 PitchClass
E,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
173716
    (Tuning
Isep,Pitch Int
4 PitchClass
E,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
161932
    (Tuning
Isep,Pitch Int
4 PitchClass
E,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
173629
    (Tuning
Isep,Pitch Int
4 PitchClass
U,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
138339
    (Tuning
Isep,Pitch Int
4 PitchClass
U,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
164364
    (Tuning
Isep,Pitch Int
4 PitchClass
U,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
146833
    (Tuning
Isep,Pitch Int
4 PitchClass
U,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
141610
    (Tuning
Isep,Pitch Int
4 PitchClass
A,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
162173
    (Tuning
Isep,Pitch Int
4 PitchClass
A,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
167837
    (Tuning
Isep,Pitch Int
4 PitchClass
A,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
161727
    (Tuning
Isep,Pitch Int
4 PitchClass
A,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
178778
    (Tuning
Isep,Pitch Int
5 PitchClass
I,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
168970
    (Tuning
Isep,Pitch Int
5 PitchClass
I,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
164306
    (Tuning
Isep,Pitch Int
5 PitchClass
I,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
158971
    (Tuning
Isep,Pitch Int
5 PitchClass
I,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
160404
    (Tuning
Isep,Pitch Int
5 PitchClass
O,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
142237
    (Tuning
Isep,Pitch Int
5 PitchClass
O,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
164023
    (Tuning
Isep,Pitch Int
5 PitchClass
O,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
161175
    (Tuning
Isep,Pitch Int
5 PitchClass
O,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
159142
    (Tuning
Isep,Pitch Int
5 PitchClass
E,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
138153
    (Tuning
Isep,Pitch Int
5 PitchClass
E,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
164070
    (Tuning
Isep,Pitch Int
5 PitchClass
E,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
166684
    (Tuning
Isep,Pitch Int
5 PitchClass
E,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
156899
    (Tuning
Isep,Pitch Int
5 PitchClass
U,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
156653
    (Tuning
Isep,Pitch Int
5 PitchClass
U,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
124361
    (Tuning
Isep,Pitch Int
5 PitchClass
U,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
147572
    (Tuning
Isep,Pitch Int
5 PitchClass
U,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
176584
    (Tuning
Isep,Pitch Int
5 PitchClass
A,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
143279
    (Tuning
Isep,Pitch Int
5 PitchClass
A,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
160463
    (Tuning
Isep,Pitch Int
5 PitchClass
A,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
106814
    (Tuning
Isep,Pitch Int
5 PitchClass
A,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
142218
    (Tuning
Isep,Pitch Int
6 PitchClass
I,Dynamic
PP) -> forall a. a -> Maybe a
Just Frames
122746
    (Tuning
Isep,Pitch Int
6 PitchClass
I,Dynamic
MP) -> forall a. a -> Maybe a
Just Frames
144354
    (Tuning
Isep,Pitch Int
6 PitchClass
I,Dynamic
MF) -> forall a. a -> Maybe a
Just Frames
185924
    (Tuning
Isep,Pitch Int
6 PitchClass
I,Dynamic
FF) -> forall a. a -> Maybe a
Just Frames
155587
    (Tuning, Pitch, Dynamic)
_ -> forall a. Maybe a
Nothing