hmt 0.15 → 0.16
raw patch · 148 files changed
+14571/−3412 lines, 148 filesdep +aesondep +fgldep +modular-arithmeticdep −utf8-stringdep ~basePVP ok
version bump matches the API change (PVP)
Dependencies added: aeson, fgl, modular-arithmetic, random, text
Dependencies removed: utf8-string
Dependency ranges changed: base
API changes (from Hackage documentation)
- Music.Theory.Array.CSV: Column_Ref :: String -> Column_Ref
- Music.Theory.Array.CSV: cell_index :: Cell_Ref -> (Int, Int)
- Music.Theory.Array.CSV: cell_range :: Cell_Range -> [Cell_Ref]
- Music.Theory.Array.CSV: cell_range_row_order :: Cell_Range -> [Cell_Ref]
- Music.Theory.Array.CSV: cell_ref_minima :: Cell_Ref
- Music.Theory.Array.CSV: cell_ref_pp :: Cell_Ref -> String
- Music.Theory.Array.CSV: column_in_range :: Column_Range -> Column_Ref -> Bool
- Music.Theory.Array.CSV: column_index :: Column_Ref -> Int
- Music.Theory.Array.CSV: column_indices :: Column_Range -> (Int, Int)
- Music.Theory.Array.CSV: column_range :: Column_Range -> [Column_Ref]
- Music.Theory.Array.CSV: column_range_size :: Column_Range -> Int
- Music.Theory.Array.CSV: column_ref :: Int -> Column_Ref
- Music.Theory.Array.CSV: column_ref_pred :: Column_Ref -> Column_Ref
- Music.Theory.Array.CSV: column_ref_string :: Column_Ref -> String
- Music.Theory.Array.CSV: column_ref_succ :: Column_Ref -> Column_Ref
- Music.Theory.Array.CSV: csv_table_read' :: (String -> a) -> FilePath -> IO (Table a)
- Music.Theory.Array.CSV: csv_table_write' :: (a -> String) -> CSV_Opt -> FilePath -> Table a -> IO ()
- Music.Theory.Array.CSV: data Column_Ref
- Music.Theory.Array.CSV: index_letter :: Int -> Char
- Music.Theory.Array.CSV: instance Enum Column_Ref
- Music.Theory.Array.CSV: instance Eq Column_Ref
- Music.Theory.Array.CSV: instance IsString Column_Ref
- Music.Theory.Array.CSV: instance Ix Column_Ref
- Music.Theory.Array.CSV: instance Ord Column_Ref
- Music.Theory.Array.CSV: instance Read Column_Ref
- Music.Theory.Array.CSV: instance Show Column_Ref
- Music.Theory.Array.CSV: interior_column_index :: Column_Range -> Column_Ref -> Int
- Music.Theory.Array.CSV: letter_index :: Char -> Int
- Music.Theory.Array.CSV: parse_cell_ref :: String -> Maybe Cell_Ref
- Music.Theory.Array.CSV: row_index :: Row_Ref -> Int
- Music.Theory.Array.CSV: row_range :: Row_Range -> [Row_Ref]
- Music.Theory.Array.CSV: type Cell_Range = (Cell_Ref, Cell_Ref)
- Music.Theory.Array.CSV: type Cell_Ref = (Column_Ref, Row_Ref)
- Music.Theory.Array.CSV: type Column_Range = (Column_Ref, Column_Ref)
- Music.Theory.Array.CSV: type Row_Range = (Row_Ref, Row_Ref)
- Music.Theory.Array.CSV: type Row_Ref = Int
- Music.Theory.Array.CSV.Midi: csv_midi_note_data_hdr :: [String]
- Music.Theory.Array.CSV.Midi: csv_midi_note_data_read :: (Read t, Real t, Read n, Real n) => (m, m) -> FilePath -> IO [(t, m, n, n)]
- Music.Theory.Array.CSV.Midi: csv_midi_note_data_read' :: (Read t, Real t, Read n, Real n) => (m, m) -> FilePath -> IO [(t, Either m String, n, n)]
- Music.Theory.Array.CSV.Midi: csv_midi_note_data_write :: (Eq m, Show t, Real t, Show n, Real n) => (m, m) -> FilePath -> [(t, m, n, n)] -> IO ()
- Music.Theory.Array.CSV.Midi: midi_tseq_read :: (Read t, Real t, Read n, Real n) => FilePath -> IO (Tseq t (On_Off (n, n)))
- Music.Theory.Array.CSV.Midi: midi_tseq_to_midi_wseq :: (Num t, Eq n) => Tseq t (On_Off (n, n)) -> Wseq t (n, n)
- Music.Theory.Array.CSV.Midi: midi_tseq_write :: (Show t, Real t, Show n, Real n) => FilePath -> Tseq t (On_Off (n, n)) -> IO ()
- Music.Theory.Array.CSV.Midi: midi_wseq_to_midi_tseq :: (Num t, Ord t) => Wseq t (n, n) -> Tseq t (On_Off (n, n))
- Music.Theory.Array.CSV.Midi: reads_err :: Read a => String -> a
- Music.Theory.Array.CSV.Midi: reads_exact :: Read a => String -> Maybe a
- Music.Theory.Array.MD: delete_trailing_whitespace :: [Char] -> [Char]
- Music.Theory.Array.MD: make_regular :: a -> [[a]] -> [[a]]
- Music.Theory.Array.MD: pad_right :: a -> Int -> [a] -> [a]
- Music.Theory.Clef: clef_octave :: Clef i -> i
- Music.Theory.Clef: clef_t :: Clef i -> Clef_T
- Music.Theory.Clef: instance Eq Clef_T
- Music.Theory.Clef: instance Eq i => Eq (Clef i)
- Music.Theory.Clef: instance Ord Clef_T
- Music.Theory.Clef: instance Ord i => Ord (Clef i)
- Music.Theory.Clef: instance Show Clef_T
- Music.Theory.Clef: instance Show i => Show (Clef i)
- Music.Theory.Contour.Polansky_1992: all_equal :: Eq a => [a] -> Bool
- Music.Theory.Contour.Polansky_1992: compare_adjacent :: Ord a => [a] -> [Ordering]
- Music.Theory.Contour.Polansky_1992: contour_description_m :: Contour_Description -> Map (Int, Int) Ordering
- Music.Theory.Contour.Polansky_1992: contour_description_n :: Contour_Description -> Int
- Music.Theory.Contour.Polansky_1992: contour_half_matrix_m :: Contour_Half_Matrix -> Matrix Ordering
- Music.Theory.Contour.Polansky_1992: contour_half_matrix_n :: Contour_Half_Matrix -> Int
- Music.Theory.Contour.Polansky_1992: genericFromEnum :: (Integral i, Enum e) => e -> i
- Music.Theory.Contour.Polansky_1992: genericToEnum :: (Integral i, Enum e) => i -> e
- Music.Theory.Contour.Polansky_1992: instance Eq Contour_Description
- Music.Theory.Contour.Polansky_1992: instance Eq Contour_Half_Matrix
- Music.Theory.Contour.Polansky_1992: instance Show Contour_Description
- Music.Theory.Contour.Polansky_1992: instance Show Contour_Half_Matrix
- Music.Theory.Contour.Polansky_1992: int_to_ord :: Integral a => a -> Ordering
- Music.Theory.Contour.Polansky_1992: ord_invert :: Ordering -> Ordering
- Music.Theory.Contour.Polansky_1992: ord_to_int :: Integral a => Ordering -> a
- Music.Theory.Contour.Polansky_1992: replace :: Integral i => [a] -> i -> a -> [a]
- Music.Theory.Duration: division :: Duration -> Integer
- Music.Theory.Duration: dots :: Duration -> Integer
- Music.Theory.Duration: duration_pp :: Duration -> Maybe String
- Music.Theory.Duration: instance Eq Duration
- Music.Theory.Duration: instance Ord Duration
- Music.Theory.Duration: instance Show Duration
- Music.Theory.Duration: multiplier :: Duration -> Rational
- Music.Theory.Duration: order_pair :: Ordering -> (t, t) -> (t, t)
- Music.Theory.Duration: sort_pair :: (t -> t -> Ordering) -> (t, t) -> (t, t)
- Music.Theory.Duration: sort_pair_m :: (t -> t -> Maybe Ordering) -> (t, t) -> Maybe (t, t)
- Music.Theory.Duration: sum_dur' :: Duration -> Duration -> Duration
- Music.Theory.Duration: whole_note_division_pp :: Integer -> Maybe Char
- Music.Theory.Duration.Annotation: adopt_shape :: Traversable t => (a -> b -> c) -> [b] -> t a -> t c
- Music.Theory.Duration.Annotation: adopt_shape_m :: Traversable t => (a -> b -> c) -> [b] -> t (Maybe a) -> t (Maybe c)
- Music.Theory.Duration.Annotation: begin_end_cmp :: (t -> Bool) -> (t -> Bool) -> t -> Ordering
- Music.Theory.Duration.Annotation: begin_end_cmp_eq :: Eq t => t -> t -> t -> Ordering
- Music.Theory.Duration.Annotation: group_tree :: (a -> Ordering) -> [a] -> Tree (Maybe a)
- Music.Theory.Duration.Annotation: instance Eq D_Annotation
- Music.Theory.Duration.Annotation: instance Show D_Annotation
- Music.Theory.Duration.Annotation: zip_with_kr :: (a -> b -> c) -> [a] -> [b] -> ([c], [b])
- Music.Theory.Duration.CT: ct_count :: CT -> (RQ, Int)
- Music.Theory.Duration.CT: ct_len :: CT -> Int
- Music.Theory.Duration.CT: ct_mark :: CT -> [(Measure, Char)]
- Music.Theory.Duration.CT: ct_tempo :: CT -> Lseq (Measure, Pulse) RQ
- Music.Theory.Duration.CT: ct_ts :: CT -> [(Measure, Rational_Time_Signature)]
- Music.Theory.Duration.CT: instance Eq CT_Node
- Music.Theory.Duration.CT: instance Show CT
- Music.Theory.Duration.CT: instance Show CT_Node
- Music.Theory.Dynamic_Mark: instance Bounded Dynamic_Mark_T
- Music.Theory.Dynamic_Mark: instance Bounded Hairpin_T
- Music.Theory.Dynamic_Mark: instance Enum Dynamic_Mark_T
- Music.Theory.Dynamic_Mark: instance Enum Hairpin_T
- Music.Theory.Dynamic_Mark: instance Eq Dynamic_Mark_T
- Music.Theory.Dynamic_Mark: instance Eq Hairpin_T
- Music.Theory.Dynamic_Mark: instance Ord Dynamic_Mark_T
- Music.Theory.Dynamic_Mark: instance Ord Hairpin_T
- Music.Theory.Dynamic_Mark: instance Show Dynamic_Mark_T
- Music.Theory.Dynamic_Mark: instance Show Hairpin_T
- Music.Theory.Instrument.Choir: instance Bounded Voice
- Music.Theory.Instrument.Choir: instance Enum Voice
- Music.Theory.Instrument.Choir: instance Eq Voice
- Music.Theory.Instrument.Choir: instance Ord Voice
- Music.Theory.Instrument.Choir: instance Show Voice
- Music.Theory.Interval: instance Bounded Interval_Q
- Music.Theory.Interval: instance Bounded Interval_T
- Music.Theory.Interval: instance Enum Interval_Q
- Music.Theory.Interval: instance Enum Interval_T
- Music.Theory.Interval: instance Eq Interval
- Music.Theory.Interval: instance Eq Interval_Q
- Music.Theory.Interval: instance Eq Interval_T
- Music.Theory.Interval: instance Ord Interval_Q
- Music.Theory.Interval: instance Ord Interval_T
- Music.Theory.Interval: instance Show Interval
- Music.Theory.Interval: instance Show Interval_Q
- Music.Theory.Interval: instance Show Interval_T
- Music.Theory.Interval: interval_direction :: Interval -> Ordering
- Music.Theory.Interval: interval_octave :: Interval -> Octave
- Music.Theory.Interval: interval_quality :: Interval -> Interval_Q
- Music.Theory.Interval: interval_type :: Interval -> Interval_T
- Music.Theory.Interval: invert_ordering :: Ordering -> Ordering
- Music.Theory.Interval: note_span :: Note_T -> Note_T -> [Note_T]
- Music.Theory.Key: instance Eq Mode_T
- Music.Theory.Key: instance Ord Mode_T
- Music.Theory.Key: instance Show Mode_T
- Music.Theory.List: ordering_invert :: Ordering -> Ordering
- Music.Theory.Metric.Buchler_1998: instance Eq R
- Music.Theory.Metric.Buchler_1998: instance Show R
- Music.Theory.Permutations.Morris_1984: instance Eq Change
- Music.Theory.Permutations.Morris_1984: instance Eq Method
- Music.Theory.Permutations.Morris_1984: instance Show Change
- Music.Theory.Permutations.Morris_1984: instance Show Method
- Music.Theory.Pitch: Pitch' :: Note_T -> Alteration_T' -> Octave -> Pitch'
- Music.Theory.Pitch: alteration :: Pitch -> Alteration_T
- Music.Theory.Pitch: data Pitch'
- Music.Theory.Pitch: instance Eq Pitch
- Music.Theory.Pitch: instance Eq Pitch'
- Music.Theory.Pitch: instance Ord Pitch
- Music.Theory.Pitch: instance Show Pitch
- Music.Theory.Pitch: instance Show Pitch'
- Music.Theory.Pitch: note :: Pitch -> Note_T
- Music.Theory.Pitch: octave :: Pitch -> Octave
- Music.Theory.Pitch: pitch'_class_pp :: Pitch' -> String
- Music.Theory.Pitch: pitch'_pp :: Pitch' -> String
- Music.Theory.Pitch.Note: alteration_t' :: Alteration_T -> Alteration_T'
- Music.Theory.Pitch.Note: instance Bounded Alteration_T
- Music.Theory.Pitch.Note: instance Bounded Note_T
- Music.Theory.Pitch.Note: instance Enum Alteration_T
- Music.Theory.Pitch.Note: instance Enum Note_T
- Music.Theory.Pitch.Note: instance Eq Alteration_T
- Music.Theory.Pitch.Note: instance Eq Note_T
- Music.Theory.Pitch.Note: instance Ord Alteration_T
- Music.Theory.Pitch.Note: instance Ord Note_T
- Music.Theory.Pitch.Note: instance Show Alteration_T
- Music.Theory.Pitch.Note: instance Show Note_T
- Music.Theory.Pitch.Note: type Alteration_T' = (Rational, String)
- Music.Theory.Pitch.Note: type Spelling n = n -> (Note_T, Alteration_T)
- Music.Theory.Pitch.Spelling: pc_spell_flat :: Integral i => Spelling i
- Music.Theory.Pitch.Spelling: pc_spell_ks :: Integral i => Spelling i
- Music.Theory.Pitch.Spelling: pc_spell_natural :: Integral i => Spelling i
- Music.Theory.Pitch.Spelling: pc_spell_natural_m :: Integral i => Spelling_M i
- Music.Theory.Pitch.Spelling: pc_spell_sharp :: Integral i => Spelling i
- Music.Theory.Pitch.Spelling: type Spelling_M i = i -> Maybe (Note_T, Alteration_T)
- Music.Theory.Pitch.Spelling.Cluster: spell_cluster_c4_table :: [([PitchClass], [Pitch])]
- Music.Theory.Time.Bel1990.R: instance Eq Par_Mode
- Music.Theory.Time.Bel1990.R: instance Eq a => Eq (Bel a)
- Music.Theory.Time.Bel1990.R: instance Eq a => Eq (Term a)
- Music.Theory.Time.Bel1990.R: instance Show Par_Mode
- Music.Theory.Time.Bel1990.R: instance Show a => Show (Bel a)
- Music.Theory.Time.Bel1990.R: instance Show a => Show (Term a)
- Music.Theory.Time.Bel1990.R: p_double :: P Double
- Music.Theory.Time.Bel1990.R: p_integer :: P Integer
- Music.Theory.Time.Bel1990.R: p_number :: P Rational
- Music.Theory.Time.Bel1990.R: p_rational :: P Rational
- Music.Theory.Time.Duration: hours :: Duration -> Int
- Music.Theory.Time.Duration: instance Eq Duration
- Music.Theory.Time.Duration: instance Read Duration
- Music.Theory.Time.Duration: instance Show Duration
- Music.Theory.Time.Duration: milliseconds :: Duration -> Int
- Music.Theory.Time.Duration: minutes :: Duration -> Int
- Music.Theory.Time.Duration: seconds :: Duration -> Int
- Music.Theory.Time.Seq: Off :: a -> On_Off a
- Music.Theory.Time.Seq: On :: a -> On_Off a
- Music.Theory.Time.Seq: cmp_on_off :: On_Off a -> On_Off b -> Ordering
- Music.Theory.Time.Seq: data On_Off a
- Music.Theory.Time.Seq: either_to_on_off :: Either a a -> On_Off a
- Music.Theory.Time.Seq: instance Enum Interpolation_T
- Music.Theory.Time.Seq: instance Eq Interpolation_T
- Music.Theory.Time.Seq: instance Eq a => Eq (On_Off a)
- Music.Theory.Time.Seq: instance Show Interpolation_T
- Music.Theory.Time.Seq: instance Show a => Show (On_Off a)
- Music.Theory.Time.Seq: on_off_to_either :: On_Off a -> Either a a
- Music.Theory.Time.Seq: tseq_on_off_to_wseq :: Num t => (a -> a -> Bool) -> Tseq t (On_Off a) -> Wseq t a
- Music.Theory.Time.Seq: wseq_on_off :: (Num t, Ord t) => Wseq t a -> Tseq t (On_Off a)
- Music.Theory.Time.Seq: wseq_on_off_either :: (Num t, Ord t) => Wseq t a -> Tseq t (Either a a)
- Music.Theory.Time.Seq: wseq_on_off_f :: (Ord t, Num t) => (a -> b) -> (a -> b) -> Wseq t a -> Tseq t b
- Music.Theory.Tuning: approximate_ratios :: Tuning -> [Approximate_Ratio]
- Music.Theory.Tuning: approximate_ratios_cyclic :: Tuning -> [Approximate_Ratio]
- Music.Theory.Tuning: cents :: Tuning -> [Cents]
- Music.Theory.Tuning: cents_i :: Integral i => Tuning -> [i]
- Music.Theory.Tuning: cents_octave :: Tuning -> [Cents]
- Music.Theory.Tuning: divisions :: Tuning -> Int
- Music.Theory.Tuning: fold_cps_to_octave_of :: (Ord a, Fractional a) => a -> a -> a
- Music.Theory.Tuning: instance Eq Tuning
- Music.Theory.Tuning: instance Show Tuning
- Music.Theory.Tuning: octave_ratio :: Tuning -> Rational
- Music.Theory.Tuning: ratios :: Tuning -> Maybe [Rational]
- Music.Theory.Tuning: ratios_err :: Tuning -> [Rational]
- Music.Theory.Tuning: ratios_or_cents :: Tuning -> Either [Rational] [Cents]
- Music.Theory.Tuning: reconstructed_ratios :: Double -> Tuning -> Maybe [Rational]
- Music.Theory.Tuning.Alves: harrison_ditone :: Tuning
- Music.Theory.Tuning.Alves: harrison_ditone_r :: [Rational]
- Music.Theory.Tuning.Gann: ben_johnston :: Tuning
- Music.Theory.Tuning.Gann: ben_johnston_r :: [Rational]
- Music.Theory.Tuning.Gann: gann_arcana_xvi :: Tuning
- Music.Theory.Tuning.Gann: gann_arcana_xvi_r :: [Rational]
- Music.Theory.Tuning.Gann: gann_superparticular :: Tuning
- Music.Theory.Tuning.Gann: gann_superparticular_r :: [Rational]
- Music.Theory.Tuning.Gann: la_monte_young :: Tuning
- Music.Theory.Tuning.Gann: la_monte_young_r :: [Rational]
- Music.Theory.Tuning.Gann: pietro_aaron_1523 :: Tuning
- Music.Theory.Tuning.Gann: pietro_aaron_1523_c :: [Cents]
- Music.Theory.Tuning.Gann: thomas_young_1799 :: Tuning
- Music.Theory.Tuning.Gann: thomas_young_1799_c :: [Cents]
- Music.Theory.Tuning.Gann: werckmeister_iii_c :: [Cents]
- Music.Theory.Tuning.Gann: zarlino :: Tuning
- Music.Theory.Tuning.Gann: zarlino_r :: [Rational]
- Music.Theory.Tuning.Microtonal_Synthesis: ben_johnston_25 :: Tuning
- Music.Theory.Tuning.Microtonal_Synthesis: ben_johnston_25_r :: [Rational]
- Music.Theory.Tuning.Microtonal_Synthesis: five_limit_tuning :: Tuning
- Music.Theory.Tuning.Microtonal_Synthesis: five_limit_tuning_r :: [Rational]
- Music.Theory.Tuning.Microtonal_Synthesis: kirnberger_iii :: Tuning
- Music.Theory.Tuning.Microtonal_Synthesis: kirnberger_iii_ar :: [Approximate_Ratio]
- Music.Theory.Tuning.Microtonal_Synthesis: lou_harrison_16 :: Tuning
- Music.Theory.Tuning.Microtonal_Synthesis: lou_harrison_16_r :: [Rational]
- Music.Theory.Tuning.Microtonal_Synthesis: mayumi_reinhard :: Tuning
- Music.Theory.Tuning.Microtonal_Synthesis: mayumi_reinhard_r :: [Rational]
- Music.Theory.Tuning.Microtonal_Synthesis: partch_43 :: Tuning
- Music.Theory.Tuning.Microtonal_Synthesis: partch_43_r :: [Rational]
- Music.Theory.Tuning.Microtonal_Synthesis: pythagorean :: Tuning
- Music.Theory.Tuning.Microtonal_Synthesis: pythagorean_r :: [Rational]
- Music.Theory.Tuning.Microtonal_Synthesis: septimal_tritone_just_intonation :: Tuning
- Music.Theory.Tuning.Microtonal_Synthesis: septimal_tritone_just_intonation_r :: [Rational]
- Music.Theory.Tuning.Microtonal_Synthesis: seven_limit_just_intonation :: Tuning
- Music.Theory.Tuning.Microtonal_Synthesis: seven_limit_just_intonation_r :: [Rational]
- Music.Theory.Tuning.Microtonal_Synthesis: vallotti :: Tuning
- Music.Theory.Tuning.Microtonal_Synthesis: vallotti_c :: [Cents]
- Music.Theory.Tuning.Polansky_1978: psaltery :: [Rational]
- Music.Theory.Tuning.Polansky_1984: pad :: Int -> String -> String
- Music.Theory.Tuning.Riley: riley_albion :: Tuning
- Music.Theory.Tuning.Riley: riley_albion_r :: [Rational]
- Music.Theory.Tuning.Scala: comment_p :: String -> Bool
- Music.Theory.Tuning.Scala: delete_trailing_point :: String -> String
- Music.Theory.Tuning.Scala: dir_subset :: [String] -> FilePath -> IO [FilePath]
- Music.Theory.Tuning.Scala: filter_cr :: String -> String
- Music.Theory.Tuning.Scala: load :: (Read i, Integral i) => FilePath -> IO (Scale i)
- Music.Theory.Tuning.Scala: load_dir :: (Read i, Integral i) => FilePath -> IO [Scale i]
- Music.Theory.Tuning.Scala: p_or :: [a -> Bool] -> a -> Bool
- Music.Theory.Tuning.Scala: parse :: (Read i, Integral i) => String -> Scale i
- Music.Theory.Tuning.Scala: pitch :: (Read i, Integral i) => String -> Pitch i
- Music.Theory.Tuning.Scala: pitch_ln :: (Read i, Integral i) => String -> Pitch i
- Music.Theory.Tuning.Scala: scale_pitch_representations :: Integral t => Scale i -> (t, t)
- Music.Theory.Tuning.Werckmeister: werckmeister_iii :: Tuning
- Music.Theory.Tuning.Werckmeister: werckmeister_iii_ar :: [Approximate_Ratio]
- Music.Theory.Tuning.Werckmeister: werckmeister_iii_ar_c :: [Cents]
- Music.Theory.Tuning.Werckmeister: werckmeister_iv :: Tuning
- Music.Theory.Tuning.Werckmeister: werckmeister_iv_ar :: [Approximate_Ratio]
- Music.Theory.Tuning.Werckmeister: werckmeister_iv_c :: [Cents]
- Music.Theory.Tuning.Werckmeister: werckmeister_v :: Tuning
- Music.Theory.Tuning.Werckmeister: werckmeister_v_ar :: [Approximate_Ratio]
- Music.Theory.Tuning.Werckmeister: werckmeister_v_c :: [Cents]
- Music.Theory.Tuning.Werckmeister: werckmeister_vi :: Tuning
- Music.Theory.Tuning.Werckmeister: werckmeister_vi_r :: [Rational]
- Music.Theory.Tuple: t2 :: [t] -> T2 t
- Music.Theory.Tuple: t2_list :: T2 a -> [a]
- Music.Theory.Tuple: t3 :: [t] -> T3 t
- Music.Theory.Tuple: t3_list :: T3 a -> [a]
- Music.Theory.Tuple: t4 :: [t] -> T4 t
- Music.Theory.Tuple: t4_list :: T4 t -> [t]
- Music.Theory.Tuple: t5 :: [t] -> T5 t
- Music.Theory.Tuple: t5_list :: T5 t -> [t]
- Music.Theory.Tuple: t6 :: [t] -> T6 t
- Music.Theory.Tuple: t6_list :: T6 t -> [t]
- Music.Theory.Tuple: t7_list :: T7 t -> [t]
- Music.Theory.Tuple: t8_list :: T8 t -> [t]
- Music.Theory.Tuple: t9_list :: T9 t -> [t]
- Music.Theory.Xenakis.S4: instance Bounded Face
- Music.Theory.Xenakis.S4: instance Bounded Label
- Music.Theory.Xenakis.S4: instance Enum Face
- Music.Theory.Xenakis.S4: instance Enum Label
- Music.Theory.Xenakis.S4: instance Eq Face
- Music.Theory.Xenakis.S4: instance Eq Label
- Music.Theory.Xenakis.S4: instance Ord Face
- Music.Theory.Xenakis.S4: instance Ord Label
- Music.Theory.Xenakis.S4: instance Show Face
- Music.Theory.Xenakis.S4: instance Show Label
- Music.Theory.Xenakis.S4: viii_6_l :: [Label]
- Music.Theory.Xenakis.S4: viii_6b_l :: [Label]
- Music.Theory.Xenakis.Sieve: instance Eq Sieve
- Music.Theory.Xenakis.Sieve: instance Show Sieve
- Music.Theory.Z.SRO: invert :: (Integral i, Functor f) => i -> i -> f i -> f i
- Music.Theory.Z.SRO: invert_ix :: Integral i => i -> Int -> [i] -> [i]
- Music.Theory.Z.SRO: mn :: (Integral i, Functor f) => i -> i -> f i -> f i
- Music.Theory.Z.SRO: rti_related :: Integral i => i -> [i] -> [[i]]
- Music.Theory.Z.SRO: t_related :: (Integral i, Functor f) => i -> f i -> [f i]
- Music.Theory.Z.SRO: ti_related :: (Eq (f i), Integral i, Functor f) => i -> f i -> [f i]
- Music.Theory.Z.SRO: tmatrix :: Integral i => i -> [i] -> [[i]]
- Music.Theory.Z.SRO: tn :: (Integral i, Functor f) => i -> i -> f i -> f i
- Music.Theory.Z.SRO: tn_to :: Integral a => a -> a -> [a] -> [a]
- Music.Theory.Z.SRO: tni :: (Integral i, Functor f) => i -> i -> f i -> f i
- Music.Theory.Z12: Z12 :: Int -> Z12
- Music.Theory.Z12: check_negative :: (Int -> Int) -> Z12 -> Z12
- Music.Theory.Z12: instance Bounded Z12
- Music.Theory.Z12: instance Enum Z12
- Music.Theory.Z12: instance Eq Z12
- Music.Theory.Z12: instance Integral Z12
- Music.Theory.Z12: instance Num Z12
- Music.Theory.Z12: instance Ord Z12
- Music.Theory.Z12: instance Real Z12
- Music.Theory.Z12: instance Show Z12
- Music.Theory.Z12: lift_binary_Z12 :: (Int -> Int -> Int) -> Z12 -> Z12 -> Z12
- Music.Theory.Z12: lift_unary_Z12 :: (Int -> Int) -> Z12 -> Z12
- Music.Theory.Z12: newtype Z12
- Music.Theory.Z12: z12_modulo :: Z12
- Music.Theory.Z12: z12_showsPrec :: Int -> Z12 -> ShowS
- Music.Theory.Z12.Drape_1999: has_ess :: [Z12] -> [Z12] -> Bool
- Music.Theory.Z12.Morris_1987: SRO :: Z12 -> Bool -> Z12 -> Bool -> Bool -> SRO
- Music.Theory.Z12.Morris_1987: data SRO
- Music.Theory.Z12.Morris_1987: instance Eq SRO
- Music.Theory.Z12.Morris_1987: instance Show SRO
- Music.Theory.Z12.Morris_1987: sro :: SRO -> [Z12] -> [Z12]
- Music.Theory.Z12.Morris_1987: sro_RTnI :: [SRO]
- Music.Theory.Z12.Morris_1987: sro_RTnMI :: [SRO]
- Music.Theory.Z12.Morris_1987: sro_Tn :: [SRO]
- Music.Theory.Z12.Morris_1987: sro_TnI :: [SRO]
- Music.Theory.Z12.Morris_1987: sro_TnMI :: [SRO]
- Music.Theory.Z12.Morris_1987: sros :: [Z12] -> [(SRO, [Z12])]
- Music.Theory.Z12.Morris_1987.Parse: rnrtnmi :: String -> SRO
- Music.Theory.Z12.SRO: invert :: Z12 -> [Z12] -> [Z12]
- Music.Theory.Z12.SRO: invert_ix :: Int -> [Z12] -> [Z12]
- Music.Theory.Z12.SRO: m5 :: [Z12] -> [Z12]
- Music.Theory.Z12.SRO: mn :: Z12 -> [Z12] -> [Z12]
- Music.Theory.Z12.SRO: rrtmi_related :: [Z12] -> [[Z12]]
- Music.Theory.Z12.SRO: rti_related :: [Z12] -> [[Z12]]
- Music.Theory.Z12.SRO: rtmi_related :: [Z12] -> [[Z12]]
- Music.Theory.Z12.SRO: t_related :: [Z12] -> [[Z12]]
- Music.Theory.Z12.SRO: ti_related :: [Z12] -> [[Z12]]
- Music.Theory.Z12.SRO: tmi_related :: [Z12] -> [[Z12]]
- Music.Theory.Z12.SRO: tn :: Z12 -> [Z12] -> [Z12]
- Music.Theory.Z12.SRO: tn_to :: Z12 -> [Z12] -> [Z12]
- Music.Theory.Z12.SRO: tni :: Z12 -> [Z12] -> [Z12]
- Music.Theory.Z12.TTO: invert :: Z12 -> [Z12] -> [Z12]
- Music.Theory.Z12.TTO: m5 :: [Z12] -> [Z12]
- Music.Theory.Z12.TTO: mn :: Z12 -> [Z12] -> [Z12]
- Music.Theory.Z12.TTO: t_related :: [Z12] -> [[Z12]]
- Music.Theory.Z12.TTO: ti_related :: [Z12] -> [[Z12]]
- Music.Theory.Z12.TTO: tn :: Z12 -> [Z12] -> [Z12]
- Music.Theory.Z12.TTO: tni :: Z12 -> [Z12] -> [Z12]
+ Music.Theory.Array: all_ix_translations :: Integral t => Dimensions t -> [Ix t] -> [[Ix t]]
+ Music.Theory.Array: all_ix_translations_uniq :: Integral t => Dimensions t -> [Ix t] -> [[Ix t]]
+ Music.Theory.Array: column_indices :: (Enum t, Num t) => t -> t -> [Ix t]
+ Music.Theory.Array: ix_modulo :: Integral t => Dimensions t -> Ix t -> Ix t
+ Music.Theory.Array: ix_translate :: Num t => (t, t) -> Ix t -> Ix t
+ Music.Theory.Array: larray :: Ix k => [(k, v)] -> Array k v
+ Music.Theory.Array: larray_bounds :: Ord k => [(k, v)] -> (k, k)
+ Music.Theory.Array: make_regular :: t -> [[t]] -> [[t]]
+ Music.Theory.Array: matrix_corner_indices :: Num t => Dimensions t -> [Ix t]
+ Music.Theory.Array: matrix_indices :: (Enum t, Num t) => Dimensions t -> [Ix t]
+ Music.Theory.Array: parallelogram_corner_indices :: Num t => (Dimensions t, t) -> [Ix t]
+ Music.Theory.Array: row_indices :: (Enum t, Num t) => t -> t -> [Ix t]
+ Music.Theory.Array: type Dimensions i = (i, i)
+ Music.Theory.Array: type Ix i = (i, i)
+ Music.Theory.Array.CSV: csv_error_recover :: CSVError -> CSVRow
+ Music.Theory.Array.CSV: csv_field_str :: CSVField -> String
+ Music.Theory.Array.CSV: csv_load_irregular :: (String -> a) -> FilePath -> IO [[a]]
+ Music.Theory.Array.CSV: csv_row_recover :: Either [CSVError] CSVRow -> CSVRow
+ Music.Theory.Array.CSV: csv_table_pp :: (a -> String) -> CSV_Opt -> CSV_Table a -> String
+ Music.Theory.Array.CSV: csv_table_read_def :: (String -> a) -> FilePath -> IO (Table a)
+ Music.Theory.Array.CSV: csv_table_read_p5 :: P5_Parser t1 t2 t3 t4 t5 -> CSV_Opt -> FilePath -> IO (Maybe [String], [(t1, t2, t3, t4, t5)])
+ Music.Theory.Array.CSV: csv_table_write_def :: (a -> String) -> FilePath -> Table a -> IO ()
+ Music.Theory.Array.CSV: csv_table_write_p5 :: P5_Writer t1 t2 t3 t4 t5 -> CSV_Opt -> FilePath -> (Maybe [String], [(t1, t2, t3, t4, t5)]) -> IO ()
+ Music.Theory.Array.CSV: type P5_Parser t1 t2 t3 t4 t5 = (String -> t1, String -> t2, String -> t3, String -> t4, String -> t5)
+ Music.Theory.Array.CSV: type P5_Writer t1 t2 t3 t4 t5 = (t1 -> String, t2 -> String, t3 -> String, t4 -> String, t5 -> String)
+ Music.Theory.Array.CSV.Midi.MND: csv_midi_parse_wseq :: (Read t, Real t, Read n, Real n) => CSV_Table String -> Wseq t (Event n)
+ Music.Theory.Array.CSV.Midi.MND: csv_midi_read_wseq :: (Read t, Real t, Read n, Real n) => FilePath -> IO (Wseq t (Event n))
+ Music.Theory.Array.CSV.Midi.MND: csv_mnd_hdr :: [String]
+ Music.Theory.Array.CSV.Midi.MND: csv_mnd_parse :: (Read t, Real t, Read n, Real n) => CSV_Table String -> [MND t n]
+ Music.Theory.Array.CSV.Midi.MND: csv_mnd_read :: (Read t, Real t, Read n, Real n) => FilePath -> IO [MND t n]
+ Music.Theory.Array.CSV.Midi.MND: csv_mnd_read_tseq :: (Read t, Real t, Read n, Real n) => FilePath -> IO (Tseq t (Begin_End (Event n)))
+ Music.Theory.Array.CSV.Midi.MND: csv_mnd_write :: (Real t, Real n) => Int -> FilePath -> [MND t n] -> IO ()
+ Music.Theory.Array.CSV.Midi.MND: csv_mnd_write_tseq :: (Real t, Real n) => Int -> FilePath -> Tseq t (Begin_End (Event n)) -> IO ()
+ Music.Theory.Array.CSV.Midi.MND: csv_mndd_hdr :: [String]
+ Music.Theory.Array.CSV.Midi.MND: csv_mndd_parse :: (Read t, Real t, Read n, Real n) => CSV_Table String -> [MNDD t n]
+ Music.Theory.Array.CSV.Midi.MND: csv_mndd_read :: (Read t, Real t, Read n, Real n) => FilePath -> IO [MNDD t n]
+ Music.Theory.Array.CSV.Midi.MND: csv_mndd_read_wseq :: (Read t, Real t, Read n, Real n) => FilePath -> IO (Wseq t (Event n))
+ Music.Theory.Array.CSV.Midi.MND: csv_mndd_write :: (Real t, Real n) => Int -> FilePath -> [MNDD t n] -> IO ()
+ Music.Theory.Array.CSV.Midi.MND: csv_mndd_write_wseq :: (Real t, Real n) => Int -> FilePath -> Wseq t (Event n) -> IO ()
+ Music.Theory.Array.CSV.Midi.MND: data_value_pp :: Real t => Int -> t -> String
+ Music.Theory.Array.CSV.Midi.MND: load_csv :: FilePath -> IO (CSV_Table String)
+ Music.Theory.Array.CSV.Midi.MND: midi_tseq_to_midi_wseq :: (Num t, Eq n) => Tseq t (Begin_End (Event n)) -> Wseq t (Event n)
+ Music.Theory.Array.CSV.Midi.MND: midi_wseq_to_midi_tseq :: (Num t, Ord t) => Wseq t x -> Tseq t (Begin_End x)
+ Music.Theory.Array.CSV.Midi.MND: mnd_to_tseq :: Num n => [MND t n] -> Tseq t (Begin_End (Event n))
+ Music.Theory.Array.CSV.Midi.MND: mndd_to_wseq :: [MNDD t n] -> Wseq t (Event n)
+ Music.Theory.Array.CSV.Midi.MND: param_parse :: String -> [Param]
+ Music.Theory.Array.CSV.Midi.MND: param_pp :: Int -> [Param] -> String
+ Music.Theory.Array.CSV.Midi.MND: type Channel = Word8
+ Music.Theory.Array.CSV.Midi.MND: type Event n = (n, n, Channel, [Param])
+ Music.Theory.Array.CSV.Midi.MND: type MND t n = (t, String, n, n, Channel, [Param])
+ Music.Theory.Array.CSV.Midi.MND: type MNDD t n = (t, t, String, n, n, Channel, [Param])
+ Music.Theory.Array.CSV.Midi.MND: type Param = (String, Double)
+ Music.Theory.Array.Cell_Ref: Column_Ref :: String -> Column_Ref
+ Music.Theory.Array.Cell_Ref: [column_ref_string] :: Column_Ref -> String
+ Music.Theory.Array.Cell_Ref: cell_index :: Cell_Ref -> (Int, Int)
+ Music.Theory.Array.Cell_Ref: cell_range :: Cell_Range -> [Cell_Ref]
+ Music.Theory.Array.Cell_Ref: cell_range_row_order :: Cell_Range -> [Cell_Ref]
+ Music.Theory.Array.Cell_Ref: cell_ref_minima :: Cell_Ref
+ Music.Theory.Array.Cell_Ref: cell_ref_pp :: Cell_Ref -> String
+ Music.Theory.Array.Cell_Ref: column_in_range :: Column_Range -> Column_Ref -> Bool
+ Music.Theory.Array.Cell_Ref: column_index :: Column_Ref -> Int
+ Music.Theory.Array.Cell_Ref: column_indices :: Column_Range -> (Int, Int)
+ Music.Theory.Array.Cell_Ref: column_range :: Column_Range -> [Column_Ref]
+ Music.Theory.Array.Cell_Ref: column_range_size :: Column_Range -> Int
+ Music.Theory.Array.Cell_Ref: column_ref :: Int -> Column_Ref
+ Music.Theory.Array.Cell_Ref: column_ref_pred :: Column_Ref -> Column_Ref
+ Music.Theory.Array.Cell_Ref: column_ref_succ :: Column_Ref -> Column_Ref
+ Music.Theory.Array.Cell_Ref: data Column_Ref
+ Music.Theory.Array.Cell_Ref: index_letter :: Int -> Char
+ Music.Theory.Array.Cell_Ref: index_to_cell :: (Int, Int) -> Cell_Ref
+ Music.Theory.Array.Cell_Ref: instance Data.String.IsString Music.Theory.Array.Cell_Ref.Column_Ref
+ Music.Theory.Array.Cell_Ref: instance GHC.Arr.Ix Music.Theory.Array.Cell_Ref.Column_Ref
+ Music.Theory.Array.Cell_Ref: instance GHC.Classes.Eq Music.Theory.Array.Cell_Ref.Column_Ref
+ Music.Theory.Array.Cell_Ref: instance GHC.Classes.Ord Music.Theory.Array.Cell_Ref.Column_Ref
+ Music.Theory.Array.Cell_Ref: instance GHC.Enum.Enum Music.Theory.Array.Cell_Ref.Column_Ref
+ Music.Theory.Array.Cell_Ref: instance GHC.Read.Read Music.Theory.Array.Cell_Ref.Column_Ref
+ Music.Theory.Array.Cell_Ref: instance GHC.Show.Show Music.Theory.Array.Cell_Ref.Column_Ref
+ Music.Theory.Array.Cell_Ref: interior_column_index :: Column_Range -> Column_Ref -> Int
+ Music.Theory.Array.Cell_Ref: is_cell_ref :: String -> Bool
+ Music.Theory.Array.Cell_Ref: letter_index :: Char -> Int
+ Music.Theory.Array.Cell_Ref: parse_cell_index :: String -> (Int, Int)
+ Music.Theory.Array.Cell_Ref: parse_cell_ref :: String -> Maybe Cell_Ref
+ Music.Theory.Array.Cell_Ref: parse_cell_ref_err :: String -> Cell_Ref
+ Music.Theory.Array.Cell_Ref: row_index :: Row_Ref -> Int
+ Music.Theory.Array.Cell_Ref: row_range :: Row_Range -> [Row_Ref]
+ Music.Theory.Array.Cell_Ref: type Cell_Range = (Cell_Ref, Cell_Ref)
+ Music.Theory.Array.Cell_Ref: type Cell_Ref = (Column_Ref, Row_Ref)
+ Music.Theory.Array.Cell_Ref: type Column_Range = (Column_Ref, Column_Ref)
+ Music.Theory.Array.Cell_Ref: type Row_Range = (Row_Ref, Row_Ref)
+ Music.Theory.Array.Cell_Ref: type Row_Ref = Int
+ Music.Theory.Array.Direction: apply_vec :: Num n => LOC n -> VEC n -> LOC n
+ Music.Theory.Array.Direction: derive_vec :: Num n => LOC n -> LOC n -> VEC n
+ Music.Theory.Array.Direction: dir_seq_to_cell_seq :: (String, [String]) -> [String]
+ Music.Theory.Array.Direction: direction_char_to_vector :: Num n => DIRECTION_C -> VEC n
+ Music.Theory.Array.Direction: direction_char_to_vector_tbl :: Num n => [(DIRECTION_C, VEC n)]
+ Music.Theory.Array.Direction: direction_to_vector :: Num n => [DIRECTION_C] -> VEC n
+ Music.Theory.Array.Direction: is_direction :: String -> Bool
+ Music.Theory.Array.Direction: segment_vec :: Integral n => VEC n -> [VEC n]
+ Music.Theory.Array.Direction: type DIRECTION_C = Char
+ Music.Theory.Array.Direction: type DIRECTION_S = String
+ Music.Theory.Array.Direction: type LOC n = (n, n)
+ Music.Theory.Array.Direction: type VEC n = (n, n)
+ Music.Theory.Array.Direction: unfold_path :: Num n => LOC n -> [VEC n] -> [LOC n]
+ Music.Theory.Array.Direction: vector_add :: Num n => VEC n -> VEC n -> VEC n
+ Music.Theory.Array.Direction: vector_sub :: Num n => VEC n -> VEC n -> VEC n
+ Music.Theory.Array.Direction: vector_sum :: Num n => [VEC n] -> VEC n
+ Music.Theory.Array.Direction: vector_to_direction_char :: (Eq n, Num n) => VEC n -> DIRECTION_C
+ Music.Theory.Array.MD: md_embolden :: String -> String
+ Music.Theory.Array.MD: md_matrix_opt :: (a -> String) -> (String -> String) -> ([a], [a]) -> [[a]] -> MD_Table String
+ Music.Theory.Bits: bit_pp :: Bool -> Char
+ Music.Theory.Bits: bits_pp :: [Bool] -> String
+ Music.Theory.Bits: gen_bitseq :: FiniteBits b => Int -> b -> [Bool]
+ Music.Theory.Bits: gen_bitseq_pp :: FiniteBits b => Int -> b -> String
+ Music.Theory.Bits: pack_bitseq :: Bits i => [Bool] -> i
+ Music.Theory.Bjorklund: bjorklund' :: STEP a -> STEP a
+ Music.Theory.Bjorklund: bjorklund_r :: Int -> (Int, Int) -> [Bool]
+ Music.Theory.Bjorklund: euler_pp :: (Int, Int) -> String
+ Music.Theory.Bjorklund: euler_pp' :: (Int, Int) -> String
+ Music.Theory.Bjorklund: euler_pp_f :: (Bool -> Char) -> (Int, Int) -> String
+ Music.Theory.Bjorklund: left :: STEP a -> STEP a
+ Music.Theory.Bjorklund: right :: STEP a -> STEP a
+ Music.Theory.Bjorklund: type STEP a = ((Int, Int), ([[a]], [[a]]))
+ Music.Theory.Bjorklund: xdot' :: Bool -> Char
+ Music.Theory.Braille: black_circle :: Char
+ Music.Theory.Braille: braille_64 :: [(String, String, String)]
+ Music.Theory.Braille: braille_ascii :: BRAILLE -> Char
+ Music.Theory.Braille: braille_char :: Int -> Char
+ Music.Theory.Braille: braille_dots :: BRAILLE -> [Int]
+ Music.Theory.Braille: braille_ix :: Int -> (Char, Char)
+ Music.Theory.Braille: braille_lookup_ascii :: Char -> Maybe BRAILLE
+ Music.Theory.Braille: braille_lookup_unicode :: Char -> Maybe BRAILLE
+ Music.Theory.Braille: braille_rng :: Integral i => (i, i)
+ Music.Theory.Braille: braille_seq :: [Char]
+ Music.Theory.Braille: braille_table :: [BRAILLE]
+ Music.Theory.Braille: braille_unicode :: BRAILLE -> Char
+ Music.Theory.Braille: decode :: Char -> Maybe String
+ Music.Theory.Braille: dots_grid :: (c, c) -> [Int] -> [[c]]
+ Music.Theory.Braille: one_letter_contractions :: [(Char, String)]
+ Music.Theory.Braille: shaded_circle :: Char
+ Music.Theory.Braille: string_html_table :: String -> String
+ Music.Theory.Braille: transcribe_char_grid :: (Char, Char) -> String -> String
+ Music.Theory.Braille: transcribe_unicode :: String -> String
+ Music.Theory.Braille: type BRAILLE = (Int, Char, [Int], Char, String)
+ Music.Theory.Braille: unicode_html :: Char -> String
+ Music.Theory.Braille: white_circle :: Char
+ Music.Theory.Byte: byte_hex_pp :: (Integral i, Show i) => i -> Maybe String
+ Music.Theory.Byte: byte_hex_pp_err :: (Integral i, Show i) => i -> String
+ Music.Theory.Byte: byte_seq_hex_pp :: (Integral i, Show i) => [i] -> String
+ Music.Theory.Byte: load_byte_seq :: Integral i => FilePath -> IO [i]
+ Music.Theory.Byte: load_hex_byte_seq :: Integral i => FilePath -> IO [i]
+ Music.Theory.Byte: read_hex_byte :: (Eq t, Num t) => String -> t
+ Music.Theory.Byte: read_hex_byte_seq :: (Eq t, Num t) => String -> [t]
+ Music.Theory.Byte: store_byte_seq :: Integral i => FilePath -> [i] -> IO ()
+ Music.Theory.Byte: store_hex_byte_seq :: (Integral i, Show i) => FilePath -> [i] -> IO ()
+ Music.Theory.Clef: [clef_octave] :: Clef i -> i
+ Music.Theory.Clef: [clef_t] :: Clef i -> Clef_T
+ Music.Theory.Clef: instance GHC.Classes.Eq Music.Theory.Clef.Clef_T
+ Music.Theory.Clef: instance GHC.Classes.Eq i => GHC.Classes.Eq (Music.Theory.Clef.Clef i)
+ Music.Theory.Clef: instance GHC.Classes.Ord Music.Theory.Clef.Clef_T
+ Music.Theory.Clef: instance GHC.Classes.Ord i => GHC.Classes.Ord (Music.Theory.Clef.Clef i)
+ Music.Theory.Clef: instance GHC.Show.Show Music.Theory.Clef.Clef_T
+ Music.Theory.Clef: instance GHC.Show.Show i => GHC.Show.Show (Music.Theory.Clef.Clef i)
+ Music.Theory.Contour.Polansky_1992: [contour_description_m] :: Contour_Description -> Map (Int, Int) Ordering
+ Music.Theory.Contour.Polansky_1992: [contour_description_n] :: Contour_Description -> Int
+ Music.Theory.Contour.Polansky_1992: [contour_half_matrix_m] :: Contour_Half_Matrix -> Matrix Ordering
+ Music.Theory.Contour.Polansky_1992: [contour_half_matrix_n] :: Contour_Half_Matrix -> Int
+ Music.Theory.Contour.Polansky_1992: instance GHC.Classes.Eq Music.Theory.Contour.Polansky_1992.Contour_Description
+ Music.Theory.Contour.Polansky_1992: instance GHC.Classes.Eq Music.Theory.Contour.Polansky_1992.Contour_Half_Matrix
+ Music.Theory.Contour.Polansky_1992: instance GHC.Classes.Ord Music.Theory.Contour.Polansky_1992.Contour_Half_Matrix
+ Music.Theory.Contour.Polansky_1992: instance GHC.Show.Show Music.Theory.Contour.Polansky_1992.Contour_Description
+ Music.Theory.Contour.Polansky_1992: instance GHC.Show.Show Music.Theory.Contour.Polansky_1992.Contour_Half_Matrix
+ Music.Theory.DB.CSV: db_load_utf8 :: FilePath -> IO DB'
+ Music.Theory.DB.CSV: db_store_utf8 :: FilePath -> DB' -> IO ()
+ Music.Theory.DB.Common: db_has_duplicate_keys :: Ord k => DB k v -> Bool
+ Music.Theory.DB.Common: db_key_histogram :: Ord k => DB k v -> [(k, Int)]
+ Music.Theory.DB.Common: db_key_set :: Ord k => DB k v -> [k]
+ Music.Theory.DB.Common: db_lookup :: (Eq k, Eq v) => k -> v -> DB k v -> [Record k v]
+ Music.Theory.DB.Common: db_lookup_by :: (k -> k -> Bool) -> (v -> v -> Bool) -> k -> v -> DB k v -> [Record k v]
+ Music.Theory.DB.Common: db_to_table :: Ord k => (Maybe v -> e) -> DB k v -> ([k], [[e]])
+ Music.Theory.DB.Common: record_collate :: Eq k => Record k v -> Record k [v]
+ Music.Theory.DB.Common: record_collate' :: Eq k => (k, [v]) -> Record k v -> Record k [v]
+ Music.Theory.DB.Common: record_delete :: Eq k => k -> Record k v -> Record k v
+ Music.Theory.DB.Common: record_delete_by :: (k -> k -> Bool) -> k -> Record k v -> Record k v
+ Music.Theory.DB.Common: record_has_duplicate_keys :: Ord k => Record k v -> Bool
+ Music.Theory.DB.Common: record_has_key :: Eq k => k -> Record k v -> Bool
+ Music.Theory.DB.Common: record_has_key_uniq :: Eq k => k -> Record k v -> Bool
+ Music.Theory.DB.Common: record_key_histogram :: Ord k => Record k v -> [(k, Int)]
+ Music.Theory.DB.Common: record_key_seq :: Record k v -> [k]
+ Music.Theory.DB.Common: record_lookup :: Eq k => k -> Record k v -> [v]
+ Music.Theory.DB.Common: record_lookup_at :: Eq k => (k, Int) -> Record k v -> Maybe v
+ Music.Theory.DB.Common: record_lookup_by :: (k -> k -> Bool) -> k -> Record k v -> [v]
+ Music.Theory.DB.Common: record_lookup_uniq :: Eq k => k -> Record k v -> Maybe v
+ Music.Theory.DB.Common: record_lookup_uniq_def :: Eq k => v -> k -> Record k v -> v
+ Music.Theory.DB.Common: record_lookup_uniq_err :: Eq k => k -> Record k v -> v
+ Music.Theory.DB.Common: record_uncollate :: Record k [v] -> Record k v
+ Music.Theory.DB.Common: type DB k v = [Record k v]
+ Music.Theory.DB.Common: type DB' = DB Key Value
+ Music.Theory.DB.Common: type Entry k v = (k, v)
+ Music.Theory.DB.Common: type Entry' = Entry Key Value
+ Music.Theory.DB.Common: type Key = String
+ Music.Theory.DB.Common: type Record k v = [Entry k v]
+ Music.Theory.DB.Common: type Record' = Record Key Value
+ Music.Theory.DB.Common: type Value = String
+ Music.Theory.DB.JSON: L :: [String] -> Maybe_List_Of_String
+ Music.Theory.DB.JSON: S :: String -> Maybe_List_Of_String
+ Music.Theory.DB.JSON: data Maybe_List_Of_String
+ Music.Theory.DB.JSON: db_load_utf8 :: FilePath -> IO DB'
+ Music.Theory.DB.JSON: db_store_utf8 :: FilePath -> DB' -> IO ()
+ Music.Theory.DB.JSON: instance Data.Aeson.Types.FromJSON.FromJSON Music.Theory.DB.JSON.Maybe_List_Of_String
+ Music.Theory.DB.JSON: instance Data.Aeson.Types.ToJSON.ToJSON Music.Theory.DB.JSON.Maybe_List_Of_String
+ Music.Theory.DB.JSON: instance GHC.Classes.Eq Music.Theory.DB.JSON.Maybe_List_Of_String
+ Music.Theory.DB.JSON: instance GHC.Show.Show Music.Theory.DB.JSON.Maybe_List_Of_String
+ Music.Theory.DB.JSON: list_to_maybe_list :: [String] -> Maybe_List_Of_String
+ Music.Theory.DB.JSON: maybe_list_to_list :: Maybe_List_Of_String -> [String]
+ Music.Theory.DB.Plain: db_load_utf8 :: SEP -> FilePath -> IO [Record]
+ Music.Theory.DB.Plain: db_parse :: SEP -> String -> [Record]
+ Music.Theory.DB.Plain: db_sort :: [(Key, Int)] -> [Record] -> [Record]
+ Music.Theory.DB.Plain: db_store_utf8 :: SEP -> FilePath -> [Record] -> IO ()
+ Music.Theory.DB.Plain: record_has_key :: Key -> Record -> Bool
+ Music.Theory.DB.Plain: record_lookup :: Key -> Record -> [Value]
+ Music.Theory.DB.Plain: record_lookup_at :: (Key, Int) -> Record -> Maybe Value
+ Music.Theory.DB.Plain: record_lookup_uniq :: Key -> Record -> Maybe Value
+ Music.Theory.DB.Plain: record_parse :: (String, String) -> String -> Record
+ Music.Theory.DB.Plain: record_pp :: (String, String) -> Record -> String
+ Music.Theory.DB.Plain: sep_plain :: SEP
+ Music.Theory.DB.Plain: type DB = [Record]
+ Music.Theory.DB.Plain: type Entry = (Key, [Value])
+ Music.Theory.DB.Plain: type Key = String
+ Music.Theory.DB.Plain: type Record = [Entry]
+ Music.Theory.DB.Plain: type SEP = (String, String, String)
+ Music.Theory.DB.Plain: type Value = String
+ Music.Theory.Directory: dir_subset :: [String] -> FilePath -> IO [FilePath]
+ Music.Theory.Directory: path_scan :: [FilePath] -> FilePath -> IO (Maybe FilePath)
+ Music.Theory.Directory: path_scan_err :: [FilePath] -> FilePath -> IO FilePath
+ Music.Theory.Directory: to_absolute_cwd :: FilePath -> IO FilePath
+ Music.Theory.Duration: [division] :: Duration -> Integer
+ Music.Theory.Duration: [dots] :: Duration -> Integer
+ Music.Theory.Duration: [multiplier] :: Duration -> Rational
+ Music.Theory.Duration: beam_count_tbl :: [(Integer, Integer)]
+ Music.Theory.Duration: division_musicxml_tbl :: [(Integer, String)]
+ Music.Theory.Duration: division_unicode_tbl :: [(Integer, Char)]
+ Music.Theory.Duration: divisions_set :: [Integer]
+ Music.Theory.Duration: duration_letter_pp :: Duration -> Maybe String
+ Music.Theory.Duration: duration_m1 :: Duration -> Bool
+ Music.Theory.Duration: duration_set :: Integer -> [Duration]
+ Music.Theory.Duration: duration_to_unicode :: Duration -> String
+ Music.Theory.Duration: instance GHC.Classes.Eq Music.Theory.Duration.Duration
+ Music.Theory.Duration: instance GHC.Classes.Ord Music.Theory.Duration.Duration
+ Music.Theory.Duration: instance GHC.Show.Show Music.Theory.Duration.Duration
+ Music.Theory.Duration: sum_dur_err :: Duration -> Duration -> Duration
+ Music.Theory.Duration: whole_note_division_letter_pp :: Integer -> Maybe Char
+ Music.Theory.Duration: whole_note_division_to_unicode_symbol :: Integer -> Char
+ Music.Theory.Duration.Annotation: instance GHC.Classes.Eq Music.Theory.Duration.Annotation.D_Annotation
+ Music.Theory.Duration.Annotation: instance GHC.Show.Show Music.Theory.Duration.Annotation.D_Annotation
+ Music.Theory.Duration.CT: [ct_count] :: CT -> (RQ, Int)
+ Music.Theory.Duration.CT: [ct_len] :: CT -> Int
+ Music.Theory.Duration.CT: [ct_mark] :: CT -> [(Measure, Char)]
+ Music.Theory.Duration.CT: [ct_tempo] :: CT -> Lseq (Measure, Pulse) RQ
+ Music.Theory.Duration.CT: [ct_ts] :: CT -> [(Measure, Rational_Time_Signature)]
+ Music.Theory.Duration.CT: instance GHC.Classes.Eq Music.Theory.Duration.CT.CT_Node
+ Music.Theory.Duration.CT: instance GHC.Show.Show Music.Theory.Duration.CT.CT
+ Music.Theory.Duration.CT: instance GHC.Show.Show Music.Theory.Duration.CT.CT_Node
+ Music.Theory.Duration.RQ: rq_duration_tbl :: Integer -> [(Rational, Duration)]
+ Music.Theory.Duration.Sequence.Notate: m_simplify_fix :: Int -> Simplify_P -> Time_Signature -> [Duration_A] -> [Duration_A]
+ Music.Theory.Dynamic_Mark: instance GHC.Classes.Eq Music.Theory.Dynamic_Mark.Dynamic_Mark_T
+ Music.Theory.Dynamic_Mark: instance GHC.Classes.Eq Music.Theory.Dynamic_Mark.Hairpin_T
+ Music.Theory.Dynamic_Mark: instance GHC.Classes.Ord Music.Theory.Dynamic_Mark.Dynamic_Mark_T
+ Music.Theory.Dynamic_Mark: instance GHC.Classes.Ord Music.Theory.Dynamic_Mark.Hairpin_T
+ Music.Theory.Dynamic_Mark: instance GHC.Enum.Bounded Music.Theory.Dynamic_Mark.Dynamic_Mark_T
+ Music.Theory.Dynamic_Mark: instance GHC.Enum.Bounded Music.Theory.Dynamic_Mark.Hairpin_T
+ Music.Theory.Dynamic_Mark: instance GHC.Enum.Enum Music.Theory.Dynamic_Mark.Dynamic_Mark_T
+ Music.Theory.Dynamic_Mark: instance GHC.Enum.Enum Music.Theory.Dynamic_Mark.Hairpin_T
+ Music.Theory.Dynamic_Mark: instance GHC.Show.Show Music.Theory.Dynamic_Mark.Dynamic_Mark_T
+ Music.Theory.Dynamic_Mark: instance GHC.Show.Show Music.Theory.Dynamic_Mark.Hairpin_T
+ Music.Theory.Enum: enum_from_to_cyclic :: (Bounded a, Enum a) => a -> a -> [a]
+ Music.Theory.Enum: enum_from_to_reverse :: Enum a => a -> a -> [a]
+ Music.Theory.Enum: enum_univ :: (Bounded t, Enum t) => [t]
+ Music.Theory.Enum: genericFromEnum :: (Integral i, Enum e) => e -> i
+ Music.Theory.Enum: genericToEnum :: (Integral i, Enum e) => i -> e
+ Music.Theory.Function: const2 :: a -> b -> c -> a
+ Music.Theory.Function: infixr 8 .:::::
+ Music.Theory.Gamelan: Bonang :: Instrument_Family
+ Music.Theory.Gamelan: Bonang_Barung :: Instrument_Name
+ Music.Theory.Gamelan: Bonang_Panerus :: Instrument_Name
+ Music.Theory.Gamelan: Gender :: Instrument_Family
+ Music.Theory.Gamelan: Gender_Barung :: Instrument_Name
+ Music.Theory.Gamelan: Gender_Panembung :: Instrument_Name
+ Music.Theory.Gamelan: Gender_Panerus :: Instrument_Name
+ Music.Theory.Gamelan: Gong :: Instrument_Family
+ Music.Theory.Gamelan: Gong_Ageng :: Instrument_Name
+ Music.Theory.Gamelan: Gong_Suwukan :: Instrument_Name
+ Music.Theory.Gamelan: Instrument :: Instrument_Name -> Maybe Scale -> Maybe [Pitch] -> Maybe [Frequency] -> Instrument
+ Music.Theory.Gamelan: Kempul :: Instrument_Name
+ Music.Theory.Gamelan: Kempyang :: Instrument_Name
+ Music.Theory.Gamelan: Kenong :: Instrument_Name
+ Music.Theory.Gamelan: Ketuk :: Instrument_Name
+ Music.Theory.Gamelan: Note :: Scale -> Pitch -> Note
+ Music.Theory.Gamelan: Pelog :: Scale
+ Music.Theory.Gamelan: Pitch :: Octave -> Degree -> Pitch
+ Music.Theory.Gamelan: Saron :: Instrument_Family
+ Music.Theory.Gamelan: Saron_Barung :: Instrument_Name
+ Music.Theory.Gamelan: Saron_Demung :: Instrument_Name
+ Music.Theory.Gamelan: Saron_Panerus :: Instrument_Name
+ Music.Theory.Gamelan: Slendro :: Scale
+ Music.Theory.Gamelan: Tone :: Instrument_Name -> Maybe Note -> Maybe Frequency -> Maybe Annotation -> Tone
+ Music.Theory.Gamelan: [instrument_frequencies] :: Instrument -> Maybe [Frequency]
+ Music.Theory.Gamelan: [instrument_name] :: Instrument -> Instrument_Name
+ Music.Theory.Gamelan: [instrument_pitches] :: Instrument -> Maybe [Pitch]
+ Music.Theory.Gamelan: [instrument_scale] :: Instrument -> Maybe Scale
+ Music.Theory.Gamelan: [note_pitch] :: Note -> Pitch
+ Music.Theory.Gamelan: [note_scale] :: Note -> Scale
+ Music.Theory.Gamelan: [pitch_degree] :: Pitch -> Degree
+ Music.Theory.Gamelan: [pitch_octave] :: Pitch -> Octave
+ Music.Theory.Gamelan: [tone_annotation] :: Tone -> Maybe Annotation
+ Music.Theory.Gamelan: [tone_frequency] :: Tone -> Maybe Frequency
+ Music.Theory.Gamelan: [tone_instrument_name] :: Tone -> Instrument_Name
+ Music.Theory.Gamelan: [tone_note] :: Tone -> Maybe Note
+ Music.Theory.Gamelan: data Instrument
+ Music.Theory.Gamelan: data Instrument_Family
+ Music.Theory.Gamelan: data Instrument_Name
+ Music.Theory.Gamelan: data Note
+ Music.Theory.Gamelan: data Pitch
+ Music.Theory.Gamelan: data Scale
+ Music.Theory.Gamelan: data Tone
+ Music.Theory.Gamelan: degree_index :: Scale -> Degree -> Maybe Int
+ Music.Theory.Gamelan: fromJust_err :: String -> Maybe a -> a
+ Music.Theory.Gamelan: instance GHC.Classes.Eq Music.Theory.Gamelan.Instrument
+ Music.Theory.Gamelan: instance GHC.Classes.Eq Music.Theory.Gamelan.Instrument_Family
+ Music.Theory.Gamelan: instance GHC.Classes.Eq Music.Theory.Gamelan.Instrument_Name
+ Music.Theory.Gamelan: instance GHC.Classes.Eq Music.Theory.Gamelan.Note
+ Music.Theory.Gamelan: instance GHC.Classes.Eq Music.Theory.Gamelan.Pitch
+ Music.Theory.Gamelan: instance GHC.Classes.Eq Music.Theory.Gamelan.Scale
+ Music.Theory.Gamelan: instance GHC.Classes.Eq Music.Theory.Gamelan.Tone
+ Music.Theory.Gamelan: instance GHC.Classes.Ord Music.Theory.Gamelan.Instrument_Family
+ Music.Theory.Gamelan: instance GHC.Classes.Ord Music.Theory.Gamelan.Instrument_Name
+ Music.Theory.Gamelan: instance GHC.Classes.Ord Music.Theory.Gamelan.Note
+ Music.Theory.Gamelan: instance GHC.Classes.Ord Music.Theory.Gamelan.Pitch
+ Music.Theory.Gamelan: instance GHC.Classes.Ord Music.Theory.Gamelan.Scale
+ Music.Theory.Gamelan: instance GHC.Classes.Ord Music.Theory.Gamelan.Tone
+ Music.Theory.Gamelan: instance GHC.Enum.Bounded Music.Theory.Gamelan.Instrument_Family
+ Music.Theory.Gamelan: instance GHC.Enum.Bounded Music.Theory.Gamelan.Instrument_Name
+ Music.Theory.Gamelan: instance GHC.Enum.Enum Music.Theory.Gamelan.Instrument_Family
+ Music.Theory.Gamelan: instance GHC.Enum.Enum Music.Theory.Gamelan.Instrument_Name
+ Music.Theory.Gamelan: instance GHC.Enum.Enum Music.Theory.Gamelan.Scale
+ Music.Theory.Gamelan: instance GHC.Read.Read Music.Theory.Gamelan.Instrument_Family
+ Music.Theory.Gamelan: instance GHC.Read.Read Music.Theory.Gamelan.Instrument_Name
+ Music.Theory.Gamelan: instance GHC.Read.Read Music.Theory.Gamelan.Scale
+ Music.Theory.Gamelan: instance GHC.Show.Show Music.Theory.Gamelan.Instrument
+ Music.Theory.Gamelan: instance GHC.Show.Show Music.Theory.Gamelan.Instrument_Family
+ Music.Theory.Gamelan: instance GHC.Show.Show Music.Theory.Gamelan.Instrument_Name
+ Music.Theory.Gamelan: instance GHC.Show.Show Music.Theory.Gamelan.Note
+ Music.Theory.Gamelan: instance GHC.Show.Show Music.Theory.Gamelan.Pitch
+ Music.Theory.Gamelan: instance GHC.Show.Show Music.Theory.Gamelan.Scale
+ Music.Theory.Gamelan: instance GHC.Show.Show Music.Theory.Gamelan.Tone
+ Music.Theory.Gamelan: instrument :: Tone_Set -> Instrument
+ Music.Theory.Gamelan: instrument_class :: Instrument -> (Instrument_Name, Maybe Scale)
+ Music.Theory.Gamelan: instrument_family :: Instrument_Name -> Maybe Instrument_Family
+ Music.Theory.Gamelan: instrument_family_set :: [Instrument_Family]
+ Music.Theory.Gamelan: instrument_gamut :: Instrument -> Maybe (Pitch, Pitch)
+ Music.Theory.Gamelan: instrument_name_clef :: Integral i => Instrument_Name -> Clef i
+ Music.Theory.Gamelan: instrument_name_clef_plain :: Integral i => Instrument_Name -> Clef i
+ Music.Theory.Gamelan: instrument_name_pp :: Instrument_Name -> String
+ Music.Theory.Gamelan: instruments :: Tone_Set -> [Instrument]
+ Music.Theory.Gamelan: map_maybe_uniform :: (a -> Maybe b) -> [a] -> Maybe [b]
+ Music.Theory.Gamelan: near_rat :: Double -> Rational
+ Music.Theory.Gamelan: note_degree :: Note -> Degree
+ Music.Theory.Gamelan: pitch_pp_ascii :: Pitch -> String
+ Music.Theory.Gamelan: pitch_pp_duple :: Pitch -> String
+ Music.Theory.Gamelan: plain_tone :: Instrument_Name -> Scale -> Octave -> Degree -> Tone
+ Music.Theory.Gamelan: scale_degrees :: Scale -> [Degree]
+ Music.Theory.Gamelan: select_tones :: Instrument_Family -> [Tone] -> [Maybe Tone]
+ Music.Theory.Gamelan: tone_12et_fmidi :: Tone -> Rational
+ Music.Theory.Gamelan: tone_12et_pitch :: Tone -> Maybe Pitch
+ Music.Theory.Gamelan: tone_12et_pitch' :: Tone -> Pitch
+ Music.Theory.Gamelan: tone_12et_pitch_detune :: Tone -> Maybe Pitch_Detune
+ Music.Theory.Gamelan: tone_12et_pitch_detune' :: Tone -> Pitch_Detune
+ Music.Theory.Gamelan: tone_24et_fmidi :: Tone -> Rational
+ Music.Theory.Gamelan: tone_24et_pitch :: Tone -> Maybe Pitch
+ Music.Theory.Gamelan: tone_24et_pitch' :: Tone -> Pitch
+ Music.Theory.Gamelan: tone_24et_pitch_detune :: Tone -> Maybe Pitch_Detune
+ Music.Theory.Gamelan: tone_24et_pitch_detune' :: Tone -> Pitch_Detune
+ Music.Theory.Gamelan: tone_class :: Tone -> (Instrument_Name, Maybe Scale)
+ Music.Theory.Gamelan: tone_class_p :: (Instrument_Name, Scale) -> Tone -> Bool
+ Music.Theory.Gamelan: tone_compare_frequency :: Tone -> Tone -> Ordering
+ Music.Theory.Gamelan: tone_degree :: Tone -> Maybe Degree
+ Music.Theory.Gamelan: tone_degree' :: Tone -> Degree
+ Music.Theory.Gamelan: tone_equivalent :: Tone -> Tone -> Bool
+ Music.Theory.Gamelan: tone_family :: Tone -> Maybe Instrument_Family
+ Music.Theory.Gamelan: tone_family_class_p :: (Instrument_Family, Scale) -> Tone -> Bool
+ Music.Theory.Gamelan: tone_family_err :: Tone -> Instrument_Family
+ Music.Theory.Gamelan: tone_fmidi :: Tone -> Double
+ Music.Theory.Gamelan: tone_frequency_err :: Tone -> Frequency
+ Music.Theory.Gamelan: tone_in_family :: Instrument_Family -> Tone -> Bool
+ Music.Theory.Gamelan: tone_octave :: Tone -> Maybe Octave
+ Music.Theory.Gamelan: tone_pitch :: Tone -> Maybe Pitch
+ Music.Theory.Gamelan: tone_scale :: Tone -> Maybe Scale
+ Music.Theory.Gamelan: tone_set_gamut :: Tone_Set -> Maybe (Pitch, Pitch)
+ Music.Theory.Gamelan: tone_set_instrument :: Tone_Set -> (Instrument_Name, Maybe Scale) -> Tone_Set
+ Music.Theory.Gamelan: tone_set_near_frequency :: Tone_Set -> Cents -> Frequency -> Tone_Set
+ Music.Theory.Gamelan: tone_subset :: Tone_Subset -> Tone_Set -> Tone_Set
+ Music.Theory.Gamelan: type Annotation = String
+ Music.Theory.Gamelan: type Degree = Integer
+ Music.Theory.Gamelan: type Frequency = Double
+ Music.Theory.Gamelan: type Gamelan = [Instrument]
+ Music.Theory.Gamelan: type Octave = Integer
+ Music.Theory.Gamelan: type Tone_Group = [Tone_Set]
+ Music.Theory.Gamelan: type Tone_Set = [Tone]
+ Music.Theory.Gamelan: type Tone_Subset = ([Instrument_Family], [Scale])
+ Music.Theory.Graph.Deacon_1934: g1 :: G
+ Music.Theory.Graph.Deacon_1934: g10 :: G
+ Music.Theory.Graph.Deacon_1934: g11 :: G
+ Music.Theory.Graph.Deacon_1934: g12 :: G
+ Music.Theory.Graph.Deacon_1934: g13 :: G
+ Music.Theory.Graph.Deacon_1934: g2 :: G
+ Music.Theory.Graph.Deacon_1934: g4 :: G
+ Music.Theory.Graph.Deacon_1934: g6 :: G
+ Music.Theory.Graph.Deacon_1934: g8 :: G
+ Music.Theory.Graph.Deacon_1934: g9 :: G
+ Music.Theory.Graph.Deacon_1934: g_all :: [G]
+ Music.Theory.Graph.Deacon_1934: gen_digraph :: Ord v => [DOT_ATTR] -> GR_PP v e -> [EDGE_L v e] -> [String]
+ Music.Theory.Graph.Deacon_1934: gen_graph :: Ord v => [DOT_ATTR] -> GR_PP v e -> [EDGE_L v e] -> [String]
+ Music.Theory.Graph.Deacon_1934: gen_graph_ul :: Ord v => [DOT_ATTR] -> (v -> String) -> [EDGE v] -> [String]
+ Music.Theory.Graph.Deacon_1934: type G = (GRAPH String, [DOT_ATTR], FilePath)
+ Music.Theory.Graph.Deacon_1934: wr :: G -> IO ()
+ Music.Theory.Graph.Deacon_1934: wr_all :: IO ()
+ Music.Theory.Graph.Dot: G_DIGRAPH :: G_TYPE
+ Music.Theory.Graph.Dot: G_UGRAPH :: G_TYPE
+ Music.Theory.Graph.Dot: assoc_union :: Eq k => [(k, v)] -> [(k, v)] -> [(k, v)]
+ Music.Theory.Graph.Dot: br_csl_pp :: Show t => [t] -> String
+ Music.Theory.Graph.Dot: data G_TYPE
+ Music.Theory.Graph.Dot: dot_attr_collate :: [DOT_ATTR] -> [DOT_ATTR_SET]
+ Music.Theory.Graph.Dot: dot_attr_def :: [DOT_ATTR]
+ Music.Theory.Graph.Dot: dot_attr_ext :: [DOT_ATTR] -> [DOT_ATTR] -> [DOT_ATTR]
+ Music.Theory.Graph.Dot: dot_attr_pp :: DOT_ATTR -> String
+ Music.Theory.Graph.Dot: dot_attr_set_pp :: DOT_ATTR_SET -> String
+ Music.Theory.Graph.Dot: dot_key_sep :: String -> (String, String)
+ Music.Theory.Graph.Dot: g_to_dot :: G_TYPE -> [DOT_ATTR] -> GR_PP v e -> Maybe (POS_FN v) -> Gr v e -> [String]
+ Music.Theory.Graph.Dot: g_to_udot :: [DOT_ATTR] -> GR_PP v e -> Gr v e -> [String]
+ Music.Theory.Graph.Dot: g_type_to_edge_symbol :: G_TYPE -> String
+ Music.Theory.Graph.Dot: g_type_to_string :: G_TYPE -> String
+ Music.Theory.Graph.Dot: gr_pp_id_br_csl :: Show e => GR_PP String [e]
+ Music.Theory.Graph.Dot: gr_pp_id_show :: Show e => GR_PP String e
+ Music.Theory.Graph.Dot: gr_pp_lift_node_f :: (v -> String) -> GR_PP v e
+ Music.Theory.Graph.Dot: maybe_quote :: String -> String
+ Music.Theory.Graph.Dot: sep1 :: Eq t => t -> [t] -> ([t], [t])
+ Music.Theory.Graph.Dot: type DOT_ATTR = (DOT_OPT, DOT_VALUE)
+ Music.Theory.Graph.Dot: type DOT_ATTR_SET = (String, [DOT_ATTR])
+ Music.Theory.Graph.Dot: type DOT_KEY = String
+ Music.Theory.Graph.Dot: type DOT_OPT = String
+ Music.Theory.Graph.Dot: type DOT_VALUE = String
+ Music.Theory.Graph.Dot: type GR_PP v e = (v -> Maybe String, v -> Maybe String, e -> Maybe String)
+ Music.Theory.Graph.Dot: type POS_FN v = v -> (Int, Int)
+ Music.Theory.Graph.FGL: e_collate_l :: Ord v => [EDGE_L v l] -> [EDGE_L v [l]]
+ Music.Theory.Graph.FGL: e_collate_normalised_l :: Ord v => [EDGE_L v l] -> [EDGE_L v [l]]
+ Music.Theory.Graph.FGL: e_is_path :: Eq t => GRAPH t -> [t] -> Bool
+ Music.Theory.Graph.FGL: e_label_seq :: [EDGE v] -> [EDGE_L v Int]
+ Music.Theory.Graph.FGL: e_normalise_l :: Ord v => EDGE_L v l -> EDGE_L v l
+ Music.Theory.Graph.FGL: e_path_to_edges :: [t] -> [EDGE t]
+ Music.Theory.Graph.FGL: e_undirected_eq :: Eq t => EDGE t -> EDGE t -> Bool
+ Music.Theory.Graph.FGL: e_univ_select_edges :: (t -> t -> Bool) -> [t] -> [EDGE t]
+ Music.Theory.Graph.FGL: e_univ_select_u_edges :: Ord t => (t -> t -> Bool) -> [t] -> [EDGE t]
+ Music.Theory.Graph.FGL: elem_by :: (p -> q -> Bool) -> p -> [q] -> Bool
+ Music.Theory.Graph.FGL: g_degree :: Gr v e -> Int
+ Music.Theory.Graph.FGL: g_from_edges :: Ord v => GRAPH v -> Gr v ()
+ Music.Theory.Graph.FGL: g_from_edges_l :: (Eq v, Ord v) => GRAPH_L v e -> Gr v e
+ Music.Theory.Graph.FGL: g_hamiltonian_path_ml :: MonadLogic m => G_NODE_SEL_F v e -> Gr v e -> Node -> m [Node]
+ Music.Theory.Graph.FGL: g_node_lookup :: (Eq v, Graph gr) => gr v e -> v -> Maybe Node
+ Music.Theory.Graph.FGL: g_node_lookup_err :: (Eq v, Graph gr) => gr v e -> v -> Node
+ Music.Theory.Graph.FGL: g_partition :: Gr v e -> [Gr v e]
+ Music.Theory.Graph.FGL: ml_from_list :: MonadLogic m => [t] -> m t
+ Music.Theory.Graph.FGL: type EDGE v = (v, v)
+ Music.Theory.Graph.FGL: type EDGE_L v l = (EDGE v, l)
+ Music.Theory.Graph.FGL: type GRAPH v = [EDGE v]
+ Music.Theory.Graph.FGL: type GRAPH_L v l = [EDGE_L v l]
+ Music.Theory.Graph.FGL: type G_NODE_SEL_F v e = Gr v e -> Node -> [Node]
+ Music.Theory.Graph.FGL: ug_hamiltonian_path_ml_0 :: MonadLogic m => Gr v e -> m [Node]
+ Music.Theory.Graph.FGL: ug_node_set_impl :: (Eq v, DynGraph gr) => gr v e -> [v] -> [Node]
+ Music.Theory.Graph.Johnson_2014: absdif :: Num a => (a, a) -> a
+ Music.Theory.Graph.Johnson_2014: combinations2 :: Ord t => [t] -> [(t, t)]
+ Music.Theory.Graph.Johnson_2014: dif :: Num a => (a, a) -> a
+ Music.Theory.Graph.Johnson_2014: doi :: Eq t => [t] -> [t] -> Int
+ Music.Theory.Graph.Johnson_2014: doi_of :: Eq t => Int -> [t] -> [t] -> Bool
+ Music.Theory.Graph.Johnson_2014: gen_flt_graph :: (Ord t, Show t) => [DOT_ATTR] -> ([t] -> [t] -> Bool) -> [[t]] -> [String]
+ Music.Theory.Graph.Johnson_2014: gen_graph_ul :: Ord v => [DOT_ATTR] -> (v -> String) -> [EDGE v] -> [String]
+ Music.Theory.Graph.Johnson_2014: gen_graph_ul_ty :: Ord v => String -> (v -> String) -> [EDGE v] -> [String]
+ Music.Theory.Graph.Johnson_2014: i_to_ic :: (Num a, Ord a) => a -> a
+ Music.Theory.Graph.Johnson_2014: loc_dif :: Num t => [t] -> [t] -> t
+ Music.Theory.Graph.Johnson_2014: loc_dif_in :: (Eq t, Num t) => [t] -> [t] -> [t] -> Bool
+ Music.Theory.Graph.Johnson_2014: loc_dif_n :: (Eq t, Num i) => [t] -> [t] -> i
+ Music.Theory.Graph.Johnson_2014: loc_dif_n_of :: Eq t => Int -> [t] -> [t] -> Bool
+ Music.Theory.Graph.Johnson_2014: loc_dif_of :: (Eq t, Num t) => t -> [t] -> [t] -> Bool
+ Music.Theory.Graph.Johnson_2014: m_doi_of :: Map Int [Z12] -> Int -> Int -> Int -> Bool
+ Music.Theory.Graph.Johnson_2014: m_get :: Ord k => Map k v -> k -> v
+ Music.Theory.Graph.Johnson_2014: min_vl :: (Num a, Ord a) => [a] -> [a] -> a
+ Music.Theory.Graph.Johnson_2014: min_vl_in :: (Num a, Ord a) => [a] -> [a] -> [a] -> Bool
+ Music.Theory.Graph.Johnson_2014: min_vl_of :: (Num a, Ord a) => a -> [a] -> [a] -> Bool
+ Music.Theory.Graph.Johnson_2014: mod12 :: Integral a => a -> a
+ Music.Theory.Graph.Johnson_2014: p114_f_3_7 :: [Z12]
+ Music.Theory.Graph.Johnson_2014: p114_gr_set :: [(String, [String])]
+ Music.Theory.Graph.Johnson_2014: p114_mk_gr :: Double -> ([Z12] -> [Z12] -> Bool) -> [String]
+ Music.Theory.Graph.Johnson_2014: p125_gr :: [String]
+ Music.Theory.Graph.Johnson_2014: p12_euler_plane :: Euler_Plane Rational
+ Music.Theory.Graph.Johnson_2014: p12_euler_plane_gr :: [String]
+ Music.Theory.Graph.Johnson_2014: p131_gr :: [String]
+ Music.Theory.Graph.Johnson_2014: p148_gr_set :: [(String, [String])]
+ Music.Theory.Graph.Johnson_2014: p148_mk_gr :: ([Int] -> [Int] -> Bool) -> [String]
+ Music.Theory.Graph.Johnson_2014: p14_edges :: [(Key, Key)]
+ Music.Theory.Graph.Johnson_2014: p14_gr :: [String]
+ Music.Theory.Graph.Johnson_2014: p162_gr :: [String]
+ Music.Theory.Graph.Johnson_2014: p172_gr_set :: [(String, [String])]
+ Music.Theory.Graph.Johnson_2014: p172_nd_map :: Map Int [Z12]
+ Music.Theory.Graph.Johnson_2014: p172_set_pp :: Int -> String
+ Music.Theory.Graph.Johnson_2014: p177_gr_set :: [(String, [String])]
+ Music.Theory.Graph.Johnson_2014: p2_and :: (t -> u -> Bool) -> (t -> u -> Bool) -> t -> u -> Bool
+ Music.Theory.Graph.Johnson_2014: p31_e_set :: [([Z12], [Z12])]
+ Music.Theory.Graph.Johnson_2014: p31_f_4_22 :: [Z12]
+ Music.Theory.Graph.Johnson_2014: p31_gr :: [String]
+ Music.Theory.Graph.Johnson_2014: partition_ic :: (Num t, Ord t, Show t) => t -> [t] -> ([t], [t])
+ Music.Theory.Graph.Johnson_2014: set_pp :: Show t => [t] -> String
+ Music.Theory.Graph.Johnson_2014: type Z12 = Int
+ Music.Theory.Graph.Johnson_2014: wr_graphs :: IO ()
+ Music.Theory.IO: read_file_iso_8859_1 :: FilePath -> IO String
+ Music.Theory.IO: read_file_locale :: FilePath -> IO String
+ Music.Theory.IO: read_file_utf8 :: FilePath -> IO String
+ Music.Theory.IO: read_file_utf8_or :: String -> FilePath -> IO String
+ Music.Theory.IO: read_file_utf8_text :: FilePath -> IO Text
+ Music.Theory.IO: write_file_utf8 :: FilePath -> String -> IO ()
+ Music.Theory.Instrument.Choir: instance GHC.Classes.Eq Music.Theory.Instrument.Choir.Voice
+ Music.Theory.Instrument.Choir: instance GHC.Classes.Ord Music.Theory.Instrument.Choir.Voice
+ Music.Theory.Instrument.Choir: instance GHC.Enum.Bounded Music.Theory.Instrument.Choir.Voice
+ Music.Theory.Instrument.Choir: instance GHC.Enum.Enum Music.Theory.Instrument.Choir.Voice
+ Music.Theory.Instrument.Choir: instance GHC.Show.Show Music.Theory.Instrument.Choir.Voice
+ Music.Theory.Instrument.Names: instrument_db :: [(String, [String], [String], [String])]
+ Music.Theory.Instrument.Names: instrument_db' :: [(String, String, String, String)]
+ Music.Theory.Interval: [interval_direction] :: Interval -> Ordering
+ Music.Theory.Interval: [interval_octave] :: Interval -> Octave
+ Music.Theory.Interval: [interval_quality] :: Interval -> Interval_Q
+ Music.Theory.Interval: [interval_type] :: Interval -> Interval_T
+ Music.Theory.Interval: instance GHC.Classes.Eq Music.Theory.Interval.Interval
+ Music.Theory.Interval: instance GHC.Classes.Eq Music.Theory.Interval.Interval_Q
+ Music.Theory.Interval: instance GHC.Classes.Eq Music.Theory.Interval.Interval_T
+ Music.Theory.Interval: instance GHC.Classes.Ord Music.Theory.Interval.Interval_Q
+ Music.Theory.Interval: instance GHC.Classes.Ord Music.Theory.Interval.Interval_T
+ Music.Theory.Interval: instance GHC.Enum.Bounded Music.Theory.Interval.Interval_Q
+ Music.Theory.Interval: instance GHC.Enum.Bounded Music.Theory.Interval.Interval_T
+ Music.Theory.Interval: instance GHC.Enum.Enum Music.Theory.Interval.Interval_Q
+ Music.Theory.Interval: instance GHC.Enum.Enum Music.Theory.Interval.Interval_T
+ Music.Theory.Interval: instance GHC.Show.Show Music.Theory.Interval.Interval
+ Music.Theory.Interval: instance GHC.Show.Show Music.Theory.Interval.Interval_Q
+ Music.Theory.Interval: instance GHC.Show.Show Music.Theory.Interval.Interval_T
+ Music.Theory.Interval: parse_interval_err :: String -> Interval
+ Music.Theory.Key: fifths_to_key :: Mode_T -> Int -> Maybe Key
+ Music.Theory.Key: implied_fifths :: Integral i => Mode_T -> [i] -> Maybe Int
+ Music.Theory.Key: implied_fifths_err :: Integral i => Mode_T -> [i] -> Int
+ Music.Theory.Key: implied_key :: Integral i => Mode_T -> [i] -> Maybe Key
+ Music.Theory.Key: implied_key_err :: Integral i => Mode_T -> [i] -> Key
+ Music.Theory.Key: instance GHC.Classes.Eq Music.Theory.Key.Mode_T
+ Music.Theory.Key: instance GHC.Classes.Ord Music.Theory.Key.Mode_T
+ Music.Theory.Key: instance GHC.Show.Show Music.Theory.Key.Mode_T
+ Music.Theory.Key: key_fifths_tbl :: [(Key, Int)]
+ Music.Theory.Key: key_identifier_pp :: (Show a, Show a1) => (a, a1, Mode_T) -> [Char]
+ Music.Theory.Key: key_lc_iso_pp :: Key -> String
+ Music.Theory.Key: key_lc_pp :: (Alteration_T -> String) -> Key -> String
+ Music.Theory.Key: key_lc_tonh_pp :: Key -> String
+ Music.Theory.Key: key_lc_uc_parse :: String -> Maybe Key
+ Music.Theory.Key: key_lc_uc_pp :: Key -> String
+ Music.Theory.Key: key_mediant :: Key -> Maybe Key
+ Music.Theory.Key: key_mode :: Key -> Mode_T
+ Music.Theory.Key: key_parallel :: Key -> Key
+ Music.Theory.Key: key_pc_set :: Integral i => Key -> [i]
+ Music.Theory.Key: key_relative :: Key -> Key
+ Music.Theory.Key: key_sequence_30 :: [Key]
+ Music.Theory.Key: key_sequence_42 :: [Key]
+ Music.Theory.Key: key_transpose :: Key -> Int -> Key
+ Music.Theory.Key: mode_identifier_pp :: Mode_T -> String
+ Music.Theory.Key: mode_parallel :: Mode_T -> Mode_T
+ Music.Theory.Key: mode_pc_seq :: Num t => Mode_T -> [t]
+ Music.Theory.Key: mode_pp :: Mode_T -> String
+ Music.Theory.Key: note_char_to_key :: Char -> Maybe Key
+ Music.Theory.List: adj :: Int -> Int -> [a] -> [[a]]
+ Music.Theory.List: adj' :: Int -> Int -> [a] -> [[a]]
+ Music.Theory.List: adopt_shape :: Traversable t => (a -> b -> c) -> [b] -> t a -> t c
+ Music.Theory.List: adopt_shape_m :: Traversable t => (a -> b -> c) -> [b] -> t (Maybe a) -> t (Maybe c)
+ Music.Theory.List: all_embeddings :: Eq t => [t] -> [t] -> [[Int]]
+ Music.Theory.List: all_embeddings_m :: (Eq t, MonadLogic m) => [t] -> [t] -> m [Int]
+ Music.Theory.List: all_equal :: Eq a => [a] -> Bool
+ Music.Theory.List: at_cyclic :: [a] -> Int -> a
+ Music.Theory.List: collate_adjacent :: Ord a => [(a, b)] -> [(a, [b])]
+ Music.Theory.List: collate_on_adjacent :: (Eq k, Ord k) => (a -> k) -> (a -> v) -> [a] -> [(k, [v])]
+ Music.Theory.List: compare_adjacent :: Ord a => [a] -> [Ordering]
+ Music.Theory.List: compare_adjacent_by :: (a -> a -> Ordering) -> [a] -> [Ordering]
+ Music.Theory.List: d_dx_by :: (t -> t -> u) -> [t] -> [u]
+ Music.Theory.List: decide_nearest :: (Num o, Ord o) => o -> (o, o) -> o
+ Music.Theory.List: decide_nearest' :: Ord o => (p -> o) -> (p, p) -> p
+ Music.Theory.List: deinterleave :: Int -> [a] -> [[a]]
+ Music.Theory.List: deinterleave2 :: [t] -> ([t], [t])
+ Music.Theory.List: drop_last :: [t] -> [t]
+ Music.Theory.List: duplicates :: Ord a => [a] -> [a]
+ Music.Theory.List: duplicates_by :: Ord a => (a -> a -> Bool) -> [a] -> [a]
+ Music.Theory.List: elemIndex_ordered :: Ord t => t -> [t] -> Maybe Int
+ Music.Theory.List: elem_ordered :: Ord t => t -> [t] -> Bool
+ Music.Theory.List: embedding :: Eq t => ([t], [t]) -> Either [Int] [Int]
+ Music.Theory.List: embedding_err :: Eq t => ([t], [t]) -> [Int]
+ Music.Theory.List: fill_gaps_ascending :: (Enum n, Ord n) => t -> (n, n) -> [(n, t)] -> [(n, t)]
+ Music.Theory.List: fill_gaps_ascending' :: (Num n, Enum n, Ord n) => t -> (n, n) -> [(n, t)] -> [(n, t)]
+ Music.Theory.List: filter_halt :: (a -> Bool) -> (a -> Bool) -> [a] -> [a]
+ Music.Theory.List: find_bounds_scl :: Bool -> (t -> s -> Ordering) -> [(t, t)] -> s -> Maybe (t, t)
+ Music.Theory.List: find_nearest :: (Num n, Ord n) => [n] -> n -> Maybe n
+ Music.Theory.List: find_nearest_err :: (Num n, Ord n) => [n] -> n -> n
+ Music.Theory.List: find_non_ascending :: (a -> a -> Ordering) -> [a] -> Maybe (a, a)
+ Music.Theory.List: generic_histogram :: (Ord a, Integral i) => [a] -> [(a, i)]
+ Music.Theory.List: group_on :: Eq x => (a -> x) -> [a] -> [[a]]
+ Music.Theory.List: group_ranges :: (Num t, Eq t) => [t] -> [(t, t)]
+ Music.Theory.List: group_tree :: (a -> Bool, a -> Bool) -> [a] -> Tree (Maybe a)
+ Music.Theory.List: histogram_by :: Ord a => (a -> a -> Bool) -> [a] -> [(a, Int)]
+ Music.Theory.List: interleave_set :: [[a]] -> [a]
+ Music.Theory.List: is_ascending :: Ord a => [a] -> Bool
+ Music.Theory.List: is_ascending_by :: (a -> a -> Ordering) -> [a] -> Bool
+ Music.Theory.List: is_embedding :: Eq t => [t] -> [t] -> Bool
+ Music.Theory.List: lookup_def :: Eq k => k -> v -> [(k, v)] -> v
+ Music.Theory.List: lookup_err :: Eq k => k -> [(k, v)] -> v
+ Music.Theory.List: lookup_err_msg :: (Eq k, Show k) => String -> k -> [(k, v)] -> v
+ Music.Theory.List: merge_on :: Ord x => (a -> x) -> [a] -> [a] -> [a]
+ Music.Theory.List: minmax :: Ord t => [t] -> (t, t)
+ Music.Theory.List: n_stage_compare :: [Compare_F a] -> Compare_F a
+ Music.Theory.List: on_elem :: Eq a => a -> Splitter a
+ Music.Theory.List: operate_ixs :: Bool -> [Int] -> [a] -> [a]
+ Music.Theory.List: pad_left :: a -> Int -> [a] -> [a]
+ Music.Theory.List: pad_right :: a -> Int -> [a] -> [a]
+ Music.Theory.List: remove_ix :: Int -> [a] -> [a]
+ Music.Theory.List: remove_ixs :: [Int] -> [a] -> [a]
+ Music.Theory.List: replace :: Eq a => [a] -> [a] -> [a] -> [a]
+ Music.Theory.List: replace_at :: Integral i => [a] -> i -> a -> [a]
+ Music.Theory.List: replace_ix :: (a -> a) -> Int -> [a] -> [a]
+ Music.Theory.List: reverse_lookup :: Eq b => b -> [(a, b)] -> Maybe a
+ Music.Theory.List: rotate_starting_from :: Eq a => a -> [a] -> Maybe [a]
+ Music.Theory.List: rotate_starting_from_err :: Eq a => a -> [a] -> [a]
+ Music.Theory.List: section :: Int -> Int -> [a] -> [a]
+ Music.Theory.List: select_ixs :: [Int] -> [a] -> [a]
+ Music.Theory.List: separate_at :: Eq a => [a] -> [a] -> Maybe ([a], [a])
+ Music.Theory.List: separate_last' :: [a] -> ([a], Maybe a)
+ Music.Theory.List: slice :: Int -> Int -> [a] -> [a]
+ Music.Theory.List: sort_by_n_stage :: Ord b => [a -> b] -> [a] -> [a]
+ Music.Theory.List: split_before :: Eq a => a -> [a] -> [[a]]
+ Music.Theory.List: take_right :: Int -> [a] -> [a]
+ Music.Theory.List: take_while_right :: (a -> Bool) -> [a] -> [a]
+ Music.Theory.List: unbracket :: [t] -> Maybe (t, [t], t)
+ Music.Theory.List: unbracket' :: [a] -> (Maybe a, [a], Maybe a)
+ Music.Theory.List: unbracket_err :: [t] -> (t, [t], t)
+ Music.Theory.List: uncollate :: [(k, [v])] -> [(k, v)]
+ Music.Theory.List: unlist1 :: [t] -> Maybe t
+ Music.Theory.List: unlist1_err :: [t] -> t
+ Music.Theory.List: zip_with_adj :: (a -> a -> b) -> [a] -> [b]
+ Music.Theory.List: zip_with_kr :: (a -> b -> c) -> [a] -> [b] -> ([c], [b])
+ Music.Theory.List: zip_with_perhaps_rhs :: (a -> b -> Either c c) -> (a -> c) -> [a] -> [b] -> [c]
+ Music.Theory.Map: map_ix :: Ord k => Map k c -> k -> Maybe c
+ Music.Theory.Map: map_ix_err :: Ord k => Map k c -> k -> c
+ Music.Theory.Map: map_lookup_err :: Ord k => k -> Map k c -> c
+ Music.Theory.Math: floor_f :: (RealFrac a, Num b) => a -> b
+ Music.Theory.Math: i_square_root :: Integral t => t -> t
+ Music.Theory.Math: in_closed_interval :: Ord a => (a, a) -> a -> Bool
+ Music.Theory.Math: in_left_half_open_interval :: Ord a => (a, a) -> a -> Bool
+ Music.Theory.Math: in_open_interval :: Ord a => (a, a) -> a -> Bool
+ Music.Theory.Math: in_right_half_open_interval :: Ord a => (a, a) -> a -> Bool
+ Music.Theory.Math: oi_divMod :: Integral t => t -> t -> (t, t)
+ Music.Theory.Math: oi_mod :: Integral a => a -> a -> a
+ Music.Theory.Math: real_floor :: (Real r, Integral i) => r -> i
+ Music.Theory.Math: real_floor_int :: Real r => r -> Int
+ Music.Theory.Math: real_pp :: Real t => Int -> t -> String
+ Music.Theory.Math: real_round :: (Real r, Integral i) => r -> i
+ Music.Theory.Math: real_round_int :: Real r => r -> Int
+ Music.Theory.Math: round_to :: RealFrac n => n -> n -> n
+ Music.Theory.Math: show_rational_decimal :: Int -> Rational -> String
+ Music.Theory.Math: whole_to_precision :: Real r => Int -> r -> Bool
+ Music.Theory.Math: zero_to_precision :: Real r => Int -> r -> Bool
+ Music.Theory.Math.Convert: double_to_float :: Double -> Float
+ Music.Theory.Math.Convert: float_to_double :: Float -> Double
+ Music.Theory.Math.Convert: int16_to_double :: Int16 -> Double
+ Music.Theory.Math.Convert: int16_to_float :: Int16 -> Float
+ Music.Theory.Math.Convert: int16_to_int :: Int16 -> Int
+ Music.Theory.Math.Convert: int16_to_int32 :: Int16 -> Int32
+ Music.Theory.Math.Convert: int16_to_int32_maybe :: Int16 -> Maybe Int32
+ Music.Theory.Math.Convert: int16_to_int64 :: Int16 -> Int64
+ Music.Theory.Math.Convert: int16_to_int64_maybe :: Int16 -> Maybe Int64
+ Music.Theory.Math.Convert: int16_to_int8 :: Int16 -> Int8
+ Music.Theory.Math.Convert: int16_to_int8_maybe :: Int16 -> Maybe Int8
+ Music.Theory.Math.Convert: int16_to_int_maybe :: Int16 -> Maybe Int
+ Music.Theory.Math.Convert: int16_to_integer :: Int16 -> Integer
+ Music.Theory.Math.Convert: int16_to_word16 :: Int16 -> Word16
+ Music.Theory.Math.Convert: int16_to_word16_maybe :: Int16 -> Maybe Word16
+ Music.Theory.Math.Convert: int16_to_word32 :: Int16 -> Word32
+ Music.Theory.Math.Convert: int16_to_word32_maybe :: Int16 -> Maybe Word32
+ Music.Theory.Math.Convert: int16_to_word64 :: Int16 -> Word64
+ Music.Theory.Math.Convert: int16_to_word64_maybe :: Int16 -> Maybe Word64
+ Music.Theory.Math.Convert: int16_to_word8 :: Int16 -> Word8
+ Music.Theory.Math.Convert: int16_to_word8_maybe :: Int16 -> Maybe Word8
+ Music.Theory.Math.Convert: int32_to_double :: Int32 -> Double
+ Music.Theory.Math.Convert: int32_to_float :: Int32 -> Float
+ Music.Theory.Math.Convert: int32_to_int :: Int32 -> Int
+ Music.Theory.Math.Convert: int32_to_int16 :: Int32 -> Int16
+ Music.Theory.Math.Convert: int32_to_int16_maybe :: Int32 -> Maybe Int16
+ Music.Theory.Math.Convert: int32_to_int64 :: Int32 -> Int64
+ Music.Theory.Math.Convert: int32_to_int64_maybe :: Int32 -> Maybe Int64
+ Music.Theory.Math.Convert: int32_to_int8 :: Int32 -> Int8
+ Music.Theory.Math.Convert: int32_to_int8_maybe :: Int32 -> Maybe Int8
+ Music.Theory.Math.Convert: int32_to_int_maybe :: Int32 -> Maybe Int
+ Music.Theory.Math.Convert: int32_to_integer :: Int32 -> Integer
+ Music.Theory.Math.Convert: int32_to_word16 :: Int32 -> Word16
+ Music.Theory.Math.Convert: int32_to_word16_maybe :: Int32 -> Maybe Word16
+ Music.Theory.Math.Convert: int32_to_word32 :: Int32 -> Word32
+ Music.Theory.Math.Convert: int32_to_word32_maybe :: Int32 -> Maybe Word32
+ Music.Theory.Math.Convert: int32_to_word64 :: Int32 -> Word64
+ Music.Theory.Math.Convert: int32_to_word64_maybe :: Int32 -> Maybe Word64
+ Music.Theory.Math.Convert: int32_to_word8 :: Int32 -> Word8
+ Music.Theory.Math.Convert: int32_to_word8_maybe :: Int32 -> Maybe Word8
+ Music.Theory.Math.Convert: int64_to_double :: Int64 -> Double
+ Music.Theory.Math.Convert: int64_to_float :: Int64 -> Float
+ Music.Theory.Math.Convert: int64_to_int :: Int64 -> Int
+ Music.Theory.Math.Convert: int64_to_int16 :: Int64 -> Int16
+ Music.Theory.Math.Convert: int64_to_int16_maybe :: Int64 -> Maybe Int16
+ Music.Theory.Math.Convert: int64_to_int32 :: Int64 -> Int32
+ Music.Theory.Math.Convert: int64_to_int32_maybe :: Int64 -> Maybe Int32
+ Music.Theory.Math.Convert: int64_to_int8 :: Int64 -> Int8
+ Music.Theory.Math.Convert: int64_to_int8_maybe :: Int64 -> Maybe Int8
+ Music.Theory.Math.Convert: int64_to_int_maybe :: Int64 -> Maybe Int
+ Music.Theory.Math.Convert: int64_to_integer :: Int64 -> Integer
+ Music.Theory.Math.Convert: int64_to_word16 :: Int64 -> Word16
+ Music.Theory.Math.Convert: int64_to_word16_maybe :: Int64 -> Maybe Word16
+ Music.Theory.Math.Convert: int64_to_word32 :: Int64 -> Word32
+ Music.Theory.Math.Convert: int64_to_word32_maybe :: Int64 -> Maybe Word32
+ Music.Theory.Math.Convert: int64_to_word64 :: Int64 -> Word64
+ Music.Theory.Math.Convert: int64_to_word64_maybe :: Int64 -> Maybe Word64
+ Music.Theory.Math.Convert: int64_to_word8 :: Int64 -> Word8
+ Music.Theory.Math.Convert: int64_to_word8_maybe :: Int64 -> Maybe Word8
+ Music.Theory.Math.Convert: int8_to_double :: Int8 -> Double
+ Music.Theory.Math.Convert: int8_to_float :: Int8 -> Float
+ Music.Theory.Math.Convert: int8_to_int :: Int8 -> Int
+ Music.Theory.Math.Convert: int8_to_int16 :: Int8 -> Int16
+ Music.Theory.Math.Convert: int8_to_int16_maybe :: Int8 -> Maybe Int16
+ Music.Theory.Math.Convert: int8_to_int32 :: Int8 -> Int32
+ Music.Theory.Math.Convert: int8_to_int32_maybe :: Int8 -> Maybe Int32
+ Music.Theory.Math.Convert: int8_to_int64 :: Int8 -> Int64
+ Music.Theory.Math.Convert: int8_to_int64_maybe :: Int8 -> Maybe Int64
+ Music.Theory.Math.Convert: int8_to_int_maybe :: Int8 -> Maybe Int
+ Music.Theory.Math.Convert: int8_to_integer :: Int8 -> Integer
+ Music.Theory.Math.Convert: int8_to_word16 :: Int8 -> Word16
+ Music.Theory.Math.Convert: int8_to_word16_maybe :: Int8 -> Maybe Word16
+ Music.Theory.Math.Convert: int8_to_word32 :: Int8 -> Word32
+ Music.Theory.Math.Convert: int8_to_word32_maybe :: Int8 -> Maybe Word32
+ Music.Theory.Math.Convert: int8_to_word64 :: Int8 -> Word64
+ Music.Theory.Math.Convert: int8_to_word64_maybe :: Int8 -> Maybe Word64
+ Music.Theory.Math.Convert: int8_to_word8 :: Int8 -> Word8
+ Music.Theory.Math.Convert: int8_to_word8_maybe :: Int8 -> Maybe Word8
+ Music.Theory.Math.Convert: int_to_double :: Int -> Double
+ Music.Theory.Math.Convert: int_to_float :: Int -> Float
+ Music.Theory.Math.Convert: int_to_int16 :: Int -> Int16
+ Music.Theory.Math.Convert: int_to_int16_maybe :: Int -> Maybe Int16
+ Music.Theory.Math.Convert: int_to_int32 :: Int -> Int32
+ Music.Theory.Math.Convert: int_to_int32_maybe :: Int -> Maybe Int32
+ Music.Theory.Math.Convert: int_to_int64 :: Int -> Int64
+ Music.Theory.Math.Convert: int_to_int64_maybe :: Int -> Maybe Int64
+ Music.Theory.Math.Convert: int_to_int8 :: Int -> Int8
+ Music.Theory.Math.Convert: int_to_int8_maybe :: Int -> Maybe Int8
+ Music.Theory.Math.Convert: int_to_integer :: Int -> Integer
+ Music.Theory.Math.Convert: int_to_word16 :: Int -> Word16
+ Music.Theory.Math.Convert: int_to_word16_maybe :: Int -> Maybe Word16
+ Music.Theory.Math.Convert: int_to_word32 :: Int -> Word32
+ Music.Theory.Math.Convert: int_to_word32_maybe :: Int -> Maybe Word32
+ Music.Theory.Math.Convert: int_to_word64 :: Int -> Word64
+ Music.Theory.Math.Convert: int_to_word64_maybe :: Int -> Maybe Word64
+ Music.Theory.Math.Convert: int_to_word8 :: Int -> Word8
+ Music.Theory.Math.Convert: int_to_word8_maybe :: Int -> Maybe Word8
+ Music.Theory.Math.Convert: integer_to_double :: Integer -> Double
+ Music.Theory.Math.Convert: integer_to_float :: Integer -> Float
+ Music.Theory.Math.Convert: integer_to_int :: Integer -> Int
+ Music.Theory.Math.Convert: integer_to_int16 :: Integer -> Int16
+ Music.Theory.Math.Convert: integer_to_int16_maybe :: Integer -> Maybe Int16
+ Music.Theory.Math.Convert: integer_to_int32 :: Integer -> Int32
+ Music.Theory.Math.Convert: integer_to_int32_maybe :: Integer -> Maybe Int32
+ Music.Theory.Math.Convert: integer_to_int64 :: Integer -> Int64
+ Music.Theory.Math.Convert: integer_to_int64_maybe :: Integer -> Maybe Int64
+ Music.Theory.Math.Convert: integer_to_int8 :: Integer -> Int8
+ Music.Theory.Math.Convert: integer_to_int8_maybe :: Integer -> Maybe Int8
+ Music.Theory.Math.Convert: integer_to_int_maybe :: Integer -> Maybe Int
+ Music.Theory.Math.Convert: integer_to_word16 :: Integer -> Word16
+ Music.Theory.Math.Convert: integer_to_word16_maybe :: Integer -> Maybe Word16
+ Music.Theory.Math.Convert: integer_to_word32 :: Integer -> Word32
+ Music.Theory.Math.Convert: integer_to_word32_maybe :: Integer -> Maybe Word32
+ Music.Theory.Math.Convert: integer_to_word64 :: Integer -> Word64
+ Music.Theory.Math.Convert: integer_to_word64_maybe :: Integer -> Maybe Word64
+ Music.Theory.Math.Convert: integer_to_word8 :: Integer -> Word8
+ Music.Theory.Math.Convert: integer_to_word8_maybe :: Integer -> Maybe Word8
+ Music.Theory.Math.Convert: real_to_double :: Real t => t -> Double
+ Music.Theory.Math.Convert: real_to_float :: Real t => t -> Float
+ Music.Theory.Math.Convert: word16_to_double :: Word16 -> Double
+ Music.Theory.Math.Convert: word16_to_float :: Word16 -> Float
+ Music.Theory.Math.Convert: word16_to_int :: Word16 -> Int
+ Music.Theory.Math.Convert: word16_to_int16 :: Word16 -> Int16
+ Music.Theory.Math.Convert: word16_to_int16_maybe :: Word16 -> Maybe Int16
+ Music.Theory.Math.Convert: word16_to_int32 :: Word16 -> Int32
+ Music.Theory.Math.Convert: word16_to_int32_maybe :: Word16 -> Maybe Int32
+ Music.Theory.Math.Convert: word16_to_int64 :: Word16 -> Int64
+ Music.Theory.Math.Convert: word16_to_int64_maybe :: Word16 -> Maybe Int64
+ Music.Theory.Math.Convert: word16_to_int8 :: Word16 -> Int8
+ Music.Theory.Math.Convert: word16_to_int8_maybe :: Word16 -> Maybe Int8
+ Music.Theory.Math.Convert: word16_to_int_maybe :: Word16 -> Maybe Int
+ Music.Theory.Math.Convert: word16_to_integer :: Word16 -> Integer
+ Music.Theory.Math.Convert: word16_to_word32 :: Word16 -> Word32
+ Music.Theory.Math.Convert: word16_to_word32_maybe :: Word16 -> Maybe Word32
+ Music.Theory.Math.Convert: word16_to_word64 :: Word16 -> Word64
+ Music.Theory.Math.Convert: word16_to_word64_maybe :: Word16 -> Maybe Word64
+ Music.Theory.Math.Convert: word16_to_word8 :: Word16 -> Word8
+ Music.Theory.Math.Convert: word16_to_word8_maybe :: Word16 -> Maybe Word8
+ Music.Theory.Math.Convert: word32_to_double :: Word32 -> Double
+ Music.Theory.Math.Convert: word32_to_float :: Word32 -> Float
+ Music.Theory.Math.Convert: word32_to_int :: Word32 -> Int
+ Music.Theory.Math.Convert: word32_to_int16 :: Word32 -> Int16
+ Music.Theory.Math.Convert: word32_to_int16_maybe :: Word32 -> Maybe Int16
+ Music.Theory.Math.Convert: word32_to_int32 :: Word32 -> Int32
+ Music.Theory.Math.Convert: word32_to_int32_maybe :: Word32 -> Maybe Int32
+ Music.Theory.Math.Convert: word32_to_int64 :: Word32 -> Int64
+ Music.Theory.Math.Convert: word32_to_int64_maybe :: Word32 -> Maybe Int64
+ Music.Theory.Math.Convert: word32_to_int8 :: Word32 -> Int8
+ Music.Theory.Math.Convert: word32_to_int8_maybe :: Word32 -> Maybe Int8
+ Music.Theory.Math.Convert: word32_to_int_maybe :: Word32 -> Maybe Int
+ Music.Theory.Math.Convert: word32_to_integer :: Word32 -> Integer
+ Music.Theory.Math.Convert: word32_to_word16 :: Word32 -> Word16
+ Music.Theory.Math.Convert: word32_to_word16_maybe :: Word32 -> Maybe Word16
+ Music.Theory.Math.Convert: word32_to_word64 :: Word32 -> Word64
+ Music.Theory.Math.Convert: word32_to_word64_maybe :: Word32 -> Maybe Word64
+ Music.Theory.Math.Convert: word32_to_word8 :: Word32 -> Word8
+ Music.Theory.Math.Convert: word32_to_word8_maybe :: Word32 -> Maybe Word8
+ Music.Theory.Math.Convert: word64_to_double :: Word64 -> Double
+ Music.Theory.Math.Convert: word64_to_float :: Word64 -> Float
+ Music.Theory.Math.Convert: word64_to_int :: Word64 -> Int
+ Music.Theory.Math.Convert: word64_to_int16 :: Word64 -> Int16
+ Music.Theory.Math.Convert: word64_to_int16_maybe :: Word64 -> Maybe Int16
+ Music.Theory.Math.Convert: word64_to_int32 :: Word64 -> Int32
+ Music.Theory.Math.Convert: word64_to_int32_maybe :: Word64 -> Maybe Int32
+ Music.Theory.Math.Convert: word64_to_int64 :: Word64 -> Int64
+ Music.Theory.Math.Convert: word64_to_int64_maybe :: Word64 -> Maybe Int64
+ Music.Theory.Math.Convert: word64_to_int8 :: Word64 -> Int8
+ Music.Theory.Math.Convert: word64_to_int8_maybe :: Word64 -> Maybe Int8
+ Music.Theory.Math.Convert: word64_to_int_maybe :: Word64 -> Maybe Int
+ Music.Theory.Math.Convert: word64_to_integer :: Word64 -> Integer
+ Music.Theory.Math.Convert: word64_to_word16 :: Word64 -> Word16
+ Music.Theory.Math.Convert: word64_to_word16_maybe :: Word64 -> Maybe Word16
+ Music.Theory.Math.Convert: word64_to_word32 :: Word64 -> Word32
+ Music.Theory.Math.Convert: word64_to_word32_maybe :: Word64 -> Maybe Word32
+ Music.Theory.Math.Convert: word64_to_word8 :: Word64 -> Word8
+ Music.Theory.Math.Convert: word64_to_word8_maybe :: Word64 -> Maybe Word8
+ Music.Theory.Math.Convert: word8_to_double :: Word8 -> Double
+ Music.Theory.Math.Convert: word8_to_float :: Word8 -> Float
+ Music.Theory.Math.Convert: word8_to_int :: Word8 -> Int
+ Music.Theory.Math.Convert: word8_to_int16 :: Word8 -> Int16
+ Music.Theory.Math.Convert: word8_to_int16_maybe :: Word8 -> Maybe Int16
+ Music.Theory.Math.Convert: word8_to_int32 :: Word8 -> Int32
+ Music.Theory.Math.Convert: word8_to_int32_maybe :: Word8 -> Maybe Int32
+ Music.Theory.Math.Convert: word8_to_int64 :: Word8 -> Int64
+ Music.Theory.Math.Convert: word8_to_int64_maybe :: Word8 -> Maybe Int64
+ Music.Theory.Math.Convert: word8_to_int8 :: Word8 -> Int8
+ Music.Theory.Math.Convert: word8_to_int8_maybe :: Word8 -> Maybe Int8
+ Music.Theory.Math.Convert: word8_to_int_maybe :: Word8 -> Maybe Int
+ Music.Theory.Math.Convert: word8_to_integer :: Word8 -> Integer
+ Music.Theory.Math.Convert: word8_to_word16 :: Word8 -> Word16
+ Music.Theory.Math.Convert: word8_to_word16_maybe :: Word8 -> Maybe Word16
+ Music.Theory.Math.Convert: word8_to_word32 :: Word8 -> Word32
+ Music.Theory.Math.Convert: word8_to_word32_maybe :: Word8 -> Maybe Word32
+ Music.Theory.Math.Convert: word8_to_word64 :: Word8 -> Word64
+ Music.Theory.Math.Convert: word8_to_word64_maybe :: Word8 -> Maybe Word64
+ Music.Theory.Math.OEIS: a000290 :: Integral n => [n]
+ Music.Theory.Math.OEIS: a002267 :: Num n => [n]
+ Music.Theory.Math.OEIS: a126709 :: Num n => [n]
+ Music.Theory.Math.OEIS: a126710 :: Num n => [n]
+ Music.Theory.Maybe: from_just :: String -> Maybe a -> a
+ Music.Theory.Metric.Buchler_1998: instance GHC.Classes.Eq Music.Theory.Metric.Buchler_1998.R
+ Music.Theory.Metric.Buchler_1998: instance GHC.Show.Show Music.Theory.Metric.Buchler_1998.R
+ Music.Theory.Monad: iterateM_ :: (Monad m) => st -> (st -> m st) -> m ()
+ Music.Theory.Monad: repeatM_ :: (Monad m) => m a -> m ()
+ Music.Theory.Ord: int_to_ord :: Int -> Ordering
+ Music.Theory.Ord: ord_invert :: Ordering -> Ordering
+ Music.Theory.Ord: ord_to_int :: Ordering -> Int
+ Music.Theory.Ord: order_pair :: Ordering -> (t, t) -> (t, t)
+ Music.Theory.Ord: sort_pair :: (t -> t -> Ordering) -> (t, t) -> (t, t)
+ Music.Theory.Ord: sort_pair_m :: (t -> t -> Maybe Ordering) -> (t, t) -> Maybe (t, t)
+ Music.Theory.Parse: is_char :: Char -> P Bool
+ Music.Theory.Parse: parse_int :: Integral i => P i
+ Music.Theory.Parse: type P a = GenParser Char () a
+ Music.Theory.Permutations.List: factorial :: (Enum a, Num a) => a -> a
+ Music.Theory.Permutations.List: multiset_permutations_n :: Ord a => [a] -> Int
+ Music.Theory.Permutations.Morris_1984: derive_holds :: (Eq a, Enum n, Num n) => ([a], [a]) -> [n]
+ Music.Theory.Permutations.Morris_1984: ecumenical_surprise_maximus :: Method
+ Music.Theory.Permutations.Morris_1984: instance GHC.Classes.Eq Music.Theory.Permutations.Morris_1984.Change
+ Music.Theory.Permutations.Morris_1984: instance GHC.Classes.Eq Music.Theory.Permutations.Morris_1984.Method
+ Music.Theory.Permutations.Morris_1984: instance GHC.Show.Show Music.Theory.Permutations.Morris_1984.Change
+ Music.Theory.Permutations.Morris_1984: instance GHC.Show.Show Music.Theory.Permutations.Morris_1984.Method
+ Music.Theory.Permutations.Morris_1984: numeric_spelling_tbl :: [(Char, Int)]
+ Music.Theory.Pitch: Pitch_R :: Note_T -> Alteration_R -> Octave -> Pitch_R
+ Music.Theory.Pitch: [alteration] :: Pitch -> Alteration_T
+ Music.Theory.Pitch: [note] :: Pitch -> Note_T
+ Music.Theory.Pitch: [octave] :: Pitch -> Octave
+ Music.Theory.Pitch: cents_is_normal :: (Num c, Ord c) => c -> Bool
+ Music.Theory.Pitch: cps_in_octave' :: Floating f => (f -> f -> f) -> f -> f -> f
+ Music.Theory.Pitch: cps_in_octave_above :: (Ord a, Fractional a) => a -> a -> a
+ Music.Theory.Pitch: cps_in_octave_above' :: (Floating f, RealFrac f) => f -> f -> f
+ Music.Theory.Pitch: cps_in_octave_below :: (Floating f, RealFrac f) => f -> f -> f
+ Music.Theory.Pitch: cps_in_octave_nearest :: (Floating f, RealFrac f) => f -> f -> f
+ Music.Theory.Pitch: cps_octave :: (Floating f, RealFrac f) => f -> Octave
+ Music.Theory.Pitch: cps_to_fmidi_f0 :: Floating a => a -> a -> a
+ Music.Theory.Pitch: data Pitch_R
+ Music.Theory.Pitch: fmidi_et12_cents_pp :: Spelling PitchClass -> Double -> String
+ Music.Theory.Pitch: fmidi_in_octave :: RealFrac f => Octave -> f -> f
+ Music.Theory.Pitch: fmidi_in_octave_above :: RealFrac a => a -> a -> a
+ Music.Theory.Pitch: fmidi_in_octave_below :: RealFrac a => a -> a -> a
+ Music.Theory.Pitch: fmidi_in_octave_nearest :: RealFrac n => n -> n -> n
+ Music.Theory.Pitch: fmidi_in_octave_of :: RealFrac f => f -> f -> f
+ Music.Theory.Pitch: fmidi_octave :: RealFrac f => f -> Octave
+ Music.Theory.Pitch: fmidi_to_cps_f0 :: Floating a => a -> a -> a
+ Music.Theory.Pitch: fmidi_to_foctpc :: RealFrac f => f -> (Octave, f)
+ Music.Theory.Pitch: fmidi_to_midi_detune :: Double -> Midi_Detune
+ Music.Theory.Pitch: fmidi_to_pitch_err :: (Show n, RealFrac n) => Spelling Int -> n -> Pitch
+ Music.Theory.Pitch: foctpc_to_fmidi :: RealFrac f => (Octave, f) -> f
+ Music.Theory.Pitch: instance GHC.Classes.Eq Music.Theory.Pitch.Pitch
+ Music.Theory.Pitch: instance GHC.Classes.Eq Music.Theory.Pitch.Pitch_R
+ Music.Theory.Pitch: instance GHC.Classes.Ord Music.Theory.Pitch.Pitch
+ Music.Theory.Pitch: instance GHC.Show.Show Music.Theory.Pitch.Pitch
+ Music.Theory.Pitch: instance GHC.Show.Show Music.Theory.Pitch.Pitch_R
+ Music.Theory.Pitch: midi_cents_pp :: Midi_Cents -> String
+ Music.Theory.Pitch: midi_detune_is_normal :: (Num c, Ord c) => Midi_Detune' c -> Bool
+ Music.Theory.Pitch: midi_detune_nearest_24et :: Midi_Detune -> Midi_Detune
+ Music.Theory.Pitch: midi_detune_normalise :: (Ord c, Num c) => Midi_Detune' c -> Midi_Detune' c
+ Music.Theory.Pitch: midi_detune_to_cps_f0 :: Real c => Double -> Midi_Detune' c -> Double
+ Music.Theory.Pitch: midi_detune_to_fmidi :: Real c => Midi_Detune' c -> Double
+ Music.Theory.Pitch: midi_detune_to_midi_cents :: Midi_Detune -> Midi_Cents
+ Music.Theory.Pitch: midi_detune_to_pitch :: Real c => Spelling Int -> Midi_Detune' c -> Pitch
+ Music.Theory.Pitch: midi_to_cps_f0 :: (Integral i, Floating f) => f -> i -> f
+ Music.Theory.Pitch: midi_to_octave_pitchclass :: Integral i => i -> Octave_PitchClass i
+ Music.Theory.Pitch: octave_pitchclass_nrm :: Integral i => Octave_PitchClass i -> Octave_PitchClass i
+ Music.Theory.Pitch: octave_pitchclass_to_midi :: Integral i => Octave_PitchClass i -> i
+ Music.Theory.Pitch: octave_pitchclass_trs :: Integral i => i -> Octave_PitchClass i -> Octave_PitchClass i
+ Music.Theory.Pitch: octpc_to_cps_f0 :: (Integral i, Floating n) => n -> Octave_PitchClass i -> n
+ Music.Theory.Pitch: parse_iso_pitch_err :: String -> Pitch
+ Music.Theory.Pitch: parse_octave :: Num a => a -> String -> Maybe a
+ Music.Theory.Pitch: pc24et_to_pitch :: Integral i => i -> Pitch
+ Music.Theory.Pitch: pc24et_univ :: [Pitch]
+ Music.Theory.Pitch: pitch_pp_opt :: (Bool, Bool) -> Pitch -> String
+ Music.Theory.Pitch: pitch_r_class_pp :: Pitch_R -> String
+ Music.Theory.Pitch: pitch_r_pp :: Pitch_R -> String
+ Music.Theory.Pitch: pitch_to_cps_f0 :: Floating n => n -> Pitch -> n
+ Music.Theory.Pitch: to_octpc :: (Integral pc, Integral oct) => (oct, pc) -> OctPC
+ Music.Theory.Pitch: type FMidi = Double
+ Music.Theory.Pitch: type FOctPC = (Int, Double)
+ Music.Theory.Pitch: type Midi = Int
+ Music.Theory.Pitch: type Midi_Cents = Midi_Detune' Int
+ Music.Theory.Pitch: type Midi_Detune' c = (Int, c)
+ Music.Theory.Pitch: type Spelling n = n -> (Note_T, Alteration_T)
+ Music.Theory.Pitch: type Spelling_M i = i -> Maybe (Note_T, Alteration_T)
+ Music.Theory.Pitch.Chord: Augmented :: Chord_Type
+ Music.Theory.Pitch.Chord: CH :: PC -> Chord_Type -> (Maybe Extension) -> (Maybe PC) -> Chord
+ Music.Theory.Pitch.Chord: D7 :: Extension
+ Music.Theory.Pitch.Chord: Diminished :: Chord_Type
+ Music.Theory.Pitch.Chord: Diminished_7 :: Chord_Type
+ Music.Theory.Pitch.Chord: Half_Diminished :: Chord_Type
+ Music.Theory.Pitch.Chord: M7 :: Extension
+ Music.Theory.Pitch.Chord: Major :: Chord_Type
+ Music.Theory.Pitch.Chord: Minor :: Chord_Type
+ Music.Theory.Pitch.Chord: Suspended_2 :: Chord_Type
+ Music.Theory.Pitch.Chord: Suspended_4 :: Chord_Type
+ Music.Theory.Pitch.Chord: bass_pp :: PC -> String
+ Music.Theory.Pitch.Chord: chord_pcset :: Chord -> (Maybe Int, [Int])
+ Music.Theory.Pitch.Chord: chord_pp :: Chord -> String
+ Music.Theory.Pitch.Chord: chord_type_dat :: Num n => Chord_Type -> ([String], [n])
+ Music.Theory.Pitch.Chord: chord_type_pcset :: Num n => Chord_Type -> [n]
+ Music.Theory.Pitch.Chord: chord_type_pp :: Chord_Type -> String
+ Music.Theory.Pitch.Chord: chord_type_tbl :: Num n => [(Chord_Type, ([String], [n]))]
+ Music.Theory.Pitch.Chord: data Chord
+ Music.Theory.Pitch.Chord: data Chord_Type
+ Music.Theory.Pitch.Chord: data Extension
+ Music.Theory.Pitch.Chord: extension_dat :: Num n => Extension -> (String, n)
+ Music.Theory.Pitch.Chord: extension_pp :: Extension -> String
+ Music.Theory.Pitch.Chord: extension_tbl :: Num n => [(Extension, (String, n))]
+ Music.Theory.Pitch.Chord: extension_to_pc :: Num n => Extension -> n
+ Music.Theory.Pitch.Chord: instance GHC.Classes.Eq Music.Theory.Pitch.Chord.Chord_Type
+ Music.Theory.Pitch.Chord: instance GHC.Classes.Eq Music.Theory.Pitch.Chord.Extension
+ Music.Theory.Pitch.Chord: instance GHC.Show.Show Music.Theory.Pitch.Chord.Chord
+ Music.Theory.Pitch.Chord: instance GHC.Show.Show Music.Theory.Pitch.Chord.Chord_Type
+ Music.Theory.Pitch.Chord: instance GHC.Show.Show Music.Theory.Pitch.Chord.Extension
+ Music.Theory.Pitch.Chord: is_suspended :: Chord_Type -> Bool
+ Music.Theory.Pitch.Chord: m_error :: String -> Maybe a -> a
+ Music.Theory.Pitch.Chord: p_alteration_t_iso :: P Alteration_T
+ Music.Theory.Pitch.Chord: p_bass :: P (Maybe PC)
+ Music.Theory.Pitch.Chord: p_chord :: P Chord
+ Music.Theory.Pitch.Chord: p_chord_type :: P Chord_Type
+ Music.Theory.Pitch.Chord: p_extension :: P Extension
+ Music.Theory.Pitch.Chord: p_mode_m :: P Mode_T
+ Music.Theory.Pitch.Chord: p_note_t :: P Note_T
+ Music.Theory.Pitch.Chord: p_pc :: P PC
+ Music.Theory.Pitch.Chord: parse_chord :: String -> Chord
+ Music.Theory.Pitch.Chord: pc_pp :: (Note_T, Alteration_T) -> [Char]
+ Music.Theory.Pitch.Chord: type P a = GenParser Char () a
+ Music.Theory.Pitch.Chord: type PC = (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note: alteration_iso_tbl :: [(Alteration_T, String)]
+ Music.Theory.Pitch.Note: alteration_r :: Alteration_T -> Alteration_R
+ Music.Theory.Pitch.Note: alteration_symbol_tbl :: [(Alteration_T, Char)]
+ Music.Theory.Pitch.Note: instance GHC.Classes.Eq Music.Theory.Pitch.Note.Alteration_T
+ Music.Theory.Pitch.Note: instance GHC.Classes.Eq Music.Theory.Pitch.Note.Note_T
+ Music.Theory.Pitch.Note: instance GHC.Classes.Ord Music.Theory.Pitch.Note.Alteration_T
+ Music.Theory.Pitch.Note: instance GHC.Classes.Ord Music.Theory.Pitch.Note.Note_T
+ Music.Theory.Pitch.Note: instance GHC.Enum.Bounded Music.Theory.Pitch.Note.Alteration_T
+ Music.Theory.Pitch.Note: instance GHC.Enum.Bounded Music.Theory.Pitch.Note.Note_T
+ Music.Theory.Pitch.Note: instance GHC.Enum.Enum Music.Theory.Pitch.Note.Alteration_T
+ Music.Theory.Pitch.Note: instance GHC.Enum.Enum Music.Theory.Pitch.Note.Note_T
+ Music.Theory.Pitch.Note: instance GHC.Read.Read Music.Theory.Pitch.Note.Note_T
+ Music.Theory.Pitch.Note: instance GHC.Show.Show Music.Theory.Pitch.Note.Alteration_T
+ Music.Theory.Pitch.Note: instance GHC.Show.Show Music.Theory.Pitch.Note.Note_T
+ Music.Theory.Pitch.Note: note_alteration_ks :: [(Note_T, Alteration_T)]
+ Music.Theory.Pitch.Note: note_alteration_to_pc :: (Note_T, Alteration_T) -> Maybe Int
+ Music.Theory.Pitch.Note: note_alteration_to_pc_err :: (Note_T, Alteration_T) -> Int
+ Music.Theory.Pitch.Note: note_pc_tbl :: Num i => [(Note_T, i)]
+ Music.Theory.Pitch.Note: note_pp :: Note_T -> Char
+ Music.Theory.Pitch.Note: note_seq :: [Note_T]
+ Music.Theory.Pitch.Note: note_span :: Note_T -> Note_T -> [Note_T]
+ Music.Theory.Pitch.Note: parse_note_t :: Bool -> Char -> Maybe Note_T
+ Music.Theory.Pitch.Note: pc_note_alteration_ks_tbl :: Integral i => [((Note_T, Alteration_T), i)]
+ Music.Theory.Pitch.Note: pc_to_note :: (Eq i, Num i) => i -> Maybe Note_T
+ Music.Theory.Pitch.Note: pc_to_note_alteration_ks :: Integral i => i -> Maybe (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note: symbol_to_alteration :: Char -> Maybe Alteration_T
+ Music.Theory.Pitch.Note: symbol_to_alteration_iso :: Char -> Maybe Alteration_T
+ Music.Theory.Pitch.Note: type Alteration_R = (Rational, String)
+ Music.Theory.Pitch.Note.Name: a :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: aeh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: aes :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: aeseh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: aeses :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: aih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: ais :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: aisih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: aisis :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: b :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: beh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: bes :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: beseh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: beses :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: bih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: bis :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: bisih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: bisis :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: c :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: ceh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: ces :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: ceseh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: ceses :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: cih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: cis :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: cisih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: cisis :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: d :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: deh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: des :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: deseh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: deses :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: dih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: dis :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: disih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: disis :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: e :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: eeh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: ees :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: eeseh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: eeses :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: eih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: eis :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: eisih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: eisis :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: f :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: feh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: fes :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: feseh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: feses :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: fih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: fis :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: fisih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: fisis :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: g :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: geh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: ges :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: geseh :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: geses :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: gih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: gis :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: gisih :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Note.Name: gisis :: (Note_T, Alteration_T)
+ Music.Theory.Pitch.Spelling: spell_midi_set :: [Midi] -> [Pitch]
+ Music.Theory.Pitch.Spelling: spell_octpc_set :: [OctPC] -> [Pitch]
+ Music.Theory.Pitch.Spelling.Cluster: cluster_is_multiple_octave :: [PitchClass] -> Bool
+ Music.Theory.Pitch.Spelling.Cluster: cluster_normal_order :: [PitchClass] -> [PitchClass]
+ Music.Theory.Pitch.Spelling.Cluster: cluster_normal_order_octpc :: Octave -> [PitchClass] -> [OctPC]
+ Music.Theory.Pitch.Spelling.Cluster: spell_cluster :: [PitchClass] -> Maybe [(Note_T, Alteration_T)]
+ Music.Theory.Pitch.Spelling.Cluster: spell_cluster_octpc :: [OctPC] -> Maybe [Pitch]
+ Music.Theory.Pitch.Spelling.Cluster: spell_cluster_table :: [([PitchClass], [(Note_T, Alteration_T)])]
+ Music.Theory.Pitch.Spelling.Key: midi_spell_implied_key :: [Midi] -> Maybe [Pitch]
+ Music.Theory.Pitch.Spelling.Key: octpc_spell_implied_key :: [OctPC] -> Maybe [Pitch]
+ Music.Theory.Pitch.Spelling.Key: pcset_spell_implied_key :: Integral i => [i] -> Maybe [(Note_T, Alteration_T)]
+ Music.Theory.Pitch.Spelling.Key: pcset_spell_implied_key_f :: Integral i => [i] -> Maybe (Spelling i)
+ Music.Theory.Pitch.Spelling.Table: fmidi_to_pitch_ks :: (Show n, RealFrac n) => n -> Pitch
+ Music.Theory.Pitch.Spelling.Table: midi_detune_to_pitch_ks :: Real c => Midi_Detune' c -> Pitch
+ Music.Theory.Pitch.Spelling.Table: midi_to_pitch_ks :: Integral i => i -> Pitch
+ Music.Theory.Pitch.Spelling.Table: octpc_to_pitch_ks :: Integral i => Octave_PitchClass i -> Pitch
+ Music.Theory.Pitch.Spelling.Table: pc_spell_flat :: Integral i => Spelling i
+ Music.Theory.Pitch.Spelling.Table: pc_spell_flat_tbl :: Integral i => Spelling_Table i
+ Music.Theory.Pitch.Spelling.Table: pc_spell_ks :: Integral i => Spelling i
+ Music.Theory.Pitch.Spelling.Table: pc_spell_ks_tbl :: Integral i => Spelling_Table i
+ Music.Theory.Pitch.Spelling.Table: pc_spell_natural :: Integral i => Spelling i
+ Music.Theory.Pitch.Spelling.Table: pc_spell_natural_m :: Integral i => Spelling_M i
+ Music.Theory.Pitch.Spelling.Table: pc_spell_natural_tbl :: Integral i => Spelling_Table i
+ Music.Theory.Pitch.Spelling.Table: pc_spell_sharp :: Integral i => Spelling i
+ Music.Theory.Pitch.Spelling.Table: pc_spell_sharp_tbl :: Integral i => Spelling_Table i
+ Music.Theory.Pitch.Spelling.Table: pc_spell_tbl :: Integral i => Spelling_Table i -> Spelling i
+ Music.Theory.Pitch.Spelling.Table: pc_spell_tbl_ks :: Integral i => Spelling_Table i -> Spelling i
+ Music.Theory.Pitch.Spelling.Table: type Spelling_Table i = [(i, (Note_T, Alteration_T))]
+ Music.Theory.Random.I_Ching: L6 :: Line
+ Music.Theory.Random.I_Ching: L7 :: Line
+ Music.Theory.Random.I_Ching: L8 :: Line
+ Music.Theory.Random.I_Ching: L9 :: Line
+ Music.Theory.Random.I_Ching: data Line
+ Music.Theory.Random.I_Ching: four_coin_gen_hexagram :: IO Hexagram
+ Music.Theory.Random.I_Ching: four_coin_sequence :: [Line]
+ Music.Theory.Random.I_Ching: hexagram_complement :: Hexagram -> Maybe Hexagram
+ Music.Theory.Random.I_Ching: hexagram_from_binary :: Int -> Hexagram
+ Music.Theory.Random.I_Ching: hexagram_has_complement :: Hexagram -> Bool
+ Music.Theory.Random.I_Ching: hexagram_names :: [(String, String)]
+ Music.Theory.Random.I_Ching: hexagram_pp :: Hexagram -> String
+ Music.Theory.Random.I_Ching: hexagram_to_binary :: Hexagram -> Int
+ Music.Theory.Random.I_Ching: hexagram_unicode_sequence :: [Char]
+ Music.Theory.Random.I_Ching: i_ching_chart :: [Line_Stat]
+ Music.Theory.Random.I_Ching: instance GHC.Classes.Eq Music.Theory.Random.I_Ching.Line
+ Music.Theory.Random.I_Ching: instance GHC.Show.Show Music.Theory.Random.I_Ching.Line
+ Music.Theory.Random.I_Ching: line_ascii_pp :: Line -> String
+ Music.Theory.Random.I_Ching: line_complement :: Line -> Maybe Line
+ Music.Theory.Random.I_Ching: line_from_bit :: Bool -> Line
+ Music.Theory.Random.I_Ching: line_is_moving :: Line -> Bool
+ Music.Theory.Random.I_Ching: line_unbroken :: Line -> Bool
+ Music.Theory.Random.I_Ching: trigram_chart :: Num i => [(i, Char, i, Char, String, Char, String, Char)]
+ Music.Theory.Random.I_Ching: trigram_unicode_sequence :: [Char]
+ Music.Theory.Random.I_Ching: type Hexagram = [Line]
+ Music.Theory.Random.I_Ching: type Line_Stat = (Line, (Rational, Rational, String, String, String))
+ Music.Theory.Read: delete_trailing_point :: String -> String
+ Music.Theory.Read: read_def :: Read a => a -> String -> a
+ Music.Theory.Read: read_double :: String -> Double
+ Music.Theory.Read: read_err :: Read a => String -> a
+ Music.Theory.Read: read_fractional_allow_trailing_point_err :: Read n => String -> n
+ Music.Theory.Read: read_hex_err :: (Eq n, Num n) => String -> n
+ Music.Theory.Read: read_int :: String -> Int
+ Music.Theory.Read: read_int_allow_commas :: String -> Int
+ Music.Theory.Read: read_integral_allow_commas_err :: (Integral i, Read i) => String -> i
+ Music.Theory.Read: read_integral_allow_commas_maybe :: Read i => String -> Maybe i
+ Music.Theory.Read: read_maybe :: Read a => String -> Maybe a
+ Music.Theory.Read: read_maybe_double :: String -> Maybe Double
+ Music.Theory.Read: read_maybe_int :: String -> Maybe Int
+ Music.Theory.Read: read_maybe_rational :: String -> Maybe Rational
+ Music.Theory.Read: read_ratio_allow_commas_err :: (Integral i, Read i) => String -> String -> Ratio i
+ Music.Theory.Read: read_ratio_with_div_err :: (Integral i, Read i) => String -> Ratio i
+ Music.Theory.Read: read_rational :: String -> Rational
+ Music.Theory.Read: reads_exact :: Read a => String -> Maybe a
+ Music.Theory.Read: reads_exact_err :: Read a => String -> String -> a
+ Music.Theory.Read: reads_to_read_precise :: ReadS t -> (String -> Maybe t)
+ Music.Theory.Read: reads_to_read_precise_err :: String -> ReadS t -> String -> t
+ Music.Theory.Set.List: nfold_cartesian_product :: [[a]] -> [[a]]
+ Music.Theory.Set.List: powerset' :: Ord a => [a] -> [[a]]
+ Music.Theory.String: delete_trailing_whitespace :: String -> String
+ Music.Theory.String: filter_cr :: String -> String
+ Music.Theory.Time.Bel1990.R: instance GHC.Classes.Eq Music.Theory.Time.Bel1990.R.Par_Mode
+ Music.Theory.Time.Bel1990.R: instance GHC.Classes.Eq a => GHC.Classes.Eq (Music.Theory.Time.Bel1990.R.Bel a)
+ Music.Theory.Time.Bel1990.R: instance GHC.Classes.Eq a => GHC.Classes.Eq (Music.Theory.Time.Bel1990.R.Term a)
+ Music.Theory.Time.Bel1990.R: instance GHC.Show.Show Music.Theory.Time.Bel1990.R.Par_Mode
+ Music.Theory.Time.Bel1990.R: instance GHC.Show.Show a => GHC.Show.Show (Music.Theory.Time.Bel1990.R.Bel a)
+ Music.Theory.Time.Bel1990.R: instance GHC.Show.Show a => GHC.Show.Show (Music.Theory.Time.Bel1990.R.Term a)
+ Music.Theory.Time.Bel1990.R: p_non_negative_double :: P Double
+ Music.Theory.Time.Bel1990.R: p_non_negative_integer :: P Integer
+ Music.Theory.Time.Bel1990.R: p_non_negative_number :: P Rational
+ Music.Theory.Time.Bel1990.R: p_non_negative_rational :: P Rational
+ Music.Theory.Time.Duration: [hours] :: Duration -> Int
+ Music.Theory.Time.Duration: [milliseconds] :: Duration -> Int
+ Music.Theory.Time.Duration: [minutes] :: Duration -> Int
+ Music.Theory.Time.Duration: [seconds] :: Duration -> Int
+ Music.Theory.Time.Duration: instance GHC.Classes.Eq Music.Theory.Time.Duration.Duration
+ Music.Theory.Time.Duration: instance GHC.Read.Read Music.Theory.Time.Duration.Duration
+ Music.Theory.Time.Duration: instance GHC.Show.Show Music.Theory.Time.Duration.Duration
+ Music.Theory.Time.Notation: csec_to_mincsec :: Integral n => n -> MinCsec n
+ Music.Theory.Time.Notation: mincsec_binop :: Integral t => (t -> t -> t) -> MinCsec t -> MinCsec t -> MinCsec t
+ Music.Theory.Time.Notation: mincsec_pp_opt :: Bool -> MINCSEC -> String
+ Music.Theory.Time.Notation: mincsec_to_csec :: Num n => MinCsec n -> n
+ Music.Theory.Time.Notation: mincsec_to_fsec :: Real n => MinCsec n -> FSEC
+ Music.Theory.Time.Notation: minsec_add :: Integral n => MinSec n -> MinSec n -> MinSec n
+ Music.Theory.Time.Notation: minsec_binop :: Integral t => (t -> t -> t) -> MinSec t -> MinSec t -> MinSec t
+ Music.Theory.Time.Notation: minsec_diff :: Integral n => MinSec n -> MinSec n -> MinSec n
+ Music.Theory.Time.Notation: minsec_parse :: (Num n, Read n) => String -> MinSec n
+ Music.Theory.Time.Notation: minsec_sub :: Integral n => MinSec n -> MinSec n -> MinSec n
+ Music.Theory.Time.Notation: minsec_sum :: Integral n => [MinSec n] -> MinSec n
+ Music.Theory.Time.Notation: minsec_to_sec :: Num n => MinSec n -> n
+ Music.Theory.Time.Notation: sec_to_minsec :: Integral n => n -> MinSec n
+ Music.Theory.Time.Notation: type MinCsec n = (n, n, n)
+ Music.Theory.Time.Notation: type MinSec n = (n, n)
+ Music.Theory.Time.Seq: Begin :: a -> Begin_End a
+ Music.Theory.Time.Seq: End :: a -> Begin_End a
+ Music.Theory.Time.Seq: begin_end_map :: (t -> u) -> Begin_End t -> Begin_End u
+ Music.Theory.Time.Seq: begin_end_partition :: [Begin_End a] -> ([a], [a])
+ Music.Theory.Time.Seq: begin_end_to_either :: Begin_End a -> Either a a
+ Music.Theory.Time.Seq: begin_end_track :: Eq a => [a] -> Begin_End a -> [a]
+ Music.Theory.Time.Seq: cmp_begin_end :: Begin_End a -> Begin_End b -> Ordering
+ Music.Theory.Time.Seq: data Begin_End a
+ Music.Theory.Time.Seq: either_to_begin_end :: Either a a -> Begin_End a
+ Music.Theory.Time.Seq: instance GHC.Classes.Eq Music.Theory.Time.Seq.Interpolation_T
+ Music.Theory.Time.Seq: instance GHC.Classes.Eq a => GHC.Classes.Eq (Music.Theory.Time.Seq.Begin_End a)
+ Music.Theory.Time.Seq: instance GHC.Enum.Enum Music.Theory.Time.Seq.Interpolation_T
+ Music.Theory.Time.Seq: instance GHC.Show.Show Music.Theory.Time.Seq.Interpolation_T
+ Music.Theory.Time.Seq: instance GHC.Show.Show a => GHC.Show.Show (Music.Theory.Time.Seq.Begin_End a)
+ Music.Theory.Time.Seq: tseq_accumulate :: Eq a => Tseq t [Begin_End a] -> Tseq t [a]
+ Music.Theory.Time.Seq: tseq_begin_end_accum :: Eq a => Tseq t [Begin_End a] -> Tseq t ([a], [a], [a])
+ Music.Theory.Time.Seq: tseq_begin_end_to_wseq :: Num t => (a -> a -> Bool) -> Tseq t (Begin_End a) -> Wseq t a
+ Music.Theory.Time.Seq: useq_to_wseq :: Num t => t -> Useq t a -> Wseq t a
+ Music.Theory.Time.Seq: w_compare :: Ord t => ((t, t), a) -> ((t, t), a) -> Ordering
+ Music.Theory.Time.Seq: wseq_accumulate :: (Eq a, Ord t, Num t) => Wseq t a -> Tseq t [a]
+ Music.Theory.Time.Seq: wseq_append :: Num t => Wseq t a -> Wseq t a -> Wseq t a
+ Music.Theory.Time.Seq: wseq_at :: (Num t, Ord t) => Wseq t a -> t -> Wseq t a
+ Music.Theory.Time.Seq: wseq_at_window :: (Num t, Ord t) => Wseq t a -> (t, t) -> Wseq t a
+ Music.Theory.Time.Seq: wseq_begin_end :: (Num t, Ord t) => Wseq t a -> Tseq t (Begin_End a)
+ Music.Theory.Time.Seq: wseq_begin_end_either :: (Num t, Ord t) => Wseq t a -> Tseq t (Either a a)
+ Music.Theory.Time.Seq: wseq_begin_end_f :: (Ord t, Num t) => (a -> b) -> (a -> b) -> Wseq t a -> Tseq t b
+ Music.Theory.Time.Seq: wseq_concat :: Num t => [Wseq t a] -> Wseq t a
+ Music.Theory.Time.Seq: wseq_cycle :: Num t => Wseq t a -> Wseq t a
+ Music.Theory.Time.Seq: wseq_cycle' :: Num t => Wseq t a -> [Wseq t a]
+ Music.Theory.Time.Seq: wseq_cycle_n :: Num t => Int -> Wseq t a -> Wseq t a
+ Music.Theory.Time.Seq: wseq_cycle_until :: (Num t, Ord t) => t -> Wseq t a -> Wseq t a
+ Music.Theory.Time.Seq: wseq_end :: Num t => Wseq t a -> t
+ Music.Theory.Time.Seq: wseq_has_overlaps :: (Ord t, Num t, Eq e) => (e -> e -> Bool) -> Wseq t e -> Bool
+ Music.Theory.Time.Seq: wseq_merge_set :: Ord t => [Wseq t a] -> Wseq t a
+ Music.Theory.Time.Seq: wseq_overlap_f :: (Eq e, Ord t, Num t) => (e -> e -> Bool) -> (t -> t) -> ((t, t), e) -> Wseq t e -> Maybe (Wseq t e)
+ Music.Theory.Time.Seq: wseq_shift :: Num t => t -> Wseq t a -> Wseq t a
+ Music.Theory.Time.Seq: wseq_sort :: Ord t => Wseq t a -> Wseq t a
+ Music.Theory.Time.Seq: wseq_start :: Num t => Wseq t a -> t
+ Music.Theory.Time.Seq: wseq_until :: Ord t => t -> Wseq t a -> Wseq t a
+ Music.Theory.Time_Signature: ts_compare :: Time_Signature -> Time_Signature -> Ordering
+ Music.Theory.Tuning: [tn_octave_ratio] :: Tuning -> Rational
+ Music.Theory.Tuning: [tn_ratios_or_cents] :: Tuning -> Either [Rational] [Cents]
+ Music.Theory.Tuning: dtt_lookup :: (Eq k, Num v, Ord v) => [(k, v)] -> [v] -> k -> (Maybe v, Maybe v)
+ Music.Theory.Tuning: dtt_lookup_err :: (Eq k, Num v, Ord v) => [(k, v)] -> [v] -> k -> (k, v, v)
+ Music.Theory.Tuning: efg_collate :: Ord i => [i] -> EFG i
+ Music.Theory.Tuning: efg_degree :: EFG i -> Int
+ Music.Theory.Tuning: efg_diagram_set :: (Enum n, Real n) => (Cents -> n, n, n, n) -> [EFG n] -> [(n, n, n, n)]
+ Music.Theory.Tuning: efg_factors :: EFG i -> [([Int], [i])]
+ Music.Theory.Tuning: efg_ratios :: Real r => Rational -> EFG r -> [([Int], Rational)]
+ Music.Theory.Tuning: efg_tones :: EFG i -> Int
+ Music.Theory.Tuning: equal_temperament_96 :: Tuning
+ Music.Theory.Tuning: fold_ratio_to_octave' :: Integral i => Ratio i -> Ratio i
+ Music.Theory.Tuning: fold_ratio_to_octave_err :: Integral i => Ratio i -> Ratio i
+ Music.Theory.Tuning: gen_cps_tuning_tbl :: Sparse_Midi_Tuning_F -> MNN_CPS_Table
+ Music.Theory.Tuning: gen_dtt_lookup_f :: MNN_CPS_Table -> MNN_CPS_Table -> Midi_Tuning_F
+ Music.Theory.Tuning: gen_dtt_lookup_tbl :: MNN_CPS_Table -> MNN_CPS_Table -> MNN_CPS_Table
+ Music.Theory.Tuning: harmonic_series :: Integer -> Rational -> Tuning
+ Music.Theory.Tuning: harmonic_series_folded_r :: Integer -> [Rational]
+ Music.Theory.Tuning: instance GHC.Classes.Eq Music.Theory.Tuning.Tuning
+ Music.Theory.Tuning: instance GHC.Show.Show Music.Theory.Tuning.Tuning
+ Music.Theory.Tuning: lift_sparse_tuning_f :: Sparse_Midi_Tuning_F -> Sparse_Midi_Tuning_ST_F st
+ Music.Theory.Tuning: lift_tuning_f :: Midi_Tuning_F -> Sparse_Midi_Tuning_F
+ Music.Theory.Tuning: min_by :: Ord a => (t -> a) -> t -> t -> t
+ Music.Theory.Tuning: oct_diff_to_ratio :: Integral a => Ratio a -> Int -> Ratio a
+ Music.Theory.Tuning: ratio_nd_sum :: Num a => Ratio a -> a
+ Music.Theory.Tuning: recur_n :: Integral n => n -> (t -> t) -> t -> t
+ Music.Theory.Tuning: tn_approximate_ratios :: Tuning -> [Approximate_Ratio]
+ Music.Theory.Tuning: tn_approximate_ratios_cyclic :: Tuning -> [Approximate_Ratio]
+ Music.Theory.Tuning: tn_approximate_ratios_lookup :: Tuning -> Int -> Approximate_Ratio
+ Music.Theory.Tuning: tn_cents :: Tuning -> [Cents]
+ Music.Theory.Tuning: tn_cents_i :: Integral i => Tuning -> [i]
+ Music.Theory.Tuning: tn_cents_octave :: Tuning -> [Cents]
+ Music.Theory.Tuning: tn_divisions :: Tuning -> Int
+ Music.Theory.Tuning: tn_ratios :: Tuning -> Maybe [Rational]
+ Music.Theory.Tuning: tn_ratios_err :: Tuning -> [Rational]
+ Music.Theory.Tuning: tn_ratios_lookup :: Tuning -> Int -> Maybe Rational
+ Music.Theory.Tuning: tn_reconstructed_ratios :: Double -> Tuning -> Maybe [Rational]
+ Music.Theory.Tuning: type EFG i = [(i, Int)]
+ Music.Theory.Tuning: type MNN_CPS_Table = [(Int, Double)]
+ Music.Theory.Tuning: type Sparse_Midi_Tuning_F = Int -> Maybe Midi_Detune
+ Music.Theory.Tuning: type Sparse_Midi_Tuning_ST_F st = st -> Int -> (st, Maybe Midi_Detune)
+ Music.Theory.Tuning.DB: named_tuning_t :: Named_Tuning -> Tuning
+ Music.Theory.Tuning.DB: tuning_db :: [Named_Tuning]
+ Music.Theory.Tuning.DB: tuning_db_lookup_scl :: String -> Maybe Tuning
+ Music.Theory.Tuning.DB: type Named_Tuning = (String, String, String, String, Tuning, String)
+ Music.Theory.Tuning.DB.Alves: harrison_ditone :: Tuning
+ Music.Theory.Tuning.DB.Alves: harrison_ditone_r :: [Rational]
+ Music.Theory.Tuning.DB.Gann: ben_johnston_mtp_1977 :: Tuning
+ Music.Theory.Tuning.DB.Gann: ben_johnston_mtp_1977_r :: [Rational]
+ Music.Theory.Tuning.DB.Gann: gann_arcana_xvi :: Tuning
+ Music.Theory.Tuning.DB.Gann: gann_arcana_xvi_r :: [Rational]
+ Music.Theory.Tuning.DB.Gann: gann_superparticular :: Tuning
+ Music.Theory.Tuning.DB.Gann: gann_superparticular_r :: [Rational]
+ Music.Theory.Tuning.DB.Gann: pietro_aaron_1523 :: Tuning
+ Music.Theory.Tuning.DB.Gann: pietro_aaron_1523_c :: [Cents]
+ Music.Theory.Tuning.DB.Gann: thomas_young_1799 :: Tuning
+ Music.Theory.Tuning.DB.Gann: thomas_young_1799_c :: [Cents]
+ Music.Theory.Tuning.DB.Gann: zarlino_1588 :: Tuning
+ Music.Theory.Tuning.DB.Gann: zarlino_1588_r :: [Rational]
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: ben_johnston_25 :: Tuning
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: ben_johnston_25_r :: [Rational]
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: five_limit_tuning :: Tuning
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: five_limit_tuning_r :: [Rational]
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: kirnberger_iii :: Tuning
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: kirnberger_iii_ar :: [Approximate_Ratio]
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: lou_harrison_16 :: Tuning
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: lou_harrison_16_r :: [Rational]
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: mayumi_tsuda :: Tuning
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: mayumi_tsuda_r :: [Rational]
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: partch_43 :: Tuning
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: partch_43_r :: [Rational]
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: pythagorean_12 :: Tuning
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: pythagorean_12_r :: [Rational]
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: septimal_tritone_just_intonation :: Tuning
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: septimal_tritone_just_intonation_r :: [Rational]
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: seven_limit_just_intonation :: Tuning
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: seven_limit_just_intonation_r :: [Rational]
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: vallotti :: Tuning
+ Music.Theory.Tuning.DB.Microtonal_Synthesis: vallotti_c :: [Cents]
+ Music.Theory.Tuning.DB.Riley: riley_albion :: Tuning
+ Music.Theory.Tuning.DB.Riley: riley_albion_r :: [Rational]
+ Music.Theory.Tuning.DB.Werckmeister: werckmeister_iii :: Tuning
+ Music.Theory.Tuning.DB.Werckmeister: werckmeister_iii_ar :: [Approximate_Ratio]
+ Music.Theory.Tuning.DB.Werckmeister: werckmeister_iii_ar_c :: [Cents]
+ Music.Theory.Tuning.DB.Werckmeister: werckmeister_iv :: Tuning
+ Music.Theory.Tuning.DB.Werckmeister: werckmeister_iv_ar :: [Approximate_Ratio]
+ Music.Theory.Tuning.DB.Werckmeister: werckmeister_iv_c :: [Cents]
+ Music.Theory.Tuning.DB.Werckmeister: werckmeister_v :: Tuning
+ Music.Theory.Tuning.DB.Werckmeister: werckmeister_v_ar :: [Approximate_Ratio]
+ Music.Theory.Tuning.DB.Werckmeister: werckmeister_v_c :: [Cents]
+ Music.Theory.Tuning.DB.Werckmeister: werckmeister_vi :: Tuning
+ Music.Theory.Tuning.DB.Werckmeister: werckmeister_vi_r :: [Rational]
+ Music.Theory.Tuning.ET: octpc_to_pitch_cps_f0 :: (Floating n) => n -> OctPC -> (Pitch, n)
+ Music.Theory.Tuning.ET: tbl_12et_f0 :: Double -> [(Pitch, Double)]
+ Music.Theory.Tuning.ET: tbl_24et_f0 :: Double -> [(Pitch, Double)]
+ Music.Theory.Tuning.Euler: all_pairs :: [t] -> [u] -> [(t, u)]
+ Music.Theory.Tuning.Euler: cents_pp :: Rational -> String
+ Music.Theory.Tuning.Euler: euler_align_rat :: T2 Rational -> T3 [Rational] -> T2 [T2 Rational]
+ Music.Theory.Tuning.Euler: euler_plane_to_dot :: (t -> String, t -> String, (t, t) -> String) -> Euler_Plane t -> [String]
+ Music.Theory.Tuning.Euler: euler_plane_to_dot_rat :: (Int, Bool) -> Euler_Plane Rational -> [String]
+ Music.Theory.Tuning.Euler: mod12 :: Integral a => a -> a
+ Music.Theory.Tuning.Euler: pc_pp :: (Integral i, Show i) => i -> String
+ Music.Theory.Tuning.Euler: rat_div :: Rational -> Rational -> Rational
+ Music.Theory.Tuning.Euler: rat_edge_label :: (Rational, Rational) -> String
+ Music.Theory.Tuning.Euler: rat_id :: Rational -> String
+ Music.Theory.Tuning.Euler: rat_label :: (Int, Bool) -> Rational -> String
+ Music.Theory.Tuning.Euler: rat_mul :: Rational -> Rational -> Rational
+ Music.Theory.Tuning.Euler: ratio_to_pc :: Int -> Rational -> Int
+ Music.Theory.Tuning.Euler: tun_seq :: Int -> Rational -> Rational -> [Rational]
+ Music.Theory.Tuning.Euler: type Euler_Plane t = ([[t]], [(t, t)])
+ Music.Theory.Tuning.Euler: zip_sme :: (t, t, t) -> [u] -> [(t, u)]
+ Music.Theory.Tuning.Gann_1993: lmy_wtp :: Tuning
+ Music.Theory.Tuning.Gann_1993: lmy_wtp_1964 :: Tuning
+ Music.Theory.Tuning.Gann_1993: lmy_wtp_1964_r :: [Rational]
+ Music.Theory.Tuning.Gann_1993: lmy_wtp_euler :: Euler_Plane Rational
+ Music.Theory.Tuning.Gann_1993: lmy_wtp_r :: [Rational]
+ Music.Theory.Tuning.Gann_1993: lmy_wtp_ratio_to_pc :: Rational -> Maybe PitchClass
+ Music.Theory.Tuning.Gann_1993: lmy_wtp_ratio_to_pc_err :: Rational -> PitchClass
+ Music.Theory.Tuning.Gann_1993: lmy_wtp_uniq :: [(Rational, [(PitchClass, PitchClass)])]
+ Music.Theory.Tuning.Gann_1993: lmy_wtp_univ :: [(Rational, (PitchClass, PitchClass))]
+ Music.Theory.Tuning.Load: default_choose_f :: RandomGen g => Choose_f g t
+ Music.Theory.Tuning.Load: load_cps_tbl :: FilePath -> IO [(Int, Double)]
+ Music.Theory.Tuning.Load: load_tuning_cps :: (String, Double, Int) -> IO Sparse_Midi_Tuning_F
+ Music.Theory.Tuning.Load: load_tuning_d12 :: (String, Double, Int) -> IO Sparse_Midi_Tuning_F
+ Music.Theory.Tuning.Load: load_tuning_scl :: String -> IO Tuning
+ Music.Theory.Tuning.Load: load_tuning_st_ty :: String -> (String, Double, Int) -> IO (Sparse_Midi_Tuning_ST_F StdGen)
+ Music.Theory.Tuning.Load: load_tuning_tbl :: (String, Double, Int) -> IO Sparse_Midi_Tuning_F
+ Music.Theory.Tuning.Load: load_tuning_tbl_st :: Choose_f st (Int, Double) -> (String, Double, Int) -> IO (Sparse_Midi_Tuning_ST_F st)
+ Music.Theory.Tuning.Load: load_tuning_ty :: String -> (String, Double, Int) -> IO Sparse_Midi_Tuning_F
+ Music.Theory.Tuning.Load: type Choose_f st t = [t] -> st -> (t, st)
+ Music.Theory.Tuning.Polansky_1978: psaltery_o_r :: [Rational]
+ Music.Theory.Tuning.Polansky_1978: psaltery_r :: [Rational]
+ Music.Theory.Tuning.Rosenboom_1979: dr_chords :: [[Pitch]]
+ Music.Theory.Tuning.Rosenboom_1979: dr_nt :: Integral i => [([i], [i])]
+ Music.Theory.Tuning.Rosenboom_1979: dr_nt_pitch :: ([Int], [Int]) -> ([Pitch], [Pitch])
+ Music.Theory.Tuning.Rosenboom_1979: dr_ratio_seq :: Num n => [[(n, n)]]
+ Music.Theory.Tuning.Rosenboom_1979: dr_ratio_seq_hist :: (Ord n, Num n) => [((n, n), Int)]
+ Music.Theory.Tuning.Rosenboom_1979: dr_scale :: [Double]
+ Music.Theory.Tuning.Rosenboom_1979: dr_scale_scala :: Scale Integer
+ Music.Theory.Tuning.Rosenboom_1979: dr_scale_tbl_12et :: [HS_R Pitch]
+ Music.Theory.Tuning.Rosenboom_1979: dr_scale_tbl_24et :: [HS_R Pitch]
+ Music.Theory.Tuning.Rosenboom_1979: dr_tuning :: [Rational]
+ Music.Theory.Tuning.Rosenboom_1979: dr_tuning_oct :: Num n => [[(n, n)]]
+ Music.Theory.Tuning.Rosenboom_1979: t2_to_ratio :: (Integer, Integer) -> Rational
+ Music.Theory.Tuning.Scala: Pitch_Cents :: Pitch_Type
+ Music.Theory.Tuning.Scala: Pitch_Ratio :: Pitch_Type
+ Music.Theory.Tuning.Scala: data Pitch_Type
+ Music.Theory.Tuning.Scala: dist_get_dir :: IO String
+ Music.Theory.Tuning.Scala: instance GHC.Classes.Eq Music.Theory.Tuning.Scala.Pitch_Type
+ Music.Theory.Tuning.Scala: instance GHC.Show.Show Music.Theory.Tuning.Scala.Pitch_Type
+ Music.Theory.Tuning.Scala: is_comment :: String -> Bool
+ Music.Theory.Tuning.Scala: is_scale_uniform :: Scale i -> Bool
+ Music.Theory.Tuning.Scala: load_dist_file :: FilePath -> IO [String]
+ Music.Theory.Tuning.Scala: parse_pitch :: (Read i, Integral i) => String -> Pitch i
+ Music.Theory.Tuning.Scala: parse_pitch_ln :: (Read i, Integral i) => String -> Pitch i
+ Music.Theory.Tuning.Scala: parse_scl :: (Read i, Integral i) => String -> String -> Scale i
+ Music.Theory.Tuning.Scala: pitch_pp :: Show i => Pitch i -> String
+ Music.Theory.Tuning.Scala: pitch_representations :: Integral t => [Pitch i] -> (t, t)
+ Music.Theory.Tuning.Scala: pitch_type :: Pitch i -> Pitch_Type
+ Music.Theory.Tuning.Scala: pitch_type_predominant :: [Pitch i] -> Pitch_Type
+ Music.Theory.Tuning.Scala: scale_cents_i :: Integral i => Scale i -> [i]
+ Music.Theory.Tuning.Scala: scale_eq :: Eq n => Scale n -> Scale n -> Bool
+ Music.Theory.Tuning.Scala: scale_eqv :: Integral n => Scale n -> Scale n -> Bool
+ Music.Theory.Tuning.Scala: scale_name :: Scale i -> String
+ Music.Theory.Tuning.Scala: scale_pp :: Show i => Scale i -> [String]
+ Music.Theory.Tuning.Scala: scale_ratios_req :: Integral i => Scale i -> [Ratio i]
+ Music.Theory.Tuning.Scala: scale_stat :: (Integral i, Show i) => Scale i -> [String]
+ Music.Theory.Tuning.Scala: scale_to_tuning :: Epsilon -> Scale Integer -> Tuning
+ Music.Theory.Tuning.Scala: scale_verify :: Scale i -> Bool
+ Music.Theory.Tuning.Scala: scale_verify_err :: Scale i -> Scale i
+ Music.Theory.Tuning.Scala: scl_derive_filename :: FilePath -> IO FilePath
+ Music.Theory.Tuning.Scala: scl_get_dir :: IO [String]
+ Music.Theory.Tuning.Scala: scl_load :: (Read i, Integral i) => String -> IO (Scale i)
+ Music.Theory.Tuning.Scala: scl_load_db :: (Read i, Integral i) => IO [Scale i]
+ Music.Theory.Tuning.Scala: scl_load_dir :: (Read i, Integral i) => FilePath -> IO [Scale i]
+ Music.Theory.Tuning.Scala: scl_load_tuning :: Epsilon -> String -> IO Tuning
+ Music.Theory.Tuning.Scala: scl_resolve_name :: String -> IO FilePath
+ Music.Theory.Tuning.Scala: tuning_to_scale :: (String, String) -> Tuning -> Scale Integer
+ Music.Theory.Tuning.Scala: uniform_pitch_type :: [Pitch i] -> Maybe Pitch_Type
+ Music.Theory.Tuning.Scala.Interval: intnam_search_description_ci :: INTNAM -> String -> [INTERVAL]
+ Music.Theory.Tuning.Scala.Interval: intnam_search_ratio :: INTNAM -> Rational -> Maybe INTERVAL
+ Music.Theory.Tuning.Scala.Interval: load_intnam :: IO INTNAM
+ Music.Theory.Tuning.Scala.Interval: parse_intnam :: [String] -> INTNAM
+ Music.Theory.Tuning.Scala.Interval: parse_intnam_entry :: [String] -> INTERVAL
+ Music.Theory.Tuning.Scala.Interval: type INTERVAL = (Rational, String)
+ Music.Theory.Tuning.Scala.Interval: type INTNAM = (Int, [INTERVAL])
+ Music.Theory.Tuning.Scala.Mode: is_integer :: String -> Bool
+ Music.Theory.Tuning.Scala.Mode: is_non_implicit_degree :: String -> Bool
+ Music.Theory.Tuning.Scala.Mode: join_long_lines :: [String] -> [String]
+ Music.Theory.Tuning.Scala.Mode: load_modenam :: IO MODENAM
+ Music.Theory.Tuning.Scala.Mode: mode_degree :: MODE -> Int
+ Music.Theory.Tuning.Scala.Mode: mode_description :: MODE -> String
+ Music.Theory.Tuning.Scala.Mode: mode_intervals :: MODE -> [Int]
+ Music.Theory.Tuning.Scala.Mode: mode_starting_degree :: MODE -> Int
+ Music.Theory.Tuning.Scala.Mode: mode_stat :: MODE -> [String]
+ Music.Theory.Tuning.Scala.Mode: modenam_modes :: MODENAM -> [MODE]
+ Music.Theory.Tuning.Scala.Mode: modenam_search_description :: MODENAM -> String -> [MODE]
+ Music.Theory.Tuning.Scala.Mode: modenam_search_seq :: MODENAM -> [Int] -> [MODE]
+ Music.Theory.Tuning.Scala.Mode: modenam_search_seq1 :: MODENAM -> [Int] -> Maybe MODE
+ Music.Theory.Tuning.Scala.Mode: non_implicit_degree :: String -> Maybe Int
+ Music.Theory.Tuning.Scala.Mode: parse_modenam :: [String] -> MODENAM
+ Music.Theory.Tuning.Scala.Mode: parse_modenam_entry :: [String] -> MODE
+ Music.Theory.Tuning.Scala.Mode: type MODE = (Int, [Int], String)
+ Music.Theory.Tuning.Scala.Mode: type MODENAM = (Int, Int, [MODE])
+ Music.Theory.Tuning.Sethares_1994: d :: (Floating n, Ord n) => (n, n) -> (n, n) -> n
+ Music.Theory.Tuning.Sethares_1994: d_h :: (Floating n, Ord n) => [(n, n)] -> [(n, n)] -> n
+ Music.Theory.Tuning.Sethares_1994: fig_1 :: (Floating n, Enum n, Ord n) => [[n]]
+ Music.Theory.Tuple: p5_from_list :: (t -> t1, t -> t2, t -> t3, t -> t4, t -> t5) -> [t] -> (t1, t2, t3, t4, t5)
+ Music.Theory.Tuple: p5_to_list :: (t1 -> t, t2 -> t, t3 -> t, t4 -> t, t5 -> t) -> (t1, t2, t3, t4, t5) -> [t]
+ Music.Theory.Tuple: p8_third :: (a, b, c, d, e, f, g, h) -> c
+ Music.Theory.Tuple: t10_map :: (p -> q) -> T10 p -> T10 q
+ Music.Theory.Tuple: t10_to_list :: T10 t -> [t]
+ Music.Theory.Tuple: t11_map :: (p -> q) -> T11 p -> T11 q
+ Music.Theory.Tuple: t11_to_list :: T11 t -> [t]
+ Music.Theory.Tuple: t12_foldr1 :: (t -> t -> t) -> T12 t -> t
+ Music.Theory.Tuple: t12_from_list :: [t] -> T12 t
+ Music.Theory.Tuple: t12_sum :: Num n => T12 n -> n
+ Music.Theory.Tuple: t12_to_list :: T12 t -> [t]
+ Music.Theory.Tuple: t2_from_list :: [t] -> T2 t
+ Music.Theory.Tuple: t2_to_list :: T2 a -> [a]
+ Music.Theory.Tuple: t3_from_list :: [t] -> T3 t
+ Music.Theory.Tuple: t3_to_list :: T3 a -> [a]
+ Music.Theory.Tuple: t4_from_list :: [t] -> T4 t
+ Music.Theory.Tuple: t4_to_list :: T4 t -> [t]
+ Music.Theory.Tuple: t5_from_list :: [t] -> T5 t
+ Music.Theory.Tuple: t5_to_list :: T5 t -> [t]
+ Music.Theory.Tuple: t6_from_list :: [t] -> T6 t
+ Music.Theory.Tuple: t6_to_list :: T6 t -> [t]
+ Music.Theory.Tuple: t7_to_list :: T7 t -> [t]
+ Music.Theory.Tuple: t8_to_list :: T8 t -> [t]
+ Music.Theory.Tuple: t9_to_list :: T9 t -> [t]
+ Music.Theory.Tuple: type T10 a = (a, a, a, a, a, a, a, a, a, a)
+ Music.Theory.Tuple: type T11 a = (a, a, a, a, a, a, a, a, a, a, a)
+ Music.Theory.Tuple: type T12 t = (t, t, t, t, t, t, t, t, t, t, t, t)
+ Music.Theory.Unicode: accidentals_rng_set :: [Unicode_Range]
+ Music.Theory.Unicode: articulations :: Unicode_Table
+ Music.Theory.Unicode: articulations_rng :: Unicode_Range
+ Music.Theory.Unicode: augmentation_dot :: Unicode_Point
+ Music.Theory.Unicode: clefs_rng :: Unicode_Range
+ Music.Theory.Unicode: dynamics :: Unicode_Table
+ Music.Theory.Unicode: dynamics_rng :: Unicode_Range
+ Music.Theory.Unicode: non_breaking_hypen :: Char
+ Music.Theory.Unicode: non_breaking_space :: Char
+ Music.Theory.Unicode: notehead_rng :: Unicode_Range
+ Music.Theory.Unicode: noteheads :: Unicode_Table
+ Music.Theory.Unicode: notes_rng :: Unicode_Range
+ Music.Theory.Unicode: rests_rng :: Unicode_Range
+ Music.Theory.Unicode: stem :: Unicode_Point
+ Music.Theory.Unicode: type Unicode_Block = (Unicode_Range, String)
+ Music.Theory.Unicode: type Unicode_Index = Int
+ Music.Theory.Unicode: type Unicode_Point = (Unicode_Index, String)
+ Music.Theory.Unicode: type Unicode_Range = (Unicode_Index, Unicode_Index)
+ Music.Theory.Unicode: unicode_blocks :: [Unicode_Block]
+ Music.Theory.Unicode: unicode_data_table_read :: FilePath -> IO Unicode_Table
+ Music.Theory.Unicode: unicode_point_hs :: Unicode_Point -> String
+ Music.Theory.Unicode: unicode_table_block :: (Int, Int) -> Unicode_Table -> Unicode_Table
+ Music.Theory.Unicode: unicode_table_hs :: Unicode_Table -> String
+ Music.Theory.Wyschnegradsky: Circumferential :: [a] -> Seq a
+ Music.Theory.Wyschnegradsky: Radial :: [a] -> Seq a
+ Music.Theory.Wyschnegradsky: add_m :: Integral a => a -> a -> a -> a
+ Music.Theory.Wyschnegradsky: clr_normalise :: (Real r, Fractional f) => f -> (r, r, r) -> (f, f, f)
+ Music.Theory.Wyschnegradsky: data Seq a
+ Music.Theory.Wyschnegradsky: dc9_circ :: Num n => [[n]]
+ Music.Theory.Wyschnegradsky: dc9_clr_hex :: [String]
+ Music.Theory.Wyschnegradsky: dc9_clr_rgb :: Fractional n => [(n, n, n)]
+ Music.Theory.Wyschnegradsky: dc9_ix :: Integral n => [[n]]
+ Music.Theory.Wyschnegradsky: dc9_rad :: Num n => [n]
+ Music.Theory.Wyschnegradsky: iw_pc_pp :: Integral n => String -> [[n]] -> IO ()
+ Music.Theory.Wyschnegradsky: normalise_step :: (Eq n, Num n) => n -> n -> n
+ Music.Theory.Wyschnegradsky: parse_hex_clr :: (Read n, Num n) => String -> (n, n, n)
+ Music.Theory.Wyschnegradsky: parse_hex_clr_int :: String -> (Int, Int, Int)
+ Music.Theory.Wyschnegradsky: parse_num_sign :: (Num n, Read n) => String -> n
+ Music.Theory.Wyschnegradsky: parse_vec :: Num n => Maybe Int -> n -> String -> [n]
+ Music.Theory.Wyschnegradsky: seq_group :: Int -> Int -> Seq a -> [[a]]
+ Music.Theory.Wyschnegradsky: u11_circ :: Num n => [[n]]
+ Music.Theory.Wyschnegradsky: u11_clr_hex :: [String]
+ Music.Theory.Wyschnegradsky: u11_clr_rgb :: Fractional n => [(n, n, n)]
+ Music.Theory.Wyschnegradsky: u11_gen_seq :: Integral i => i -> Int -> [i] -> [i]
+ Music.Theory.Wyschnegradsky: u11_rad :: Integral n => [[n]]
+ Music.Theory.Wyschnegradsky: u11_seq_rule :: Integral i => Maybe Int -> [i]
+ Music.Theory.Wyschnegradsky: u3_ch_ix :: Char -> Int
+ Music.Theory.Wyschnegradsky: u3_ch_seq_to_vec :: [Char] -> [Int]
+ Music.Theory.Wyschnegradsky: u3_circ_ch :: [(Int, [Char])]
+ Music.Theory.Wyschnegradsky: u3_clr_hex :: [String]
+ Music.Theory.Wyschnegradsky: u3_clr_nm :: [String]
+ Music.Theory.Wyschnegradsky: u3_clr_rgb :: Fractional n => [(n, n, n)]
+ Music.Theory.Wyschnegradsky: u3_ix_ch :: Integral i => i -> Char
+ Music.Theory.Wyschnegradsky: u3_ix_radial :: Integral n => [[n]]
+ Music.Theory.Wyschnegradsky: u3_radial_ch :: [(Int, [Char])]
+ Music.Theory.Wyschnegradsky: u3_vec_ix :: Num n => ([[n]], [[n]])
+ Music.Theory.Wyschnegradsky: u3_vec_text_iw :: [(String, String)]
+ Music.Theory.Wyschnegradsky: u3_vec_text_rw :: [(String, String)]
+ Music.Theory.Wyschnegradsky: ull_rad_text :: [Char]
+ Music.Theory.Wyschnegradsky: vec_expand :: Num n => Int -> [n]
+ Music.Theory.Xenakis.S4: fib_proc :: (a -> a -> a) -> a -> a -> [a]
+ Music.Theory.Xenakis.S4: instance GHC.Classes.Eq Music.Theory.Xenakis.S4.Face
+ Music.Theory.Xenakis.S4: instance GHC.Classes.Eq Music.Theory.Xenakis.S4.Label
+ Music.Theory.Xenakis.S4: instance GHC.Classes.Ord Music.Theory.Xenakis.S4.Face
+ Music.Theory.Xenakis.S4: instance GHC.Classes.Ord Music.Theory.Xenakis.S4.Label
+ Music.Theory.Xenakis.S4: instance GHC.Enum.Bounded Music.Theory.Xenakis.S4.Face
+ Music.Theory.Xenakis.S4: instance GHC.Enum.Bounded Music.Theory.Xenakis.S4.Label
+ Music.Theory.Xenakis.S4: instance GHC.Enum.Enum Music.Theory.Xenakis.S4.Face
+ Music.Theory.Xenakis.S4: instance GHC.Enum.Enum Music.Theory.Xenakis.S4.Label
+ Music.Theory.Xenakis.S4: instance GHC.Show.Show Music.Theory.Xenakis.S4.Face
+ Music.Theory.Xenakis.S4: instance GHC.Show.Show Music.Theory.Xenakis.S4.Label
+ Music.Theory.Xenakis.S4: viii_6_lseq :: [Label]
+ Music.Theory.Xenakis.S4: viii_6b_lseq :: [Label]
+ Music.Theory.Xenakis.S4: viii_7_lseq :: [Label]
+ Music.Theory.Xenakis.Sieve: Complement :: Sieve -> Sieve
+ Music.Theory.Xenakis.Sieve: c :: Sieve -> Sieve
+ Music.Theory.Xenakis.Sieve: i_complement :: [I] -> [I]
+ Music.Theory.Xenakis.Sieve: infixl 3 ∪
+ Music.Theory.Xenakis.Sieve: infixl 4 ∩
+ Music.Theory.Xenakis.Sieve: infixl 5 ⋄
+ Music.Theory.Xenakis.Sieve: instance GHC.Classes.Eq Music.Theory.Xenakis.Sieve.Sieve
+ Music.Theory.Xenakis.Sieve: instance GHC.Show.Show Music.Theory.Xenakis.Sieve.Sieve
+ Music.Theory.Xenakis.Sieve: sieve_pp :: Sieve -> String
+ Music.Theory.Z: div_err :: Integral i => String -> i -> i -> i
+ Music.Theory.Z: integral_to_digit :: Integral t => t -> Char
+ Music.Theory.Z: is_z16 :: Integral t => t -> Bool
+ Music.Theory.Z: is_z_n :: (Num a, Ord a) => a -> a -> Bool
+ Music.Theory.Z: mod12 :: Integral i => Z i
+ Music.Theory.Z: mod16 :: Integral i => Z i
+ Music.Theory.Z: mod5 :: Integral i => Z i
+ Music.Theory.Z: mod7 :: Integral i => Z i
+ Music.Theory.Z: type Z t = t -> t
+ Music.Theory.Z: z16_seq_pp :: Integral t => [t] -> String
+ Music.Theory.Z: z16_set_pp :: Integral t => [t] -> String
+ Music.Theory.Z: z16_to_char :: Integral t => t -> Char
+ Music.Theory.Z: z16_vec_pp :: Integral t => [t] -> String
+ Music.Theory.Z: z_modulus :: Integral i => Z i -> i
+ Music.Theory.Z: z_univ :: Integral i => Z i -> [i]
+ Music.Theory.Z.Boros_1990: all_tn :: Integral i => [i] -> [[i]]
+ Music.Theory.Z.Boros_1990: all_tni :: Integral i => [i] -> [[i]]
+ Music.Theory.Z.Boros_1990: ath :: PCSET
+ Music.Theory.Z.Boros_1990: ath_complement :: PCSET -> PCSET
+ Music.Theory.Z.Boros_1990: ath_completions :: PCSET -> SC -> [PCSET]
+ Music.Theory.Z.Boros_1990: ath_gr_extend :: GRAPH PCSET -> PCSET -> [EDGE PCSET]
+ Music.Theory.Z.Boros_1990: ath_pp :: PCSET -> String
+ Music.Theory.Z.Boros_1990: ath_tni :: PCSET -> TTO PC
+ Music.Theory.Z.Boros_1990: ath_trichords :: [PCSET]
+ Music.Theory.Z.Boros_1990: ath_univ :: [PCSET]
+ Music.Theory.Z.Boros_1990: d_fig_1 :: [String]
+ Music.Theory.Z.Boros_1990: d_fig_3 :: [String]
+ Music.Theory.Z.Boros_1990: d_fig_3' :: [[String]]
+ Music.Theory.Z.Boros_1990: d_fig_3_g :: GR
+ Music.Theory.Z.Boros_1990: d_fig_4 :: [String]
+ Music.Theory.Z.Boros_1990: d_fig_4_g :: GR
+ Music.Theory.Z.Boros_1990: d_fig_5 :: [String]
+ Music.Theory.Z.Boros_1990: d_fig_5' :: [String]
+ Music.Theory.Z.Boros_1990: d_fig_5_e :: [EDGE_L PCSET PCSET]
+ Music.Theory.Z.Boros_1990: d_fig_5_g :: GR
+ Music.Theory.Z.Boros_1990: d_fig_5_g' :: Gr PCSET PCSET
+ Music.Theory.Z.Boros_1990: elem_by :: (t -> t -> Bool) -> t -> [t] -> Bool
+ Music.Theory.Z.Boros_1990: fig_1 :: GRAPH PCSET
+ Music.Theory.Z.Boros_1990: fig_1_gr :: Gr PCSET ()
+ Music.Theory.Z.Boros_1990: fig_2 :: [[PCSET]]
+ Music.Theory.Z.Boros_1990: fig_3 :: [GRAPH PCSET]
+ Music.Theory.Z.Boros_1990: fig_3_gr :: [Gr PCSET ()]
+ Music.Theory.Z.Boros_1990: fig_4 :: [GRAPH PCSET]
+ Music.Theory.Z.Boros_1990: fig_5 :: [GRAPH PCSET]
+ Music.Theory.Z.Boros_1990: gr_pp :: GR_PP PCSET ()
+ Music.Theory.Z.Boros_1990: gr_pp' :: (PCSET -> String) -> GR_PP PCSET ()
+ Music.Theory.Z.Boros_1990: gr_trs :: Int -> GRAPH PCSET -> GRAPH PCSET
+ Music.Theory.Z.Boros_1990: is_ath :: PCSET -> Bool
+ Music.Theory.Z.Boros_1990: pcset_pp :: PCSET -> String
+ Music.Theory.Z.Boros_1990: pcset_pp_hex :: PCSET -> String
+ Music.Theory.Z.Boros_1990: pcset_trs :: Int -> PCSET -> PCSET
+ Music.Theory.Z.Boros_1990: realise_ath_seq :: [PCSET] -> [[PCSET]]
+ Music.Theory.Z.Boros_1990: self_inv :: PCSET -> Bool
+ Music.Theory.Z.Boros_1990: set_eq :: Ord t => [t] -> [t] -> Bool
+ Music.Theory.Z.Boros_1990: set_shape :: PCSET -> String
+ Music.Theory.Z.Boros_1990: singular :: String -> [t] -> t
+ Music.Theory.Z.Boros_1990: table_3 :: [((PCSET, SC, SC_Name), (PCSET, SC, SC_Name))]
+ Music.Theory.Z.Boros_1990: table_3_md :: [String]
+ Music.Theory.Z.Boros_1990: table_4 :: [((PCSET, PCSET, SC_Name), (PCSET, PCSET, SC_Name))]
+ Music.Theory.Z.Boros_1990: table_4_md :: [String]
+ Music.Theory.Z.Boros_1990: table_5 :: [(PCSET, Int)]
+ Music.Theory.Z.Boros_1990: table_5_md :: [String]
+ Music.Theory.Z.Boros_1990: table_6 :: [(PCSET, Int, Int)]
+ Music.Theory.Z.Boros_1990: table_6_md :: [String]
+ Music.Theory.Z.Boros_1990: trichords :: [PCSET]
+ Music.Theory.Z.Boros_1990: tto_tni_univ :: Integral i => [TTO i]
+ Music.Theory.Z.Boros_1990: type GR = Gr PCSET ()
+ Music.Theory.Z.Boros_1990: type PC = Int
+ Music.Theory.Z.Boros_1990: type PCSET = [PC]
+ Music.Theory.Z.Boros_1990: type SC = PCSET
+ Music.Theory.Z.Boros_1990: uedge_set :: Ord v => [EDGE v] -> [EDGE v]
+ Music.Theory.Z.Boros_1990: uniq_tni :: Integral i => [i] -> [[i]]
+ Music.Theory.Z.Clough_1979: chord_to_dpcset :: Integral n => [n] -> [n]
+ Music.Theory.Z.Clough_1979: complement :: Integral n => [n] -> [n]
+ Music.Theory.Z.Clough_1979: dpcset_complement :: Integral n => [n] -> [n]
+ Music.Theory.Z.Clough_1979: dpcset_to_chord :: Integral n => [n] -> [n]
+ Music.Theory.Z.Clough_1979: i_to_ic :: Integral n => n -> n
+ Music.Theory.Z.Clough_1979: inf :: Integral n => [n] -> [n]
+ Music.Theory.Z.Clough_1979: inf_cmp :: Ord a => [a] -> [a] -> Ordering
+ Music.Theory.Z.Clough_1979: invert :: [n] -> [n]
+ Music.Theory.Z.Clough_1979: is_chord :: Integral n => [n] -> Bool
+ Music.Theory.Z.Clough_1979: is_ic :: Integral n => n -> Bool
+ Music.Theory.Z.Clough_1979: is_z4 :: Integral n => n -> Bool
+ Music.Theory.Z.Clough_1979: is_z7 :: Integral n => n -> Bool
+ Music.Theory.Z.Clough_1979: is_z_n :: Integral n => n -> n -> Bool
+ Music.Theory.Z.Clough_1979: iseq :: Integral n => [n] -> [n]
+ Music.Theory.Z.Clough_1979: iv :: Integral n => [n] -> [n]
+ Music.Theory.Z.Clough_1979: mod7 :: Integral n => n -> n
+ Music.Theory.Z.Clough_1979: transpose_to_zero :: Num n => [n] -> [n]
+ Music.Theory.Z.Clough_1979: z7_univ :: Integral n => [n]
+ Music.Theory.Z.Clough_1979: z_n_univ :: Integral n => n -> [n]
+ Music.Theory.Z.Drape_1999: rs :: Integral t => t -> Z t -> [t] -> [t] -> [TTO t]
+ Music.Theory.Z.Drape_1999: rsg :: Integral i => i -> Z i -> [i] -> [i] -> [SRO i]
+ Music.Theory.Z.Forte_1973: forte_prime_name :: (Num n, Eq n) => [n] -> (SC_Name, [n])
+ Music.Theory.Z.Forte_1973: sc :: Num n => SC_Name -> [n]
+ Music.Theory.Z.Forte_1973: sc_name :: Integral i => Z i -> [i] -> SC_Name
+ Music.Theory.Z.Forte_1973: sc_name' :: Integral i => Z i -> [(SC_Name, [i])] -> [i] -> SC_Name
+ Music.Theory.Z.Forte_1973: sc_name_long :: Integral i => Z i -> [i] -> SC_Name
+ Music.Theory.Z.Forte_1973: sc_name_unicode :: Integral i => Z i -> [i] -> SC_Name
+ Music.Theory.Z.Forte_1973: sc_table :: Num n => [(SC_Name, [n])]
+ Music.Theory.Z.Forte_1973: sc_table_unicode :: Num n => [(SC_Name, [n])]
+ Music.Theory.Z.Forte_1973: sc_tbl_lookup :: Integral i => Z i -> [(SC_Name, [i])] -> [i] -> Maybe (SC_Name, [i])
+ Music.Theory.Z.Forte_1973: sc_tbl_lookup_err :: Integral i => Z i -> [(SC_Name, [i])] -> [i] -> (SC_Name, [i])
+ Music.Theory.Z.Forte_1973: sc_univ :: Integral i => Z i -> [[i]]
+ Music.Theory.Z.Forte_1973: scs :: Num n => [[n]]
+ Music.Theory.Z.Forte_1973: scs_n :: (Integral i, Num n) => i -> [[n]]
+ Music.Theory.Z.Forte_1973: tics :: Integral i => Z i -> [i] -> [Int]
+ Music.Theory.Z.Forte_1973: type SC_Name = String
+ Music.Theory.Z.Forte_1973: z_relation_of :: Integral i => i -> [i] -> Maybe [i]
+ Music.Theory.Z.SRO: SRO :: Int -> Bool -> t -> Bool -> Bool -> SRO t
+ Music.Theory.Z.SRO: [sro_I] :: SRO t -> Bool
+ Music.Theory.Z.SRO: [sro_M] :: SRO t -> Bool
+ Music.Theory.Z.SRO: [sro_R] :: SRO t -> Bool
+ Music.Theory.Z.SRO: [sro_T] :: SRO t -> t
+ Music.Theory.Z.SRO: [sro_r] :: SRO t -> Int
+ Music.Theory.Z.SRO: data SRO t
+ Music.Theory.Z.SRO: instance GHC.Classes.Eq t => GHC.Classes.Eq (Music.Theory.Z.SRO.SRO t)
+ Music.Theory.Z.SRO: instance GHC.Show.Show t => GHC.Show.Show (Music.Theory.Z.SRO.SRO t)
+ Music.Theory.Z.SRO: p_sro :: Integral t => GenParser Char () (SRO t)
+ Music.Theory.Z.SRO: sro_parse :: Integral i => String -> SRO i
+ Music.Theory.Z.SRO: sro_pp :: Show t => SRO t -> String
+ Music.Theory.Z.SRO: z_sro_RTnI :: Integral i => Z i -> [SRO i]
+ Music.Theory.Z.SRO: z_sro_RTnMI :: Integral i => Z i -> [SRO i]
+ Music.Theory.Z.SRO: z_sro_Tn :: Integral i => Z i -> [SRO i]
+ Music.Theory.Z.SRO: z_sro_TnI :: Integral i => Z i -> [SRO i]
+ Music.Theory.Z.SRO: z_sro_TnMI :: Integral i => Z i -> [SRO i]
+ Music.Theory.Z.SRO: z_sro_apply :: Integral i => i -> Z i -> SRO i -> [i] -> [i]
+ Music.Theory.Z.SRO: z_sro_invert :: (Integral i, Functor f) => Z i -> i -> f i -> f i
+ Music.Theory.Z.SRO: z_sro_invert_ix :: Integral i => Z i -> Int -> [i] -> [i]
+ Music.Theory.Z.SRO: z_sro_mn :: (Integral i, Functor f) => Z i -> i -> f i -> f i
+ Music.Theory.Z.SRO: z_sro_rti_related :: Integral i => Z i -> [i] -> [[i]]
+ Music.Theory.Z.SRO: z_sro_t_related :: (Integral i, Functor f) => Z i -> f i -> [f i]
+ Music.Theory.Z.SRO: z_sro_ti_related :: (Eq (f i), Integral i, Functor f) => Z i -> f i -> [f i]
+ Music.Theory.Z.SRO: z_sro_tn :: (Integral i, Functor f) => Z i -> i -> f i -> f i
+ Music.Theory.Z.SRO: z_sro_tn_to :: Integral i => Z i -> i -> [i] -> [i]
+ Music.Theory.Z.SRO: z_sro_tni :: (Integral i, Functor f) => Z i -> i -> f i -> f i
+ Music.Theory.Z.SRO: z_sro_univ :: Integral i => Int -> Z i -> [SRO i]
+ Music.Theory.Z.SRO: z_tmatrix :: Integral i => Z i -> [i] -> [[i]]
+ Music.Theory.Z.TTO: TTO :: t -> Bool -> Bool -> TTO t
+ Music.Theory.Z.TTO: [tto_I] :: TTO t -> Bool
+ Music.Theory.Z.TTO: [tto_M] :: TTO t -> Bool
+ Music.Theory.Z.TTO: [tto_T] :: TTO t -> t
+ Music.Theory.Z.TTO: data TTO t
+ Music.Theory.Z.TTO: instance GHC.Classes.Eq t => GHC.Classes.Eq (Music.Theory.Z.TTO.TTO t)
+ Music.Theory.Z.TTO: instance GHC.Show.Show t => GHC.Show.Show (Music.Theory.Z.TTO.TTO t)
+ Music.Theory.Z.TTO: p_tto :: Integral t => GenParser Char () (TTO t)
+ Music.Theory.Z.TTO: tto_apply :: Integral t => t -> TTO t -> [t] -> [t]
+ Music.Theory.Z.TTO: tto_identity :: Num t => TTO t
+ Music.Theory.Z.TTO: tto_parse :: Integral i => String -> TTO i
+ Music.Theory.Z.TTO: tto_pp :: Show t => TTO t -> String
+ Music.Theory.Z.TTO: z_pcset :: Ord t => Z t -> [t] -> [t]
+ Music.Theory.Z.TTO: z_tto_apply :: Integral t => t -> Z t -> TTO t -> [t] -> [t]
+ Music.Theory.Z.TTO: z_tto_f :: Integral t => t -> Z t -> TTO t -> (t -> t)
+ Music.Theory.Z.TTO: z_tto_rel :: (Ord t, Integral t) => t -> Z t -> [t] -> [t] -> [TTO t]
+ Music.Theory.Z.TTO: z_tto_univ :: Integral t => Z t -> [TTO t]
+ Music.Theory.Z12: char_to_z12 :: Char -> Z12
+ Music.Theory.Z12: enumFromThenTo_cyc :: KnownNat n => Z n -> Z n -> Z n -> [Z n]
+ Music.Theory.Z12: enumFromTo_cyc :: KnownNat n => Z n -> Z n -> [Z n]
+ Music.Theory.Z12: int_from_Z12 :: Z12 -> Int
+ Music.Theory.Z12: int_to_Z12 :: Int -> Z12
+ Music.Theory.Z12: type Z n = Mod Int n
+ Music.Theory.Z12: type Z12 = Mod Int 12
+ Music.Theory.Z12: z12_seq_pp :: [Z12] -> String
+ Music.Theory.Z12: z12_set_pp :: [Z12] -> String
+ Music.Theory.Z12: z12_to_char :: Z12 -> Char
+ Music.Theory.Z12: z12_vec_pp :: [Z12] -> String
+ Music.Theory.Z12.Castren_1994: type Z12 = Int
+ Music.Theory.Z12.Drape_1999: chn_t0 :: Int -> [Z12] -> [[Z12]]
+ Music.Theory.Z12.Drape_1999: frg :: [Z12] -> T6 [String]
+ Music.Theory.Z12.Drape_1999: frg_cyc :: T6 [[Z12]]
+ Music.Theory.Z12.Drape_1999: frg_hdr :: [String]
+ Music.Theory.Z12.Drape_1999: frg_pp :: [Z12] -> String
+ Music.Theory.Z12.Drape_1999: ic_cycle_vector :: [Z12] -> T6 [Int]
+ Music.Theory.Z12.Drape_1999: ic_cycle_vector_pp :: T6 [Int] -> String
+ Music.Theory.Z12.Drape_1999: rs1 :: [Z12] -> [Z12] -> Maybe (TTO Z12)
+ Music.Theory.Z12.Drape_1999: scc :: [Z12] -> [Z12] -> [[Z12]]
+ Music.Theory.Z12.Drape_1999: si :: [Z12] -> [String]
+ Music.Theory.Z12.Drape_1999: si_hdr :: [String]
+ Music.Theory.Z12.Drape_1999: si_raw :: [Z12] -> (SI, [Z12], [Int], SI, SI)
+ Music.Theory.Z12.Drape_1999: si_raw_pp :: [Z12] -> [String]
+ Music.Theory.Z12.Drape_1999: sra :: [Z12] -> [[Z12]]
+ Music.Theory.Z12.Drape_1999: sro :: SRO Z12 -> [Z12] -> [Z12]
+ Music.Theory.Z12.Drape_1999: tics :: [Z12] -> [Int]
+ Music.Theory.Z12.Drape_1999: tmatrix :: [Z12] -> [[Z12]]
+ Music.Theory.Z12.Drape_1999: trs :: [Z12] -> [Z12] -> [[Z12]]
+ Music.Theory.Z12.Drape_1999: trs_m :: [Z12] -> [Z12] -> [[Z12]]
+ Music.Theory.Z12.Drape_1999: type SI = ([Z12], TTO Z12, [Z12])
+ Music.Theory.Z12.Forte_1973: icv' :: [Z12] -> [Int]
+ Music.Theory.Z12.Forte_1973: sc_name_long :: [Z12] -> SC_Name
+ Music.Theory.Z12.Forte_1973: z_relation_of :: [Z12] -> Maybe [Z12]
+ Music.Theory.Z12.Lewin_1980: type Z12 = Int
+ Music.Theory.Z12.SRO: sro_invert :: Z12 -> [Z12] -> [Z12]
+ Music.Theory.Z12.SRO: sro_invert_ix :: Int -> [Z12] -> [Z12]
+ Music.Theory.Z12.SRO: sro_m5 :: [Z12] -> [Z12]
+ Music.Theory.Z12.SRO: sro_mn :: Z12 -> [Z12] -> [Z12]
+ Music.Theory.Z12.SRO: sro_rrtmi_related :: [Z12] -> [[Z12]]
+ Music.Theory.Z12.SRO: sro_rti_related :: [Z12] -> [[Z12]]
+ Music.Theory.Z12.SRO: sro_rtmi_related :: [Z12] -> [[Z12]]
+ Music.Theory.Z12.SRO: sro_t_related :: [Z12] -> [[Z12]]
+ Music.Theory.Z12.SRO: sro_ti_related :: [Z12] -> [[Z12]]
+ Music.Theory.Z12.SRO: sro_tmi_related :: [Z12] -> [[Z12]]
+ Music.Theory.Z12.SRO: sro_tn :: Z12 -> [Z12] -> [Z12]
+ Music.Theory.Z12.SRO: sro_tn_to :: Z12 -> [Z12] -> [Z12]
+ Music.Theory.Z12.SRO: sro_tni :: Z12 -> [Z12] -> [Z12]
+ Music.Theory.Z12.TTO: tto_invert :: Z12 -> [Z12] -> [Z12]
+ Music.Theory.Z12.TTO: tto_m5 :: [Z12] -> [Z12]
+ Music.Theory.Z12.TTO: tto_mn :: Z12 -> [Z12] -> [Z12]
+ Music.Theory.Z12.TTO: tto_t_related :: [Z12] -> [[Z12]]
+ Music.Theory.Z12.TTO: tto_ti_related :: [Z12] -> [[Z12]]
+ Music.Theory.Z12.TTO: tto_tn :: Z12 -> [Z12] -> [Z12]
+ Music.Theory.Z12.TTO: tto_tni :: Z12 -> [Z12] -> [Z12]
- Music.Theory.Array.MD: md_matrix :: a -> [a] -> [[a]] -> MD_Table a
+ Music.Theory.Array.MD: md_matrix :: a -> ([a], [a]) -> [[a]] -> MD_Table a
- Music.Theory.Array.MD: md_matrix_bold :: [String] -> [[String]] -> MD_Table String
+ Music.Theory.Array.MD: md_matrix_bold :: Show a => ([a], [a]) -> [[a]] -> MD_Table String
- Music.Theory.Array.MD: md_table_opt :: Bool -> MD_Table String -> [String]
+ Music.Theory.Array.MD: md_table_opt :: (Bool, Bool, String) -> MD_Table String -> [String]
- Music.Theory.Bjorklund: xdot :: [Bool] -> String
+ Music.Theory.Bjorklund: xdot :: Bool -> Char
- Music.Theory.Block_Design.Johnson_2007: c_7_3_1 :: Num i => [i]
+ Music.Theory.Block_Design.Johnson_2007: c_7_3_1 :: (Num i) => [i]
- Music.Theory.Combinations: combinations :: Integral t => t -> [a] -> [[a]]
+ Music.Theory.Combinations: combinations :: Int -> [a] -> [[a]]
- Music.Theory.Contour.Polansky_1992: build_contour :: Ord e => Build_f st e -> Contour_Description -> Int -> st -> (Maybe [e], st)
+ Music.Theory.Contour.Polansky_1992: build_contour :: (Ord e) => Build_f st e -> Contour_Description -> Int -> st -> (Maybe [e], st)
- Music.Theory.Contour.Polansky_1992: build_contour_retry :: Ord e => Build_f st e -> Contour_Description -> Int -> Int -> st -> (Maybe [e], st)
+ Music.Theory.Contour.Polansky_1992: build_contour_retry :: (Ord e) => Build_f st e -> Contour_Description -> Int -> Int -> st -> (Maybe [e], st)
- Music.Theory.Contour.Polansky_1992: build_contour_set :: Ord e => Build_f st e -> Contour_Description -> Int -> Int -> st -> [[e]]
+ Music.Theory.Contour.Polansky_1992: build_contour_set :: (Ord e) => Build_f st e -> Contour_Description -> Int -> Int -> st -> [[e]]
- Music.Theory.Duration.Sequence.Notate: notate :: Simplify_P -> [Time_Signature] -> [RQ] -> Either String [[Duration_A]]
+ Music.Theory.Duration.Sequence.Notate: notate :: Int -> Simplify_P -> [Time_Signature] -> [RQ] -> Either String [[Duration_A]]
- Music.Theory.Duration.Sequence.Notate: notate_mm_ascribe :: Show a => [Simplify_T] -> [Time_Signature] -> Maybe [[RQ]] -> [RQ] -> [a] -> Either String [[(Duration_A, a)]]
+ Music.Theory.Duration.Sequence.Notate: notate_mm_ascribe :: Show a => Int -> [Simplify_T] -> [Time_Signature] -> Maybe [[RQ]] -> [RQ] -> [a] -> Either String [[(Duration_A, a)]]
- Music.Theory.Duration.Sequence.Notate: notate_mm_ascribe_err :: Show a => [Simplify_T] -> [Time_Signature] -> Maybe [[RQ]] -> [RQ] -> [a] -> [[(Duration_A, a)]]
+ Music.Theory.Duration.Sequence.Notate: notate_mm_ascribe_err :: Show a => Int -> [Simplify_T] -> [Time_Signature] -> Maybe [[RQ]] -> [RQ] -> [a] -> [[(Duration_A, a)]]
- Music.Theory.Duration.Sequence.Notate: notate_rqp :: Simplify_P -> [Time_Signature] -> Maybe [[RQ]] -> [RQ] -> Either String [[Duration_A]]
+ Music.Theory.Duration.Sequence.Notate: notate_rqp :: Int -> Simplify_P -> [Time_Signature] -> Maybe [[RQ]] -> [RQ] -> Either String [[Duration_A]]
- Music.Theory.Dynamic_Mark: midi_dynamic_mark :: (Ord n, Eq n, Num n, Enum n) => n -> Maybe Dynamic_Mark_T
+ Music.Theory.Dynamic_Mark: midi_dynamic_mark :: (Ord n, Num n, Enum n) => n -> Maybe Dynamic_Mark_T
- Music.Theory.Interval.Barlow_1987: from_rational :: Integral t => Ratio t -> (t, t)
+ Music.Theory.Interval.Barlow_1987: from_rational :: Ratio t -> (t, t)
- Music.Theory.Key: key_fifths :: Key -> Int
+ Music.Theory.Key: key_fifths :: Key -> Maybe Int
- Music.Theory.List: collate_on :: (Eq k, Ord k) => (a -> k) -> (a -> v) -> [a] -> [(k, [v])]
+ Music.Theory.List: collate_on :: Ord k => (a -> k) -> (a -> v) -> [a] -> [(k, [v])]
- Music.Theory.List: d_dx :: Num a => [a] -> [a]
+ Music.Theory.List: d_dx :: (Num a) => [a] -> [a]
- Music.Theory.List: difference :: Eq a => [a] -> [a] -> [a]
+ Music.Theory.List: difference :: (Eq a) => [a] -> [a] -> [a]
- Music.Theory.List: dx_d :: Num a => a -> [a] -> [a]
+ Music.Theory.List: dx_d :: (Num a) => a -> [a] -> [a]
- Music.Theory.List: elem_index_unique :: Eq a => a -> [a] -> Int
+ Music.Theory.List: elem_index_unique :: (Eq a) => a -> [a] -> Int
- Music.Theory.List: find_bounds' :: Bool -> (t -> s -> Ordering) -> [(t, t)] -> s -> Maybe (t, t)
+ Music.Theory.List: find_bounds' :: (t -> s -> Ordering) -> [(t, t)] -> s -> Either ((t, t), Ordering) (t, t)
- Music.Theory.List: genericAdj2 :: Integral n => n -> [t] -> [(t, t)]
+ Music.Theory.List: genericAdj2 :: (Integral n) => n -> [t] -> [(t, t)]
- Music.Theory.List: histogram :: (Ord a, Integral i) => [a] -> [(a, i)]
+ Music.Theory.List: histogram :: Ord a => [a] -> [(a, Int)]
- Music.Theory.List: interleave :: [b] -> [b] -> [b]
+ Music.Theory.List: interleave :: [a] -> [a] -> [a]
- Music.Theory.List: rotate :: Integral n => n -> [a] -> [a]
+ Music.Theory.List: rotate :: (Integral n) => n -> [a] -> [a]
- Music.Theory.List: rotate_r :: Integral n => n -> [a] -> [a]
+ Music.Theory.List: rotate_r :: (Integral n) => n -> [a] -> [a]
- Music.Theory.List: subsequence :: Eq a => [a] -> [a] -> Bool
+ Music.Theory.List: subsequence :: (Eq a) => [a] -> [a] -> Bool
- Music.Theory.Math: rational_nd :: Integral t => Ratio t -> (t, t)
+ Music.Theory.Math: rational_nd :: Ratio t -> (t, t)
- Music.Theory.Meter.Barlow_1987: at :: Integral n => [a] -> n -> a
+ Music.Theory.Meter.Barlow_1987: at :: (Integral n) => [a] -> n -> a
- Music.Theory.Meter.Barlow_1987: reverse_primes :: (Integral n, Show n) => n -> [n]
+ Music.Theory.Meter.Barlow_1987: reverse_primes :: Integral n => n -> [n]
- Music.Theory.Meter.Barlow_1987: to_r :: (Integral n, Show n) => n -> R
+ Music.Theory.Meter.Barlow_1987: to_r :: Integral n => n -> R
- Music.Theory.Metric.Buchler_1998: satv_f :: Integral n => ((n, n, n) -> D n) -> [Z12] -> [D n]
+ Music.Theory.Metric.Buchler_1998: satv_f :: (Integral n) => ((n, n, n) -> D n) -> [Z12] -> [D n]
- Music.Theory.Metric.Buchler_1998: sc_table_n :: Integral n => n -> [[Z12]]
+ Music.Theory.Metric.Buchler_1998: sc_table_n :: (Integral n) => n -> [[Z12]]
- Music.Theory.Metric.Buchler_1998: two_part_difference_vector :: Integral i => [D i] -> SATV i -> [i]
+ Music.Theory.Metric.Buchler_1998: two_part_difference_vector :: (Integral i) => [D i] -> SATV i -> [i]
- Music.Theory.Metric.Buchler_1998: two_part_difference_vector_set :: Integral i => SATV i -> SATV i -> ([i], [i])
+ Music.Theory.Metric.Buchler_1998: two_part_difference_vector_set :: (Integral i) => SATV i -> SATV i -> ([i], [i])
- Music.Theory.Metric.Morris_1980: asim :: Integral n => [Z12] -> [Z12] -> Ratio n
+ Music.Theory.Metric.Morris_1980: asim :: (Integral n) => [Z12] -> [Z12] -> Ratio n
- Music.Theory.Metric.Polansky_1996: direction_vector :: Integral i => Ord a => [a] -> (i, i, i)
+ Music.Theory.Metric.Polansky_1996: direction_vector :: Integral i => (Ord a) => [a] -> (i, i, i)
- Music.Theory.Metric.Polansky_1996: ocm :: (Fractional a, Enum a, Fractional n) => Interval a n -> [a] -> [a] -> n
+ Music.Theory.Metric.Polansky_1996: ocm :: Fractional n => Interval a n -> [a] -> [a] -> n
- Music.Theory.Metric.Polansky_1996: ocm_absolute_scaled :: (Ord a, Fractional a, Enum a, Ord n, Fractional n) => Interval a n -> [a] -> [a] -> n
+ Music.Theory.Metric.Polansky_1996: ocm_absolute_scaled :: (Ord n, Fractional n) => Interval a n -> [a] -> [a] -> n
- Music.Theory.Metric.Polansky_1996: ocm_zcm :: (Fractional n, Num a) => Interval a n -> [a] -> [a] -> (n, n, [n])
+ Music.Theory.Metric.Polansky_1996: ocm_zcm :: Fractional n => Interval a n -> [a] -> [a] -> (n, n, [n])
- Music.Theory.Metric.Polansky_1996: olm :: (Fractional a, Enum a) => Psi a -> Delta n a -> ([a] -> a) -> [n] -> [n] -> a
+ Music.Theory.Metric.Polansky_1996: olm :: Fractional a => Psi a -> Delta n a -> ([a] -> a) -> [n] -> [n] -> a
- Music.Theory.Metric.Polansky_1996: olm_general :: (Fractional a, Enum a, Fractional n) => Interval a n -> [a] -> [a] -> n
+ Music.Theory.Metric.Polansky_1996: olm_general :: Fractional n => Interval a n -> [a] -> [a] -> n
- Music.Theory.Metric.Polansky_1996: olm_no_delta :: (Real a, Real n, Enum n, Fractional n) => [a] -> [a] -> n
+ Music.Theory.Metric.Polansky_1996: olm_no_delta :: (Real a, Real n, Fractional n) => [a] -> [a] -> n
- Music.Theory.Metric.Polansky_1996: olm_no_delta_second_order :: (Real a, Enum a, Fractional a) => [a] -> [a] -> a
+ Music.Theory.Metric.Polansky_1996: olm_no_delta_second_order :: (Real a, Fractional a) => [a] -> [a] -> a
- Music.Theory.Metric.Polansky_1996: olm_no_delta_squared :: (Enum a, Floating a) => [a] -> [a] -> a
+ Music.Theory.Metric.Polansky_1996: olm_no_delta_squared :: Floating a => [a] -> [a] -> a
- Music.Theory.Metric.Polansky_1996: olm_no_delta_squared_second_order :: (Enum a, Floating a) => [a] -> [a] -> a
+ Music.Theory.Metric.Polansky_1996: olm_no_delta_squared_second_order :: Floating a => [a] -> [a] -> a
- Music.Theory.Metric.Polansky_1996: second_order :: Num n => ([n] -> [n] -> t) -> [n] -> [n] -> t
+ Music.Theory.Metric.Polansky_1996: second_order :: (Num n) => ([n] -> [n] -> t) -> [n] -> [n] -> t
- Music.Theory.Permutations: apply_permutation :: Eq a => Permute -> [a] -> [a]
+ Music.Theory.Permutations: apply_permutation :: Permute -> [a] -> [a]
- Music.Theory.Permutations: apply_permutation_c :: Eq a => [[Int]] -> [a] -> [a]
+ Music.Theory.Permutations: apply_permutation_c :: [[Int]] -> [a] -> [a]
- Music.Theory.Permutations: n_permutations :: Integral a => a -> a
+ Music.Theory.Permutations: n_permutations :: (Integral a) => a -> a
- Music.Theory.Permutations: permutation :: Eq a => [a] -> [a] -> Permute
+ Music.Theory.Permutations: permutation :: (Eq a) => [a] -> [a] -> Permute
- Music.Theory.Permutations.List: multiset_permutations :: Ord a => [a] -> [[a]]
+ Music.Theory.Permutations.List: multiset_permutations :: (Ord a) => [a] -> [[a]]
- Music.Theory.Permutations.List: permutations :: Eq a => [a] -> [[a]]
+ Music.Theory.Permutations.List: permutations :: [a] -> [[a]]
- Music.Theory.Permutations.Morris_1984: apply_change :: Eq a => Int -> Change -> [a] -> [a]
+ Music.Theory.Permutations.Morris_1984: apply_change :: Int -> Change -> [a] -> [a]
- Music.Theory.Permutations.Morris_1984: apply_method :: Eq a => Method -> [a] -> ([a], [[a]])
+ Music.Theory.Permutations.Morris_1984: apply_method :: Method -> [a] -> ([a], [[a]])
- Music.Theory.Permutations.Morris_1984: swap_abbrev :: Eq a => Int -> [Int] -> [a] -> [a]
+ Music.Theory.Permutations.Morris_1984: swap_abbrev :: Int -> [Int] -> [a] -> [a]
- Music.Theory.Pitch: fmidi_to_pitch :: RealFrac n => Spelling Int -> n -> Pitch
+ Music.Theory.Pitch: fmidi_to_pitch :: RealFrac n => Spelling PitchClass -> n -> Maybe Pitch
- Music.Theory.Pitch: midi_detune_to_cps :: Midi_Detune -> Double
+ Music.Theory.Pitch: midi_detune_to_cps :: Real c => Midi_Detune' c -> Double
- Music.Theory.Pitch: midi_to_octpc :: Integral i => i -> Octave_PitchClass i
+ Music.Theory.Pitch: midi_to_octpc :: Midi -> OctPC
- Music.Theory.Pitch: octpc_nrm :: Integral i => Octave_PitchClass i -> Octave_PitchClass i
+ Music.Theory.Pitch: octpc_nrm :: OctPC -> OctPC
- Music.Theory.Pitch: octpc_to_midi :: Integral i => Octave_PitchClass i -> i
+ Music.Theory.Pitch: octpc_to_midi :: OctPC -> Midi
- Music.Theory.Pitch: octpc_trs :: Integral i => i -> Octave_PitchClass i -> Octave_PitchClass i
+ Music.Theory.Pitch: octpc_trs :: Int -> OctPC -> OctPC
- Music.Theory.Pitch: pitch_class_names_12et :: Integral n => n -> n -> [String]
+ Music.Theory.Pitch: pitch_class_names_12et :: Integral n => Spelling n -> n -> n -> [String]
- Music.Theory.Pitch: pitch_tranpose :: RealFrac n => Spelling Int -> n -> Pitch -> Pitch
+ Music.Theory.Pitch: pitch_tranpose :: (RealFrac n, Show n) => Spelling Int -> n -> Pitch -> Pitch
- Music.Theory.Pitch: type Midi_Detune = (Int, Double)
+ Music.Theory.Pitch: type Midi_Detune = Midi_Detune' Double
- Music.Theory.Pitch.Note: note_to_pc :: Integral i => Note_T -> i
+ Music.Theory.Pitch.Note: note_to_pc :: Num i => Note_T -> i
- Music.Theory.Set.List: expand_set :: Ord a => Int -> [a] -> [[a]]
+ Music.Theory.Set.List: expand_set :: (Ord a) => Int -> [a] -> [[a]]
- Music.Theory.Set.List: set :: Ord a => [a] -> [a]
+ Music.Theory.Set.List: set :: (Ord a) => [a] -> [a]
- Music.Theory.Set.Set: set :: Ord a => [a] -> Set a
+ Music.Theory.Set.Set: set :: (Ord a) => [a] -> Set a
- Music.Theory.Tempo_Marking: mm_name :: (Num a, Ord a) => [(String, (a, a))] -> a -> Maybe String
+ Music.Theory.Tempo_Marking: mm_name :: Ord a => [(String, (a, a))] -> a -> Maybe String
- Music.Theory.Time.Duration: sms_s :: Integral i => (i, i) -> Double
+ Music.Theory.Time.Duration: sms_s :: (Integral i) => (i, i) -> Double
- Music.Theory.Time_Signature: rq_to_ts :: Rational -> Time_Signature
+ Music.Theory.Time_Signature: rq_to_ts :: RQ -> Time_Signature
- Music.Theory.Tuning: cps_midi_tuning_f :: CPS_Midi_Tuning -> Midi_Tuning_F
+ Music.Theory.Tuning: cps_midi_tuning_f :: CPS_Midi_Tuning -> Sparse_Midi_Tuning_F
- Music.Theory.Tuning: fold_ratio_to_octave :: Integral i => Ratio i -> Ratio i
+ Music.Theory.Tuning: fold_ratio_to_octave :: Integral i => Ratio i -> Maybe (Ratio i)
- Music.Theory.Tuning: harmonic_series_folded :: Integer -> [Rational]
+ Music.Theory.Tuning: harmonic_series_folded :: Integer -> Rational -> Tuning
- Music.Theory.Tuning: ratio_to_cents :: Rational -> Cents
+ Music.Theory.Tuning: ratio_to_cents :: Integral i => Ratio i -> Cents
- Music.Theory.Tuning.ET: nearest_72et_tone :: Double -> HS_R Pitch'
+ Music.Theory.Tuning.ET: nearest_72et_tone :: Double -> HS_R Pitch_R
- Music.Theory.Tuning.ET: octpc_to_pitch_cps :: Floating n => OctPC -> (Pitch, n)
+ Music.Theory.Tuning.ET: octpc_to_pitch_cps :: (Floating n) => OctPC -> (Pitch, n)
- Music.Theory.Tuning.ET: pitch_72et :: (Int, Int) -> (Pitch', Double)
+ Music.Theory.Tuning.ET: pitch_72et :: (Int, Int) -> (Pitch_R, Double)
- Music.Theory.Tuning.ET: tbl_72et :: [(Pitch', Double)]
+ Music.Theory.Tuning.ET: tbl_72et :: [(Pitch_R, Double)]
- Music.Theory.Tuning.Polansky_1978: psaltery_o :: [Rational]
+ Music.Theory.Tuning.Polansky_1978: psaltery_o :: Tuning
- Music.Theory.Tuning.Scala: pitch_cents :: Pitch Integer -> Cents
+ Music.Theory.Tuning.Scala: pitch_cents :: Integral i => Pitch i -> Cents
- Music.Theory.Tuning.Scala: scale_cents :: Scale Integer -> [Cents]
+ Music.Theory.Tuning.Scala: scale_cents :: Integral i => Scale i -> [Cents]
- Music.Theory.Tuning.Scala: scale_degree :: Scale i -> i
+ Music.Theory.Tuning.Scala: scale_degree :: Scale i -> Int
- Music.Theory.Tuning.Scala: type Scale i = (String, i, [Pitch i])
+ Music.Theory.Tuning.Scala: type Scale i = (String, String, Int, [Pitch i])
- Music.Theory.Unicode: type Unicode_Table = [(Int, String)]
+ Music.Theory.Unicode: type Unicode_Table = [Unicode_Point]
- Music.Theory.Xenakis.S4: reverse_lookup :: Eq a => a -> [(b, a)] -> Maybe b
+ Music.Theory.Xenakis.S4: reverse_lookup :: (Eq a) => a -> [(b, a)] -> Maybe b
- Music.Theory.Xenakis.Sieve: de_meziriac :: Integral a => a -> a -> a
+ Music.Theory.Xenakis.Sieve: de_meziriac :: (Integral a) => a -> a -> a
- Music.Theory.Xenakis.Sieve: differentiate :: Num a => [a] -> [a]
+ Music.Theory.Xenakis.Sieve: differentiate :: (Num a) => [a] -> [a]
- Music.Theory.Xenakis.Sieve: euclid :: Integral a => a -> a -> a
+ Music.Theory.Xenakis.Sieve: euclid :: (Integral a) => a -> a -> a
- Music.Theory.Xenakis.Sieve: reduce_intersection :: Integral t => (t, t) -> (t, t) -> Maybe (t, t)
+ Music.Theory.Xenakis.Sieve: reduce_intersection :: (Integral t) => (t, t) -> (t, t) -> Maybe (t, t)
- Music.Theory.Z: lift_binary_Z :: Integral a => a -> (s -> t -> a) -> s -> t -> a
+ Music.Theory.Z: lift_binary_Z :: Z i -> (s -> t -> i) -> s -> t -> i
- Music.Theory.Z: lift_unary_Z :: Integral a => a -> (t -> a) -> t -> a
+ Music.Theory.Z: lift_unary_Z :: Z i -> (t -> i) -> t -> i
- Music.Theory.Z: to_Z :: Integral i => i -> i -> i
+ Music.Theory.Z: to_Z :: Integral i => Z i -> i -> i
- Music.Theory.Z: z_abs :: t -> t1 -> t2
+ Music.Theory.Z: z_abs :: t -> u -> v
- Music.Theory.Z: z_add :: Integral a => a -> a -> a -> a
+ Music.Theory.Z: z_add :: Integral i => Z i -> i -> i -> i
- Music.Theory.Z: z_complement :: (Enum a, Eq a, Num a) => a -> [a] -> [a]
+ Music.Theory.Z: z_complement :: Integral i => Z i -> [i] -> [i]
- Music.Theory.Z: z_div :: Integral c => c -> c -> c -> c
+ Music.Theory.Z: z_div :: Integral i => Z i -> i -> i -> i
- Music.Theory.Z: z_divMod :: Integral t => t -> t -> t -> (t, t)
+ Music.Theory.Z: z_divMod :: Integral i => Z i -> i -> i -> (i, i)
- Music.Theory.Z: z_fromInteger :: Integral a => a -> Integer -> a
+ Music.Theory.Z: z_fromInteger :: Integral i => Z i -> Integer -> i
- Music.Theory.Z: z_mod :: Integral c => c -> c -> c -> c
+ Music.Theory.Z: z_mod :: Integral i => Z i -> i -> i -> i
- Music.Theory.Z: z_mul :: Integral a => a -> a -> a -> a
+ Music.Theory.Z: z_mul :: Integral i => Z i -> i -> i -> i
- Music.Theory.Z: z_negate :: Integral a => a -> a -> a
+ Music.Theory.Z: z_negate :: Integral i => Z i -> i -> i
- Music.Theory.Z: z_quot :: Integral i => i -> i -> i -> i
+ Music.Theory.Z: z_quot :: Integral i => Z i -> i -> i -> i
- Music.Theory.Z: z_quotRem :: Integral t => t -> t -> t -> (t, t)
+ Music.Theory.Z: z_quotRem :: Integral i => Z i -> i -> i -> (i, i)
- Music.Theory.Z: z_rem :: Integral c => c -> c -> c -> c
+ Music.Theory.Z: z_rem :: Integral i => Z i -> i -> i -> i
- Music.Theory.Z: z_signum :: t -> t1 -> t2
+ Music.Theory.Z: z_signum :: t -> u -> v
- Music.Theory.Z: z_sub :: Integral a => a -> a -> a -> a
+ Music.Theory.Z: z_sub :: Integral i => Z i -> i -> i -> i
- Music.Theory.Z: z_toInteger :: Integral i => i -> i -> i
+ Music.Theory.Z: z_toInteger :: Integral i => Z i -> i -> i
- Music.Theory.Z.Forte_1973: forte_cmp :: Ord t => [t] -> [t] -> Ordering
+ Music.Theory.Z.Forte_1973: forte_cmp :: (Ord t) => [t] -> [t] -> Ordering
- Music.Theory.Z.Forte_1973: forte_prime :: Integral a => a -> [a] -> [a]
+ Music.Theory.Z.Forte_1973: forte_prime :: Integral i => Z i -> [i] -> [i]
- Music.Theory.Z.Forte_1973: ic :: Integral a => a -> a -> a
+ Music.Theory.Z.Forte_1973: ic :: Integral i => i -> i -> i
- Music.Theory.Z.Forte_1973: minimumBy_or :: a -> (a -> a -> Ordering) -> [a] -> a
+ Music.Theory.Z.Forte_1973: minimumBy_or :: t -> (t -> t -> Ordering) -> [t] -> t
- Music.Theory.Z.Forte_1973: t_cmp_prime :: Integral a => a -> ([a] -> [a] -> Ordering) -> [a] -> [a]
+ Music.Theory.Z.Forte_1973: t_cmp_prime :: Integral i => Z i -> ([i] -> [i] -> Ordering) -> [i] -> [i]
- Music.Theory.Z.Forte_1973: t_prime :: Integral a => a -> [a] -> [a]
+ Music.Theory.Z.Forte_1973: t_prime :: Integral i => Z i -> [i] -> [i]
- Music.Theory.Z.Forte_1973: t_rotations :: Integral a => a -> [a] -> [[a]]
+ Music.Theory.Z.Forte_1973: t_rotations :: Integral i => Z i -> [i] -> [[i]]
- Music.Theory.Z.Forte_1973: ti_cmp_prime :: Integral a => a -> ([a] -> [a] -> Ordering) -> [a] -> [a]
+ Music.Theory.Z.Forte_1973: ti_cmp_prime :: Integral i => Z i -> ([i] -> [i] -> Ordering) -> [i] -> [i]
- Music.Theory.Z.Forte_1973: ti_rotations :: Integral a => a -> [a] -> [[a]]
+ Music.Theory.Z.Forte_1973: ti_rotations :: Integral i => Z i -> [i] -> [[i]]
- Music.Theory.Z.Read_1978: encode_prime :: Integral i => i -> [i] -> [i]
+ Music.Theory.Z.Read_1978: encode_prime :: Integral i => Z i -> [i] -> [i]
- Music.Theory.Z12.Castren_1994: rle_decode :: Integral i => [(i, a)] -> [a]
+ Music.Theory.Z12.Castren_1994: rle_decode :: (Integral i) => [(i, a)] -> [a]
- Music.Theory.Z12.Castren_1994: rle_length :: Integral i => [(i, a)] -> i
+ Music.Theory.Z12.Castren_1994: rle_length :: (Integral i) => [(i, a)] -> i
- Music.Theory.Z12.Drape_1999: cf :: Integral n => [n] -> [[a]] -> [[a]]
+ Music.Theory.Z12.Drape_1999: cf :: (Integral n) => [n] -> [[a]] -> [[a]]
- Music.Theory.Z12.Drape_1999: cg_r :: Integral n => n -> [a] -> [[a]]
+ Music.Theory.Z12.Drape_1999: cg_r :: (Integral n) => n -> [a] -> [[a]]
- Music.Theory.Z12.Drape_1999: d_nm :: Integral a => [a] -> Maybe Char
+ Music.Theory.Z12.Drape_1999: d_nm :: (Integral a) => [a] -> Maybe Char
- Music.Theory.Z12.Drape_1999: dis :: Integral t => [Int] -> [t]
+ Music.Theory.Z12.Drape_1999: dis :: (Integral t) => [Int] -> [t]
- Music.Theory.Z12.Drape_1999: has_sc_pf :: Integral a => ([a] -> [a]) -> [a] -> [a] -> Bool
+ Music.Theory.Z12.Drape_1999: has_sc_pf :: (Integral a) => ([a] -> [a]) -> [a] -> [a] -> Bool
- Music.Theory.Z12.Drape_1999: ici :: Num t => [Int] -> [[t]]
+ Music.Theory.Z12.Drape_1999: ici :: (Num t) => [Int] -> [[t]]
- Music.Theory.Z12.Drape_1999: imb :: Integral n => [n] -> [a] -> [[a]]
+ Music.Theory.Z12.Drape_1999: imb :: (Integral n) => [n] -> [a] -> [[[a]]]
- Music.Theory.Z12.Drape_1999: nrm :: Ord a => [a] -> [a]
+ Music.Theory.Z12.Drape_1999: nrm :: (Ord a) => [a] -> [a]
- Music.Theory.Z12.Drape_1999: nrm_r :: Ord a => [a] -> [a]
+ Music.Theory.Z12.Drape_1999: nrm_r :: (Ord a) => [a] -> [a]
- Music.Theory.Z12.Drape_1999: pci :: [Z12] -> [Z12] -> [[Z12]]
+ Music.Theory.Z12.Drape_1999: pci :: [Int] -> [Z12] -> [[Z12]]
- Music.Theory.Z12.Drape_1999: rs :: [Z12] -> [Z12] -> [(SRO, [Z12])]
+ Music.Theory.Z12.Drape_1999: rs :: [Z12] -> [Z12] -> [(TTO Z12, [Z12])]
- Music.Theory.Z12.Drape_1999: rsg :: [Z12] -> [Z12] -> [SRO]
+ Music.Theory.Z12.Drape_1999: rsg :: [Z12] -> [Z12] -> [SRO Z12]
- Music.Theory.Z12.Drape_1999: spsc :: [[Z12]] -> [String]
+ Music.Theory.Z12.Drape_1999: spsc :: [[Z12]] -> [[Z12]]
- Music.Theory.Z12.Forte_1973: type SC_Name = String
+ Music.Theory.Z12.Forte_1973: type SC_Name = SC_Name
- Music.Theory.Z12.Morris_1974: all_interval_m :: MonadPlus m => Int -> m [Int]
+ Music.Theory.Z12.Morris_1974: all_interval_m :: MonadLogic m => Int -> m [Int]
- Music.Theory.Z12.TTO: pcset :: Integral a => [a] -> [Z12]
+ Music.Theory.Z12.TTO: pcset :: (Integral a) => [a] -> [Z12]
Files
- Help/hmt.help.lhs +0/−175
- Music/Theory/Array.hs +90/−0
- Music/Theory/Array/CSV.hs +81/−238
- Music/Theory/Array/CSV/Midi.hs +0/−86
- Music/Theory/Array/CSV/Midi/MND.hs +203/−0
- Music/Theory/Array/Cell_Ref.hs +228/−0
- Music/Theory/Array/Direction.hs +84/−0
- Music/Theory/Array/MD.hs +41/−44
- Music/Theory/Bits.hs +38/−0
- Music/Theory/Bjorklund.hs +89/−61
- Music/Theory/Block_Design/Johnson_2007.hs +1/−1
- Music/Theory/Braille.hs +273/−0
- Music/Theory/Byte.hs +55/−0
- Music/Theory/Clef.hs +2/−2
- Music/Theory/Combinations.hs +3/−3
- Music/Theory/Contour/Polansky_1992.hs +8/−58
- Music/Theory/DB/CSV.hs +24/−0
- Music/Theory/DB/Common.hs +130/−0
- Music/Theory/DB/JSON.hs +67/−0
- Music/Theory/DB/Plain.hs +60/−0
- Music/Theory/Directory.hs +38/−0
- Music/Theory/Duration.hs +102/−77
- Music/Theory/Duration/Annotation.hs +4/−85
- Music/Theory/Duration/CT.hs +2/−2
- Music/Theory/Duration/Name/Abbreviation.hs +2/−1
- Music/Theory/Duration/RQ.hs +6/−20
- Music/Theory/Duration/Sequence/Notate.hs +20/−13
- Music/Theory/Dynamic_Mark.hs +1/−1
- Music/Theory/Enum.hs +38/−0
- Music/Theory/Function.hs +8/−1
- Music/Theory/Gamelan.hs +325/−0
- Music/Theory/Graph/Deacon_1934.hs +131/−0
- Music/Theory/Graph/Dot.hs +131/−0
- Music/Theory/Graph/FGL.hs +141/−0
- Music/Theory/Graph/Johnson_2014.hs +290/−0
- Music/Theory/IO.hs +34/−0
- Music/Theory/Instrument/Names.hs +114/−0
- Music/Theory/Interval.hs +25/−46
- Music/Theory/Interval/Barlow_1987.hs +22/−15
- Music/Theory/Key.hs +189/−17
- Music/Theory/List.hs +691/−44
- Music/Theory/Map.hs +17/−0
- Music/Theory/Math.hs +111/−2
- Music/Theory/Math/Convert.hs +1121/−0
- Music/Theory/Math/OEIS.hs +27/−0
- Music/Theory/Maybe.hs +5/−1
- Music/Theory/Meter/Barlow_1987.hs +2/−2
- Music/Theory/Metric/Polansky_1996.hs +10/−10
- Music/Theory/Monad.hs +10/−0
- Music/Theory/Ord.hs +38/−0
- Music/Theory/Parse.hs +16/−0
- Music/Theory/Permutations.hs +6/−2
- Music/Theory/Permutations/List.hs +22/−3
- Music/Theory/Permutations/Morris_1984.hs +31/−16
- Music/Theory/Pitch.hs +440/−156
- Music/Theory/Pitch/Chord.hs +159/−0
- Music/Theory/Pitch/Note.hs +125/−50
- Music/Theory/Pitch/Note/Name.hs +88/−0
- Music/Theory/Pitch/Spelling.hs +14/−70
- Music/Theory/Pitch/Spelling/Cluster.hs +164/−117
- Music/Theory/Pitch/Spelling/Key.hs +33/−0
- Music/Theory/Pitch/Spelling/Table.hs +101/−0
- Music/Theory/Random/I_Ching.hs +192/−0
- Music/Theory/Read.hs +147/−0
- Music/Theory/Set/List.hs +33/−9
- Music/Theory/Show.hs +2/−0
- Music/Theory/String.hs +15/−0
- Music/Theory/Tempo_Marking.hs +1/−1
- Music/Theory/Tiling/Canon.hs +41/−37
- Music/Theory/Time/Bel1990/R.hs +28/−204
- Music/Theory/Time/Notation.hs +89/−5
- Music/Theory/Time/Seq.hs +271/−83
- Music/Theory/Time_Signature.hs +8/−1
- Music/Theory/Tuning.hs +296/−73
- Music/Theory/Tuning/Alves.hs +0/−25
- Music/Theory/Tuning/Alves_1997.hs +8/−2
- Music/Theory/Tuning/DB.hs +62/−0
- Music/Theory/Tuning/DB/Alves.hs +26/−0
- Music/Theory/Tuning/DB/Gann.hs +130/−0
- Music/Theory/Tuning/DB/Microtonal_Synthesis.hs +230/−0
- Music/Theory/Tuning/DB/Riley.hs +22/−0
- Music/Theory/Tuning/DB/Werckmeister.hs +117/−0
- Music/Theory/Tuning/ET.hs +53/−42
- Music/Theory/Tuning/Euler.hs +138/−0
- Music/Theory/Tuning/Gann.hs +0/−141
- Music/Theory/Tuning/Gann_1993.hs +139/−0
- Music/Theory/Tuning/Load.hs +78/−0
- Music/Theory/Tuning/Meyer_1929.hs +6/−5
- Music/Theory/Tuning/Microtonal_Synthesis.hs +0/−205
- Music/Theory/Tuning/Polansky_1978.hs +40/−24
- Music/Theory/Tuning/Polansky_1984.hs +7/−11
- Music/Theory/Tuning/Riley.hs +0/−18
- Music/Theory/Tuning/Rosenboom_1979.hs +190/−0
- Music/Theory/Tuning/Scala.hs +313/−125
- Music/Theory/Tuning/Scala/Interval.hs +62/−0
- Music/Theory/Tuning/Scala/Mode.hs +117/−0
- Music/Theory/Tuning/Sethares_1994.hs +39/−0
- Music/Theory/Tuning/Werckmeister.hs +0/−105
- Music/Theory/Tuple.hs +94/−33
- Music/Theory/Unicode.hs +186/−3
- Music/Theory/Wyschnegradsky.hs +331/−0
- Music/Theory/Xenakis/S4.hs +81/−25
- Music/Theory/Xenakis/Sieve.hs +105/−0
- Music/Theory/Z.hs +103/−50
- Music/Theory/Z/Boros_1990.hs +296/−0
- Music/Theory/Z/Clough_1979.hs +116/−0
- Music/Theory/Z/Drape_1999.hs +36/−0
- Music/Theory/Z/Forte_1973.hs +381/−33
- Music/Theory/Z/Read_1978.hs +16/−13
- Music/Theory/Z/SRO.hs +149/−43
- Music/Theory/Z/TTO.hs +75/−0
- Music/Theory/Z12.hs +84/−75
- Music/Theory/Z12/Castren_1994.hs +15/−14
- Music/Theory/Z12/Drape_1999.hs +360/−114
- Music/Theory/Z12/Forte_1973.hs +31/−244
- Music/Theory/Z12/Lewin_1980.hs +2/−1
- Music/Theory/Z12/Morris_1974.hs +18/−18
- Music/Theory/Z12/Morris_1987.hs +0/−87
- Music/Theory/Z12/Morris_1987/Parse.hs +1/−37
- Music/Theory/Z12/Rahn_1980.hs +1/−1
- Music/Theory/Z12/Read_1978.hs +1/−1
- Music/Theory/Z12/SRO.hs +44/−43
- Music/Theory/Z12/TTO.hs +28/−27
- README +7/−1
- data/csv/mnd/1080-C01.csv +1801/−0
- data/dot/euler-j5-a.dot +30/−0
- data/dot/euler-j5-b.dot +30/−0
- data/dot/euler-j7.dot +29/−0
- data/dot/euler-wtp.dot +30/−0
- data/dot/tj_oh_p012.dot +30/−0
- data/dot/tj_oh_p014.dot +58/−0
- data/dot/tj_oh_p031.dot +53/−0
- data/dot/tj_oh_p125.dot +72/−0
- data/dot/tj_oh_p131.dot +26/−0
- data/dot/tj_oh_p162.dot +83/−0
- data/scl/dr_itb_etude_1.scl +41/−0
- data/scl/et12.scl +17/−0
- data/scl/et19.scl +24/−0
- data/scl/et31.scl +36/−0
- data/scl/et53.scl +58/−0
- data/scl/et72.scl +77/−0
- data/scl/et96.scl +101/−0
- data/scl/hs17.scl +22/−0
- data/scl/hs19.scl +24/−0
- data/scl/hs21.scl +26/−0
- data/scl/hs23.scl +28/−0
- data/scl/young-lm_piano_1964.scl +17/−0
- hmt.cabal +66/−14
− Help/hmt.help.lhs
@@ -1,175 +0,0 @@-# Pct--> import Control.Arrow {- base -}-> import Data.Function {- base -}-> import Data.List {- base -}-> import Data.Maybe {- base -}-> import Music.Theory.List {- hmt -}-> import Music.Theory.Permutations {- hmt -}-> import Music.Theory.Set.List {- hmt -}-> import Music.Theory.Z12.Drape_1999 {- hmt -}-> import Music.Theory.Z12.Forte_1973 {- hmt -}-> import Music.Theory.Z12.Morris_1987 {- hmt -}-> import Music.Theory.Z12.Morris_1987.Parse {- hmt -}-> import Music.Theory.Z12.SRO {- hmt -}--This file illustrates equivalent expressions in pct and hmt terms.-- $ pcom pcseg iseg 01549 | pcom iseg icseg | pcom icseg icset- 145--> (set . map ic . int) [0,1,5,4,9] == [1,4,5]-- $ pcom pcseg pcset 01549 | pcom pcset sc | pcom sc icv | pcom icv icset- 1345--> let icv_icset x = let f x y = if x > 0 then Just y else Nothing-> in catMaybes (zipWith f x [1..6])-> in (icv_icset . icv . forte_prime) [0,1,5,4,9] == [1,3,4,5]-- $ pg 5-Z17 | bip | sort -u > 5-Z17.bip ; \- pg 5-Z37 | bip | sort -u > 5-Z37.bip ; \- comm 5-Z17.bip 5-Z37.bip -1 -2 | wc -l- 16--> let f = nub . map bip . permutations . sc-> in length (f "5-Z17" `intersect` f "5-Z37") == 16-- $ cat ../db.sh- for sc in $(fl -c $1)- do- pg $sc | bip | sort -u > $sc- done- $ sh ../db.sh 4- $ ls- 4-1 4-12 4-16 4-19 4-21 4-24 4-27 4-4 4-7 4-Z15- 4-10 4-13 4-17 4-2 4-22 4-25 4-28 4-5 4-8 4-Z29- 4-11 4-14 4-18 4-20 4-23 4-26 4-3 4-6 4-9--> let {s = filter ((== 4) . length) scs-> ;x = map permutations s}-> in zip (map sc_name s) (map (set . (map bip)) x)-- $ cat view.sh- for i in $(fl -c $1 | pg | bip | sort -u)- do- echo $i":" $(grep -l $i * | sort -t '-' +1 -n | tr "\n" " ")- done- $ sh view.sh 4- 111: 4-1- 112: 4-1 4-2 4-3- 113: 4-1 4-3 4-4 4-7- ...--> let {n = 4-> ;s = filter ((== n) . length) scs-> ;x = map permutations s-> ;z = zip (map sc_name s) (map (set . (map bip)) x)-> ;f b (s,bs) = if b `elem` bs then Just s else Nothing-> ;g b = catMaybes (map (f b) z)-> ;a = set (map bip (concat x))}-> in zip a (map g a)-- $ cyc < ~/src/pct/lib/scs | epmq \- > "in cset 89" "is icset 12" "hasnt icseg 11" | scdb- 7-34 ascending melodic minor collection- 7-35 diatonic collection (d)- 8-28 octotonic collection (Messiaen Mode II)--> let {cyc xs = xs ++ [head xs]-> ;a = filter (\p -> length p `elem` [8,9]) (map cyc scs)-> ;b = filter (\p -> set (int p) == [1,2]) a-> ;c = filter (\p -> not ([1,1] `isInfixOf` int p)) b}-> in map (sc_name . nub) c == ["7-34","7-35","8-28"]-- $ epmq < ~/src/pct/lib/univ "in cset 6" "in pcset 579t024" \- > "has sc 5-35" "hasnt sc 2-6" "notin pcset 024579e"- 02579A--> let {a = cf [6] (powerset [0..11])-> ;b = filter (is_superset [0,2,4,5,7,9,10]) a-> ;c = filter (`has_sc` (sc "5-35")) b-> ;d = filter (not . (`has_sc` (sc "2-6"))) c-> ;e = filter (not . is_superset [0,2,4,5,7,9,11]) d}-> in e == [[0,2,5,7,9,10]]-- $ echo 156 | sro T0I | sro T4- 3BA--> let {i = SRO 0 False 0 False True-> ;t4 = SRO 0 False 4 False False}-> in (sro i >>> sro t4) [1,5,6] == [3,11,10]-- $ echo 156 | sro T4 | sro T0I- 732--> let {i = SRO 0 False 0 False True-> ;t4 = SRO 0 False 4 False False}-> in (sro i . sro t4) [1,5,6] == [7,3,2]--Note that pct uses right rotation rotation.--> sro (SRO 1 True 1 True False) [0,1,2,3] == [11,6,1,4]-> sro (SRO 1 False 4 True True) [0,1,2,3] == [11,6,1,4]-- I = MB; TnI = TnMB,--> mn 11 [0,1,4,9] == tni 0 [0,1,4,9]-- MI = IM = M7 = MBM5; TnMI = TnM7--> sro (rnrtnmi "T0MI") [0,1,4,9] == mn 7 [0,1,4,9]-- T0 = T0M1; Tn = TnM1- M = M5; TnM = TnM5,-- $ se -c5 123- 12333- 12233- 12223- 11233- 11223- 11123--> expand_set 5 [1,2,3]--> ici [1,2,3]-> cgg [[0],[1,11],[2,10],[3,9],[4,8],[5,7],[6]]-- $ se -c5 1245 | pg | ici | pcom iseg sc | \- sort -u | epmq "in cset 6" | wc -l- 42--> let {a = expand_set 5 [1,2,4,5]-> ;b = concatMap permutations a-> ;c = concatMap ici b-> ;d = map (forte_prime . dx_d 0) c-> ;e = nub d-> ;f = cf [6] e}-> in length f == 42-- $ imb -c34 024579 | pfmt- 024 245 457 579- 0245 2457 4579--> imb [3,4] [0,2,4,5,7,9]-- $ rs 0123 e614- T1M- $ rs 0123 641e416- T1M-- $ sb 6-32 6-8 | fn | pfmt- 1-1- 2-1 2-2 2-3 2-4 2-5- 3-2 3-4 3-6 3-7 3-9 3-11- 4-10 4-11 4-14 4-22 4-23- 5-23- $ for i in `cat ~/src/pct/lib/scs | cf 6 | fn` ; \- do echo $i >> LIST ; sb $i | cf 3 | wc -l >> LIST ; done--> map sc_name (sb [sc "6-32",sc "6-8"])--> let f p = let xs = cf [3] (sb [p])-> in (sc_name p,length xs)-> in map f (cf [6] scs)
+ Music/Theory/Array.hs view
@@ -0,0 +1,90 @@+module Music.Theory.Array where++import Data.List {- base -}+import qualified Data.Array as A {- array -}++import qualified Music.Theory.List as T {- hmt -}++-- * Association List (List Array)++larray_bounds :: Ord k => [(k,v)] -> (k,k)+larray_bounds = T.minmax . map fst++larray :: A.Ix k => [(k,v)] -> A.Array k v+larray a = A.array (larray_bounds a) a++-- * List Table++-- | Append a sequence of /nil/ (or default) values to each row of /tbl/+-- so to make it regular (ie. all rows of equal length).+make_regular :: t -> [[t]] -> [[t]]+make_regular k tbl =+ let z = maximum (map length tbl)+ in map (T.pad_right k z) tbl++-- * Matrix Indices++-- | Matrix dimensions are written (rows,columns).+type Dimensions i = (i,i)++-- | Matrix indices are written (row,column) & are here _zero_ indexed.+type Ix i = (i,i)++-- | Translate 'Ix' by row and column delta.+--+-- > ix_translate (1,2) (3,4) == (4,6)+ix_translate :: Num t => (t,t) -> Ix t -> Ix t+ix_translate (dr,dc) (r,c) = (r + dr,c + dc)++-- | Modulo 'Ix' by 'Dimensions'.+--+-- > ix_modulo (4,4) (3,7) == (3,3)+ix_modulo :: Integral t => Dimensions t -> Ix t -> Ix t+ix_modulo (nr,nc) (r,c) = (r `mod` nr,c `mod` nc)++-- | Given number of columns and row index, list row indices.+--+-- > row_indices 3 1 == [(1,0),(1,1),(1,2)]+row_indices :: (Enum t, Num t) => t -> t -> [Ix t]+row_indices nc r = map (\c -> (r,c)) [0 .. nc - 1]++-- | Given number of rows and column index, list column indices.+--+-- > column_indices 3 1 == [(0,1),(1,1),(2,1)]+column_indices :: (Enum t, Num t) => t -> t -> [Ix t]+column_indices nr c = map (\r -> (r,c)) [0 .. nr - 1]++-- | All zero-indexed matrix indices, in row order. This is the order+-- given by 'sort'.+--+-- > matrix_indices (2,3) == [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)]+-- > sort (matrix_indices (2,3)) == matrix_indices (2,3)+matrix_indices :: (Enum t, Num t) => Dimensions t -> [Ix t]+matrix_indices (nr,nc) = concatMap (row_indices nc) [0 .. nr - 1 ]++-- | Corner indices of given 'Dimensions', in row order.+--+-- > matrix_corner_indices (2,3) == [(0,0),(0,2),(1,0),(1,2)]+matrix_corner_indices :: Num t => Dimensions t -> [Ix t]+matrix_corner_indices (nr,nc) = [(0,0),(0,nc - 1),(nr - 1,0),(nr - 1,nc - 1)]++-- | Parallelogram corner indices, given as rectangular 'Dimensions' with an+-- offset for the lower indices.+--+-- > parallelogram_corner_indices ((2,3),2) == [(0,0),(0,2),(1,2),(1,4)]+parallelogram_corner_indices :: Num t => (Dimensions t,t) -> [Ix t]+parallelogram_corner_indices ((nr,nc),o) = [(0,0),(0,nc - 1),(nr - 1,o),(nr - 1,nc + o - 1)]++-- | Apply 'ix_modulo' and 'ix_translate' for all 'matrix_indices',+-- ie. all translations of a 'shape' in row order. The resulting 'Ix'+-- sets are not sorted and may have duplicates.+--+-- > concat (all_ix_translations (2,3) [(0,0)]) == matrix_indices (2,3)+all_ix_translations :: Integral t => Dimensions t -> [Ix t] -> [[Ix t]]+all_ix_translations dm ix =+ let f z = ix_modulo dm . ix_translate z+ in map (\dx -> map (f dx) ix) (matrix_indices dm)++-- | Sort sets into row order and remove duplicates.+all_ix_translations_uniq :: Integral t => Dimensions t -> [Ix t] -> [[Ix t]]+all_ix_translations_uniq dm = nub . map sort . all_ix_translations dm
Music/Theory/Array/CSV.hs view
@@ -1,228 +1,25 @@ -- | Regular matrix array data, CSV, column & row indexing. module Music.Theory.Array.CSV where -import Data.Array {- array -}-import Data.Char {- base -}-import Data.Function {- base -}+import qualified Data.Array as A {- array -} import Data.List {- base -}-import Data.String {- base -} import qualified Text.CSV.Lazy.String as C {- lazy-csv -} +import qualified Music.Theory.Array.Cell_Ref as T {- hmt -}+import qualified Music.Theory.IO as T {- hmt -} import qualified Music.Theory.List as T {- hmt -}---- * Indexing---- | @A@ indexed case-insensitive column references. The column--- following @Z@ is @AA@.-data Column_Ref = Column_Ref {column_ref_string :: String}--instance IsString Column_Ref where fromString = Column_Ref-instance Read Column_Ref where readsPrec _ s = [(Column_Ref s,[])]-instance Show Column_Ref where show = column_ref_string-instance Eq Column_Ref where (==) = (==) `on` column_index-instance Ord Column_Ref where compare = compare `on` column_index--instance Enum Column_Ref where- fromEnum = column_index- toEnum = column_ref--instance Ix Column_Ref where- range = column_range- index = interior_column_index- inRange = column_in_range- rangeSize = column_range_size---- | Inclusive range of column references.-type Column_Range = (Column_Ref,Column_Ref)---- | @1@-indexed row reference.-type Row_Ref = Int---- | Zero index of 'Row_Ref'.-row_index :: Row_Ref -> Int-row_index r = r - 1---- | Inclusive range of row references.-type Row_Range = (Row_Ref,Row_Ref)---- | Cell reference, column then row.-type Cell_Ref = (Column_Ref,Row_Ref)---- | Inclusive range of cell references.-type Cell_Range = (Cell_Ref,Cell_Ref)---- | Case folding letter to index function. Only valid for ASCII letters.------ > map letter_index ['A' .. 'Z'] == [0 .. 25]--- > map letter_index ['a','d' .. 'm'] == [0,3 .. 12]-letter_index :: Char -> Int-letter_index c = fromEnum (toUpper c) - fromEnum 'A'---- | Inverse of 'letter_index'.------ > map index_letter [0,3 .. 12] == ['A','D' .. 'M']-index_letter :: Int -> Char-index_letter i = toEnum (i + fromEnum 'A')---- | Translate column reference to @0@-index.------ > :set -XOverloadedStrings--- > map column_index ["A","c","z","ac","XYZ"] == [0,2,25,28,17575]-column_index :: Column_Ref -> Int-column_index (Column_Ref c) =- let m = iterate (* 26) 1- i = reverse (map letter_index c)- in sum (zipWith (*) m (zipWith (+) [0..] i))---- | Column reference to interior index within specified range. Type--- specialised 'Data.Ix.index'.------ > map (Data.Ix.index ('A','Z')) ['A','C','Z'] == [0,2,25]--- > map (interior_column_index ("A","Z")) ["A","C","Z"] == [0,2,25]------ > map (Data.Ix.index ('B','C')) ['B','C'] == [0,1]--- > map (interior_column_index ("B","C")) ["B","C"] == [0,1]-interior_column_index :: Column_Range -> Column_Ref -> Int-interior_column_index (l,r) c =- let n = column_index c- l' = column_index l- r' = column_index r- in if n > r'- then error (show ("interior_column_index",l,r,c))- else n - l'---- | Inverse of 'column_index'.------ > let c = ["A","Z","AA","AZ","BA","BZ","CA"]--- > in map column_ref [0,25,26,51,52,77,78] == c------ > column_ref (0+25+1+25+1+25+1) == "CA"-column_ref :: Int -> Column_Ref-column_ref =- let rec n = case n `quotRem` 26 of- (0,r) -> [index_letter r]- (q,r) -> index_letter (q - 1) : rec r- in Column_Ref . rec---- | Type specialised 'pred'.------ > column_ref_pred "DF" == "DE"-column_ref_pred :: Column_Ref -> Column_Ref-column_ref_pred = pred---- | Type specialised 'succ'.------ > column_ref_succ "DE" == "DF"-column_ref_succ :: Column_Ref -> Column_Ref-column_ref_succ = succ---- | Bimap of 'column_index'.------ > column_indices ("b","p") == (1,15)--- > column_indices ("B","IT") == (1,253)-column_indices :: Column_Range -> (Int,Int)-column_indices =- let bimap f (i,j) = (f i,f j)- in bimap column_index---- | Type specialised 'Data.Ix.range'.------ > column_range ("L","R") == ["L","M","N","O","P","Q","R"]--- > Data.Ix.range ('L','R') == "LMNOPQR"-column_range :: Column_Range -> [Column_Ref]-column_range rng =- let (l,r) = column_indices rng- in map column_ref [l .. r]---- | Type specialised 'Data.Ix.inRange'.------ > map (column_in_range ("L","R")) ["A","N","Z"] == [False,True,False]--- > map (column_in_range ("L","R")) ["L","N","R"] == [True,True,True]------ > map (Data.Ix.inRange ('L','R')) ['A','N','Z'] == [False,True,False]--- > map (Data.Ix.inRange ('L','R')) ['L','N','R'] == [True,True,True]-column_in_range :: Column_Range -> Column_Ref -> Bool-column_in_range rng c =- let (l,r) = column_indices rng- k = column_index c- in k >= l && k <= r---- | Type specialised 'Data.Ix.rangeSize'.------ > map column_range_size [("A","Z"),("AA","ZZ")] == [26,26 * 26]--- > Data.Ix.rangeSize ('A','Z') == 26-column_range_size :: Column_Range -> Int-column_range_size = (+ 1) . negate . uncurry (-) . column_indices---- | Type specialised 'Data.Ix.range'.-row_range :: Row_Range -> [Row_Ref]-row_range = range---- | The standard uppermost leftmost cell reference, @A1@.------ > Just cell_ref_minima == parse_cell_ref "A1"-cell_ref_minima :: Cell_Ref-cell_ref_minima = (Column_Ref "A",1)---- | Cell reference parser for standard notation of (column,row).------ > parse_cell_ref "CC348" == Just ("CC",348)-parse_cell_ref :: String -> Maybe Cell_Ref-parse_cell_ref s =- case span isUpper s of- ([],_) -> Nothing- (c,r) -> case span isDigit r of- (n,[]) -> Just (Column_Ref c,read n)- _ -> Nothing---- | Cell reference pretty printer.------ > cell_ref_pp ("CC",348) == "CC348"-cell_ref_pp :: Cell_Ref -> String-cell_ref_pp (Column_Ref c,r) = c ++ show r---- | Translate cell reference to @0@-indexed pair.------ > cell_index ("CC",348) == (80,347)--- > Data.Ix.index (("AA",1),("ZZ",999)) ("CC",348) == 54293-cell_index :: Cell_Ref -> (Int,Int)-cell_index (c,r) = (column_index c,row_index r)---- | Type specialised 'Data.Ix.range', cells are in column-order.------ > cell_range (("AA",1),("AC",1)) == [("AA",1),("AB",1),("AC",1)]------ > let r = [("AA",1),("AA",2),("AB",1),("AB",2),("AC",1),("AC",2)]--- > in cell_range (("AA",1),("AC",2)) == r------ > Data.Ix.range (('A',1),('C',1)) == [('A',1),('B',1),('C',1)]------ > let r = [('A',1),('A',2),('B',1),('B',2),('C',1),('C',2)]--- > in Data.Ix.range (('A',1),('C',2)) == r-cell_range :: Cell_Range -> [Cell_Ref]-cell_range ((c1,r1),(c2,r2)) =- [(c,r) |- c <- column_range (c1,c2)- ,r <- row_range (r1,r2)]---- | Variant of 'cell_range' in row-order.------ > let r = [(AA,1),(AB,1),(AC,1),(AA,2),(AB,2),(AC,2)]--- > in cell_range_row_order (("AA",1),("AC",2)) == r-cell_range_row_order :: Cell_Range -> [Cell_Ref]-cell_range_row_order ((c1,r1),(c2,r2)) =- [(c,r) |- r <- row_range (r1,r2)- ,c <- column_range (c1,c2)]+import qualified Music.Theory.Tuple as T {- hmt -} -- * TABLE -- | When reading a CSV file is the first row a header? type CSV_Has_Header = Bool +-- | Alias for 'Char', allow characters other than @,@ as delimiter. type CSV_Delimiter = Char +-- | Alias for 'Bool', allow linebreaks in fields. type CSV_Allow_Linebreaks = Bool -- | When writing a CSV file should the delimiters be aligned,@@ -242,26 +39,28 @@ -- columns. type Table a = [[a]] --- | CSV table, ie. a table with perhaps a header.+-- | CSV table, ie. a 'Table' with 'Maybe' a header. type CSV_Table a = (Maybe [String],Table a) --- | Read 'Table' from @CSV@ file.+-- | Read 'CSV_Table' from @CSV@ file. csv_table_read :: CSV_Opt -> (String -> a) -> FilePath -> IO (CSV_Table a) csv_table_read (hdr,delim,brk,_) f fn = do- s <- readFile fn+ s <- T.read_file_utf8 fn let t = C.csvTable (C.parseDSV brk delim s) p = C.fromCSVTable t (h,d) = if hdr then (Just (head p),tail p) else (Nothing,p) return (h,map (map f) d) -- | Read 'Table' only with 'def_csv_opt'.-csv_table_read' :: (String -> a) -> FilePath -> IO (Table a)-csv_table_read' f = fmap snd . csv_table_read def_csv_opt f+csv_table_read_def :: (String -> a) -> FilePath -> IO (Table a)+csv_table_read_def f = fmap snd . csv_table_read def_csv_opt f --- | Read and process @CSV@ 'Table'.+-- | Read and process @CSV@ 'CSV_Table'. csv_table_with :: CSV_Opt -> (String -> a) -> FilePath -> (CSV_Table a -> b) -> IO b csv_table_with opt f fn g = fmap g (csv_table_read opt f fn) +-- | Align table according to 'CSV_Align_Columns'.+-- -- > csv_table_align CSV_No_Align [["a","row","and"],["then","another","one"]] csv_table_align :: CSV_Align_Columns -> Table String -> Table String csv_table_align align tbl =@@ -274,40 +73,43 @@ CSV_Align_Right -> s ++ pd in transpose (zipWith (map . ext) n c) --- | Write 'Table' to @CSV@ file.+-- | Pretty-print 'CSV_Table'.+csv_table_pp :: (a -> String) -> CSV_Opt -> CSV_Table a -> String+csv_table_pp f (_,delim,brk,align) (hdr,tbl) =+ let tbl' = csv_table_align align (T.mcons hdr (map (map f) tbl))+ (_,t) = C.toCSVTable tbl'+ in C.ppDSVTable brk delim t++-- | 'T.write_file_utf8' of 'csv_table_pp'. csv_table_write :: (a -> String) -> CSV_Opt -> FilePath -> CSV_Table a -> IO ()-csv_table_write f (_,delim,brk,align) fn (hdr,tbl) = do- let tbl' = csv_table_align align (map (map f) tbl)- (_,t) = C.toCSVTable (T.mcons hdr tbl')- s = C.ppDSVTable brk delim t- writeFile fn s+csv_table_write f opt fn csv = T.write_file_utf8 fn (csv_table_pp f opt csv) --- | Write 'Table' only (no header).-csv_table_write' :: (a -> String) -> CSV_Opt -> FilePath -> Table a -> IO ()-csv_table_write' f opt fn tbl = csv_table_write f opt fn (Nothing,tbl)+-- | Write 'Table' only (no header) with 'def_csv_opt'.+csv_table_write_def :: (a -> String) -> FilePath -> Table a -> IO ()+csv_table_write_def f fn tbl = csv_table_write f def_csv_opt fn (Nothing,tbl) -- | @0@-indexed (row,column) cell lookup. table_lookup :: Table a -> (Int,Int) -> a table_lookup t (r,c) = (t !! r) !! c -- | Row data.-table_row :: Table a -> Row_Ref -> [a]-table_row t r = t !! row_index r+table_row :: Table a -> T.Row_Ref -> [a]+table_row t r = t !! T.row_index r -- | Column data.-table_column :: Table a -> Column_Ref -> [a]-table_column t c = transpose t !! column_index c+table_column :: Table a -> T.Column_Ref -> [a]+table_column t c = transpose t !! T.column_index c -- | Lookup value across columns.-table_column_lookup :: Eq a => Table a -> (Column_Ref,Column_Ref) -> a -> Maybe a+table_column_lookup :: Eq a => Table a -> (T.Column_Ref,T.Column_Ref) -> a -> Maybe a table_column_lookup t (c1,c2) e = let a = zip (table_column t c1) (table_column t c2) in lookup e a -- | Table cell lookup.-table_cell :: Table a -> Cell_Ref -> a+table_cell :: Table a -> T.Cell_Ref -> a table_cell t (c,r) =- let (r',c') = (row_index r,column_index c)+ let (r',c') = (T.row_index r,T.column_index c) in table_lookup t (r',c') -- | @0@-indexed (row,column) cell lookup over column range.@@ -317,9 +119,9 @@ in take (c1 - c0 + 1) (drop c0 r') -- | Range of cells from row.-table_row_segment :: Table a -> (Row_Ref,Column_Range) -> [a]+table_row_segment :: Table a -> (T.Row_Ref,T.Column_Range) -> [a] table_row_segment t (r,c) =- let (r',c') = (row_index r,column_indices c)+ let (r',c') = (T.row_index r,T.column_indices c) in table_lookup_row_segment t (r',c') -- * Array@@ -333,14 +135,55 @@ -- > > (((A,1),(C,2)) -- > > ,[(A,1),(A,2),(B,1),(B,2),(C,1),(C,2)] -- > > ,[0,2,1,4,3,5])-table_to_array :: Table a -> Array Cell_Ref a+table_to_array :: Table a -> A.Array T.Cell_Ref a table_to_array t = let nr = length t nc = length (t !! 0)- bnd = (cell_ref_minima,(toEnum (nc - 1),nr))- asc = zip (cell_range_row_order bnd) (concat t)- in array bnd asc+ bnd = (T.cell_ref_minima,(toEnum (nc - 1),nr))+ asc = zip (T.cell_range_row_order bnd) (concat t)+ in A.array bnd asc -- | 'table_to_array' of 'csv_table_read'.-csv_array_read :: CSV_Opt -> (String -> a) -> FilePath -> IO (Array Cell_Ref a)+csv_array_read :: CSV_Opt -> (String -> a) -> FilePath -> IO (A.Array T.Cell_Ref a) csv_array_read opt f fn = fmap (table_to_array . snd) (csv_table_read opt f fn)++-- * Irregular++csv_field_str :: C.CSVField -> String+csv_field_str f =+ case f of+ C.CSVField _ _ _ _ s _ -> s+ C.CSVFieldError _ _ _ _ _ -> error "csv_field_str"++csv_error_recover :: C.CSVError -> C.CSVRow+csv_error_recover e =+ case e of+ C.IncorrectRow _ _ _ f -> f+ C.BlankLine _ _ _ _ -> []+ _ -> error "csv_error_recover: not recoverable"++csv_row_recover :: Either [C.CSVError] C.CSVRow -> C.CSVRow+csv_row_recover r =+ case r of+ Left [e] -> csv_error_recover e+ Left _ -> error "csv_row_recover: multiple errors"+ Right r' -> r'++-- | Read irregular @CSV@ file, ie. rows may have any number of columns, including no columns.+csv_load_irregular :: (String -> a) -> FilePath -> IO [[a]]+csv_load_irregular f fn = do+ s <- T.read_file_utf8 fn+ return (map (map (f . csv_field_str) . csv_row_recover) (C.parseCSV s))++-- * Tuples++type P5_Parser t1 t2 t3 t4 t5 = (String -> t1,String -> t2,String -> t3,String -> t4,String -> t5)+type P5_Writer t1 t2 t3 t4 t5 = (t1 -> String,t2 -> String,t3 -> String,t4 -> String,t5 -> String)++csv_table_read_p5 :: P5_Parser t1 t2 t3 t4 t5 -> CSV_Opt -> FilePath -> IO (Maybe [String],[(t1,t2,t3,t4,t5)])+csv_table_read_p5 f opt fn = do+ (hdr,dat) <- csv_table_read opt id fn+ return (hdr,map (T.p5_from_list f) dat)++csv_table_write_p5 :: P5_Writer t1 t2 t3 t4 t5 -> CSV_Opt -> FilePath -> (Maybe [String],[(t1,t2,t3,t4,t5)]) -> IO ()+csv_table_write_p5 f opt fn (hdr,dat) = csv_table_write id opt fn (hdr,map (T.p5_to_list f) dat)
− Music/Theory/Array/CSV/Midi.hs
@@ -1,86 +0,0 @@--- | Functions for reading midi note data from CSV files.-module Music.Theory.Array.CSV.Midi where--import Data.Function {- base -}-import Data.Maybe {- base -}--import qualified Music.Theory.Array.CSV as T {- hmt -}-import qualified Music.Theory.Time.Seq as T {- hmt -}---- | Variant of 'reads' requiring exact match.-reads_exact :: Read a => String -> Maybe a-reads_exact s =- case reads s of- [(r,"")] -> Just r- _ -> Nothing---- | Variant of 'reads_exact' that errors on failure.-reads_err :: Read a => String -> a-reads_err str = fromMaybe (error ("could not read: " ++ str)) (reads_exact str)---- | The required header field.-csv_midi_note_data_hdr :: [String]-csv_midi_note_data_hdr = ["time","on/off","note","velocity"]---- | Midi note data, header is @time,on/off,note,velocity@.--- Translation values for on/off are consulted.------ > let fn = "/home/rohan/cvs/uc/uc-26/daily-practice/2014-08-13.1.csv"--- > csv_midi_note_data_read' ("ON","OFF") fn :: IO [(Double,Either String String,Double,Double)]-csv_midi_note_data_read' :: (Read t,Real t,Read n,Real n) => (m,m) -> FilePath -> IO [(t,Either m String,n,n)]-csv_midi_note_data_read' (m_on,m_off) =- let err x = error ("csv_midi_note_data_read: " ++ x)- read_md x = case x of- "on" -> Left m_on- "off" -> Left m_off- _ -> Right x- f m =- case m of- [st,md,mnn,amp] -> (reads_err st,read_md md,reads_err mnn,reads_err amp)- _ -> err "entry?"- g (hdr,dat) = case hdr of- Just hdr' -> if hdr' == csv_midi_note_data_hdr then dat else err "header?"- Nothing -> err "no header?"- in fmap (map f . g) . T.csv_table_read (True,',',False,T.CSV_No_Align) id---- | Variant of 'csv_midi_note_data_read'' that errors on non on/off data.-csv_midi_note_data_read :: (Read t,Real t,Read n,Real n) => (m,m) -> FilePath -> IO [(t,m,n,n)]-csv_midi_note_data_read m =- let f (t,p,q,r) = (t,either id (error "not on/off") p,q,r)- in fmap (map f) . csv_midi_note_data_read' m---- | 'Tseq' form of 'csv_read_midi_note_data'.-midi_tseq_read :: (Read t,Real t,Read n,Real n) => FilePath -> IO (T.Tseq t (T.On_Off (n,n)))-midi_tseq_read =- let mk_node (st,md,mnn,amp) = if md- then (st,T.On (mnn,amp))- else (st,T.Off (mnn,0))- in fmap (map mk_node) . csv_midi_note_data_read (True,False)---- | Translate from 'Tseq' form to 'Wseq' form.-midi_tseq_to_midi_wseq :: (Num t,Eq n) => T.Tseq t (T.On_Off (n,n)) -> T.Wseq t (n,n)-midi_tseq_to_midi_wseq = T.tseq_on_off_to_wseq ((==) `on` fst)---- | Off-velocity is zero.-midi_wseq_to_midi_tseq :: (Num t,Ord t) => T.Wseq t (n,n) -> T.Tseq t (T.On_Off (n,n))-midi_wseq_to_midi_tseq = T.wseq_on_off---- | Writer.-csv_midi_note_data_write :: (Eq m,Show t,Real t,Show n,Real n) => (m,m) -> FilePath -> [(t,m,n,n)] -> IO ()-csv_midi_note_data_write (m_on,m_off) nm =- let show_md md = if md == m_on- then "on" else if md == m_off- then "off"- else error "csv_midi_note_data_write"- un_node (st,md,mnn,amp) = [show st,show_md md,show mnn,show amp]- with_hdr dat = (Just csv_midi_note_data_hdr,dat)- in T.csv_table_write id T.def_csv_opt nm . with_hdr . map un_node---- | 'Tseq' form of 'csv_midi_note_data_write'.-midi_tseq_write :: (Show t,Real t,Show n,Real n) => FilePath -> T.Tseq t (T.On_Off (n,n)) -> IO ()-midi_tseq_write nm sq =- let f (t,e) = case e of- T.On (n,v) -> (t,True,n,v)- T.Off (n,v) -> (t,False,n,v)- sq' = map f sq- in csv_midi_note_data_write (True,False) nm sq'
+ Music/Theory/Array/CSV/Midi/MND.hs view
@@ -0,0 +1,203 @@+-- | Functions for reading midi note data (MND) from CSV files.+-- This is /not/ a generic text midi notation.+-- The defined commands are @on@ and @off@, but others may be present.+-- Non-integral note number and key velocity data are allowed.+module Music.Theory.Array.CSV.Midi.MND where++import Data.List.Split {- split -}+import Data.List {- base -}+import Data.Maybe {- base -}+import Data.Word {- base -}++import qualified Music.Theory.Array.CSV as T {- hmt -}+import qualified Music.Theory.Math as T {- hmt -}+import qualified Music.Theory.Read as T {- hmt -}+import qualified Music.Theory.Time.Seq as T {- hmt -}++-- | If /r/ is whole to /k/ places then show as integer, else as float to /k/ places.+data_value_pp :: Real t => Int -> t -> String+data_value_pp k r =+ if T.whole_to_precision k r+ then show (T.real_floor_int r)+ else T.real_pp k r++-- | Channel values are 4-bit (0-15).+type Channel = Word8++-- | The required header field.+csv_mnd_hdr :: [String]+csv_mnd_hdr = ["time","on/off","note","velocity","channel","param"]++type Param = (String,Double)++param_parse :: String -> [Param]+param_parse str =+ let f x = case splitOn "=" x of+ [lhs,rhs] -> (lhs,read rhs)+ _ -> error ("param_parse: " ++ x)+ in if null str then [] else map f (splitOn ";" str)++param_pp :: Int -> [Param] -> String+param_pp k =+ let f (lhs,rhs) = concat [lhs,"=",T.real_pp k rhs]+ in intercalate ";" . map f++-- | Midi note data, the type parameters are to allow for fractional note & velocity values.+-- The command is a string, @on@ and @off@ are standard, other commands may be present.+--+-- > unwords csv_mnd_hdr == "time on/off note velocity channel param"+type MND t n = (t,String,n,n,Channel,[Param])++csv_mnd_parse :: (Read t,Real t,Read n,Real n) => T.CSV_Table String -> [MND t n]+csv_mnd_parse (hdr,dat) =+ let err x = error ("csv_mnd_read: " ++ x)+ f m = case m of+ [st,msg,mnn,vel,ch,pm] ->+ (T.reads_exact_err "time:real" st+ ,msg+ ,T.reads_exact_err "note:real" mnn+ ,T.reads_exact_err "velocity:real" vel+ ,T.reads_exact_err "channel:int" ch+ ,param_parse pm)+ _ -> err "entry?"+ in case hdr of+ Just hdr' -> if hdr' == csv_mnd_hdr then map f dat else err "header?"+ Nothing -> err "no header?"++load_csv :: FilePath -> IO (T.CSV_Table String)+load_csv = T.csv_table_read (True,',',False,T.CSV_No_Align) id++-- | Midi note data.+--+-- > let fn = "/home/rohan/cvs/uc/uc-26/daily-practice/2014-08-13.1.csv"+-- > m <- csv_mnd_read fn :: IO [MND Double Double]+-- > length m == 17655+-- > csv_mnd_write 4 "/tmp/t.csv" m+csv_mnd_read :: (Read t,Real t,Read n,Real n) => FilePath -> IO [MND t n]+csv_mnd_read = fmap csv_mnd_parse . load_csv++-- | Writer.+csv_mnd_write :: (Real t,Real n) => Int -> FilePath -> [MND t n] -> IO ()+csv_mnd_write r_prec nm =+ let un_node (st,msg,mnn,vel,ch,pm) =+ [T.real_pp r_prec st+ ,msg+ ,data_value_pp r_prec mnn+ ,data_value_pp r_prec vel+ ,show ch+ ,param_pp r_prec pm]+ with_hdr dat = (Just csv_mnd_hdr,dat)+ in T.csv_table_write id T.def_csv_opt nm . with_hdr . map un_node++-- * MND Seq forms++-- | (p0=midi-note,p1=velocity,channel,param)+type Event n = (n,n,Channel,[Param])++-- | Translate from 'Tseq' form to 'Wseq' form.+midi_tseq_to_midi_wseq :: (Num t,Eq n) => T.Tseq t (T.Begin_End (Event n)) -> T.Wseq t (Event n)+midi_tseq_to_midi_wseq = T.tseq_begin_end_to_wseq (\(n0,_,c0,_) (n1,_,c1,_) -> c0 == c1 && n0 == n1)++midi_wseq_to_midi_tseq :: (Num t,Ord t) => T.Wseq t x -> T.Tseq t (T.Begin_End x)+midi_wseq_to_midi_tseq = T.wseq_begin_end++-- | Ignores non on/off messages.+mnd_to_tseq :: Num n => [MND t n] -> T.Tseq t (T.Begin_End (Event n))+mnd_to_tseq =+ let mk_node (st,msg,mnn,vel,ch,pm) =+ case msg of+ "on" -> Just (st,T.Begin (mnn,vel,ch,pm))+ "off" -> Just (st,T.End (mnn,0,ch,pm))+ _ -> Nothing+ in mapMaybe mk_node++-- | 'Tseq' form of 'csv_mnd_read', channel information is retained, off-velocity is zero.+csv_mnd_read_tseq :: (Read t,Real t,Read n,Real n) => FilePath -> IO (T.Tseq t (T.Begin_End (Event n)))+csv_mnd_read_tseq = fmap mnd_to_tseq . csv_mnd_read++-- | 'Tseq' form of 'csv_mnd_write', data is .+csv_mnd_write_tseq :: (Real t,Real n) => Int -> FilePath -> T.Tseq t (T.Begin_End (Event n)) -> IO ()+csv_mnd_write_tseq r_prec nm sq =+ let f (t,e) = case e of+ T.Begin (n,v,c,p) -> (t,"on",n,v,c,p)+ T.End (n,_,c,p) -> (t,"off",n,0,c,p)+ in csv_mnd_write r_prec nm (map f sq)++-- * MNDD (simplifies cases where overlaps on the same channel are allowed).++-- | Message should be @note@ for note data.+csv_mndd_hdr :: [String]+csv_mndd_hdr = ["time","duration","message","note","velocity","channel","param"]++-- > unwords csv_mndd_hdr == "time duration message note velocity channel param"+type MNDD t n = (t,t,String,n,n,Channel,[Param])++csv_mndd_parse :: (Read t,Real t,Read n,Real n) => T.CSV_Table String -> [MNDD t n]+csv_mndd_parse (hdr,dat) =+ let err x = error ("csv_mndd_read: " ++ x)+ f m =+ case m of+ [st,du,msg,mnn,vel,ch,pm] ->+ (T.reads_exact_err "time" st+ ,T.reads_exact_err "duration" du+ ,msg+ ,T.reads_exact_err "note" mnn+ ,T.reads_exact_err "velocity" vel+ ,T.reads_exact_err "channel" ch+ ,param_parse pm)+ _ -> err "entry?"+ in case hdr of+ Just hdr' -> if hdr' == csv_mndd_hdr then map f dat else err "header?"+ Nothing -> err "no header?"++-- | Midi note/duration data.+csv_mndd_read :: (Read t,Real t,Read n,Real n) => FilePath -> IO [MNDD t n]+csv_mndd_read = fmap csv_mndd_parse . load_csv++-- | Writer.+csv_mndd_write :: (Real t,Real n) => Int -> FilePath -> [MNDD t n] -> IO ()+csv_mndd_write r_prec nm =+ let un_node (st,du,msg,mnn,vel,ch,pm) =+ [T.real_pp r_prec st,T.real_pp r_prec du,msg+ ,data_value_pp r_prec mnn,data_value_pp r_prec vel+ ,show ch+ ,param_pp r_prec pm]+ with_hdr dat = (Just csv_mndd_hdr,dat)+ in T.csv_table_write id T.def_csv_opt nm . with_hdr . map un_node++-- * MNDD Seq forms++-- | Ignores non note messages.+mndd_to_wseq :: [MNDD t n] -> T.Wseq t (Event n)+mndd_to_wseq =+ let mk_node (st,du,msg,mnn,vel,ch,pm) =+ case msg of+ "note" -> Just ((st,du),(mnn,vel,ch,pm))+ _ -> Nothing+ in mapMaybe mk_node++-- | 'Wseq' form of 'csv_mndd_read'.+csv_mndd_read_wseq :: (Read t,Real t,Read n,Real n) => FilePath -> IO (T.Wseq t (Event n))+csv_mndd_read_wseq = fmap mndd_to_wseq . csv_mndd_read++-- | 'Wseq' form of 'csv_mndd_write'.+csv_mndd_write_wseq :: (Real t,Real n) => Int -> FilePath -> T.Wseq t (Event n) -> IO ()+csv_mndd_write_wseq r_prec nm =+ let f ((st,du),(mnn,vel,ch,pm)) = (st,du,"note",mnn,vel,ch,pm)+ in csv_mndd_write r_prec nm . map f++-- * Composite++-- | Parse either MND or MNDD data to Wseq, CSV type is decided by header.+csv_midi_parse_wseq :: (Read t,Real t,Read n,Real n) => T.CSV_Table String -> T.Wseq t (Event n)+csv_midi_parse_wseq (hdr,dat) = do+ case hdr of+ Just hdr' -> if hdr' == csv_mnd_hdr+ then midi_tseq_to_midi_wseq (mnd_to_tseq (csv_mnd_parse (hdr,dat)))+ else if hdr' == csv_mndd_hdr+ then mndd_to_wseq (csv_mndd_parse (hdr,dat))+ else error "csv_midi_read_wseq: not MND or MNDD"+ _ -> error "csv_midi_read_wseq: header?"++csv_midi_read_wseq :: (Read t,Real t,Read n,Real n) => FilePath -> IO (T.Wseq t (Event n))+csv_midi_read_wseq = fmap csv_midi_parse_wseq . load_csv
+ Music/Theory/Array/Cell_Ref.hs view
@@ -0,0 +1,228 @@+-- | Cell references & indexing.+module Music.Theory.Array.Cell_Ref where++import qualified Data.Array as A {- array -}+import Data.Char {- base -}+import Data.Function {- base -}+import Data.Maybe {- base -}+import Data.String {- base -}++-- | @A@ indexed case-insensitive column references. The column+-- following @Z@ is @AA@.+data Column_Ref = Column_Ref {column_ref_string :: String}++instance IsString Column_Ref where fromString = Column_Ref+instance Read Column_Ref where readsPrec _ s = [(Column_Ref s,[])]+instance Show Column_Ref where show = column_ref_string+instance Eq Column_Ref where (==) = (==) `on` column_index+instance Ord Column_Ref where compare = compare `on` column_index++instance Enum Column_Ref where+ fromEnum = column_index+ toEnum = column_ref++instance A.Ix Column_Ref where+ range = column_range+ index = interior_column_index+ inRange = column_in_range+ rangeSize = column_range_size++-- | Inclusive range of column references.+type Column_Range = (Column_Ref,Column_Ref)++-- | @1@-indexed row reference.+type Row_Ref = Int++-- | Zero index of 'Row_Ref'.+row_index :: Row_Ref -> Int+row_index r = r - 1++-- | Inclusive range of row references.+type Row_Range = (Row_Ref,Row_Ref)++-- | Cell reference, column then row.+type Cell_Ref = (Column_Ref,Row_Ref)++-- | Inclusive range of cell references.+type Cell_Range = (Cell_Ref,Cell_Ref)++-- | Case folding letter to index function. Only valid for ASCII letters.+--+-- > map letter_index ['A' .. 'Z'] == [0 .. 25]+-- > map letter_index ['a','d' .. 'm'] == [0,3 .. 12]+letter_index :: Char -> Int+letter_index c = fromEnum (toUpper c) - fromEnum 'A'++-- | Inverse of 'letter_index'.+--+-- > map index_letter [0,3 .. 12] == ['A','D' .. 'M']+index_letter :: Int -> Char+index_letter i = toEnum (i + fromEnum 'A')++-- | Translate column reference to @0@-index.+--+-- > :set -XOverloadedStrings+-- > map column_index ["A","c","z","ac","XYZ"] == [0,2,25,28,17575]+column_index :: Column_Ref -> Int+column_index (Column_Ref c) =+ let m = iterate (* 26) 1+ i = reverse (map letter_index c)+ in sum (zipWith (*) m (zipWith (+) [0..] i))++-- | Column reference to interior index within specified range. Type+-- specialised 'Data.Ix.index'.+--+-- > map (Data.Ix.index ('A','Z')) ['A','C','Z'] == [0,2,25]+-- > map (interior_column_index ("A","Z")) ["A","C","Z"] == [0,2,25]+--+-- > map (Data.Ix.index ('B','C')) ['B','C'] == [0,1]+-- > map (interior_column_index ("B","C")) ["B","C"] == [0,1]+interior_column_index :: Column_Range -> Column_Ref -> Int+interior_column_index (l,r) c =+ let n = column_index c+ l' = column_index l+ r' = column_index r+ in if n > r'+ then error (show ("interior_column_index",l,r,c))+ else n - l'++-- | Inverse of 'column_index'.+--+-- > let c = ["A","Z","AA","AZ","BA","BZ","CA"]+-- > in map column_ref [0,25,26,51,52,77,78] == c+--+-- > column_ref (0+25+1+25+1+25+1) == "CA"+column_ref :: Int -> Column_Ref+column_ref =+ let rec n = case n `quotRem` 26 of+ (0,r) -> [index_letter r]+ (q,r) -> index_letter (q - 1) : rec r+ in Column_Ref . rec++-- | Type specialised 'pred'.+--+-- > column_ref_pred "DF" == "DE"+column_ref_pred :: Column_Ref -> Column_Ref+column_ref_pred = pred++-- | Type specialised 'succ'.+--+-- > column_ref_succ "DE" == "DF"+column_ref_succ :: Column_Ref -> Column_Ref+column_ref_succ = succ++-- | Bimap of 'column_index'.+--+-- > column_indices ("b","p") == (1,15)+-- > column_indices ("B","IT") == (1,253)+column_indices :: Column_Range -> (Int,Int)+column_indices =+ let bimap f (i,j) = (f i,f j)+ in bimap column_index++-- | Type specialised 'Data.Ix.range'.+--+-- > column_range ("L","R") == ["L","M","N","O","P","Q","R"]+-- > Data.Ix.range ('L','R') == "LMNOPQR"+column_range :: Column_Range -> [Column_Ref]+column_range rng =+ let (l,r) = column_indices rng+ in map column_ref [l .. r]++-- | Type specialised 'Data.Ix.inRange'.+--+-- > map (column_in_range ("L","R")) ["A","N","Z"] == [False,True,False]+-- > map (column_in_range ("L","R")) ["L","N","R"] == [True,True,True]+--+-- > map (Data.Ix.inRange ('L','R')) ['A','N','Z'] == [False,True,False]+-- > map (Data.Ix.inRange ('L','R')) ['L','N','R'] == [True,True,True]+column_in_range :: Column_Range -> Column_Ref -> Bool+column_in_range rng c =+ let (l,r) = column_indices rng+ k = column_index c+ in k >= l && k <= r++-- | Type specialised 'Data.Ix.rangeSize'.+--+-- > map column_range_size [("A","Z"),("AA","ZZ")] == [26,26 * 26]+-- > Data.Ix.rangeSize ('A','Z') == 26+column_range_size :: Column_Range -> Int+column_range_size = (+ 1) . negate . uncurry (-) . column_indices++-- | Type specialised 'Data.Ix.range'.+row_range :: Row_Range -> [Row_Ref]+row_range = A.range++-- | The standard uppermost leftmost cell reference, @A1@.+--+-- > Just cell_ref_minima == parse_cell_ref "A1"+cell_ref_minima :: Cell_Ref+cell_ref_minima = (Column_Ref "A",1)++-- | Cell reference parser for standard notation of (column,row).+--+-- > parse_cell_ref "CC348" == Just ("CC",348)+parse_cell_ref :: String -> Maybe Cell_Ref+parse_cell_ref s =+ case span isUpper s of+ ([],_) -> Nothing+ (c,r) -> case span isDigit r of+ (n,[]) -> Just (Column_Ref c,read n)+ _ -> Nothing++is_cell_ref :: String -> Bool+is_cell_ref = isJust . parse_cell_ref++parse_cell_ref_err :: String -> Cell_Ref+parse_cell_ref_err = fromMaybe (error "parse_cell_ref") . parse_cell_ref++-- | Cell reference pretty printer.+--+-- > cell_ref_pp ("CC",348) == "CC348"+cell_ref_pp :: Cell_Ref -> String+cell_ref_pp (Column_Ref c,r) = c ++ show r++-- | Translate cell reference to @0@-indexed pair.+--+-- > cell_index ("CC",348) == (80,347)+-- > Data.Ix.index (("AA",1),("ZZ",999)) ("CC",348) == 54293+cell_index :: Cell_Ref -> (Int,Int)+cell_index (c,r) = (column_index c,row_index r)++-- | Inverse of cell_index.+--+-- > index_to_cell (80,347) == (Column_Ref "CC",348)+-- > index_to_cell (4,5) == (Column_Ref "E",6)+index_to_cell :: (Int,Int) -> Cell_Ref+index_to_cell (c,r) = (column_ref c,r + 1)++parse_cell_index :: String -> (Int,Int)+parse_cell_index = cell_index . parse_cell_ref_err++-- | Type specialised 'Data.Ix.range', cells are in column-order.+--+-- > cell_range (("AA",1),("AC",1)) == [("AA",1),("AB",1),("AC",1)]+--+-- > let r = [("AA",1),("AA",2),("AB",1),("AB",2),("AC",1),("AC",2)]+-- > in cell_range (("AA",1),("AC",2)) == r+--+-- > Data.Ix.range (('A',1),('C',1)) == [('A',1),('B',1),('C',1)]+--+-- > let r = [('A',1),('A',2),('B',1),('B',2),('C',1),('C',2)]+-- > in Data.Ix.range (('A',1),('C',2)) == r+cell_range :: Cell_Range -> [Cell_Ref]+cell_range ((c1,r1),(c2,r2)) =+ [(c,r) |+ c <- column_range (c1,c2)+ ,r <- row_range (r1,r2)]++-- | Variant of 'cell_range' in row-order.+--+-- > let r = [(AA,1),(AB,1),(AC,1),(AA,2),(AB,2),(AC,2)]+-- > in cell_range_row_order (("AA",1),("AC",2)) == r+cell_range_row_order :: Cell_Range -> [Cell_Ref]+cell_range_row_order ((c1,r1),(c2,r2)) =+ [(c,r) |+ r <- row_range (r1,r2)+ ,c <- column_range (c1,c2)]+
+ Music/Theory/Array/Direction.hs view
@@ -0,0 +1,84 @@+-- | Directions in an array.+module Music.Theory.Array.Direction where++import Data.List {- base -}+import Data.Maybe {- base -}++import qualified Music.Theory.Array.Cell_Ref as T {- hmt -}+import qualified Music.Theory.List as T {- hmt -}++-- * LOC / VEC++-- | (column,row)+type LOC n = (n,n)++-- | (Δcolumn,Δrow), rows /descend/, ie. down is positive, up is negative.+type VEC n = (n,n)++vector_add :: Num n => VEC n -> VEC n -> VEC n+vector_add (c1,r1) (c2,r2) = (c1 + c2,r1 + r2)++vector_sub :: Num n => VEC n -> VEC n -> VEC n+vector_sub (c1,r1) (c2,r2) = (c1 - c2,r1 - r2)++vector_sum :: Num n => [VEC n] -> VEC n+vector_sum = foldl1 vector_add++apply_vec :: Num n => LOC n -> VEC n -> LOC n+apply_vec (c,r) (dc,dr) = (c + dc,r + dr)++-- | Segment 'VEC' into a sequence of unit steps.+--+-- > let r = [[(0,0)],[(0,1)],[(0,1),(-1,0)],[(0,1),(0,1),(0,1),(-1,0),(-1,0)]]+-- > in map segment_vec [(0,0),(0,1),(-1,1),(-2,3)] == r+segment_vec :: Integral n => VEC n -> [VEC n]+segment_vec v =+ case v of+ (0,0) -> [v]+ (c,r) -> genericReplicate (abs r) (0,signum r) ++ genericReplicate (abs c) (signum c,0)++derive_vec :: Num n => LOC n -> LOC n -> VEC n+derive_vec (c1,r1) (c2,r2) = (c2 - c1,r2 - r1)++unfold_path :: Num n => LOC n -> [VEC n] -> [LOC n]+unfold_path l p = scanl apply_vec l p++-- * DIRECTION (non-diagonal)++type DIRECTION_S = String++-- | Directions are D=down, L=left, R=right, U=up.+is_direction :: String -> Bool+is_direction = (`elem` "DLRU.") . head++type DIRECTION_C = Char++-- | Reads either S|D W|L E|R N|U, reverse lookup gives SWEN. A period+-- indicates (0,0). S=south, W=west, E=east, N=north.+direction_char_to_vector_tbl :: Num n => [(DIRECTION_C,VEC n)]+direction_char_to_vector_tbl =+ [('.',(0,0))+ ,('S',(0,1)),('W',(-1,0)),('E',(1,0)),('N',(0,-1))+ ,('D',(0,1)),('L',(-1,0)),('R',(1,0)),('U',(0,-1))]++-- > map direction_char_to_vector "LU"+direction_char_to_vector :: Num n => DIRECTION_C -> VEC n+direction_char_to_vector d = fromMaybe (error "dir?") $ lookup d direction_char_to_vector_tbl++-- > let r = [(0,-1),(0,1),(-1,0),(1,0),(-1,-1),(1,1),(-2,0),(-1,-1)]+-- > in map direction_to_vector (words "U D L R UL DR LL LU") == r+direction_to_vector :: Num n => [DIRECTION_C] -> VEC n+direction_to_vector = vector_sum . map direction_char_to_vector++vector_to_direction_char :: (Eq n, Num n) => VEC n -> DIRECTION_C+vector_to_direction_char v =+ let r = T.reverse_lookup v direction_char_to_vector_tbl+ in fromMaybe (error "vec->dir?") r++-- | Direction sequence to cell references.+dir_seq_to_cell_seq :: (String,[String]) -> [String]+dir_seq_to_cell_seq (l,v) =+ let p = map direction_to_vector v+ c = T.parse_cell_index l+ in map (T.cell_ref_pp . T.index_to_cell) (unfold_path c p)+
Music/Theory/Array/MD.hs view
@@ -1,25 +1,11 @@ -- | Regular array data as markdown (MD) tables. module Music.Theory.Array.MD where -import Data.Char {- base -} import Data.List {- base -} +import qualified Music.Theory.Array as T {- hmt -} import qualified Music.Theory.List as T {- hmt -}---- | Append /k/ to the right of /l/ until result has /n/ places.-pad_right :: a -> Int -> [a] -> [a]-pad_right k n l = take n (l ++ repeat k)---- | Append /k/ to each row of /tbl/ as required to be regular (all--- rows equal length).-make_regular :: a -> [[a]] -> [[a]]-make_regular k tbl =- let z = maximum (map length tbl)- in map (pad_right k z) tbl---- | Delete trailing 'Char' where 'isSpace' holds.-delete_trailing_whitespace :: [Char] -> [Char]-delete_trailing_whitespace = reverse . dropWhile isSpace . reverse+import qualified Music.Theory.String as T {- hmt -} -- | Optional header row then data rows. type MD_Table t = (Maybe [String],[[t]])@@ -39,19 +25,21 @@ in (hdr',tbl') -- | Markdown table, perhaps with header. Table is in row order.--- Options are: /pad_left/.+-- Options are /pad_left/ and /eq_width/. ----- > md_table_opt False (Nothing,[["a","bc","def"],["ghij","klm","no","p"]])-md_table_opt :: Bool -> MD_Table String -> [String]-md_table_opt pleft (hdr,t) =- let t' = maybe t (:t) hdr- c = transpose (make_regular "" t')- n = map (maximum . map length) c- ext k s = let pd = replicate (k - length s) ' '- in if pleft then pd ++ s else s ++ pd- m = unwords (map (flip replicate '-') n)- w = map unwords (transpose (zipWith (map . ext) n c))- d = map delete_trailing_whitespace w+-- > let tbl = [["a","bc","def"],["ghij","klm","no","p"]]+-- > putStrLn$unlines$"": md_table_opt (True,True," · ") (Nothing,tbl)+md_table_opt :: (Bool,Bool,String) -> MD_Table String -> [String]+md_table_opt (pad_left,eq_width,col_sep) (hdr,t) =+ let c = transpose (T.make_regular "" (maybe t (:t) hdr))+ nc = length c+ n = let k = map (maximum . map length) c+ in if eq_width then replicate nc (maximum k) else k+ ext k s = if pad_left then T.pad_left ' ' k s else T.pad_right ' ' k s+ jn = intercalate col_sep+ m = jn (map (flip replicate '-') n)+ w = map jn (transpose (zipWith (map . ext) n c))+ d = map T.delete_trailing_whitespace w in case hdr of Nothing -> T.bracket (m,m) d Just _ -> case d of@@ -59,7 +47,7 @@ d0:d' -> d0 : T.bracket (m,m) d' md_table' :: MD_Table String -> [String]-md_table' = md_table_opt True+md_table' = md_table_opt (True,False," ") -- | 'curry' of 'md_table''. md_table :: Maybe [String] -> [[String]] -> [String]@@ -88,24 +76,33 @@ {- | Matrix form, ie. header in both first row and first column, in each case displaced by one location which is empty. -> let t = md_matrix "" (map return "abc") (map (map show) [[1,2,3],[2,3,1],[3,1,2]])+> let h = (map return "abc",map return "efgh")+> let t = md_matrix "" h (map (map show) [[1,2,3,4],[2,3,4,1],[3,4,1,2]]) >>> putStrLn $ unlines $ md_table' t-- - - -- a b c-a 1 2 3-b 2 3 1-c 3 1 2-- - - -+- - - - -+ e f g h+a 1 2 3 4+b 2 3 4 1+c 3 4 1 2+- - - - - -}-md_matrix :: a -> [a] -> [[a]] -> MD_Table a-md_matrix nil nm t = md_table_join (Nothing,[nil] : map return nm) (Nothing,nm : t)+md_matrix :: a -> ([a],[a]) -> [[a]] -> MD_Table a+md_matrix nil (r,c) t = md_table_join (Nothing,[nil] : map return r) (Nothing,c : t) --- | Variant for 'String' tables where /nil/ is the empty string and+-- | Variant that takes a 'show' function and a /header decoration/ function.+md_matrix_opt :: (a -> String) -> (String -> String) -> ([a],[a]) -> [[a]] -> MD_Table String+md_matrix_opt show_f hd_f nm t =+ let t' = map (map show_f) t+ nm' = T.bimap1 (map (hd_f . show_f)) nm+ in md_matrix "" nm' t'++-- | MD embolden function.+md_embolden :: String -> String+md_embolden x = "__" ++ x ++ "__"++-- | 'md_matrix_opt' with 'show' and markdown /bold/ annotations for header. -- the header cells are in bold.-md_matrix_bold :: [String] -> [[String]] -> MD_Table String-md_matrix_bold nm t =- let bold x = "__" ++ x ++ "__"- nm' = map bold nm- in md_matrix "" nm' t+md_matrix_bold :: Show a => ([a],[a]) -> [[a]] -> MD_Table String+md_matrix_bold = md_matrix_opt show md_embolden
+ Music/Theory/Bits.hs view
@@ -0,0 +1,38 @@+-- | Bits functions.+module Music.Theory.Bits where++import Data.Bits {- base -}++bit_pp :: Bool -> Char+bit_pp b = if b then '1' else '0'++bits_pp :: [Bool] -> String+bits_pp = map bit_pp++-- | Generate /n/ place bit sequence for /x/.+gen_bitseq :: FiniteBits b => Int -> b -> [Bool]+gen_bitseq n x =+ if finiteBitSize x < n+ then error "gen_bitseq"+ else map (testBit x) (reverse [0 .. n - 1])++-- | Given bit sequence (most to least significant) generate 'Bits' value.+--+-- > :set -XBinaryLiterals+-- > pack_bitseq [True,False,True,False] == 0b1010+-- > pack_bitseq [True,False,False,True,False,False] == 0b100100+-- > 0b100100 == 36+pack_bitseq :: Bits i => [Bool] -> i+pack_bitseq =+ last .+ scanl (\n (k,b) -> if b then setBit n k else n) zeroBits .+ zip [0..] .+ reverse++-- | 'bits_pp' of 'gen_bitseq'.+--+-- > :set -XBinaryLiterals+-- > 0xF0 == 0b11110000+-- > gen_bitseq_pp 8 (0xF0::Int) == "11110000"+gen_bitseq_pp :: FiniteBits b => Int -> b -> String+gen_bitseq_pp n = bits_pp . gen_bitseq n
Music/Theory/Bjorklund.hs view
@@ -3,10 +3,12 @@ -- /Journal of Computational Geometry: Theory and Applications/ -- Volume 42, Issue 5, July, 2009 -- (<http://dx.doi.org/10.1016/j.comgeo.2008.04.005>)-module Music.Theory.Bjorklund (bjorklund,xdot,iseq,iseq_str) where+module Music.Theory.Bjorklund where import Data.List.Split {- split -} +import qualified Music.Theory.List as T+ type STEP a = ((Int,Int),([[a]],[[a]])) left :: STEP a -> STEP a@@ -26,63 +28,58 @@ then (n,x) else bjorklund' (if i > j then left (n,x) else right (n,x)) --- | Bjorklund's algorithm to construct a binary sequence of /n/ bits--- with /k/ ones such that the /k/ ones are distributed as evenly as--- possible among the (/n/ - /k/) zeroes.------ > bjorklund (5,9) == [True,False,True,False,True,False,True,False,True]--- > xdot (bjorklund (5,9)) == "x.x.x.x.x"------ > let es = [(2,3),(2,5)--- > ,(3,4),(3,5),(3,8)--- > ,(4,7),(4,9),(4,12),(4,15)--- > ,(5,6),(5,7),(5,8),(5,9),(5,11),(5,12),(5,13),(5,16)--- > ,(6,7),(6,13)--- > ,(7,8),(7,9),(7,10),(7,12),(7,15),(7,16),(7,17),(7,18)--- > ,(8,17),(8,19)--- > ,(9,14),(9,16),(9,22),(9,23)--- > ,(11,12),(11,24)--- > ,(13,24)--- > ,(15,34)]--- > in map (\e -> let e' = bjorklund e in (e,xdot e',iseq_str e')) es------ > [((2,3),"xx.","(12)")--- > ,((2,5),"x.x..","(23)")--- > ,((3,4),"xxx.","(112)")--- > ,((3,5),"x.x.x","(221)")--- > ,((3,8),"x..x..x.","(332)")--- > ,((4,7),"x.x.x.x","(2221)")--- > ,((4,9),"x.x.x.x..","(2223)")--- > ,((4,12),"x..x..x..x..","(3333)")--- > ,((4,15),"x...x...x...x..","(4443)")--- > ,((5,6),"xxxxx.","(11112)")--- > ,((5,7),"x.xx.xx","(21211)")--- > ,((5,8),"x.xx.xx.","(21212)")--- > ,((5,9),"x.x.x.x.x","(22221)")--- > ,((5,11),"x.x.x.x.x..","(22223)")--- > ,((5,12),"x..x.x..x.x.","(32322)")--- > ,((5,13),"x..x.x..x.x..","(32323)")--- > ,((5,16),"x..x..x..x..x...","(33334)")--- > ,((6,7),"xxxxxx.","(111112)")--- > ,((6,13),"x.x.x.x.x.x..","(222223)")--- > ,((7,8),"xxxxxxx.","(1111112)")--- > ,((7,9),"x.xxx.xxx","(2112111)")--- > ,((7,10),"x.xx.xx.xx","(2121211)")--- > ,((7,12),"x.xx.x.xx.x.","(2122122)")--- > ,((7,15),"x.x.x.x.x.x.x..","(2222223)")--- > ,((7,16),"x..x.x.x..x.x.x.","(3223222)")--- > ,((7,17),"x..x.x..x.x..x.x.","(3232322)")--- > ,((7,18),"x..x.x..x.x..x.x..","(3232323)")--- > ,((8,17),"x.x.x.x.x.x.x.x..","(22222223)")--- > ,((8,19),"x..x.x.x..x.x.x..x.","(32232232)")--- > ,((9,14),"x.xx.xx.xx.xx.","(212121212)")--- > ,((9,16),"x.xx.x.x.xx.x.x.","(212221222)")--- > ,((9,22),"x..x.x..x.x..x.x..x.x.","(323232322)")--- > ,((9,23),"x..x.x..x.x..x.x..x.x..","(323232323)")--- > ,((11,12),"xxxxxxxxxxx.","(11111111112)")--- > ,((11,24),"x..x.x.x.x.x..x.x.x.x.x.","(32222322222)")--- > ,((13,24),"x.xx.x.x.x.x.xx.x.x.x.x.","(2122222122222)")--- > ,((15,34),"x..x.x.x.x..x.x.x.x..x.x.x.x..x.x.","(322232223222322)")]+{- | Bjorklund's algorithm to construct a binary sequence of /n/ bits+with /k/ ones such that the /k/ ones are distributed as evenly as+possible among the (/n/ - /k/) zeroes.++> bjorklund (5,9) == [True,False,True,False,True,False,True,False,True]+> map xdot (bjorklund (5,9)) == "x.x.x.x.x"++> let {es = [(2,[3,5]),(3,[4,5,8]),(4,[7,9,12,15]),(5,[6,7,8,9,11,12,13,16])+> ,(6,[7,13]),(7,[8,9,10,12,15,16,17,18]),(8,[17,19])+> ,(9,[14,16,22,23]),(11,[12,24]),(13,[24]),(15,[34])]+> ;es' = concatMap (\(i,j) -> map ((,) i) j) es}+> in mapM_ (putStrLn . euler_pp') es'++> > E(2,3) [××·] (12)+> > E(2,5) [×·×··] (23)+> > E(3,4) [×××·] (112)+> > E(3,5) [×·×·×] (221)+> > E(3,8) [×··×··×·] (332)+> > E(4,7) [×·×·×·×] (2221)+> > E(4,9) [×·×·×·×··] (2223)+> > E(4,12) [×··×··×··×··] (3333)+> > E(4,15) [×···×···×···×··] (4443)+> > E(5,6) [×××××·] (11112)+> > E(5,7) [×·××·××] (21211)+> > E(5,8) [×·××·××·] (21212)+> > E(5,9) [×·×·×·×·×] (22221)+> > E(5,11) [×·×·×·×·×··] (22223)+> > E(5,12) [×··×·×··×·×·] (32322)+> > E(5,13) [×··×·×··×·×··] (32323)+> > E(5,16) [×··×··×··×··×···] (33334)+> > E(6,7) [××××××·] (111112)+> > E(6,13) [×·×·×·×·×·×··] (222223)+> > E(7,8) [×××××××·] (1111112)+> > E(7,9) [×·×××·×××] (2112111)+> > E(7,10) [×·××·××·××] (2121211)+> > E(7,12) [×·××·×·××·×·] (2122122)+> > E(7,15) [×·×·×·×·×·×·×··] (2222223)+> > E(7,16) [×··×·×·×··×·×·×·] (3223222)+> > E(7,17) [×··×·×··×·×··×·×·] (3232322)+> > E(7,18) [×··×·×··×·×··×·×··] (3232323)+> > E(8,17) [×·×·×·×·×·×·×·×··] (22222223)+> > E(8,19) [×··×·×·×··×·×·×··×·] (32232232)+> > E(9,14) [×·××·××·××·××·] (212121212)+> > E(9,16) [×·××·×·×·××·×·×·] (212221222)+> > E(9,22) [×··×·×··×·×··×·×··×·×·] (323232322)+> > E(9,23) [×··×·×··×·×··×·×··×·×··] (323232323)+> > E(11,12) [×××××××××××·] (11111111112)+> > E(11,24) [×··×·×·×·×·×··×·×·×·×·×·] (32222322222)+> > E(13,24) [×·××·×·×·×·×·××·×·×·×·×·] (2122222122222)+> > E(15,34) [×··×·×·×·×··×·×·×·×··×·×·×·×··×·×·] (322232223222322)++-} bjorklund :: (Int,Int) -> [Bool] bjorklund (i,j') = let j = j' - i@@ -91,11 +88,42 @@ (_,(x',y')) = bjorklund' ((i,j),(x,y)) in concat x' ++ concat y' +-- | 'T.rotate_right' of 'bjorklund'.+--+-- > map xdot' (bjorklund_r 2 (5,16)) == "··×··×··×··×··×·"+bjorklund_r :: Int -> (Int, Int) -> [Bool]+bjorklund_r n = T.rotate_right n . bjorklund++-- | Pretty printer, generalise.+euler_pp_f :: (Bool -> Char) -> (Int,Int) -> String+euler_pp_f f e =+ let r = bjorklund e+ in concat ["E",show e," [",map f r,"] ",iseq_str r]++-- | Unicode form, ie. @×·@.+--+-- > euler_pp' (7,12) == "E(7,12) [×·××·×·××·×·] (2122122)"+euler_pp' :: (Int, Int) -> String+euler_pp' = euler_pp_f xdot'++-- | ASCII form, ie. @x.@.+--+-- > euler_pp (7,12) == "E(7,12) [x.xx.x.xx.x.] (2122122)"+euler_pp :: (Int, Int) -> String+euler_pp = euler_pp_f xdot+ -- | /xdot/ notation for pattern. ----- > xdot (bjorklund (5,9)) == "x.x.x.x.x"-xdot :: [Bool] -> String-xdot = map (\x -> if x then 'x' else '.')+-- > map xdot (bjorklund (5,9)) == "x.x.x.x.x"+xdot :: Bool -> Char+xdot x = if x then 'x' else '.'++-- | Unicode variant.+--+-- > map xdot' (bjorklund (5,12)) == "×··×·×··×·×·"+-- > map xdot' (bjorklund (5,16)) == "×··×··×··×··×···"+xdot' :: Bool -> Char+xdot' x = if x then '×' else '·' -- | The 'iseq' of a pattern is the distance between 'True' values. --
Music/Theory/Block_Design/Johnson_2007.hs view
@@ -2,7 +2,7 @@ -- Computation in Music, Berlin, May 2007. module Music.Theory.Block_Design.Johnson_2007 where -import Control.Arrow {- base -}+import Control.Arrow ((***)) {- base -} import Data.List {- base -} import qualified Music.Theory.List as T
+ Music/Theory/Braille.hs view
@@ -0,0 +1,273 @@+-- | <http://en.wikipedia.org/wiki/Braille_Patterns>+module Music.Theory.Braille where++import Data.Char {- base -}+import Data.List {- base -}+import Data.Maybe {- base -}+import Text.Printf {- base -}++-- | Braille coding data. Elements are: (ASCII HEX,ASCII CHAR,DOT+-- LIST,UNICODE CHAR,MEANING). The dot numbers are in column order.+type BRAILLE = (Int,Char,[Int],Char,String)++-- | ASCII 'Char' of 'BRAILLE'.+braille_ascii :: BRAILLE -> Char+braille_ascii (_,c,_,_,_) = c++-- | Unicode 'Char' of 'BRAILLE'.+braille_unicode :: BRAILLE -> Char+braille_unicode (_,_,_,c,_) = c++-- | Dot list of 'BRAILLE'.+braille_dots :: BRAILLE -> [Int]+braille_dots (_,_,d,_,_) = d++-- | ASCII Braille table.+--+-- > all id (map (\(x,c,_,_,_) -> x == fromEnum c) braille_table) == True+braille_table :: [BRAILLE]+braille_table =+ [(0x20,' ',[],'⠀'," ")+ ,(0x21,'!',[2,3,4,6],'⠮',"the")+ ,(0x22,'"',[5],'⠐',"contraction")+ ,(0x23,'#',[3,4,5,6],'⠼',"number prefix")+ ,(0x24,'$',[1,2,4,6],'⠫',"ed")+ ,(0x25,'%',[1,4,6],'⠩',"sh")+ ,(0x26,'&',[1,2,3,4,6],'⠯',"and")+ ,(0x27,'\'',[3],'⠄',"'")+ ,(0x28,'(',[1,2,3,5,6],'⠷',"of")+ ,(0x29,')',[2,3,4,5,6],'⠾',"with")+ ,(0x2A,'*',[1,6],'⠡',"ch")+ ,(0x2B,'+',[3,4,6],'⠬',"ing")+ ,(0x2C,',',[6],'⠠',"uppercase prefix")+ ,(0x2D,'-',[3,6],'⠤',"-")+ ,(0x2E,'.',[4,6],'⠨',"italic prefix")+ ,(0x2F,'/',[3,4],'⠌',"st")+ ,(0x30,'0',[3,5,6],'⠴',"”")+ ,(0x31,'1',[2],'⠂',",")+ ,(0x32,'2',[2,3],'⠆',";")+ ,(0x33,'3',[2,5],'⠒',":")+ ,(0x34,'4',[2,5,6],'⠲',".")+ ,(0x35,'5',[2,6],'⠢',"en")+ ,(0x36,'6',[2,3,5],'⠖',"!")+ ,(0x37,'7',[2,3,5,6],'⠶',"( or )")+ ,(0x38,'8',[2,3,6],'⠦',"“ or ?")+ ,(0x39,'9',[3,5],'⠔',"in")+ ,(0x3A,':',[1,5,6],'⠱',"wh")+ ,(0x3B,';',[5,6],'⠰',"letter prefix")+ ,(0x3C,'<',[1,2,6],'⠣',"gh")+ ,(0x3D,'=',[1,2,3,4,5,6],'⠿',"for")+ ,(0x3E,'>',[3,4,5],'⠜',"ar")+ ,(0x3F,'?',[1,4,5,6],'⠹',"th")+ ,(0x40,'@',[4],'⠈',"accent prefix")+ ,(0x41,'A',[1],'⠁',"a")+ ,(0x42,'B',[1,2],'⠃',"b")+ ,(0x43,'C',[1,4],'⠉',"c")+ ,(0x44,'D',[1,4,5],'⠙',"d")+ ,(0x45,'E',[1,5],'⠑',"e")+ ,(0x46,'F',[1,2,4],'⠋',"f")+ ,(0x47,'G',[1,2,4,5],'⠛',"g")+ ,(0x48,'H',[1,2,5],'⠓',"h")+ ,(0x49,'I',[2,4],'⠊',"i")+ ,(0x4A,'J',[2,4,5],'⠚',"j")+ ,(0x4B,'K',[1,3],'⠅',"k")+ ,(0x4C,'L',[1,2,3],'⠇',"l")+ ,(0x4D,'M',[1,3,4],'⠍',"m")+ ,(0x4E,'N',[1,3,4,5],'⠝',"n")+ ,(0x4F,'O',[1,3,5],'⠕',"o")+ ,(0x50,'P',[1,2,3,4],'⠏',"p")+ ,(0x51,'Q',[1,2,3,4,5],'⠟',"q")+ ,(0x52,'R',[1,2,3,5],'⠗',"r")+ ,(0x53,'S',[2,3,4],'⠎',"s")+ ,(0x54,'T',[2,3,4,5],'⠞',"t")+ ,(0x55,'U',[1,3,6],'⠥',"u")+ ,(0x56,'V',[1,2,3,6],'⠧',"v")+ ,(0x57,'W',[2,4,5,6],'⠺',"w")+ ,(0x58,'X',[1,3,4,6],'⠭',"x")+ ,(0x59,'Y',[1,3,4,5,6],'⠽',"y")+ ,(0x5A,'Z',[1,3,5,6],'⠵',"z")+ ,(0x5B,'[',[2,4,6],'⠪',"ow")+ ,(0x5C,'\\',[1,2,5,6],'⠳',"ou")+ ,(0x5D,']',[1,2,4,5,6],'⠻',"er")+ ,(0x5E,'^',[4,5],'⠘',"currency prefix")+ ,(0x5F,'_',[4,5,6],'⠸',"contraction")+ ]++-- | Lookup 'BRAILLE' value for unicode character.+--+-- > braille_lookup_unicode '⠝' == Just (0x4E,'N',[1,3,4,5],'⠝',"n")+braille_lookup_unicode :: Char -> Maybe BRAILLE+braille_lookup_unicode c = find ((== c) . braille_unicode) braille_table++-- | Lookup 'BRAILLE' value for ascii character (case invariant).+--+-- > braille_lookup_ascii 'N' == Just (0x4E,'N',[1,3,4,5],'⠝',"n")+braille_lookup_ascii :: Char -> Maybe BRAILLE+braille_lookup_ascii c = find ((== (toUpper c)) . braille_ascii) braille_table++-- | The arrangement of the 6-dot patterns into /decades/, sequences+-- of (1,10,3) cells. The cell to the left of the decade is the empty+-- cell, the two cells to the right are the first two cells of the+-- decade shifted right.+--+-- For each decade there are two extra cells that shift+-- the first two cells of the decade right one place. Subsequent+-- decades are derived by simple transformation of the first. The+-- second is the first with the addition of dot @3@, the third adds+-- dots @3@ and @6@, the fourth adds dot @6@ and the fifth shifts the+-- first down one row.+--+-- The first decade has the 13 of the 16 4-dot patterns, the remaining+-- 3 are in the fifth decade, that is they are the three 4-dot+-- patterns that are down shifts of a 4-dot pattern.+--+-- > let trimap f (p,q,r) = (f p,f q,f r)+-- > let f = map (fromJust . decode) in map (trimap f) braille_64+braille_64 :: [(String,String,String)]+braille_64 =+ [("⠀","⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚","⠈⠘")+ ,("⠄","⠅⠇⠍⠝⠕⠏⠟⠗⠎⠞","⠌⠜")+ ,("⠤","⠥⠧⠭⠽⠵⠯⠿⠷⠮⠾","⠬⠼")+ ,("⠠","⠡⠣⠩⠹⠱⠫⠻⠳⠪⠺","⠨⠸")+ ,("","⠂⠆⠒⠲⠢⠖⠶⠦⠔⠴","⠐⠰")]++-- | Transcribe ASCII to unicode braille.+--+-- > transcribe_unicode "BRAILLE ASCII CHAR GRID" == "⠃⠗⠁⠊⠇⠇⠑⠀⠁⠎⠉⠊⠊⠀⠉⠓⠁⠗⠀⠛⠗⠊⠙"+-- > transcribe_unicode "BRAILLE HTML TABLE GRID" == "⠃⠗⠁⠊⠇⠇⠑⠀⠓⠞⠍⠇⠀⠞⠁⠃⠇⠑⠀⠛⠗⠊⠙"+transcribe_unicode :: String -> String+transcribe_unicode = map (braille_unicode . fromJust . braille_lookup_ascii)++-- | Generate a character grid using inidicated values for filled and empty cells.+--+-- > let ch = (' ','.')+-- > putStrLn$ transcribe_char_grid ch "BRAILLE ASCII CHAR GRID"+--+-- > let ch = (white_circle,black_circle)+-- > putStrLn$ string_html_table $ transcribe_char_grid ch "BRAILLE HTML TABLE GRID"+transcribe_char_grid :: (Char,Char) -> String -> String+transcribe_char_grid (w,b) =+ unlines .+ map concat .+ transpose .+ map (dots_grid (w,b) . braille_dots . fromJust . braille_lookup_ascii)++-- | Generate 6-dot grid given (white,black) values.+--+-- > dots_grid (0,1) [1,2,3,5] == [[1,0],[1,1],[1,0]]+dots_grid :: (c,c) -> [Int] -> [[c]]+dots_grid (w,b) d =+ let f n = if n `elem` d then b else w+ in map (map f) [[1,4],[2,5],[3,6]]++string_html_table :: String -> String+string_html_table s =+ let f x = "<td>" ++ [x] ++ "</td>"+ g x = "<tr>" ++ concatMap f x ++ "</tr>"+ h x = "<table>" ++ concatMap g x ++ "</table>"+ in h (lines s)++{- | Decoding.++> let t0 = ["⠠⠁⠇⠇⠀⠓⠥⠍⠁⠝⠀⠆⠬⠎⠀⠜⠑⠀⠃⠕⠗⠝⠀⠋⠗⠑⠑⠀⠯⠀⠑⠟⠥⠁⠇⠀⠔⠀⠙⠊⠛⠝⠰⠽⠀⠯⠀⠐⠗⠎⠲"+> ,"⠠⠮⠽⠀⠜⠑⠀⠢⠙⠪⠫⠀⠾⠀⠗⠂⠎⠕⠝⠀⠯⠀⠒⠎⠉⠊⠰⠑⠀⠯⠀⠩⠙⠀⠁⠉⠞⠀⠞⠪⠜⠙⠎⠀⠐⠕⠀⠁⠝⠕⠤"+> ,"⠮⠗⠀⠔⠀⠁⠀⠸⠎⠀⠷⠀⠃⠗⠕⠮⠗⠓⠕⠕⠙⠲"]++> concatMap (fromMaybe "#" . decode) (concat t0)++-}+decode :: Char -> Maybe String+decode c =+ case braille_lookup_unicode c of+ Just (_,_,_,_,s) -> Just s+ Nothing -> Nothing++-- | Start and end unicode indices.+braille_rng :: Integral i => (i,i)+braille_rng = (0x2800,0x28FF)++-- | All characters, in sequence.+--+-- > length braille_seq == 256+-- > putStrLn braille_seq+braille_seq :: [Char]+braille_seq = let (l,r) = braille_rng in [toEnum l .. toEnum r]++-- | The /n/th character, zero indexed.+braille_char :: Int -> Char+braille_char = toEnum . (+) 0x2800++-- | Two element index, 255 * 255 = 65025 places.+--+-- > map braille_ix [100,300]+braille_ix :: Int -> (Char,Char)+braille_ix n =+ let (i,j) = n `divMod` 255+ f k = braille_char (k + 1)+ in (f i,f j)++-- | HTML character encoding (as hex integer).+--+-- > unwords $ map unicode_html braille_seq+unicode_html :: Char -> String+unicode_html = printf "&#x%x;" . fromEnum++-- * Unicode++-- | White (empty) circle.+white_circle :: Char+white_circle = '○'++-- | Black (filled) circle.+black_circle :: Char+black_circle = '●'++-- | Shaded (hatched) circle.+shaded_circle :: Char+shaded_circle = '◍'++-- * Contractions++-- | Table of one letter contractions.+one_letter_contractions :: [(Char,String)]+one_letter_contractions =+ [('⠃',"but")+ ,('⠉',"can")+ ,('⠙',"do")+ ,('⠑',"every")+ ,('⠋',"from,-self")+ ,('⠛',"go")+ ,('⠓',"have")+ ,('⠚',"just")+ ,('⠅',"knowledge")+ ,('⠇',"like")+ ,('⠍',"more")+ ,('⠝',"not")+ ,('⠏',"people")+ ,('⠟',"quite")+ ,('⠗',"rather")+ ,('⠎',"so")+ ,('⠞',"that")+ ,('⠌',"still")+ ,('⠥',"us")+ ,('⠧',"very")+ ,('⠭',"it")+ ,('⠽',"you")+ ,('⠵',"as")+ ,('⠡',"child")+ ,('⠩',"shall")+ ,('⠹',"this")+ ,('⠱',"which")+ ,('⠳',"out")+ ,('⠺',"will")+ ,('⠆',"be,be-")+ ,('⠒',"con-")+ ,('⠲',"dis-")+ ,('⠢',"enough")+ ,('⠖',"to")+ ,('⠶',"were")+ ,('⠦',"his")+ ,('⠔',"in")+ ,('⠴',"by,was")+ ,('⠤',"com-")+ ]
+ Music/Theory/Byte.hs view
@@ -0,0 +1,55 @@+-- | Byte functions.+module Music.Theory.Byte where++import qualified Data.ByteString as B {- bytestring -}+import Data.Char {- base -}+import Data.List.Split {- split -}+import Data.Maybe {- base -}+import Numeric {- base -}++import qualified Music.Theory.Read as T {- hmt -}++-- | Given /n/ in (0,255) make two character hex string.+--+-- > mapMaybe byte_hex_pp [0x0F,0xF0,0xF0F] == ["0F","F0"]+byte_hex_pp :: (Integral i, Show i) => i -> Maybe String+byte_hex_pp n =+ case showHex n "" of+ [c] -> Just ['0',toUpper c]+ [c,d] -> Just (map toUpper [c,d])+ _ -> Nothing++-- | Erroring variant.+byte_hex_pp_err :: (Integral i, Show i) => i -> String+byte_hex_pp_err = fromMaybe (error "byte_hex_pp") . byte_hex_pp++-- | 'unwords' of 'map' of 'byte_hex_pp_err'.+--+-- > byte_seq_hex_pp [0x0F,0xF0] == "0F F0"+byte_seq_hex_pp :: (Integral i, Show i) => [i] -> String+byte_seq_hex_pp = unwords . map byte_hex_pp_err++-- | Read two character hexadecimal string.+read_hex_byte :: (Eq t,Num t) => String -> t+read_hex_byte s =+ case s of+ [_,_] -> T.reads_to_read_precise_err "readHex" readHex s+ _ -> error "read_hex_byte"++read_hex_byte_seq :: (Eq t,Num t) => String -> [t]+read_hex_byte_seq = map read_hex_byte . words++-- | Load binary 'U8' sequence from file.+load_byte_seq :: Integral i => FilePath -> IO [i]+load_byte_seq = fmap (map fromIntegral . B.unpack) . B.readFile++store_byte_seq :: Integral i => FilePath -> [i] -> IO ()+store_byte_seq fn = B.writeFile fn . B.pack . map fromIntegral++-- | Load hexadecimal text 'U8' sequence from file.+load_hex_byte_seq :: Integral i => FilePath -> IO [i]+load_hex_byte_seq = fmap (map read_hex_byte . words) . readFile++-- | Store 'U8' sequence as hexadecimal text, 16 words per line.+store_hex_byte_seq :: (Integral i,Show i) => FilePath -> [i] -> IO ()+store_hex_byte_seq fn = writeFile fn . unlines . map unwords . chunksOf 16 . map byte_hex_pp_err
Music/Theory/Clef.hs view
@@ -1,8 +1,8 @@ -- | Common music notation clefs. module Music.Theory.Clef where -import Music.Theory.Pitch-import Music.Theory.Pitch.Name+import Music.Theory.Pitch {- hmt -}+import Music.Theory.Pitch.Name {- hmt -} -- | Clef enumeration type. data Clef_T = Bass | Tenor | Alto | Treble | Percussion
Music/Theory/Combinations.hs view
@@ -1,19 +1,19 @@ -- | Combination functions. module Music.Theory.Combinations where -import Music.Theory.Permutations+import qualified Music.Theory.Permutations as T -- | Number of /k/ element combinations of a set of /n/ elements. -- -- > (nk_combinations 6 3,nk_combinations 13 3) == (20,286) nk_combinations :: Integral a => a -> a -> a-nk_combinations n k = nk_permutations n k `div` factorial k+nk_combinations n k = T.nk_permutations n k `div` T.factorial k -- | /k/ element subsets of /s/. -- -- > combinations 3 [1..4] == [[1,2,3],[1,2,4],[1,3,4],[2,3,4]] -- > length (combinations 3 [1..5]) == nk_combinations 5 3-combinations :: Integral t => t -> [a] -> [[a]]+combinations :: Int -> [a] -> [[a]] combinations k s = case (k,s) of (0,_) -> [[]]
Music/Theory/Contour/Polansky_1992.hs view
@@ -10,33 +10,13 @@ import Data.Maybe {- base -} import Data.Ratio {- base -} -import qualified Music.Theory.Set.List as T+import qualified Music.Theory.List as T+import qualified Music.Theory.Ord as T import qualified Music.Theory.Permutations.List as T---- * List functions---- | Replace the /i/th value at /ns/ with /x/.------ > replace "test" 2 'n' == "tent"-replace :: Integral i => [a] -> i -> a -> [a]-replace ns i x =- let f j y = if i == j then x else y- in zipWith f [0..] ns---- | Are all elements equal.------ > all_equal "aaa" == True-all_equal :: Eq a => [a] -> Bool-all_equal xs = all id (zipWith (==) xs (tail xs))+import qualified Music.Theory.Set.List as T -- * Indices --- | Compare adjacent elements (p.262) left to right.------ > compare_adjacent [0,1,3,2] == [LT,LT,GT]-compare_adjacent :: Ord a => [a] -> [Ordering]-compare_adjacent xs = zipWith compare xs (tail xs)- -- | Construct set of /n/ '-' @1@ adjacent indices, left right order. -- -- > adjacent_indices 5 == [(0,1),(1,2),(2,3),(3,4)]@@ -51,36 +31,6 @@ let n' = n - 1 in [(i,j) | i <- [0 .. n'], j <- [i + 1 .. n']] --- * 'Enum' functions---- | Generic variant of 'fromEnum' (p.263).-genericFromEnum :: (Integral i,Enum e) => e -> i-genericFromEnum = fromIntegral . fromEnum---- | Generic variant of 'toEnum' (p.263).-genericToEnum :: (Integral i,Enum e) => i -> e-genericToEnum = toEnum . fromIntegral---- * 'Ordering' functions---- | Specialised 'genericFromEnum'.-ord_to_int :: Integral a => Ordering -> a-ord_to_int = genericFromEnum---- | Specialised 'genericToEnum'.-int_to_ord :: Integral a => a -> Ordering-int_to_ord = genericToEnum---- | Invert 'Ordering'.------ > map ord_invert [LT,EQ,GT] == [GT,EQ,LT]-ord_invert :: Ordering -> Ordering-ord_invert x =- case x of- LT -> GT- EQ -> EQ- GT -> LT- -- * Matrix -- | A list notation for matrices.@@ -109,7 +59,7 @@ data Contour_Half_Matrix = Contour_Half_Matrix {contour_half_matrix_n :: Int ,contour_half_matrix_m :: Matrix Ordering}- deriving (Eq)+ deriving (Eq,Ord) -- | Half 'Matrix' of contour given comparison function /f/. --@@ -183,7 +133,7 @@ -- > let c = ["abc","bbb","cba"] -- > in map (uniform.contour_description) c == [True,True,True] uniform :: Contour_Description -> Bool-uniform (Contour_Description _ m) = all_equal (M.elems m)+uniform (Contour_Description _ m) = T.all_equal (M.elems m) -- | 'True' if contour does not containt any 'EQ' elements. --@@ -317,7 +267,7 @@ LT -> i' + adjustment j' EQ -> i' GT -> i' - adjustment j'- in Just (replace ns j j'')+ in Just (T.replace_at ns j j'') refine [] ns = ns refine (i:is) ns = case step i ns of Nothing -> refine is ns@@ -330,7 +280,7 @@ -- > in draw_contour (contour_description_invert c) == [3,2,0,1] contour_description_invert :: Contour_Description -> Contour_Description contour_description_invert (Contour_Description n m) =- Contour_Description n (M.map ord_invert m)+ Contour_Description n (M.map T.ord_invert m) -- * Construction @@ -499,5 +449,5 @@ ex_4 = let ns :: [[Int]] ns = [[2,2,2,1],[2,2,0],[0,0],[1]]- ns' = map (map int_to_ord) ns+ ns' = map (map T.int_to_ord) ns in half_matrix_to_description (Contour_Half_Matrix 5 ns')
+ Music/Theory/DB/CSV.hs view
@@ -0,0 +1,24 @@+-- | Keys are given in the header, empty fields are omitted from records.+module Music.Theory.DB.CSV where++import Data.Maybe {- base -}+import qualified Text.CSV.Lazy.String as C {- lazy-csv -}++import Music.Theory.DB.Common {- hmt -}+import qualified Music.Theory.IO as T {- hmt -}++-- | Load 'DB' from 'FilePath'.+db_load_utf8 :: FilePath -> IO DB'+db_load_utf8 fn = do+ s <- T.read_file_utf8 fn+ let p = C.fromCSVTable (C.csvTable (C.parseCSV s))+ (h,d) = (head p,tail p)+ f k v = if null v then Nothing else Just (k,v)+ return (map (catMaybes . zipWith f h) d)++db_store_utf8 :: FilePath -> DB' -> IO ()+db_store_utf8 fn db = do+ let (hdr,tbl) = db_to_table (fromMaybe "") db+ (_,tbl') = C.toCSVTable (hdr : tbl)+ str = C.ppCSVTable tbl'+ T.write_file_utf8 fn str
+ Music/Theory/DB/Common.hs view
@@ -0,0 +1,130 @@+module Music.Theory.DB.Common where++import Data.List {- base -}+import Data.Maybe {- base -}+import Safe {- safe -}++import qualified Music.Theory.List as T {- base -}+import qualified Music.Theory.Maybe as T {- base -}++-- * Type++type Entry k v = (k,v)+type Record k v = [Entry k v]+type DB k v = [Record k v]++type Key = String+type Value = String+type Entry' = Entry Key Value+type Record' = Record Key Value+type DB' = DB Key Value++-- * Record++-- | The sequence of keys at 'Record'.+record_key_seq :: Record k v -> [k]+record_key_seq = map fst++-- | 'True' if 'Key' is present in 'Entity'.+record_has_key :: Eq k => k -> Record k v -> Bool+record_has_key k = elem k . record_key_seq++-- | 'T.histogram' of 'record_key_seq'.+record_key_histogram :: Ord k => Record k v -> [(k,Int)]+record_key_histogram = T.histogram . record_key_seq++-- | Duplicate keys predicate.+record_has_duplicate_keys :: Ord k => Record k v -> Bool+record_has_duplicate_keys = any (> 0) . map snd . record_key_histogram++-- | Find all associations for key using given equality function.+record_lookup_by :: (k -> k -> Bool) -> k -> Record k v -> [v]+record_lookup_by f k = map snd . filter (f k . fst)++-- | 'record_lookup_by' of '=='.+record_lookup :: Eq k => k -> Record k v -> [v]+record_lookup = record_lookup_by (==)++-- | /n/th element of 'record_lookup'.+record_lookup_at :: Eq k => (k,Int) -> Record k v -> Maybe v+record_lookup_at (c,n) = flip atMay n . record_lookup c++-- | Variant of 'record_lookup' requiring a unique key. 'Nothing' indicates+-- there is no entry, it is an 'error' if duplicate keys are present.+record_lookup_uniq :: Eq k => k -> Record k v -> Maybe v+record_lookup_uniq k r =+ case record_lookup k r of+ [] -> Nothing+ [v] -> Just v+ _ -> error "record_lookup_uniq: non uniq"++-- | 'True' if key exists and is unique.+record_has_key_uniq :: Eq k => k -> Record k v -> Bool+record_has_key_uniq k = isJust . record_lookup_uniq k++-- | Error variant.+record_lookup_uniq_err :: Eq k => k -> Record k v -> v+record_lookup_uniq_err k = T.from_just "record_lookup_uniq: none" . record_lookup_uniq k++-- | Default value variant.+record_lookup_uniq_def :: Eq k => v -> k -> Record k v -> v+record_lookup_uniq_def v k = fromMaybe v . record_lookup_uniq k++-- | Remove all associations for key using given equality function.+record_delete_by :: (k -> k -> Bool) -> k -> Record k v -> Record k v+record_delete_by f k = filter (not . f k . fst)++-- | 'record_delete_by' of '=='.+record_delete :: Eq k => k -> Record k v -> Record k v+record_delete = record_delete_by (==)++-- * DB++-- | Preserves order of occurence.+db_key_set :: Ord k => DB k v -> [k]+db_key_set = nub . map fst . concat++db_lookup_by :: (k -> k -> Bool) -> (v -> v -> Bool) -> k -> v -> DB k v -> [Record k v]+db_lookup_by k_cmp v_cmp k v =+ let f = any (v_cmp v) . record_lookup_by k_cmp k+ in filter f++db_lookup :: (Eq k,Eq v) => k -> v -> DB k v -> [Record k v]+db_lookup = db_lookup_by (==) (==)++db_has_duplicate_keys :: Ord k => DB k v -> Bool+db_has_duplicate_keys = any id . map record_has_duplicate_keys++db_key_histogram :: Ord k => DB k v -> [(k,Int)]+db_key_histogram db =+ let h = concatMap record_key_histogram db+ f k = (k,maximum (record_lookup k h))+ in map f (db_key_set db)++db_to_table :: Ord k => (Maybe v -> e) -> DB k v -> ([k],[[e]])+db_to_table f db =+ let kh = db_key_histogram db+ hdr = concatMap (\(k,n) -> replicate n k) kh+ ix = concatMap (\(k,n) -> zip (repeat k) [0 .. n - 1]) kh+ in (hdr,map (\r -> map (\i -> f (record_lookup_at i r)) ix) db)++-- * Collating duplicate keys.++record_collate' :: Eq k => (k,[v]) -> Record k v -> Record k [v]+record_collate' (k,v) r =+ case r of+ [] -> [(k,reverse v)]+ (k',v'):r' ->+ if k == k'+ then record_collate' (k,v' : v) r'+ else (k,reverse v) : record_collate' (k',[v']) r'++-- | Collate adjacent entries of existing sequence with equal key.+record_collate :: Eq k => Record k v -> Record k [v]+record_collate r =+ case r of+ [] -> error "record_collate: nil"+ (k,v):r' -> record_collate' (k,[v]) r'++record_uncollate :: Record k [v] -> Record k v+record_uncollate = concatMap (\(k,v) -> zip (repeat k) v)
+ Music/Theory/DB/JSON.hs view
@@ -0,0 +1,67 @@+-- | JSON string association database.+-- JSON objects do no allow multiple keys.+-- Here multiple keys are read & written as arrays.+module Music.Theory.DB.JSON where++import qualified Data.Aeson as A {- aeson -}+import qualified Data.ByteString.Lazy as B {- bytestring -}+import qualified Data.Map as M {- containers -}++import qualified Music.Theory.DB.Common as DB++-- | Load 'DB' from 'FilePath'.+db_load_utf8 :: FilePath -> IO DB.DB'+db_load_utf8 fn = do+ b <- B.readFile fn+ case A.decode b of+ Just m ->+ let f = DB.record_uncollate .+ map (fmap maybe_list_to_list) .+ M.toList+ in return (map f m)+ Nothing -> return []++-- | Store 'DB' to 'FilePath'.+--+-- > let fn = "/home/rohan/ut/www-spr/data/db.js"+-- > db <- db_load_utf8 fn+-- > length db == 1334+-- > db_store_utf8 "/tmp/sp.js" db+db_store_utf8 :: FilePath -> DB.DB' -> IO ()+db_store_utf8 fn db = do+ let db' = let f = map (fmap list_to_maybe_list) . DB.record_collate+ in map f db+ b = A.encode (map M.fromList db')+ B.writeFile fn b++-- * Maybe List of String++data Maybe_List_Of_String = S String | L [String] deriving (Eq,Show)++maybe_list_to_list :: Maybe_List_Of_String -> [String]+maybe_list_to_list m =+ case m of+ S s -> [s]+ L l -> l++list_to_maybe_list :: [String] -> Maybe_List_Of_String+list_to_maybe_list l =+ case l of+ [s] -> S s+ _ -> L l++-- > A.toJSON (S "x")+-- > A.toJSON (L ["x","y"])+instance A.ToJSON Maybe_List_Of_String where+ toJSON (S s) = A.toJSON s+ toJSON (L l) = A.toJSON l++-- > :set -XOverloadedStrings+-- > A.decode "\"x\"" :: Maybe Maybe_List_Of_String+-- > A.decode "[\"x\",\"y\"]" :: Maybe Maybe_List_Of_String+instance A.FromJSON Maybe_List_Of_String where+ parseJSON v =+ case v of+ A.String _ -> fmap S (A.parseJSON v)+ A.Array _ -> fmap L (A.parseJSON v)+ _ -> error "parseJSON: Maybe_List_String"
+ Music/Theory/DB/Plain.hs view
@@ -0,0 +1,60 @@+-- | @key: value@ database, allows duplicate @key@s.+module Music.Theory.DB.Plain where++import Data.List {- base -}+import qualified Data.List.Split as Split {- split -}+import Data.Maybe {- base -}+import qualified Safe as Safe {- safe -}++import qualified Music.Theory.IO as IO {- hmt -}+import qualified Music.Theory.List as T {- hmt -}++-- | (RECORD-SEPARATOR,FIELD-SEPARATOR,ENTRY-SEPARATOR)+type SEP = (String,String,String)++type Key = String+type Value = String+type Entry = (Key,[Value])+type Record = [Entry]+type DB = [Record]++sep_plain :: SEP+sep_plain = (['\n','\n'],['\n'],": ")++-- > record_parse (";","=") "F=f/rec;E=au;C=A;K=P;K=Q"+record_parse :: (String,String) -> String -> Record+record_parse (fs,es) = T.collate_adjacent . mapMaybe (T.separate_at es) . Split.splitOn fs++record_lookup :: Key -> Record -> [Value]+record_lookup k = fromMaybe [] . lookup k++record_lookup_at :: (Key,Int) -> Record -> Maybe Value+record_lookup_at (k,n) = flip Safe.atMay n . record_lookup k++record_has_key :: Key -> Record -> Bool+record_has_key k = isJust . lookup k++record_lookup_uniq :: Key -> Record -> Maybe Value+record_lookup_uniq k r =+ case record_lookup k r of+ [] -> Nothing+ [v] -> Just v+ _ -> error "record_lookup_uniq: non uniq"++db_parse :: SEP -> String -> [Record]+db_parse (rs,fs,es) s =+ let r = Split.splitOn rs s+ in map (record_parse (fs,es)) r++db_sort :: [(Key,Int)] -> [Record] -> [Record]+db_sort k = T.sort_by_n_stage (map record_lookup_at k)++db_load_utf8 :: SEP -> FilePath -> IO [Record]+db_load_utf8 sep = fmap (db_parse sep) . IO.read_file_utf8++-- > record_pp (";","=") [("F","f/rec.au"),("C","A")]+record_pp :: (String,String) -> Record -> String+record_pp (fs,es) = intercalate fs . map (\(k,v) -> k ++ es ++ v) . T.uncollate++db_store_utf8 :: SEP -> FilePath -> [Record] -> IO ()+db_store_utf8 (rs,fs,es) fn = IO.write_file_utf8 fn . intercalate rs . map (record_pp (fs,es))
+ Music/Theory/Directory.hs view
@@ -0,0 +1,38 @@+-- | Directory functions.+module Music.Theory.Directory where++import Data.List {- base -}+import Data.Maybe {- base -}+import System.Directory {- directory -}+import System.FilePath {- filepath -}++-- | Scan a list of directories until a file is located, or not.+path_scan :: [FilePath] -> FilePath -> IO (Maybe FilePath)+path_scan p fn =+ case p of+ [] -> return Nothing+ dir:p' -> let nm = dir </> fn+ f x = if x then return (Just nm) else path_scan p' fn+ in doesFileExist nm >>= f++path_scan_err :: [FilePath] -> FilePath -> IO FilePath+path_scan_err p x =+ let err = (error ("path_scan: " ++ show p ++ ": " ++ x))+ in fmap (fromMaybe err) (path_scan p x)++-- | Subset of files in /dir/ with an extension in /ext/.+dir_subset :: [String] -> FilePath -> IO [FilePath]+dir_subset ext dir = do+ let f nm = takeExtension nm `elem` ext+ c <- getDirectoryContents dir+ return (map (dir </>) (sort (filter f c)))++-- | If path is not absolute, prepend current working directory.+--+-- > to_absolute_cwd "x"+to_absolute_cwd :: FilePath -> IO FilePath+to_absolute_cwd x =+ if isAbsolute x+ then return x+ else fmap (</> x) getCurrentDirectory+
Music/Theory/Duration.hs view
@@ -6,6 +6,9 @@ import Data.Maybe {- base -} import Data.Ratio {- base -} +import qualified Music.Theory.List as T {- hmt -}+import qualified Music.Theory.Ord as T {- hmt -}+ -- | Common music notation durational model data Duration = Duration {division :: Integer -- ^ division of whole note ,dots :: Integer -- ^ number of dots@@ -17,6 +20,10 @@ duration_meq :: Duration -> Duration -> Bool duration_meq p q = multiplier p == multiplier q +-- | Is multiplier the identity (ie. @1@)?+duration_m1 :: Duration -> Bool+duration_m1 = (== 1) . multiplier+ -- | Compare durations with equal multipliers. duration_compare_meq :: Duration -> Duration -> Maybe Ordering duration_compare_meq y0 y1 =@@ -40,22 +47,6 @@ instance Ord Duration where compare = duration_compare_meq_err -order_pair :: Ordering -> (t,t) -> (t,t)-order_pair o (x,y) =- case o of- LT -> (x,y)- EQ -> (x,y)- GT -> (y,x)---- | Sort a pair of equal type values using given comparison function.------ > sort_pair compare ('b','a') == ('a','b')-sort_pair :: (t -> t -> Ordering) -> (t,t) -> (t,t)-sort_pair fn (x,y) = order_pair (fn x y) (x,y)--sort_pair_m :: (t -> t -> Maybe Ordering) -> (t,t) -> Maybe (t,t)-sort_pair_m fn (x,y) = fmap (`order_pair` (x,y)) (fn x y)- -- | True if neither duration is dotted. no_dots :: (Duration, Duration) -> Bool no_dots (x0,x1) = dots x0 == 0 && dots x1 == 0@@ -102,100 +93,134 @@ then sum_dur_undotted (division x0, division x1) else sum_dur_dotted (division x0, dots x0 ,division x1, dots x1)- in join (fmap f (sort_pair_m duration_compare_meq (y0,y1)))+ in join (fmap f (T.sort_pair_m duration_compare_meq (y0,y1))) -- | Erroring variant of 'sum_dur'.-sum_dur' :: Duration -> Duration -> Duration-sum_dur' y0 y1 =+sum_dur_err :: Duration -> Duration -> Duration+sum_dur_err y0 y1 = let y2 = sum_dur y0 y1 err = error ("sum_dur': " ++ show (y0,y1)) in fromMaybe err y2 --- | Give @MusicXML@ type for division.+-- | Standard divisions (from 0 to 256). MusicXML allows @-1@ as a division (for @long@).+divisions_set :: [Integer]+divisions_set = [0,1,2,4,8,16,32,64,128,256]++-- | Durations set derived from 'divisions_set' with up to /k/ dots. Multiplier of @1@.+duration_set :: Integer -> [Duration]+duration_set k = [Duration dv dt 1 | dv <- divisions_set, dt <- [0..k]]++-- | Table of number of beams at notated division.+beam_count_tbl :: [(Integer,Integer)]+beam_count_tbl = zip (-1 : divisions_set) [0,0,0,0,0,1,2,3,4,5,6]++-- | Lookup 'beam_count_tbl'. --+-- > whole_note_division_to_beam_count 32 == Just 3+whole_note_division_to_beam_count :: Integer -> Maybe Integer+whole_note_division_to_beam_count x = lookup x beam_count_tbl++-- | Calculate number of beams at 'Duration'.+--+-- > map duration_beam_count [Duration 2 0 1,Duration 16 0 1] == [0,2]+duration_beam_count :: Duration -> Integer+duration_beam_count (Duration x _ _) =+ let err = error "duration_beam_count"+ bc = whole_note_division_to_beam_count x+ in fromMaybe err bc++-- * MusicXML++-- | Table giving @MusicXML@ types for divisions.+division_musicxml_tbl :: [(Integer,String)]+division_musicxml_tbl =+ let nm = ["long","breve","whole","half","quarter","eighth"+ ,"16th","32nd","64th","128th","256th"]+ in zip (-1 : divisions_set) nm++-- | Lookup 'division_musicxml_tbl'.+-- -- > map whole_note_division_to_musicxml_type [2,4] == ["half","quarter"] whole_note_division_to_musicxml_type :: Integer -> String whole_note_division_to_musicxml_type x =- case x of- 256 -> "256th"- 128 -> "128th"- 64 -> "64th"- 32 -> "32nd"- 16 -> "16th"- 8 -> "eighth"- 4 -> "quarter"- 2 -> "half"- 1 -> "whole"- 0 -> "breve"- -1 -> "long"- _ -> error ("whole_note_division_to_musicxml_type: " ++ show x)+ T.lookup_err_msg "division_musicxml_tbl" x division_musicxml_tbl -- | Variant of 'whole_note_division_to_musicxml_type' extracting--- 'division' from 'Duration'.+-- 'division' from 'Duration', dots & multipler are ignored. ----- > duration_to_musicxml_type quarter_note == "quarter"+-- > duration_to_musicxml_type (Duration 4 0 1) == "quarter" duration_to_musicxml_type :: Duration -> String duration_to_musicxml_type = whole_note_division_to_musicxml_type . division +-- * Unicode++-- | Table giving @Unicode@ symbols for divisions.+division_unicode_tbl :: [(Integer,Char)]+division_unicode_tbl = zip [0,1,2,4,8,16,32,64,128,256] "𝅜𝅝𝅗𝅥𝅘𝅥𝅘𝅥𝅮𝅘𝅥𝅯𝅘𝅥𝅰𝅘𝅥𝅱𝅘𝅥𝅲"++-- | Lookup 'division_unicode_tbl'.+--+-- > map whole_note_division_to_unicode_symbol [1,2,4,8] == "𝅝𝅗𝅥𝅘𝅥𝅘𝅥𝅮"+whole_note_division_to_unicode_symbol :: Integer -> Char+whole_note_division_to_unicode_symbol x =+ T.lookup_err_msg "division_unicode_tbl" x division_unicode_tbl++-- | Give Unicode string for 'Duration'. The duration multiplier is /not/ written.+--+-- > map duration_to_unicode [Duration 1 2 1,Duration 4 1 1] == ["𝅝𝅭𝅭","𝅘𝅥𝅭"]+duration_to_unicode :: Duration -> String+duration_to_unicode (Duration dv d _) =+ let dv' = whole_note_division_to_unicode_symbol dv+ in dv' : replicate (fromIntegral d) '𝅭'++-- * Lilypond+ -- | Give /Lilypond/ notation for 'Duration'. Note that the duration -- multiplier is /not/ written. ----- > import Music.Theory.Duration.Name--- > map duration_to_lilypond_type [half_note,dotted_quarter_note] == ["2","4."]+-- > map duration_to_lilypond_type [Duration 2 0 1,Duration 4 1 1] == ["2","4."] duration_to_lilypond_type :: Duration -> String duration_to_lilypond_type (Duration dv d _) = let dv' = if dv == 0 then "\\breve" else show dv in dv' ++ replicate (fromIntegral d) '.' --- | Calculate number of beams at notated division.------ > whole_note_division_to_beam_count 32 == Just 3-whole_note_division_to_beam_count :: Integer -> Maybe Integer-whole_note_division_to_beam_count x =- let t = [(256,6),(128,5),(64,4),(32,3),(16,2),(8,1)- ,(4,0),(2,0),(1,0),(0,0),(-1,0)]- in lookup x t+-- * Humdrum --- | Calculate number of beams at 'Duration'.------ > map duration_beam_count [half_note,sixteenth_note] == [0,2]-duration_beam_count :: Duration -> Integer-duration_beam_count (Duration x _ _) =- let err = error "duration_beam_count"- bc = whole_note_division_to_beam_count x- in fromMaybe err bc+{- | Duration to @**recip@ notation. -whole_note_division_pp :: Integer -> Maybe Char-whole_note_division_pp x =+<http://humdrum.org/Humdrum/representations/recip.rep.html>++> let d = map (\z -> Duration z 0 1) [0,1,2,4,8,16,32]+> in map duration_recip_pp d == ["0","1","2","4","8","16","32"]++> let d = [Duration 1 1 (1/3),Duration 4 1 1,Duration 4 1 (2/3)]+> in map duration_recip_pp d == ["3.","4.","6."]++-}+duration_recip_pp :: Duration -> String+duration_recip_pp (Duration x d m) =+ let (mn,md) = (numerator m,denominator m)+ r = (x % mn) * (md % 1)+ in if denominator r == 1+ then show (numerator r) ++ genericReplicate d '.'+ else error (show ("duration_recip_pp",x,d,m,r))++-- * Letter++whole_note_division_letter_pp :: Integer -> Maybe Char+whole_note_division_letter_pp x = let t = [(16,'s'),(8,'e'),(4,'q'),(2,'h'),(1,'w')] in lookup x t --- > import Music.Theory.Duration.Name.Abbreviation--- > map duration_pp [q,h',e''] == [Just "q",Just "h'",Just "e''"]-duration_pp :: Duration -> Maybe String-duration_pp (Duration x d m) =+-- > mapMaybe duration_letter_pp [Duration 4 0 1,Duration 2 1 1,Duration 8 2 1] == ["q","h'","e''"]+-- > duration_letter_pp+duration_letter_pp :: Duration -> Maybe String+duration_letter_pp (Duration x d m) = let d' = genericReplicate d '\'' m' = case (numerator m,denominator m) of (1,1) -> "" (1,i) -> '/' : show i (i,j) -> '*' : show i ++ "/" ++ show j- in case whole_note_division_pp x of+ in case whole_note_division_letter_pp x of Just x' -> Just (x' : d' ++ m') _ -> Nothing---- | Duration to @**recip@ notation.------ http://humdrum.org/Humdrum/representations/recip.rep.html------ > let d = map (\z -> Duration z 0 1) [0,1,2,4,8,16,32]--- > in map duration_recip_pp d == ["0","1","2","4","8","16","32"]------ > let d = [Duration 1 1 (1/3),Duration 4 1 1,Duration 4 1 (2/3)]--- > in map duration_recip_pp d == ["3.","4.","6."]-duration_recip_pp :: Duration -> String-duration_recip_pp (Duration x d m) =- let (mn,md) = (numerator m,denominator m)- r = (x % mn) * (md % 1)- in if denominator r == 1- then show (numerator r) ++ genericReplicate d '.'- else error (show ("duration_recip_pp",x,d,m,r))
Music/Theory/Duration/Annotation.hs view
@@ -3,11 +3,11 @@ import Data.Maybe {- base -} import Data.Ratio {- base -}-import qualified Data.Traversable as T {- base -} import Data.Tree {- containers -} import Music.Theory.Duration import Music.Theory.Duration.RQ+import qualified Music.Theory.List as L {- hmt -} -- | Standard music notation durational model annotations data D_Annotation = Tie_Right@@ -63,52 +63,6 @@ jn (p,q) z = (p,q++z) in zipWith jn (map fn x) ts --- | Transform predicates into 'Ordering' predicate such that if /f/--- holds then 'LT', if /g/ holds then 'GT' else 'EQ'.------ > map (begin_end_cmp (== '{') (== '}')) "{a}" == [LT,EQ,GT]-begin_end_cmp :: (t -> Bool) -> (t -> Bool) -> t -> Ordering-begin_end_cmp f g x = if f x then LT else if g x then GT else EQ---- | Variant of 'begin_end_cmp', predicates are constructed by '=='.------ > map (begin_end_cmp_eq '{' '}') "{a}" == [LT,EQ,GT]-begin_end_cmp_eq :: Eq t => t -> t -> t -> Ordering-begin_end_cmp_eq p q = begin_end_cmp (== p) (== q)---- | Given an 'Ordering' predicate where 'LT' opens a group, 'GT'--- closes a group, and 'EQ' continues current group, construct tree--- from list.------ > let {l = "a {b {c d} e f} g h i"--- > ;t = group_tree (begin_end_cmp_eq '{' '}') l}--- > in catMaybes (flatten t) == l------ > let d = putStrLn . drawTree . fmap show--- > in d (group_tree (begin_end_cmp_eq '(' ')') "a(b(cd)ef)ghi")-group_tree :: (a -> Ordering) -> [a] -> Tree (Maybe a)-group_tree f =- let unit e = Node (Just e) []- nil = Node Nothing []- insert_e (Node t l) e = Node t (e:l)- reverse_n (Node t l) = Node t (reverse l)- push (r,z) e = case z of- h:z' -> (r,insert_e h (unit e) : z')- [] -> (unit e : r,[])- open (r,z) = (r,nil:z)- close (r,z) = case z of- h0:h1:z' -> (r,insert_e h1 (reverse_n h0) : z')- h:z' -> (reverse_n h : r,z')- [] -> (r,z)- go st x =- case x of- [] -> Node Nothing (reverse (fst st))- e:x' -> case f e of- LT -> go (push (open st) e) x'- EQ -> go (push st e) x'- GT -> go (close (push st e)) x'- in go ([],[])- -- | Group tuplets into a 'Tree'. Branch nodes have label 'Nothing', -- leaf nodes label 'Just' 'Duration_A'. --@@ -121,9 +75,7 @@ -- > ,(q,[])] -- > in catMaybes (flatten (da_group_tuplets d)) == d da_group_tuplets :: [Duration_A] -> Tree (Maybe Duration_A)-da_group_tuplets =- let f = begin_end_cmp da_begins_tuplet da_ends_tuplet- in group_tree f+da_group_tuplets = L.group_tree (da_begins_tuplet,da_ends_tuplet) -- | Variant of 'break' that places separator at left. --@@ -165,22 +117,11 @@ in Right (d : t) : da_group_tuplets_nn x'' else Left d : da_group_tuplets_nn x' --- | Keep right variant of 'zipWith', unused rhs values are returned.------ > zip_with_kr (,) [1..3] ['a'..'e'] == ([(1,'a'),(2,'b'),(3,'c')],"de")-zip_with_kr :: (a -> b -> c) -> [a] -> [b] -> ([c],[b])-zip_with_kr f =- let go r p q =- case (p,q) of- (i:p',j:q') -> go (f i j : r) p' q'- _ -> (reverse r,q)- in go []- -- | Keep right variant of 'zip', unused rhs values are returned. -- -- > zip_kr [1..4] ['a'..'f'] == ([(1,'a'),(2,'b'),(3,'c'),(4,'d')],"ef") zip_kr :: [a] -> [b] -> ([(a,b)],[b])-zip_kr = zip_with_kr (,)+zip_kr = L.zip_with_kr (,) -- | 'zipWith' variant that adopts the shape of the lhs. --@@ -192,31 +133,9 @@ case (p,q) of (e:p',i:q') -> case e of Left j -> Left (f j i) : nn_reshape f p' q'- Right j -> let (j',q'') = zip_with_kr f j q+ Right j -> let (j',q'') = L.zip_with_kr f j q in Right j' : nn_reshape f p' q'' _ -> []---- | Replace elements at 'Traversable' with result of joining with--- elements from list.-adopt_shape :: T.Traversable t => (a -> b -> c) -> [b] -> t a -> t c-adopt_shape jn l =- let f (i:j) k = (j,jn k i)- f [] _ = error "adopt_shape: rhs ends"- in snd . T.mapAccumL f l---- | Variant of 'adopt_shape' that considers only 'Just' elements at--- 'Traversable'.------ > let {s = "a(b(cd)ef)ghi"--- > ;t = group_tree (begin_end_cmp_eq '(' ')') s}--- > in adopt_shape_m (,) [1..13] t-adopt_shape_m :: T.Traversable t => (a -> b-> c) -> [b] -> t (Maybe a) -> t (Maybe c)-adopt_shape_m jn l =- let f (i:j) k = case k of- Nothing -> (i:j,Nothing)- Just k' -> (j,Just (jn k' i))- f [] _ = error "adopt_shape_m: rhs ends"- in snd . T.mapAccumL f l -- | Does /a/ have 'Tie_Left' and 'Tie_Right'? d_annotated_tied_lr :: [D_Annotation] -> (Bool,Bool)
Music/Theory/Duration/CT.hs view
@@ -124,7 +124,7 @@ ct_measure:: T.Lseq T.RQ T.RQ -> ([T.RQ],Maybe Char,Maybe (),[[T.RQ]]) -> [(Rational,CT_Node)] ct_measure sq (mrq,mk,pr,dv) =- let dv' = concatMap (zip [1..]) dv+ let dv' = concatMap (zip [1::Int ..]) dv f (p,rq,(g,du)) = let nm = if p == 1 then case mk of@@ -134,7 +134,7 @@ then CT_Pre du else if g == 1 then CT_Edge du else CT_Normal du in (du * (60 / ct_tempo_at sq rq),nm)- in map f (zip3 [1..] mrq dv')+ in map f (zip3 [1::Int ..] mrq dv') -- | Click track definition. data CT = CT {ct_len :: Int
Music/Theory/Duration/Name/Abbreviation.hs view
@@ -2,7 +2,8 @@ -- There are /letter/ names where 'w' is 'whole_note' and so on, and -- /numerical/ names where '_4' is 'quarter_note' and so on. In both -- cases a @'@ extension means a @dot@ so that 'e''' is a double--- dotted 'eighth_note'.+-- dotted 'eighth_note'. The prefix is @_@ not @d@ since @d4@ etc. are+-- also note names. -- -- > zipWith duration_compare_meq [e,e,e,e'] [e,s,q,e] == [EQ,GT,LT,GT] -- > zipWith sum_dur [e,q,q'] [e,e,e] == [Just q,Just q',Just h]
Music/Theory/Duration/RQ.hs view
@@ -6,36 +6,22 @@ import Data.Maybe {- base -} import Data.Ratio {- base -} -import Music.Theory.Duration-import Music.Theory.Duration.Name+import Music.Theory.Duration {- hmt -} -- | Rational Quarter-Note type RQ = Rational +-- > rq_duration_tbl 2+rq_duration_tbl :: Integer -> [(Rational,Duration)]+rq_duration_tbl k = map (\d -> (duration_to_rq d,d)) (duration_set k)+ -- | Rational quarter note to duration value. It is a mistake to hope -- this could handle tuplets directly since, for instance, a @3:2@ -- dotted note will be of the same duration as a plain undotted note. -- -- > rq_to_duration (3/4) == Just dotted_eighth_note rq_to_duration :: RQ -> Maybe Duration-rq_to_duration x =- case (numerator x,denominator x) of- (1,8) -> Just thirtysecond_note- (3,16) -> Just dotted_thirtysecond_note- (1,4) -> Just sixteenth_note- (3,8) -> Just dotted_sixteenth_note- (1,2) -> Just eighth_note- (3,4) -> Just dotted_eighth_note- (1,1) -> Just quarter_note- (3,2) -> Just dotted_quarter_note- (2,1) -> Just half_note- (3,1) -> Just dotted_half_note- (7,2) -> Just double_dotted_half_note- (4,1) -> Just whole_note- (6,1) -> Just dotted_whole_note- (8,1) -> Just breve- (12,1) -> Just dotted_breve- _ -> Nothing+rq_to_duration x = lookup x (rq_duration_tbl 2) -- | Is 'RQ' a /cmn/ duration. --
Music/Theory/Duration/Sequence/Notate.hs view
@@ -17,7 +17,6 @@ -- 5. Ascribe values to notated durations, see 'ascribe'. module Music.Theory.Duration.Sequence.Notate where -import Control.Applicative {- base -} import Control.Monad {- base -} import Data.List {- base -} import Data.List.Split {- split -}@@ -646,6 +645,14 @@ z i (j,_) = i + duration_to_rq j in coalesce_sum z 0 f +-- | Run simplifier until it reaches a fix-point, or for at most 'limit' passes.+m_simplify_fix :: Int -> Simplify_P -> Time_Signature -> [Duration_A] -> [Duration_A]+m_simplify_fix limit p ts d =+ let d' = m_simplify p ts d+ in if d == d' || limit == 1+ then d'+ else m_simplify_fix (limit - 1) p ts d'+ -- | Pulse simplifier predicate, which is 'const' 'True'. p_simplify_rule :: Simplify_P p_simplify_rule = const True@@ -674,23 +681,23 @@ > ts_p = [[1/2,1,1/2],[1/2,1]] > rq = map (/6) [1,1,1,1,1,1,4,1,2,1,1,2,1,3] > sr x = T.default_rule [] x-> in T.notate_rqp sr ts (Just ts_p) rq+> in T.notate_rqp 4 sr ts (Just ts_p) rq -}-notate_rqp :: Simplify_P -> [Time_Signature] -> Maybe [[RQ]] -> [RQ] ->+notate_rqp :: Int -> Simplify_P -> [Time_Signature] -> Maybe [[RQ]] -> [RQ] -> Either String [[Duration_A]]-notate_rqp r ts ts_p x = do+notate_rqp limit r ts ts_p x = do let ts_p' = fromMaybe (map ts_divisions ts) ts_p mm <- to_divisions_rq ts_p' x dd <- mm_notate mm- return (zipWith (m_simplify r) ts dd)+ return (zipWith (m_simplify_fix limit r) ts dd) -- | Variant of 'notate_rqp' without pulse divisions (derive). ----- > notate (default_rule [((3,2),0,(2,2)),((3,2),0,(4,2))]) [(3,2)] [6]-notate :: Simplify_P -> [Time_Signature] -> [RQ] ->+-- > notate 4 (default_rule [((3,2),0,(2,2)),((3,2),0,(4,2))]) [(3,2)] [6]+notate :: Int -> Simplify_P -> [Time_Signature] -> [RQ] -> Either String [[Duration_A]]-notate r ts x = notate_rqp r ts Nothing x+notate limit r ts x = notate_rqp limit r ts Nothing x -- * Ascribe @@ -772,17 +779,17 @@ in r : mm_ascribe mm' x' -- | 'mm_ascribe of 'notate'.-notate_mm_ascribe :: Show a => [Simplify_T] -> [Time_Signature] -> Maybe [[RQ]] -> [RQ] -> [a] ->+notate_mm_ascribe :: Show a => Int -> [Simplify_T] -> [Time_Signature] -> Maybe [[RQ]] -> [RQ] -> [a] -> Either String [[(Duration_A,a)]]-notate_mm_ascribe r ts rqp d p =- let n = notate_rqp (default_rule r) ts rqp d+notate_mm_ascribe limit r ts rqp d p =+ let n = notate_rqp limit (default_rule r) ts rqp d f = flip mm_ascribe p err str = show ("notate_ascribe",str,ts,d,p) in either (Left . err) (Right . f) n -notate_mm_ascribe_err :: Show a => [Simplify_T] -> [Time_Signature] -> Maybe [[RQ]] -> [RQ] -> [a] ->+notate_mm_ascribe_err :: Show a => Int -> [Simplify_T] -> [Time_Signature] -> Maybe [[RQ]] -> [RQ] -> [a] -> [[(Duration_A,a)]]-notate_mm_ascribe_err = either error id .:::: notate_mm_ascribe+notate_mm_ascribe_err = either error id .::::: notate_mm_ascribe -- | Group elements as /chords/ where a chord element is indicated by -- the given predicate.
Music/Theory/Dynamic_Mark.hs view
@@ -33,7 +33,7 @@ -- | Map midi velocity (0-127) to dynamic mark. -- -- > histogram (mapMaybe midi_dynamic_mark [0 .. 127])-midi_dynamic_mark :: (Ord n,Eq n,Num n,Enum n) => n -> Maybe Dynamic_Mark_T+midi_dynamic_mark :: (Ord n,Num n,Enum n) => n -> Maybe Dynamic_Mark_T midi_dynamic_mark m = let r = zip (0 : [12,24 .. 132]) [0..] in fmap (toEnum . snd) (find ((>= m) . fst) r)
+ Music/Theory/Enum.hs view
@@ -0,0 +1,38 @@+-- | Enumeration functions.+module Music.Theory.Enum where++-- | Generic variant of 'fromEnum' (p.263).+genericFromEnum :: (Integral i,Enum e) => e -> i+genericFromEnum = fromIntegral . fromEnum++-- | Generic variant of 'toEnum' (p.263).+genericToEnum :: (Integral i,Enum e) => i -> e+genericToEnum = toEnum . fromIntegral++-- | Variant of 'enumFromTo' that, if /p/ is after /q/, cycles from+-- 'maxBound' to 'minBound'.+--+-- > import Data.Word+-- > enum_from_to_cyclic (254 :: Word8) 1 == [254,255,0,1]+enum_from_to_cyclic :: (Bounded a, Enum a) => a -> a -> [a]+enum_from_to_cyclic p q =+ if fromEnum p > fromEnum q+ then [p .. maxBound] ++ [minBound .. q]+ else [p .. q]++-- | Variant of 'enumFromTo' that, if /p/ is after /q/, enumerates+-- from /q/ to /p/.+--+-- > enum_from_to_reverse 5 1 == [5,4,3,2,1]+-- > enum_from_to_reverse 1 5 == enumFromTo 1 5+enum_from_to_reverse :: Enum a => a -> a -> [a]+enum_from_to_reverse p q =+ if fromEnum p > fromEnum q+ then reverse [q .. p]+ else [p .. q]++-- | All elements in sequence.+--+-- > (enum_univ :: [Data.Word.Word8]) == [0 .. 255]+enum_univ :: (Bounded t,Enum t) => [t]+enum_univ = [minBound .. maxBound]
Music/Theory/Function.hs view
@@ -1,6 +1,13 @@ -- | "Data.Function" related functions. module Music.Theory.Function where +-- | 'const' of 'const'.+--+-- > const2 5 undefined undefined == 5+-- > const (const 5) undefined undefined == 5+const2 :: a -> b -> c -> a+const2 x _ _ = x+ -- * Predicate composition. -- | '&&' of predicates.@@ -18,7 +25,7 @@ predicate_or :: (t -> Bool) -> (t -> Bool) -> t -> Bool predicate_or f g x = f x || g x --- | 'any' of predicates.+-- | 'any' of predicates, ie. logical /or/ of list of predicates. -- -- > let r = [True,False,True,False,True,True] -- > in map (predicate_any [(== 0),(== 5),even]) [0..5] == r
+ Music/Theory/Gamelan.hs view
@@ -0,0 +1,325 @@+module Music.Theory.Gamelan where++import Data.Char {- base -}+import Data.Function {- base -}+import Data.List {- base -}+import Data.Maybe {- base -}+import Data.Ratio {- base -}+import Text.Printf {- base -}++import qualified Music.Theory.Clef as T {- hmt -}+import qualified Music.Theory.Enum as T {- hmt -}+import qualified Music.Theory.Pitch as T {- hmt -}+import qualified Music.Theory.Tuning as T {- hmt -}+import qualified Music.Theory.Tuning.ET as T {- hmt-diagrams -}++-- | 'fromJust' with error message.+fromJust_err :: String -> Maybe a -> a+fromJust_err err = fromMaybe (error err)++-- | 'approxRational' of 0.01.+near_rat :: Double -> Rational+near_rat = flip approxRational 0.01++-- * Gamelan++-- | Enumeration of gamelan instrument families.+data Instrument_Family+ = Bonang+ | Gender+ | Gong+ | Saron+ deriving (Enum,Bounded,Eq,Ord,Show,Read)++-- | Universe+instrument_family_set :: [Instrument_Family]+instrument_family_set = T.enum_univ++-- | Enumeration of Gamelan instruments.+data Instrument_Name+ = Bonang_Barung -- ^ Bonang Barung (horizontal gong, middle)+ | Bonang_Panerus -- ^ Bonang Panerus (horizontal gong, high)+ | Gender_Barung -- ^ Gender Barung (key&resonator, middle)+ | Gender_Panerus -- ^ Gender Panembung (key&resonator, high)+ | Gender_Panembung -- ^ Gender Panembung, Slenthem (key&resonator, low)+ | Gong_Ageng -- ^ Gong Ageng (hanging gong, low)+ | Gong_Suwukan -- ^ Gong Suwukan (hanging gong, middle)+ | Kempul -- ^ Kempul (hanging gong, middle)+ | Kempyang -- ^ Kempyang (horizontal gong, high)+ | Kenong -- ^ Kenong (horizontal gong, low)+ | Ketuk -- ^ Ketuk (horizontal gong, middle)+ | Saron_Barung -- ^ Saron Barung, Saron (key, middle)+ | Saron_Demung -- ^ Saron Demung, Demung (key, low)+ | Saron_Panerus -- ^ Saron Panerus, Peking (key, high)+ deriving (Enum,Bounded,Eq,Ord,Show,Read)++instrument_family :: Instrument_Name -> Maybe Instrument_Family+instrument_family nm =+ case nm of+ Bonang_Barung -> Just Bonang+ Bonang_Panerus -> Just Bonang+ Gender_Barung -> Just Gender+ Gender_Panerus -> Just Gender+ Gender_Panembung -> Just Gender+ Gong_Ageng -> Just Gong+ Gong_Suwukan -> Just Gong+ Kempul -> Just Gong+ Kempyang -> Nothing+ Kenong -> Nothing+ Ketuk -> Nothing+ Saron_Barung -> Just Saron+ Saron_Demung -> Just Saron+ Saron_Panerus -> Just Saron++instrument_name_pp :: Instrument_Name -> String+instrument_name_pp =+ let f c = if c == '_' then ' ' else c+ in map f . show++-- | 'Clef' appropriate for 'Instrument_Name'.+instrument_name_clef :: Integral i => Instrument_Name -> T.Clef i+instrument_name_clef nm =+ case nm of+ Bonang_Barung -> T.Clef T.Treble 0+ Bonang_Panerus -> T.Clef T.Treble 1+ Gender_Barung -> T.Clef T.Treble 0+ Gender_Panerus -> T.Clef T.Treble 1+ Gender_Panembung -> T.Clef T.Bass 0+ Gong_Ageng -> T.Clef T.Bass 0+ Gong_Suwukan -> T.Clef T.Bass 0+ Kempul -> T.Clef T.Bass 0+ Kempyang -> T.Clef T.Treble 1+ Kenong -> T.Clef T.Treble 0+ Ketuk -> T.Clef T.Alto 0+ Saron_Barung -> T.Clef T.Treble 0+ Saron_Demung -> T.Clef T.Treble 0+ Saron_Panerus -> T.Clef T.Treble 1++instrument_name_clef_plain :: Integral i => Instrument_Name -> T.Clef i+instrument_name_clef_plain = T.clef_zero . instrument_name_clef++-- | Enumeration of Gamelan scales.+data Scale = Pelog | Slendro deriving (Enum,Eq,Ord,Show,Read)++type Octave = Integer+type Degree = Integer+type Frequency = Double+type Annotation = String++data Pitch = Pitch {pitch_octave :: Octave+ ,pitch_degree :: Degree}+ deriving (Eq,Ord,Show)++pitch_pp_ascii :: Pitch -> String+pitch_pp_ascii (Pitch o d) =+ let d' = intToDigit (fromIntegral d)+ o' = if o < 0+ then genericReplicate (abs o) '-'+ else genericReplicate o '+'+ in o' ++ [d']++pitch_pp_duple :: Pitch -> String+pitch_pp_duple (Pitch o d) = printf "(%d,%d)" o d++data Note = Note {note_scale :: Scale+ ,note_pitch :: Pitch}+ deriving (Eq,Ord,Show)++note_degree :: Note -> Degree+note_degree = pitch_degree . note_pitch++data Tone = Tone {tone_instrument_name :: Instrument_Name+ ,tone_note :: Maybe Note+ ,tone_frequency :: Maybe Frequency+ ,tone_annotation :: Maybe Annotation}+ deriving (Eq,Show)++tone_frequency_err :: Tone -> Frequency+tone_frequency_err = fromJust_err "tone_frequency" . tone_frequency++-- | Orderable if frequency is given.+instance Ord Tone where compare = tone_compare_frequency++-- | Constructor for 'Tone' without /frequency/ or /annotation/.+plain_tone :: Instrument_Name -> Scale -> Octave -> Degree -> Tone+plain_tone nm sc o d = Tone nm (Just (Note sc (Pitch o d))) Nothing Nothing++-- | Tones are considered /equivalent/ if they have the same+-- 'Instrument_Name' and 'Note'.+tone_equivalent :: Tone -> Tone -> Bool+tone_equivalent p q =+ let Tone nm nt _ _ = p+ Tone nm' nt' _ _ = q+ in nm == nm' && nt == nt'++tone_24et_pitch :: Tone -> Maybe T.Pitch+tone_24et_pitch =+ let f i = let (_,pt,_,_,_) = T.nearest_24et_tone i in pt+ in fmap f . tone_frequency++tone_24et_pitch' :: Tone -> T.Pitch+tone_24et_pitch' = fromJust_err "tone_24et_pitch" . tone_24et_pitch++tone_24et_pitch_detune :: Tone -> Maybe T.Pitch_Detune+tone_24et_pitch_detune = fmap T.nearest_pitch_detune_24et . tone_frequency++tone_24et_pitch_detune' :: Tone -> T.Pitch_Detune+tone_24et_pitch_detune' = fromJust_err "tone_24et_pitch_detune" . tone_24et_pitch_detune++tone_fmidi :: Tone -> Double+tone_fmidi = T.cps_to_fmidi . tone_frequency_err++-- | Fractional (rational) 24-et midi note number of 'Tone'.+tone_24et_fmidi :: Tone -> Rational+tone_24et_fmidi = near_rat . T.pitch_to_fmidi . tone_24et_pitch'++tone_12et_pitch :: Tone -> Maybe T.Pitch+tone_12et_pitch =+ let f i = let (_,pt,_,_,_) = T.nearest_12et_tone i in pt+ in fmap f . tone_frequency++tone_12et_pitch' :: Tone -> T.Pitch+tone_12et_pitch' = fromJust_err "tone_12et_pitch" . tone_12et_pitch++tone_12et_pitch_detune :: Tone -> Maybe T.Pitch_Detune+tone_12et_pitch_detune = fmap T.nearest_pitch_detune_12et . tone_frequency++tone_12et_pitch_detune' :: Tone -> T.Pitch_Detune+tone_12et_pitch_detune' = fromJust_err "tone_12et_pitch_detune" . tone_12et_pitch_detune++-- | Fractional (rational) 24-et midi note number of 'Tone'.+tone_12et_fmidi :: Tone -> Rational+tone_12et_fmidi = near_rat . T.pitch_to_fmidi . tone_12et_pitch'++tone_family :: Tone -> Maybe Instrument_Family+tone_family = instrument_family . tone_instrument_name++tone_family_err :: Tone -> Instrument_Family+tone_family_err = fromJust_err "tone_family" . tone_family++tone_in_family :: Instrument_Family -> Tone -> Bool+tone_in_family c t = tone_family t == Just c++select_tones :: Instrument_Family -> [Tone] -> [Maybe Tone]+select_tones c =+ let f t = if tone_family t == Just c then Just t else Nothing+ in map f++-- | Specify subset as list of families and scales.+type Tone_Subset = ([Instrument_Family],[Scale])++-- | Extract subset of 'Tone_Set'.+tone_subset :: Tone_Subset -> Tone_Set -> Tone_Set+tone_subset (fm,sc) =+ let f t = fromJust_err "tone_subset" (tone_family t) `elem` fm &&+ fromJust_err "tone_subset" (tone_scale t) `elem` sc+ in filter f++data Instrument = Instrument {instrument_name :: Instrument_Name+ ,instrument_scale :: Maybe Scale+ ,instrument_pitches :: Maybe [Pitch]+ ,instrument_frequencies :: Maybe [Frequency]}+ deriving (Eq,Show)++type Tone_Set = [Tone]+type Tone_Group = [Tone_Set]+type Gamelan = [Instrument]++tone_scale :: Tone -> Maybe Scale+tone_scale = fmap note_scale . tone_note++tone_pitch :: Tone -> Maybe Pitch+tone_pitch = fmap note_pitch . tone_note++tone_degree :: Tone -> Maybe Degree+tone_degree = fmap pitch_degree . tone_pitch++tone_degree' :: Tone -> Degree+tone_degree' = fromJust_err "tone_degree" . tone_degree++tone_octave :: Tone -> Maybe Octave+tone_octave = fmap pitch_octave . tone_pitch++tone_class :: Tone -> (Instrument_Name,Maybe Scale)+tone_class t = (tone_instrument_name t,tone_scale t)++instrument_class :: Instrument -> (Instrument_Name,Maybe Scale)+instrument_class i = (instrument_name i,instrument_scale i)++tone_class_p :: (Instrument_Name, Scale) -> Tone -> Bool+tone_class_p (nm,sc) t =+ tone_instrument_name t == nm &&+ tone_scale t == Just sc++tone_family_class_p :: (Instrument_Family,Scale) -> Tone -> Bool+tone_family_class_p (fm,sc) t =+ instrument_family (tone_instrument_name t) == Just fm &&+ tone_scale t == Just sc++-- | Given a 'Tone_Set', find those 'Tone's that are within 'T.Cents' of 'Frequency'.+tone_set_near_frequency :: Tone_Set -> T.Cents -> Frequency -> Tone_Set+tone_set_near_frequency t k n =+ let near i = abs (T.cps_difference_cents i n) <= k+ near_t i = maybe False near (tone_frequency i)+ in filter near_t t++-- | Compare 'Tone's by frequency. 'Tone's without frequency compare+-- as if at frequency @0@.+tone_compare_frequency :: Tone -> Tone -> Ordering+tone_compare_frequency = compare `on` (maybe 0 id . tone_frequency)++-- | If all /f/ of /a/ are 'Just' /b/, then 'Just' /[b]/, else+-- 'Nothing'.+map_maybe_uniform :: (a -> Maybe b) -> [a] -> Maybe [b]+map_maybe_uniform f x =+ let x' = map f x+ in if any isNothing x' then Nothing else Just (catMaybes x')++instrument :: Tone_Set -> Instrument+instrument c =+ let sf = fmap note_scale . tone_note+ pf = fmap note_pitch . tone_note+ pm = map_maybe_uniform pf c+ fm = map_maybe_uniform tone_frequency c+ (p,f) = case (pm,fm) of+ (Just i,Just j) -> let (i',j') = unzip (sort (zip i j))+ in (Just i',Just j')+ _ -> (pm,fm)+ in case c of+ t:_ -> Instrument (tone_instrument_name t) (sf t) p f+ [] -> undefined++instruments :: Tone_Set -> [Instrument]+instruments c =+ let c' = sortBy (compare `on` tone_instrument_name) c+ c'' = groupBy ((==) `on` tone_class) c'+ in map instrument c''++instrument_gamut :: Instrument -> Maybe (Pitch,Pitch)+instrument_gamut =+ let f p = (head p,last p)+ in fmap f . instrument_pitches++scale_degrees :: Scale -> [Degree]+scale_degrees s =+ case s of+ Pelog -> [1..7]+ Slendro -> [1,2,3,5,6]++-- > degree_index Slendro 4 == Nothing+-- > degree_index Pelog 4 == Just 3+degree_index :: Scale -> Degree -> Maybe Int+degree_index s d = findIndex (== d) (scale_degrees s)++-- * Tone set++tone_set_gamut :: Tone_Set -> Maybe (Pitch,Pitch)+tone_set_gamut g =+ case mapMaybe (fmap note_pitch . tone_note) g of+ [] -> Nothing+ p -> Just (minimum p,maximum p)++tone_set_instrument :: Tone_Set -> (Instrument_Name,Maybe Scale) -> Tone_Set+tone_set_instrument db (i,s) =+ let f t = tone_class t == (i,s)+ in filter f db
+ Music/Theory/Graph/Deacon_1934.hs view
@@ -0,0 +1,131 @@+-- | Geometrical Drawings+--+-- A. Bernard Deacon and Camilla H. Wedgwood. “Geometrical Drawings+-- from Malekula and Other Islands of the New Hebrides”. The Journal+-- of the Royal Anthropological Institute of Great Britain and+-- Ireland, 64:129—175, 1934.+module Music.Theory.Graph.Deacon_1934 where++import Data.List {- base -}++import qualified Music.Theory.Array.Cell_Ref as T {- hmt -}+import qualified Music.Theory.Array.Direction as T {- hmt -}+import qualified Music.Theory.Graph.Dot as T {- hmt -}+import qualified Music.Theory.Graph.FGL as T {- hmt -}+import qualified Music.Theory.List as T {- hmt -}+import qualified Music.Theory.Tuple as T {- hmt -}++gen_graph :: Ord v => [T.DOT_ATTR] -> T.GR_PP v e -> [T.EDGE_L v e] -> [String]+gen_graph opt pp es = T.g_to_udot opt pp (T.g_from_edges_l es)++gen_graph_ul :: Ord v => [T.DOT_ATTR] -> (v -> String) -> [T.EDGE v] -> [String]+gen_graph_ul opt pp es = T.g_to_udot opt (T.gr_pp_lift_node_f pp) (T.g_from_edges es)++gen_digraph :: Ord v => [T.DOT_ATTR] -> T.GR_PP v e -> [T.EDGE_L v e] -> [String]+gen_digraph opt pp es = T.g_to_dot T.G_DIGRAPH opt pp Nothing (T.g_from_edges_l es)++type G = (T.GRAPH String,[T.DOT_ATTR],FilePath)++-- * E+g1 :: G+g1 =+ let c1 = words "A1 B2 A3 B4 C3 B2 C1 D2 C3 D4 D3 D2 D1 C2 D3 C4 B3 C2 B1 A2 B3 A4 A3 A2 A1"+ o1 = [("node:shape","circle"),("edge:len","1.5"),("edge:fontsize","7")]+ in (T.adj2 1 c1,o1,"E")++-- * D+g2 :: G+g2 =+ let c2' = words "B3 C2 = C3 B2 A1 = A2 B1 C2 = C1 B2 A3 = A2 B3 C3 C2 B2 B3 ~ C3 ~ C2 C1 == C3 C2 C1 B1 B2 C2 ~ C1 ~ B1 A1 C1 B1 A1 A2 B2 B1 ~ A1 ~ A2 A3 == A1 A2 A3 B3 B2 A2 ~ A3 ~ B3 C3 C3 ~~ C1 ~~ A1 ~~ A3 A3 B3"+ c2 = filter T.is_cell_ref c2'+ o2 = [("node:shape","circle"),("edge:len","3"),("edge:fontsize","7")]+ in (T.adj2 1 c2,o2,"D")++-- * A+g4 :: G+g4 =+ let c4' = words "B1 C2 C3 B3 B2 C2 ~~ C3 C2 ~~ C1 C2 C2 B3 A3 A2 B2 B3 ~~ A3 B3 ~~ C3 B3 B3 A2 A1 B1 B2 A2 ~~ A1 A2 ~~ A3 A2 A2 B1 C1 C2 B2 B1 ~~ C1 B1 ~~ A1 B1 B1"+ c4 = filter T.is_cell_ref c4'+ o4 = [("node:shape","circle"),("edge:len","3"),("edge:fontsize","7")]+ in (T.adj2 1 c4,o4,"A")++g6 :: G+g6 =+ let c6' = words "B1 C2 B2 C1 B1 A2 B2 A1 B1 B2 B3 B3 B3 B3 B2 B1 B0 B0 B0 B0 B1 C1 ~~~ C2 B2 B2 B2 A2 ~~~ A1 B1 B1 B1"+ c6 = filter T.is_cell_ref c6'+ o6 = [("node:shape","circle"),("edge:len","3"),("edge:fontsize","7")]+ in (T.adj2 1 c6,o6,"B")++g8 :: G+g8 =+ let c8' = words "C2 B1 B1 A2 ~ (04) B1 B2 B3 ~ (08) C2 B3 B3 A2 ~ (13) B3 B2 A2 (17) A3 A3 B2 C1 C1 C2 B2 B1 ~ (23) C2 B2 A2 A1 A1 B2 C3 C3 C2"+ c8 = filter T.is_cell_ref c8'+ o8 = [("node:shape","circle"),("edge:len","3"),("edge:fontsize","7")]+ in (T.adj2 1 c8,o8,"C")++g9 :: G+g9 =+ let d9' = ("E6",words "U R D LL (03/D6) U R R U L D D LL (11/C6) U R R U U R D L L D D LL (22/B6) U R R U U R R U L D D L L D D LL (38/A6) U R R U U R R U U R D L L D D L L D D LUU (56/A4) R R U U R R U L D D L L D D L UU (71/A3) R R U U R D L L D D L UU (83/A2) R R U L D D L UU (91/A1) R D L")+ d9 = (fst d9',filter T.is_direction (snd d9'))+ c9 = T.dir_seq_to_cell_seq d9+ o9 = [("node:shape","circle"),("edge:len","1.5"),("edge:fontsize","7")]+ in (T.adj2 1 c9,o9,"F")++g10 :: G+g10 =+ let d10' = ("B7",words "U R LL (03/A6) R R U L D D LUU (10/A5) R R U L D D L UU (18/A4) R R U L D D L UU (26/A3) R R U L D D L UU (34/A2) R R U L D D L UU (41/A1) R D L")+ d10 = (fst d10',filter T.is_direction (snd d10'))+ c10 = T.dir_seq_to_cell_seq d10+ e10 = T.adj2 1 c10+ o10 = [("node:shape","circle"),("edge:len","1.5"),("edge:fontsize","7")]+ in (e10,o10,"G")++g11 :: G+g11 =+ let d11' = ("C3",words "DR DDL UUR U L (05/C3) DL DDR UUL U R (10/C3) D D U UL UUR DDL (16/B3) DL R U (18/B3) L DR R (21/C4) UR UUL DDR DR L (26/D4) U R DL L U (31/C3) U D (33/C3) R UUR DDDDD UUL L . (40/C4) L DDL UUUUU DDR R (44/C3)")+ d11 = (fst d11',filter T.is_direction (snd d11'))+ c11 = T.dir_seq_to_cell_seq d11+ e11 = T.adj2 1 c11+ o11 = [("node:shape","circle"),("edge:len","1.5"),("edge:fontsize","7")]+ in (e11,o11,"H")++g12 :: G+g12 =+ let d12' = ("C2",words "DR UR (02/E2) L DL UL L (06/A2) DR UR UR DR (10/E2) L UL DL L (14/A2) UR DR (16/C2)")+ d12 = (fst d12',filter T.is_direction (snd d12'))+ c12 = T.dir_seq_to_cell_seq d12+ e12 = T.adj2 1 c12+ o12 = [("node:shape","circle"),("edge:len","1.5"),("edge:fontsize","7")]+ in (e12,o12,"I")++g13 :: G+g13 =+ let d13' = ("B3",words "U D D U R DDL UUL R (07/C3) R UU DDL L UU DDR (11/C3)")+ d13 = (fst d13',filter T.is_direction (snd d13'))+ c13 = T.dir_seq_to_cell_seq d13+ e13 = T.adj2 1 c13+ o13 = [("node:shape","circle"),("edge:len","1.5"),("edge:fontsize","7")]+ in (e13,o13,"J")++g_all :: [G]+g_all = [g1,g2,g4,g6,g8,g9,g10,g11,g12,g13]++-- G = unlabeled, GL = labeled+-- GC = collated, GF = filtered (unique edges)+-- GD = directed+wr :: G -> IO ()+wr (e,o,nm) = do+ let mk_nm ty = "/home/rohan/sw/hmt/data/dot/deacon/" ++ nm ++ "_" ++ ty ++ ".dot"+ wr_f ty g = writeFile (mk_nm ty) (unlines g)+ wr_f "G" (gen_graph_ul o id e)+ wr_f "GL" (gen_graph o T.gr_pp_id_show (T.e_label_seq e))+ wr_f "GC" (gen_graph o T.gr_pp_id_br_csl (T.e_collate_normalised_l (T.e_label_seq e)))+ wr_f "GF" (gen_graph_ul o id (nub (map T.t2_sort e)))+ wr_f "GD" (gen_digraph o T.gr_pp_id_br_csl (T.e_collate_normalised_l (T.e_label_seq e)))+{-+ let o' = ("graph:layout","fdp") : o+ wr_f "GC_" (gen_graph o' T.gr_pp_id_br_csl (T.e_collate_normalised_l (T.e_label_seq e)))+-}++wr_all :: IO ()+wr_all = mapM_ wr g_all
+ Music/Theory/Graph/Dot.hs view
@@ -0,0 +1,131 @@+-- | Graph (dot) functions.+module Music.Theory.Graph.Dot where++import Data.Char {- base -}+import Data.List {- base -}++import qualified Data.Graph.Inductive.Graph as G {- fgl -}+import qualified Data.Graph.Inductive.PatriciaTree as G {- fgl -}++import qualified Music.Theory.List as T {- hmt -}++-- * UTIL++-- | Separate at element.+--+-- > sep1 ':' "graph:layout"+sep1 :: Eq t => t -> [t] -> ([t],[t])+sep1 e l =+ case break (== e) l of+ (p,_:q) -> (p,q)+ _ -> error "sep1"++-- | Quote /s/ if it includes white space.+--+-- > map maybe_quote ["abc","a b c"] == ["abc","\"a b c\""]+maybe_quote :: String -> String+maybe_quote s = if any isSpace s then concat ["\"",s,"\""] else s++-- | Left biased union of association lists /p/ and /q/.+--+-- > assoc_union [(5,"a"),(3,"b")] [(5,"A"),(7,"C")] == [(5,"a"),(3,"b"),(7,"C")]+assoc_union :: Eq k => [(k,v)] -> [(k,v)] -> [(k,v)]+assoc_union p q =+ let p_k = map fst p+ q' = filter ((`notElem` p_k) . fst) q+ in p ++ q'++-- * ATTR++-- | area:opt (area = graph|node|edge)+type DOT_KEY = String+type DOT_OPT = String+type DOT_VALUE = String+type DOT_ATTR = (DOT_OPT,DOT_VALUE)+type DOT_ATTR_SET = (String,[DOT_ATTR])++-- > dot_key_sep "graph:layout"+dot_key_sep :: String -> (String,String)+dot_key_sep = sep1 ':'++dot_attr_pp :: DOT_ATTR -> String+dot_attr_pp (lhs,rhs) = concat [lhs,"=",maybe_quote rhs]++dot_attr_set_pp :: DOT_ATTR_SET -> String+dot_attr_set_pp (ty,opt) = concat [ty," [",intercalate "," (map dot_attr_pp opt),"];"]++dot_attr_collate :: [DOT_ATTR] -> [DOT_ATTR_SET]+dot_attr_collate opt =+ let f (k,v) = let (ty,nm) = dot_key_sep k in (ty,(nm,v))+ c = map f opt+ in T.collate c++dot_attr_ext :: [DOT_ATTR] -> [DOT_ATTR] -> [DOT_ATTR]+dot_attr_ext = assoc_union++-- > map dot_attr_set_pp (dot_attr_collate dot_attr_def)+dot_attr_def :: [DOT_ATTR]+dot_attr_def =+ [("graph:layout","neato")+ ,("graph:epsilon","0.000001")+ ,("node:shape","plaintext")+ ,("node:fontsize","10")+ ,("node:fontname","century schoolbook")]++-- * GRAPH++-- | Graph pretty-printer, (node->shape,node->label,edge->label)+type GR_PP v e = (v -> Maybe String,v -> Maybe String,e -> Maybe String)++gr_pp_lift_node_f :: (v -> String) -> GR_PP v e+gr_pp_lift_node_f f = (const Nothing, Just . f, const Nothing)++gr_pp_id_show :: Show e => GR_PP String e+gr_pp_id_show = (const Nothing,Just . id,Just . show)++-- | br = brace, csl = comma separated list+br_csl_pp :: Show t => [t] -> String+br_csl_pp l =+ case l of+ [e] -> show e+ _ -> T.bracket ('{','}') (intercalate "," (map show l))++gr_pp_id_br_csl :: Show e => GR_PP String [e]+gr_pp_id_br_csl = (const Nothing,Just . id,Just . br_csl_pp)++-- | Graph type, directed or un-directed.+data G_TYPE = G_DIGRAPH | G_UGRAPH++g_type_to_string :: G_TYPE -> String+g_type_to_string ty =+ case ty of+ G_DIGRAPH -> "digraph"+ G_UGRAPH -> "graph"++g_type_to_edge_symbol :: G_TYPE -> String+g_type_to_edge_symbol ty =+ case ty of+ G_DIGRAPH -> " -> "+ G_UGRAPH -> " -- "++-- | Vertex position function.+type POS_FN v = (v -> (Int,Int))++g_to_dot :: G_TYPE -> [DOT_ATTR] -> GR_PP v e -> Maybe (POS_FN v) -> G.Gr v e -> [String]+g_to_dot g_typ opt (n_sh,n_pp,e_pp) pos_f gr =+ let p_f (c,r) = concat [",pos=\"",show (c * 100),",",show (r * 100),"\""]+ l_f p x = concat [" [label=\"",x,"\"",p,"]"]+ n_f (k,n) = let p = maybe "" (\f -> p_f (f n)) pos_f+ p' = maybe p (\z -> p ++ ",shape=\"" ++ z ++ "\"") (n_sh n)+ a = maybe "" (l_f p') (n_pp n)+ in concat [show k,a,";"]+ e_f (lhs,rhs,e) = let l = maybe "" (l_f "") (e_pp e)+ in concat [show lhs,g_type_to_edge_symbol g_typ,show rhs,l,";"]+ in concat [[g_type_to_string g_typ," g {"]+ ,map dot_attr_set_pp (dot_attr_collate (assoc_union opt dot_attr_def))+ ,map n_f (G.labNodes gr)+ ,map e_f (G.labEdges gr)+ ,["}"]]++g_to_udot :: [DOT_ATTR] -> GR_PP v e -> G.Gr v e -> [String]+g_to_udot o pp = g_to_dot G_UGRAPH o pp Nothing
+ Music/Theory/Graph/FGL.hs view
@@ -0,0 +1,141 @@+-- | Graph (fgl) functions.+module Music.Theory.Graph.FGL where++import Data.List {- base -}+import Data.Maybe {- base -}++import qualified Data.Map as M {- containers -}++import qualified Data.Graph.Inductive.Graph as G {- fgl -}+import qualified Data.Graph.Inductive.Query as G {- fgl -}+import qualified Data.Graph.Inductive.PatriciaTree as G {- fgl -}++import qualified Control.Monad.Logic as L {- logict -}++import qualified Music.Theory.List as T {- hmt -}++-- | Synonym for 'G.noNodes'.+g_degree :: G.Gr v e -> Int+g_degree = G.noNodes++-- | 'G.subgraph' of each of 'G.components'.+g_partition :: G.Gr v e -> [G.Gr v e]+g_partition gr = map (\n -> G.subgraph n gr) (G.components gr)++-- | Find first 'G.Node' with given label.+g_node_lookup :: (Eq v,G.Graph gr) => gr v e -> v -> Maybe G.Node+g_node_lookup gr l = fmap fst (find ((== l) . snd) (G.labNodes gr))++-- | Erroring variant.+g_node_lookup_err :: (Eq v,G.Graph gr) => gr v e -> v -> G.Node+g_node_lookup_err gr = fromMaybe (error "g_node_lookup") . g_node_lookup gr++-- | Set of nodes with given labels, plus all neighbours of these nodes.+-- (impl = implications)+ug_node_set_impl :: (Eq v,G.DynGraph gr) => gr v e -> [v] -> [G.Node]+ug_node_set_impl gr nl =+ let n = map (g_node_lookup_err gr) nl+ in nub (sort (n ++ concatMap (G.neighbors gr) n))++-- * Hamiltonian++type G_NODE_SEL_F v e = G.Gr v e -> G.Node -> [G.Node]++-- | 'L.msum' '.' 'map' 'return'.+ml_from_list :: L.MonadLogic m => [t] -> m t+ml_from_list = L.msum . map return++-- | Use /sel_f/ of 'G.pre' for directed graphs and 'G.neighbors' for undirected.+g_hamiltonian_path_ml :: L.MonadLogic m => G_NODE_SEL_F v e -> G.Gr v e -> G.Node -> m [G.Node]+g_hamiltonian_path_ml sel_f gr =+ let n_deg = g_degree gr+ recur r c =+ if length r == n_deg - 1+ then return (c:r)+ else do i <- ml_from_list (sel_f gr c)+ L.guard (i `notElem` r)+ recur (c:r) i+ in recur []++-- > map (L.observeAll . ug_hamiltonian_path_ml_0) (g_partition gr)+ug_hamiltonian_path_ml_0 :: L.MonadLogic m => G.Gr v e -> m [G.Node]+ug_hamiltonian_path_ml_0 gr = g_hamiltonian_path_ml G.neighbors gr (G.nodes gr !! 0)++-- * G (from edges)++-- | Edge, no label.+type EDGE v = (v,v)++-- | Graph as set of edges.+type GRAPH v = [EDGE v]++-- | Edge, with label.+type EDGE_L v l = (EDGE v,l)++-- | Graph as set of labeled edges.+type GRAPH_L v l = [EDGE_L v l]++-- | Generate a graph given a set of labelled edges.+g_from_edges_l :: (Eq v,Ord v) => GRAPH_L v e -> G.Gr v e+g_from_edges_l e =+ let n = nub (concatMap (\((lhs,rhs),_) -> [lhs,rhs]) e)+ n_deg = length n+ n_id = [0 .. n_deg - 1]+ m = M.fromList (zip n n_id)+ m_get k = M.findWithDefault (error "g_from_edges: m_get") k m+ e' = map (\((lhs,rhs),label) -> (m_get lhs,m_get rhs,label)) e+ in G.mkGraph (zip n_id n) e'++-- | Variant that supplies '()' as the (constant) edge label.+--+-- > let g = G.mkGraph [(0,'a'),(1,'b'),(2,'c')] [(0,1,()),(1,2,())]+-- > in g_from_edges_ul [('a','b'),('b','c')] == g+g_from_edges :: Ord v => GRAPH v -> G.Gr v ()+g_from_edges = let f e = (e,()) in g_from_edges_l . map f++-- * Edges++-- | Label sequence of edges starting at one.+e_label_seq :: [EDGE v] -> [EDGE_L v Int]+e_label_seq = map (\(k,e) -> (e,k)) . zip [1..]++-- | Normalised undirected labeled edge (ie. order nodes).+e_normalise_l :: Ord v => EDGE_L v l -> EDGE_L v l+e_normalise_l ((p,q),r) = ((min p q,max p q),r)++-- | Collate labels for edges that are otherwise equal.+e_collate_l :: Ord v => [EDGE_L v l] -> [EDGE_L v [l]]+e_collate_l = T.collate++-- | 'e_collate_l' of 'e_normalise_l'.+e_collate_normalised_l :: Ord v => [EDGE_L v l] -> [EDGE_L v [l]]+e_collate_normalised_l = e_collate_l . map e_normalise_l++-- | Apply predicate to universe of possible edges.+e_univ_select_edges :: (t -> t -> Bool) -> [t] -> [EDGE t]+e_univ_select_edges f l = [(p,q) | p <- l, q <- l, f p q]++-- | Consider only edges (p,q) where p < q.+e_univ_select_u_edges :: Ord t => (t -> t -> Bool) -> [t] -> [EDGE t]+e_univ_select_u_edges f = let g p q = p < q && f p q in e_univ_select_edges g++-- | Sequence of connected vertices to edges.+--+-- > e_path_to_edges "abcd" == [('a','b'),('b','c'),('c','d')]+e_path_to_edges :: [t] -> [EDGE t]+e_path_to_edges = T.adj2 1++-- | Undirected edge equality.+e_undirected_eq :: Eq t => EDGE t -> EDGE t -> Bool+e_undirected_eq (a,b) (c,d) = (a == c && b == d) || (a == d && b == c)++elem_by :: (p -> q -> Bool) -> p -> [q] -> Bool+elem_by f = any . f++-- | Is the sequence of vertices a path at the graph, ie. are all+-- adjacencies in the sequence edges.+e_is_path :: Eq t => GRAPH t -> [t] -> Bool+e_is_path e sq =+ case sq of+ p:q:sq' -> elem_by e_undirected_eq (p,q) e && e_is_path e (q:sq')+ _ -> True
+ Music/Theory/Graph/Johnson_2014.hs view
@@ -0,0 +1,290 @@+-- | Tom Johnson. /Other Harmony: Beyond Tonal and Atonal/. Editions 75, 2014.+module Music.Theory.Graph.Johnson_2014 where++import Control.Monad {- base -}+import Data.List {- base -}+import qualified Data.Map as M {- containers -}+import Data.Maybe {- base -}++import qualified Music.Theory.Combinations as T {- hmt -}+import qualified Music.Theory.Graph.Dot as T {- hmt -}+import qualified Music.Theory.Graph.FGL as T {- hmt -}+import qualified Music.Theory.Key as T {- hmt -}+import qualified Music.Theory.List as T {- hmt -}+import qualified Music.Theory.Pitch.Note as T {- hmt -}+import qualified Music.Theory.Tuning as T {- hmt -}+import qualified Music.Theory.Tuning.Euler as T {- hmt -}+import qualified Music.Theory.Z.SRO as T {- hmt -}++-- * Common++type Z12 = Int++mod12 :: Integral a => a -> a+mod12 n = n `mod` 12++dif :: Num a => (a, a) -> a+dif = uncurry (-)++absdif :: Num a => (a, a) -> a+absdif = abs . dif++-- | interval (0,11) to interval class (0,6)+i_to_ic :: (Num a, Ord a) => a -> a+i_to_ic n = if n > 6 then 12 - n else n++p2_and :: (t -> u -> Bool) -> (t -> u -> Bool) -> t -> u -> Bool+p2_and p q i j = p i j && q i j++-- | degree of intersection+doi :: Eq t => [t] -> [t] -> Int+doi p = length . intersect p++doi_of :: Eq t => Int -> [t] -> [t] -> Bool+doi_of n p = (==) n . doi p++-- | The sum of the pointwise absolute difference.+loc_dif :: Num t => [t] -> [t] -> t+loc_dif p q = let f i j = abs (i - j) in sum (zipWith f p q)++loc_dif_of :: (Eq t, Num t) => t -> [t] -> [t] -> Bool+loc_dif_of n p q = loc_dif p q == n++loc_dif_in :: (Eq t, Num t) => [t] -> [t] -> [t] -> Bool+loc_dif_in n p q = loc_dif p q `elem` n++-- | The number of places that are, pointwise, not equal.+--+-- > loc_dif_n "test" "pest" == 1+loc_dif_n :: (Eq t,Num i) => [t] -> [t] -> i+loc_dif_n p q =+ let f i j = if i == j then 0 else 1+ in sum (zipWith f p q)++loc_dif_n_of :: Eq t => Int -> [t] -> [t] -> Bool+loc_dif_n_of n p q = loc_dif_n p q == n++-- > min_vl [6,11,13] [6,10,14] == 2+min_vl :: (Num a,Ord a) => [a] -> [a] -> a+min_vl p q =+ let f x = sum (map absdif (zip p x))+ in minimum (map f (permutations q))++min_vl_of :: (Num a, Ord a) => a -> [a] -> [a] -> Bool+min_vl_of n p q = min_vl p q == n++min_vl_in :: (Num a, Ord a) => [a] -> [a] -> [a] -> Bool+min_vl_in n p q = min_vl p q `elem` n++combinations2 :: Ord t => [t] -> [(t, t)]+combinations2 p = [(i,j) | i <- p, j <- p, i < j]++set_pp :: Show t => [t] -> String+set_pp = intercalate "," . map show++-- * Map++m_get :: Ord k => M.Map k v -> k -> v+m_get m i = fromMaybe (error "get") (M.lookup i m)++-- | degree of intersection+m_doi_of :: M.Map Int [Z12] -> Int -> Int -> Int -> Bool+m_doi_of m n p q = doi_of n (m_get m p) (m_get m q)++-- * Graph++gen_graph_ul :: Ord v => [T.DOT_ATTR] -> (v -> String) -> [T.EDGE v] -> [String]+gen_graph_ul opt pp es = T.g_to_udot opt (T.gr_pp_lift_node_f pp) (T.g_from_edges es)++gen_graph_ul_ty :: Ord v => String -> (v -> String) -> [T.EDGE v] -> [String]+gen_graph_ul_ty ty = gen_graph_ul [("graph:layout",ty)]++gen_flt_graph :: (Ord t, Show t) => [T.DOT_ATTR] -> ([t] -> [t] -> Bool) -> [[t]] -> [String]+gen_flt_graph o f p = gen_graph_ul o set_pp (T.e_univ_select_u_edges f p)++-- * P.12++-- | <http://localhost/rd/?t=j&e=2016-04-04.md>+p12_euler_plane :: T.Euler_Plane Rational+p12_euler_plane =+ let f = T.fold_ratio_to_octave_err+ l1 = T.tun_seq 4 (3/2) (f (1 * 2/3 * 5/4))+ l2 = T.tun_seq 5 (3/2) (f (1 * 2/3 * 2/3))+ l3 = T.tun_seq 3 (3/2) (f (1 * 2/3 * 4/5))+ (c1,c2) = T.euler_align_rat (5/4,5/4) (l1,l2,l3)+ in ([l1,l2,l3],c1 ++ c2)++p12_euler_plane_gr :: [String]+p12_euler_plane_gr = T.euler_plane_to_dot_rat (0,True) p12_euler_plane++-- * P.14++p14_edges :: [(T.Key,T.Key)]+p14_edges =+ let univ = [0::Int .. 11]+ trs n = map (mod12 . (+ n))+ e_par = zip univ univ+ e_rel = zip univ (trs 9 univ)+ e_med = zip univ (trs 4 univ)+ del_par = [10]+ del_rel = [5,6]+ del_med = [2,5,8,11]+ rem_set r = filter (\(lhs,_) -> lhs `notElem` r)+ pc_to_key m pc = let Just (n,a) = T.pc_to_note_alteration_ks pc in (n,a,m)+ e_lift (lhs,rhs) = (pc_to_key T.Major_Mode lhs,pc_to_key T.Minor_Mode rhs)+ e_mod = concat [rem_set del_par e_par,rem_set del_rel e_rel,rem_set del_med e_med]+ in map e_lift e_mod++p14_gr :: [String]+p14_gr =+ let opt = [("graph:start","168732")]+ pp = T.gr_pp_lift_node_f T.key_lc_uc_pp+ gr = T.g_from_edges p14_edges+ in T.g_to_udot opt pp gr++-- * P.31++p31_f_4_22 :: [Z12]+p31_f_4_22 = [0,2,4,7]++p31_e_set :: [([Z12],[Z12])]+p31_e_set = T.e_univ_select_u_edges (doi_of 3) (map sort (T.z_sro_ti_related mod12 p31_f_4_22))++p31_gr :: [String]+p31_gr = gen_graph_ul [] set_pp p31_e_set++-- * P.114++p114_f_3_7 :: [Z12]+p114_f_3_7 = [0,2,5]++p114_mk_gr :: Double -> ([Z12] -> [Z12] -> Bool) -> [String]+p114_mk_gr el flt =+ let o = [("node:shape","box")+ ,("edge:len",show el)]+ in gen_flt_graph o flt (map sort (T.z_sro_ti_related mod12 p114_f_3_7))++p114_gr_set :: [(String,[String])]+p114_gr_set =+ [("p114.1.dot",p114_mk_gr 2.5 (doi_of 2))+ ,("p114.2.dot"+ ,let o = [("edge:len","1.25")]+ in gen_flt_graph o (loc_dif_of 1) (T.combinations 3 [1::Int .. 6]))+ ,("p114.3.dot",p114_mk_gr 1.5 (loc_dif_n_of 1))+ ,("p114.4.dot",p114_mk_gr 1.5 (loc_dif_of 1))+ ,("p114.5.dot",p114_mk_gr 1.5 (loc_dif_of 2))+ ,("p114.6.dot",p114_mk_gr 1.5 (loc_dif_in [1,2]))+ ,("p114.7.dot",p114_mk_gr 1.5 (loc_dif_in [1,2,3]))+ ,("p114.8.dot",p114_mk_gr 1.5 (min_vl_in [1,2,3]))+ ,("p114.9.dot",p114_mk_gr 2.0 (min_vl_in [1,2,3,4]))+ ]++-- * P.125++p125_gr :: [String]+p125_gr =+ let t :: [[Int]]+ t = [[p,q,r] | p <- [0 .. 11], q <- [0 .. 11], r <- [0 ..11], q > p, r > q]+ c = T.collate (zip (map sum t) t)+ with_h n = lookup n c+ ch = fromJust (liftM2 (++) (with_h 15) (with_h 16))+ in gen_graph_ul [] set_pp (T.e_univ_select_u_edges (doi_of 2) ch)++-- * P.131++p131_gr :: [String]+p131_gr =+ let c = let u = [6::Int .. 14]+ in [[p,q,r] | p <- u, q <- u, r <- u, q > p, r > q, p + q + r == 30]+ in gen_graph_ul [] set_pp (T.e_univ_select_u_edges (min_vl_of 2) c)++-- * P.148++p148_mk_gr :: ([Int] -> [Int] -> Bool) -> [String]+p148_mk_gr f =+ let mid_set_pp :: [Int] -> String+ mid_set_pp = concatMap show . take 3 . drop 1+ i_seq :: Num i => [[i]]+ i_seq = permutations [1,2,3,4]+ p_seq :: (Ord i,Num i) => [[i]]+ p_seq = sort (map (T.dx_d 0) i_seq)+ in gen_graph_ul [("edge:len","1.75")] mid_set_pp (T.e_univ_select_u_edges f p_seq)++p148_gr_set :: [(String,[String])]+p148_gr_set =+ [("p148.0.dot",p148_mk_gr (doi_of 4))+ ,("p148.1.dot",p148_mk_gr (min_vl_in [1]))+ ,("p148.2.dot",p148_mk_gr (min_vl_in [1,2]))+ ,("p148.3.dot",p148_mk_gr (p2_and (doi_of 4) (min_vl_in [1])))+ ,("p148.4.dot",p148_mk_gr (p2_and (doi_of 4) (min_vl_in [1,2])))+ ,("p148.5.dot",p148_mk_gr (loc_dif_n_of 1))+ ,("p148.6.dot",p148_mk_gr (loc_dif_of 1))+ ]++-- * P.162++p162_gr :: [String]+p162_gr =+ let n = [0::Int,1,2,3,4,5,6,7,8]+ c = T.combinations 4 n+ ch = filter ((== 1) . (`mod` 4) . sum) c+ opt = [("graph:layout","neato")+ ,("edge:len","1.75")]+ in gen_graph_ul opt set_pp (T.e_univ_select_u_edges (doi_of 3) ch)++-- * P.172++p172_nd_map :: M.Map Int [Z12]+p172_nd_map =+ let nd_exp = map sort (T.z_sro_ti_related mod12 [0,1,3,7])+ in M.fromList (zip [0..] nd_exp)++p172_set_pp :: Int -> String+p172_set_pp = set_pp . m_get p172_nd_map++p172_gr_set :: [(String,[String])]+p172_gr_set =+ [("p172.0.dot"+ ,let nd_e_set = T.e_univ_select_u_edges (m_doi_of p172_nd_map 0) [0..23]+ in gen_graph_ul_ty "circo" p172_set_pp nd_e_set)+ ,("p172.1.dot"+ ,let nd_e_set = concatMap T.e_path_to_edges+ [[22,11,20,9,18,7,16,5,14,3,12,1,22]+ ,[23,2,13,8,19,10,21,4,15,6,17,0,23]]+ in gen_graph_ul_ty "circo" p172_set_pp nd_e_set)]++-- * P.177++-- > map (partition_ic 4) p_set+-- > map (partition_ic 6) p_set+partition_ic :: (Num t, Ord t, Show t) => t -> [t] -> ([t], [t])+partition_ic n p =+ case find ((== n) . i_to_ic . absdif) (combinations2 p) of+ Just (i,j) -> let q = sort [i,j] in (q,sort (p \\ q))+ Nothing -> error (show ("partition_ic",n,p))++p177_gr_set :: [(String,[String])]+p177_gr_set =+ let p_set = concatMap (T.z_sro_ti_related mod12) [[0::Int,1,4,6],[0,1,3,7]]+ in [("p177.0.dot",gen_graph_ul [] set_pp (map (partition_ic 4) p_set))+ ,("p177.1.dot",gen_graph_ul_ty "circo" set_pp (map (partition_ic 6) p_set))+ ,("p177.2.dot"+ ,let gr_pp = T.gr_pp_lift_node_f set_pp+ gr = T.g_from_edges (map (partition_ic 6) p_set)+ in T.g_to_udot [("edge:len","1.5")] gr_pp gr)]++-- * IO++wr_graphs :: IO ()+wr_graphs = do+ let f (nm,gr) = writeFile ("/home/rohan/sw/hmt/data/dot/tj_oh_" ++ nm) (unlines gr)+ f ("p012.dot",p12_euler_plane_gr)+ f ("p014.dot",p14_gr)+ f ("p031.dot",p31_gr)+ mapM_ f p114_gr_set+ f ("p125.dot",p125_gr)+ f ("p131.dot",p131_gr)+ mapM_ f p148_gr_set+ f ("p162.dot",p162_gr)+ mapM_ f p172_gr_set+ mapM_ f p177_gr_set
+ Music/Theory/IO.hs view
@@ -0,0 +1,34 @@+-- | "System.IO" related functions.+module Music.Theory.IO where++import qualified Data.ByteString as B {- bytestring -}+import qualified Data.Text as T {- text -}+import qualified Data.Text.Encoding as T {- text -}+import qualified Data.Text.IO as T {- text -}+import qualified System.Directory as D {- directory -}++-- | 'T.decodeUtf8' of 'B.readFile'.+read_file_utf8_text :: FilePath -> IO T.Text+read_file_utf8_text = fmap T.decodeUtf8 . B.readFile++-- | Read (strictly) a UTF-8 encoded text file, implemented via "Data.Text".+read_file_utf8 :: FilePath -> IO String+read_file_utf8 = fmap T.unpack . read_file_utf8_text++-- | 'read_file_utf8', or a default value if the file doesn't exist.+read_file_utf8_or :: String -> FilePath -> IO String+read_file_utf8_or def f = do+ x <- D.doesFileExist f+ if x then read_file_utf8 f else return def++-- | Write UTF8 string as file, via "Data.Text".+write_file_utf8 :: FilePath -> String -> IO ()+write_file_utf8 fn = B.writeFile fn . T.encodeUtf8 . T.pack++-- | 'readFile' variant using 'Text' for @ISO 8859-1@ (Latin 1) encoding.+read_file_iso_8859_1 :: FilePath -> IO String+read_file_iso_8859_1 = fmap (T.unpack . T.decodeLatin1) . B.readFile++-- | 'readFile' variant using 'Text' for local encoding.+read_file_locale :: FilePath -> IO String+read_file_locale = fmap T.unpack . T.readFile
+ Music/Theory/Instrument/Names.hs view
@@ -0,0 +1,114 @@+module Music.Theory.Instrument.Names where++import Data.List.Split {- split -}++-- (family,abbreviations,names,transpositions)+instrument_db' :: [(String,String,String,String)]+instrument_db' =+ [("br","b.tbn","bass trombone","")+ ,("br","b.tuba","bass tuba","")+ ,("br","euph","euphonium","")+ ,("br","hn","french horn","F")+ ,("br","tbn;trm","trombone","")+ ,("br","tb;tba","tuba","")+ ,("br","tpt","trumpet","B♭")+ ,("br","t.tbn","tenor trombone","")+ ,("br","crt","cornet","")+ ,("br","fgh;flhn","flugel horn","")+ ,("br","p.tpt","piccolo trumpet","")+ ,("el","cd","compact disc","")+ ,("el","el;elec","electronics","")+ ,("el","tp","tape","")+ ,("el","om","ondes martenot","")+ ,("kb","h;hrm","harmonium","")+ ,("kb","e.pf","electric piano","")+ ,("kb","p;pf;pno","piano;pianoforte","")+ ,("kb","o;or;org","organ","")+ ,("kb","kb;kbd","keyboard","")+ ,("kb","cel","celeste","")+ ,("kb","clvd","clavichord","")+ ,("kb","hpd;hpcd","harpsichord","")+ ,("kb","syn","synthesiser","")+ ,("pc","bd","bass drum","")+ ,("pc","btl","bottle","")+ ,("pc","cast","castanets","")+ ,("pc","cbell","cow-bell","")+ ,("pc","bell","bell","chimes")+ ,("pc","clv","clave","")+ ,("pc","crot","crotales","")+ ,("pc","cym","cymbals","")+ ,("pc","dm","drum","")+ ,("pc","gl;glsp","glockenspiel","")+ ,("pc","mcas","maracas","")+ ,("pc","met.bl","metal block","")+ ,("pc","mr;mar","marimba","")+ ,("pc","sd","side drum","")+ ,("pc","sn.dm","snare drum","")+ ,("pc","sus.cym","suspended cymbal","")+ ,("pc","tamb","tambourine","")+ ,("pc","tam","tam tam","")+ ,("pc","t.bells","tubular bells","")+ ,("pc","td","tenor drum","")+ ,("pc","tri;tgl","triangle","")+ ,("pc","tm;timp","timpani","")+ ,("pc","tpl.bl","temple blocks","")+ ,("pc","vb;vib","vibraphone","")+ ,("pc","wdbl","wood block","")+ ,("pc","xyl","xylophone","")+ ,("str","va;vla","viola","")+ ,("str","vc;vlc","cello;violoncello","")+ ,("str","vn;vln","violin","")+ ,("str","cb","contrabass","")+ ,("str","db","double bass","")+ ,("str","vda","viola d'amore","")+ ,("str","b.gtr","bass guitar","")+ ,("str","e.gtr","electric guitar","")+ ,("str","gtr","guitar","")+ ,("str","","lute","")+ ,("str","zith","zither","")+ ,("str","hp","harp","")+ ,("str","dulc","dulcimer","")+ ,("str","mand","mandolin","")+ ,("vc","a;alt","alto","")+ ,("vc","b;bass","bass","")+ ,("vc","mz;mez","mezzo-soprano","")+ ,("vc","n;nar","narrator","")+ ,("vc","s;sop","soprano","")+ ,("vc","t;tn","tenor","")+ ,("vc","v;vc;voc","voice","")+ ,("vc","ch","chorus","")+ ,("vc","ctral","contralto","")+ ,("vc","ctrbs","contrabass","")+ ,("vc","bar","baritone","")+ ,("vc","b.bar","bass baritone","")+ ,("ww","b.cl","bass clarinet","")+ ,("ww","cb.cl","contrabass clarinet","")+ ,("ww","c;cl","clarinet","B♭")+ ,("ww","a.fl","alto flute","G")+ ,("ww","b.fl","bass flute","C")+ ,("ww","bn;bsn","bassoon","")+ ,("ww","f;fl","flute","")+ ,("ww","hb;htb","hautbois","")+ ,("ww","o;ob","oboe","")+ ,("ww","p;picc","piccolo","")+ ,("ww","ca","cor anglais","")+ ,("ww","c.bn","contrabassoon","")+ ,("ww","a.sax","alto saxophone","E♭")+ ,("ww","b.sax","baritone saxophone","E♭")+ ,("ww","b.ob","bass oboe","")+ ,("ww","cfg","contrafagotto","")+ ,("ww","eh;en.hn","english horn","")+ ,("ww","fg","fagotto","")+ ,("ww","rec","recorder","")+ ,("ww","sax","saxophone","")+ ,("ww","s.sax","soprano saxophone","B♭")+ ,("ww","t.sax","tenor saxophone","B♭")+ ,("ww","oca","ocarina","")+ ]++-- (family,[abbreviations],[names],[transpositions])+instrument_db :: [(String,[String],[String],[String])]+instrument_db =+ let sep = splitOn ";"+ f (fm,ab,nm,tr) = (fm,sep ab,sep nm,sep tr)+ in map f instrument_db'
Music/Theory/Interval.hs view
@@ -4,8 +4,9 @@ import Data.List {- base -} import Data.Maybe {- base -} -import Music.Theory.Pitch-import Music.Theory.Pitch.Note+import qualified Music.Theory.Ord as T+import qualified Music.Theory.Pitch as T+import qualified Music.Theory.Pitch.Note as T -- | Interval type or degree. data Interval_T = Unison | Second | Third | Fourth@@ -24,13 +25,13 @@ data Interval = Interval {interval_type :: Interval_T ,interval_quality :: Interval_Q ,interval_direction :: Ordering- ,interval_octave :: Octave}+ ,interval_octave :: T.Octave} deriving (Eq,Show) -- | Interval type between 'Note_T' values. -- -- > map (interval_ty C) [E,B] == [Third,Seventh]-interval_ty :: Note_T -> Note_T -> Interval_T+interval_ty :: T.Note_T -> T.Note_T -> Interval_T interval_ty n1 n2 = toEnum ((fromEnum n2 - fromEnum n1) `mod` 7) -- | Table of interval qualities. For each 'Interval_T' gives@@ -95,41 +96,17 @@ in if dir == GT then negate n - o else n + o Nothing -> error "interval_semitones" --- | Inclusive set of 'Note_T' within indicated interval. This is not--- equal to 'enumFromTo' which is not circular.------ > note_span E B == [E,F,G,A,B]--- > note_span B D == [B,C,D]--- > enumFromTo B D == []-note_span :: Note_T -> Note_T -> [Note_T]-note_span n1 n2 =- let fn x = toEnum (x `mod` 7)- n1' = fromEnum n1- n2' = fromEnum n2- n2'' = if n1' > n2' then n2' + 7 else n2'- in map fn [n1' .. n2'']---- | Invert 'Ordering', ie. 'GT' becomes 'LT' and vice versa.------ > map invert_ordering [LT,EQ,GT] == [GT,EQ,LT]-invert_ordering :: Ordering -> Ordering-invert_ordering x =- case x of- LT -> GT- EQ -> EQ- GT -> LT- -- | Determine 'Interval' between two 'Pitch'es. -- -- > interval (Pitch C Sharp 4) (Pitch D Flat 4) == Interval Second Diminished EQ 0 -- > interval (Pitch C Sharp 4) (Pitch E Sharp 5) == Interval Third Major LT 1-interval :: Pitch -> Pitch -> Interval+interval :: T.Pitch -> T.Pitch -> Interval interval p1 p2 = let c = compare p1 p2- (Pitch n1 _ o1) = p1- (Pitch n2 _ o2) = p2- p1' = pitch_to_pc p1- p2' = pitch_to_pc p2+ (T.Pitch n1 _ o1) = p1+ (T.Pitch n2 _ o2) = p2+ p1' = T.pitch_to_pc p1+ p2' = T.pitch_to_pc p2 st = (p2' - p1') `mod` 12 ty = interval_ty n1 n2 (Just qu) = interval_q ty (fromIntegral st)@@ -138,13 +115,11 @@ GT -> (interval p2 p1) { interval_direction = GT } _ -> Interval ty qu c (o2 - o1 + o_a) --- | Apply 'invert_ordering' to 'interval_direction' of 'Interval'.+-- | Apply 'T.ord_invert' to 'interval_direction' of 'Interval'. -- -- > invert_interval (Interval Third Major LT 1) == Interval Third Major GT 1 invert_interval :: Interval -> Interval-invert_interval (Interval t qu d o) =- let d' = invert_ordering d- in Interval t qu d' o+invert_interval (Interval t qu d o) = Interval t qu (T.ord_invert d) o -- | The signed difference in semitones between two 'Interval_Q' -- values when applied to the same 'Interval_T'. Can this be written@@ -185,9 +160,9 @@ -- | Transpose a 'Pitch' by an 'Interval'. -- -- > transpose (Interval Third Diminished LT 0) (Pitch C Sharp 4) == Pitch E Flat 4-pitch_transpose :: Interval -> Pitch -> Pitch+pitch_transpose :: Interval -> T.Pitch -> T.Pitch pitch_transpose i ip =- let (Pitch p_n p_a p_o) = ip+ let (T.Pitch p_n p_a p_o) = ip (Interval i_t i_q i_d i_o) = i i_d' = if i_d == GT then -1@@ -199,10 +174,10 @@ else if p_n' < p_n && i_d == LT then 1 else 0- ip' = Pitch p_n' p_a (p_o + i_o + oa)+ ip' = T.Pitch p_n' p_a (p_o + i_o + oa) st = if i_d == GT- then (pitch_to_pc ip - pitch_to_pc ip') `mod` 12- else (pitch_to_pc ip' - pitch_to_pc ip) `mod` 12+ then (T.pitch_to_pc ip - T.pitch_to_pc ip') `mod` 12+ else (T.pitch_to_pc ip' - T.pitch_to_pc ip) `mod` 12 ty = if i_d == GT then interval_ty p_n' p_n else interval_ty p_n p_n'@@ -210,14 +185,14 @@ in fromMaybe err (interval_q ty (fromIntegral st)) qd = quality_difference qu i_q * i_d' p_a' = toEnum (fromEnum p_a + (qd * 2))- in ip' { alteration = p_a' }+ in ip' {T.alteration = p_a'} -- | Make leftwards (perfect fourth) and and rightwards (perfect -- fifth) circles from 'Pitch'. -- -- > let c = circle_of_fifths (Pitch F Sharp 4) -- > in map pitch_to_pc (snd c) == [6,1,8,3,10,5,12,7,2,9,4,11]-circle_of_fifths :: Pitch -> ([Pitch], [Pitch])+circle_of_fifths :: T.Pitch -> ([T.Pitch], [T.Pitch]) circle_of_fifths x = let p4 = Interval Fourth Perfect LT 0 p5 = Interval Fifth Perfect LT 0@@ -228,7 +203,7 @@ -- displacement. -- -- > mapMaybe parse_interval_type (map show [1 .. 15])-parse_interval_type :: String -> Maybe (Interval_T,Octave)+parse_interval_type :: String -> Maybe (Interval_T,T.Octave) parse_interval_type n = case reads n of [(n',[])] -> if n' == 0@@ -249,7 +224,7 @@ -- 'parse_interval_type'. -- -- > map interval_type_degree [(Third,0),(Second,1),(Unison,2)] == [3,9,15]-interval_type_degree :: (Interval_T,Octave) -> Int+interval_type_degree :: (Interval_T,T.Octave) -> Int interval_type_degree (t,o) = fromEnum t + 1 + (fromIntegral o * 7) -- | Inverse of 'parse_interval_quality.@@ -282,6 +257,10 @@ '+':q:n -> f q n q:n -> f q n _ -> Nothing++-- | 'error' variant.+parse_interval_err :: String -> Interval+parse_interval_err = fromMaybe (error "parse_interval") . parse_interval -- | Pretty printer for intervals, inverse of 'parse_interval'. interval_pp :: Interval -> String
Music/Theory/Interval/Barlow_1987.hs view
@@ -5,12 +5,13 @@ import Data.List {- base -} import Data.Maybe {- base -}-import Data.Numbers.Primes {- primes -} import Data.Ratio {- base -} import Text.Printf {- base -} -import Music.Theory.Tuning+import qualified Data.Numbers.Primes as P {- primes -} +import qualified Music.Theory.Tuning as T {- hmt -}+ -- | Barlow's /indigestibility/ function for prime numbers. -- -- > map barlow [1,2,3,5,7,11,13] == [0,1,8/3,32/5,72/7,200/11,288/13]@@ -22,22 +23,26 @@ -- | Generate list of factors of /n/ from /x/. ----- > factor primes 315 == [3,3,5,7]+-- > factor P.primes 315 == [3,3,5,7]+-- > P.primeFactors 315 == [3,3,5,7] factor :: Integral a => [a] -> a -> [a] factor x n = case x of [] -> undefined- i:x' -> if i * i > n- then [n]- else if rem n i == 0- then i : factor x (quot n i)- else factor x' n+ i:x' -> if n < i+ then [] -- ie. prime factors of 1...+ else if i * i > n+ then [n]+ else if rem n i == 0+ then i : factor x (quot n i)+ else factor x' n -- | 'factor' /n/ from 'primes'. ----- > prime_factors 315 == [3,3,5,7]+-- > map prime_factors [1,4,231,315] == [[],[2,2],[3,7,11],[3,3,5,7]]+-- > map P.primeFactors [1,4,231,315] == [[],[2,2],[3,7,11],[3,3,5,7]] prime_factors :: Integral a => a -> [a]-prime_factors = factor primes+prime_factors = factor P.primes -- | Collect number of occurences of each element of a sorted list. --@@ -49,11 +54,11 @@ e:_ -> (e,genericLength x) in map f . group --- | 'multiplicities' '.' 'prime_factors'.+-- | 'multiplicities' '.' 'P.primeFactors'. -- -- > prime_factors_m 315 == [(3,2),(5,1),(7,1)] prime_factors_m :: Integral a => a -> [(a,a)]-prime_factors_m = multiplicities . prime_factors+prime_factors_m = multiplicities . P.primeFactors -- | Merging function for 'rational_prime_factors_m'. merge :: (Ord a,Num b,Eq b) => [(a,b)] -> [(a,b)] -> [(a,b)]@@ -91,10 +96,11 @@ -- up to the /n/th prime. -- -- > rational_prime_factors_t 6 (12,7) == [2,1,0,-1,0,0]+-- > rational_prime_factors_t 6 (32,9) == [5,-2,0,0,0,0] rational_prime_factors_t :: Integral b => Int -> (b,b) -> [b] rational_prime_factors_t n x = let r = rational_prime_factors_m x- in map (\i -> fromMaybe 0 (lookup i r)) (take n primes)+ in map (\i -> fromMaybe 0 (lookup i r)) (take n P.primes) -- | Compute the disharmonicity of the interval /(p,q)/ using the -- prime valuation function /pv/.@@ -120,7 +126,7 @@ to_rational = uncurry (%) -- | Make 'numerator' 'denominator' pair of /n/.-from_rational :: Integral t => Ratio t -> (t, t)+from_rational :: Ratio t -> (t, t) from_rational n = (numerator n,denominator n) -- | Set of 1. interval size (cents), 2. intervals as product of@@ -130,13 +136,14 @@ -- | Table 2 (p.45) -- -- > length (table_2 0.06) == 24+-- > length (table_2 0.04) == 66 table_2 :: Double -> [Table_2_Row] table_2 z = let g n = n <= 2 && n >= 1 r = nub (sort (filter g [p % q | p <- [1..81],q <- [1..81]])) h = map (harmonicity_r barlow) r f = (> z) . snd- k (i,j) = (fratio_to_cents i,rational_prime_factors_t 6 (from_rational i),i,j)+ k (i,j) = (T.fratio_to_cents i,rational_prime_factors_t 6 (from_rational i),i,j) in map k (filter f (zip r h)) -- | Pretty printer for 'Table_2_Row' values.
Music/Theory/Key.hs view
@@ -1,33 +1,205 @@ -- | Common music keys. module Music.Theory.Key where +import Control.Monad {- base -}+import Data.Char {- base -} import Data.List {- base -}+import Data.Maybe {- base -} -import Music.Theory.Pitch-import Music.Theory.Pitch.Name-import Music.Theory.Pitch.Note-import Music.Theory.Interval+import qualified Music.Theory.List as T+import qualified Music.Theory.Pitch as T+import qualified Music.Theory.Pitch.Name as T+import qualified Music.Theory.Pitch.Note as T+import qualified Music.Theory.Interval as T -- | Enumeration of common music notation modes. data Mode_T = Minor_Mode | Major_Mode deriving (Eq,Ord,Show) --- | A common music notation key is a 'Note_T', 'Alteration_T',--- 'Mode_T' triple.-type Key = (Note_T,Alteration_T,Mode_T)+-- | Pretty printer for 'Mode_T'.+mode_pp :: Mode_T -> String+mode_pp m =+ case m of+ Minor_Mode -> "Minor"+ Major_Mode -> "Major" +-- | Lower-cased 'mode_pp'.+mode_identifier_pp :: Mode_T -> String+mode_identifier_pp = map toLower . mode_pp++-- | There are two modes, given one return the other.+mode_parallel :: Mode_T -> Mode_T+mode_parallel m = if m == Minor_Mode then Major_Mode else Minor_Mode++mode_pc_seq :: Num t => Mode_T -> [t]+mode_pc_seq md =+ case md of+ Major_Mode -> [0,2,4,5,7,9,11]+ Minor_Mode -> [0,2,3,5,7,8,10]++-- | A common music notation key is a 'Note_T', 'Alteration_T', 'Mode_T' triple.+type Key = (T.Note_T,T.Alteration_T,Mode_T)++-- | 'Mode_T' of 'Key'.+key_mode :: Key -> Mode_T+key_mode (_,_,m) = m++-- | Enumeration of 42 CMN keys.+--+-- > length key_sequence_42 == 7 * 3 * 2+key_sequence_42 :: [Key]+key_sequence_42 =+ let a_seq = [T.Flat,T.Natural,T.Sharp]+ m_seq = [Major_Mode,Minor_Mode]+ in [(n,a,m) | n <- T.note_seq,a <- a_seq,m <- m_seq]++-- | Subset of 'key_sequence' not including very eccentric keys (where+-- there are more than 7 alterations).+--+-- > length key_sequence_30 == 30+key_sequence_30 :: [Key]+key_sequence_30 = filter (\k -> maybe False ((< 8) . abs) (key_fifths k)) key_sequence_42++-- | Parallel key, ie. 'mode_parallel' of 'Key'.+key_parallel :: Key -> Key+key_parallel (n,a,m) = (n,a,mode_parallel m)++-- | Transposition of 'Key'.+key_transpose :: Key -> Int -> Key+key_transpose (n,a,m) x =+ let Just pc = T.note_alteration_to_pc (n,a)+ Just (n',a') = T.pc_to_note_alteration_ks ((pc + x) `mod` 12)+ in (n',a',m)++-- | Relative key (ie. 'mode_parallel' with the same number of and type of alterations.+--+-- > let k = [(T.C,T.Natural,Major_Mode),(T.E,T.Natural,Minor_Mode)]+-- > in map (key_lc_uc_pp . key_relative) k == ["a♮","G♮"]+key_relative :: Key -> Key+key_relative k =+ case key_mode k of+ Major_Mode -> key_parallel (key_transpose k 9)+ Minor_Mode -> key_parallel (key_transpose k 3)++-- | Mediant minor of major key.+--+-- > key_mediant (T.C,T.Natural,Major_Mode) == Just (T.E,T.Natural,Minor_Mode)+key_mediant :: Key -> Maybe Key+key_mediant k =+ case key_mode k of+ Major_Mode -> Just (key_parallel (key_transpose k 4))+ _ -> Nothing++-- > fmap key_pc_set (key_lc_uc_parse "E")+key_pc_set :: Integral i => Key -> [i]+key_pc_set (n,a,md) =+ let pc0 = T.note_to_pc n + T.alteration_to_diff_err a+ in sort (map ((`mod` 12) . (+ pc0)) (mode_pc_seq md))++-- | Pretty-printer where 'Minor_Mode' is written in lower case (lc) and+-- alteration symbol is shown using indicated function.+key_lc_pp :: (T.Alteration_T -> String) -> Key -> String+key_lc_pp a_pp (n,a,m) =+ let c = T.note_pp n+ c' = if m == Minor_Mode then toLower c else c+ in c' : a_pp a++-- | 'key_lc_pp' with unicode (uc) alteration.+--+-- > map key_lc_uc_pp [(C,Sharp,Minor_Mode),(E,Flat,Major_Mode)] == ["c♯","E♭"]+key_lc_uc_pp :: Key -> String+key_lc_uc_pp = key_lc_pp (return . T.alteration_symbol)++-- | 'key_lc_pp' with ISO alteration.+key_lc_iso_pp :: Key -> String+key_lc_iso_pp = key_lc_pp T.alteration_iso++-- | 'key_lc_pp' with tonh alteration.+--+-- > map key_lc_tonh_pp [(T.C,T.Sharp,Minor_Mode),(T.E,T.Flat,Major_Mode)]+key_lc_tonh_pp :: Key -> String+key_lc_tonh_pp = key_lc_pp T.alteration_tonh++-- > map key_identifier_pp [(T.C,T.Sharp,Minor_Mode),(T.E,T.Flat,Major_Mode)]+key_identifier_pp :: (Show a, Show a1) => (a, a1, Mode_T) -> [Char]+key_identifier_pp (n,a,m) = map toLower (intercalate "_" [show n,show a,mode_pp m])++-- > import Data.Maybe+-- > mapMaybe note_char_to_key "CdEfGaB"+note_char_to_key :: Char -> Maybe Key+note_char_to_key c =+ let m = if isUpper c then Major_Mode else Minor_Mode+ in fmap (\n -> (n,T.Natural,m)) (T.parse_note_t True c)++-- | Parse 'Key' from /lc-uc/ string.+--+-- > import Data.Maybe+--+-- > let k = mapMaybe key_lc_uc_parse ["c","E","f♯","ab","G#"]+-- > in map key_lc_uc_pp k == ["c♮","E♮","f♯","a♭","G♯"]+key_lc_uc_parse :: String -> Maybe Key+key_lc_uc_parse k =+ let with_k a (n,_,m) = (n,a,m)+ with_a n a = fmap (with_k a) (note_char_to_key n)+ in case k of+ [c] -> note_char_to_key c+ [n,a] -> join (fmap (with_a n) (T.symbol_to_alteration_iso a))+ _ -> Nothing+ -- | Distance along circle of fifths path of indicated 'Key'. A -- positive number indicates the number of sharps, a negative number -- the number of flats. ----- > key_fifths (A,Natural,Minor_Mode) == 0--- > key_fifths (A,Natural,Major_Mode) == 3--- > key_fifths (C,Natural,Minor_Mode) == -3-key_fifths :: Key -> Int+-- > key_fifths (T.A,T.Natural,Minor_Mode) == Just 0+-- > key_fifths (T.A,T.Natural,Major_Mode) == Just 3+-- > key_fifths (T.C,T.Natural,Minor_Mode) == Just (-3)+-- > key_fifths (T.B,T.Sharp,Minor_Mode) == Just 9+-- > key_fifths (T.E,T.Sharp,Major_Mode) == Just 11+-- > key_fifths (T.B,T.Sharp,Major_Mode) == Nothing+--+-- > zip (map key_lc_iso_pp key_sequence_42) (map key_fifths key_sequence_42)+key_fifths :: Key -> Maybe Int key_fifths (n,a,m) =- let cf x = let (p,q) = circle_of_fifths x in p ++ q- eq (Pitch n' a' _) = n == n' && a == a'- (Just ix) = case m of- Major_Mode -> findIndex eq (cf c4)- Minor_Mode -> findIndex eq (cf a4)- in if ix < 13 then negate ix else ix - 12+ let cf x = let (p,q) = T.circle_of_fifths x in p ++ q+ eq (T.Pitch n' a' _) = n == n' && a == a'+ ix = case m of+ Major_Mode -> findIndex eq (cf T.c4)+ Minor_Mode -> findIndex eq (cf T.a4)+ in fmap (\i -> if i < 13 then negate i else i - 12) ix++-- | Table mapping 'Key' to 'key_fifths' value.+key_fifths_tbl :: [(Key,Int)]+key_fifths_tbl =+ let f (k,n) = maybe Nothing (\n' -> Just (k,n')) n+ in mapMaybe f (zip key_sequence_42 (map key_fifths key_sequence_42))++-- | Lookup 'key_fifths' value in 'key_fifths_tbl'.+--+-- > let a = [0,1,-1,2,-2,3,-3,4,-4,5,-5]+-- > let f md = map key_lc_iso_pp . mapMaybe (fifths_to_key md)+-- > f Minor_Mode a+-- > f Major_Mode a+fifths_to_key :: Mode_T -> Int -> Maybe Key+fifths_to_key md n =+ let eq_f = (\((_,_,md'),n') -> md == md' && n == n')+ in fmap fst (find eq_f key_fifths_tbl)++-- | Given sorted pitch-class set, find simplest implied key in given mode.+--+-- > mapMaybe (implied_key Major_Mode) [[0,2,4],[1,3],[4,10],[3,9],[8,9]]+-- > map (implied_key Major_Mode) [[0,1,2],[0,1,3,4]] == [Nothing,Nothing]+implied_key :: Integral i => Mode_T -> [i] -> Maybe Key+implied_key md pc_set =+ let a_seq = [0,1,-1,2,-2,3,-3,4,-4,5,-5,6,-6]+ key_seq = mapMaybe (fifths_to_key md) a_seq+ in find (\k -> pc_set `T.is_subset` key_pc_set k) key_seq++-- | 'key_fifths' of 'implied_key'.+implied_fifths :: Integral i => Mode_T -> [i] -> Maybe Int+implied_fifths md = join . fmap key_fifths . implied_key md++implied_key_err :: Integral i => Mode_T -> [i] -> Key+implied_key_err md = fromMaybe (error "implied_key") . implied_key md++implied_fifths_err :: Integral i => Mode_T -> [i] -> Int+implied_fifths_err md = fromMaybe (error "implied_fifths") . key_fifths . implied_key_err md
Music/Theory/List.hs view
@@ -1,24 +1,95 @@ -- | List functions. module Music.Theory.List where +import Data.Either {- base -} import Data.Function {- base -}+import qualified Data.IntMap as Map {- containers -} import Data.List {- base -}-import qualified Data.List.Ordered as O {- data-ordlist -}-import Data.List.Split {- split -} import Data.Maybe {- base -}+import Data.Tree {- containers -}+import qualified Data.Traversable as T {- base -} +import qualified Data.List.Ordered as O {- data-ordlist -}+import qualified Data.List.Split as S {- split -}+import qualified Data.List.Split.Internals as S {- split -}++import qualified Control.Monad.Logic as L {- logict -}++-- | Data.Vector.slice, ie. starting index (zero-indexed) and number of elements.+--+-- > slice 4 5 [1..] == [5,6,7,8,9]+slice :: Int -> Int -> [a] -> [a]+slice i n = take n . drop i++-- | Variant of slice with start and end indices (zero-indexed).+--+-- > section 4 8 [1..] == [5,6,7,8,9]+section :: Int -> Int -> [a] -> [a]+section l r = take (r - l + 1) . drop l+ -- | Bracket sequence with left and right values. -- -- > bracket ('<','>') "1,2,3" == "<1,2,3>" bracket :: (a,a) -> [a] -> [a] bracket (l,r) x = l : x ++ [r] +unbracket' :: [a] -> (Maybe a,[a],Maybe a)+unbracket' x =+ case x of+ [] -> (Nothing,[],Nothing)+ l:x' -> let (m,r) = separate_last' x' in (Just l,m,r)++-- | The first & middle & last elements of a list.+--+-- > unbracket "[12]" == Just ('[',"12",']')+unbracket :: [t] -> Maybe (t,[t],t)+unbracket x =+ case unbracket' x of+ (Just l,m,Just r) -> Just (l,m,r)+ _ -> Nothing++unbracket_err :: [t] -> (t,[t],t)+unbracket_err = fromMaybe (error "unbracket") . unbracket+ -- | Variant where brackets are sequences. -- -- > bracket_l ("<:",":>") "1,2,3" == "<:1,2,3:>" bracket_l :: ([a],[a]) -> [a] -> [a] bracket_l (l,r) s = l ++ s ++ r +-- * Split++-- | Relative of 'splitOn', but only makes first separation.+--+-- > splitOn "//" "lhs//rhs//rem" == ["lhs","rhs","rem"]+-- > separate_at "//" "lhs//rhs//rem" == Just ("lhs","rhs//rem")+separate_at :: Eq a => [a] -> [a] -> Maybe ([a],[a])+separate_at x =+ let n = length x+ f lhs rhs =+ if null rhs+ then Nothing+ else if x == take n rhs+ then Just (reverse lhs,drop n rhs)+ else f (head rhs : lhs) (tail rhs)+ in f []++-- | 'Splitter' comparing single element.+on_elem :: Eq a => a -> S.Splitter a+on_elem e = S.defaultSplitter { S.delimiter = S.Delimiter [(==) e] }++-- | Split before the indicated element.+--+-- > split_before 'x' "axbcxdefx" == ["a","xbc","xdef","x"]+-- > split_before 'x' "xa" == ["","xa"]+--+-- > map (flip split_before "abcde") "ae_" == [["","abcde"],["abcd","e"],["abcde"]]+-- > map (flip break "abcde" . (==)) "ae_" == [("","abcde"),("abcd","e"),("abcde","")]+split_before :: Eq a => a -> [a] -> [[a]]+split_before = S.split . S.keepDelimsL . on_elem++-- * Rotate+ -- | Generic form of 'rotate_left'. genericRotate_left :: Integral i => i -> [a] -> [a] genericRotate_left n =@@ -63,6 +134,42 @@ rotations :: [a] -> [[a]] rotations p = map (`rotate_left` p) [0 .. length p - 1] +-- | Rotate list so that is starts at indicated element.+--+-- > rotate_starting_from 'c' "abcde" == Just "cdeab"+-- > rotate_starting_from '_' "abc" == Nothing+rotate_starting_from :: Eq a => a -> [a] -> Maybe [a]+rotate_starting_from x l =+ case break (== x) l of+ (_,[]) -> Nothing+ (lhs,rhs) -> Just (rhs ++ lhs)++-- | Erroring variant.+rotate_starting_from_err :: Eq a => a -> [a] -> [a]+rotate_starting_from_err x =+ fromMaybe (error "rotate_starting_from: non-element") .+ rotate_starting_from x++-- | Sequence of /n/ adjacent elements, moving forward by /k/ places.+-- The last element may have fewer than /n/ places, but will reach the+-- end of the input sequence.+--+-- > adj 3 2 "adjacent" == ["adj","jac","cen","nt"]+adj :: Int -> Int -> [a] -> [[a]]+adj n k l =+ case take n l of+ [] -> []+ r -> r : adj n k (drop k l)++-- | Variant of 'adj' where the last element has /n/ places but may+-- not reach the end of the input sequence.+--+-- > adj' 3 2 "adjacent" == ["adj","jac","cen"]+adj' :: Int -> Int -> [a] -> [[a]]+adj' n k l =+ let r = take n l+ in if length r == n then r : adj' n k (drop k l) else []+ -- | Generic form of 'adj2'. genericAdj2 :: (Integral n) => n -> [t] -> [(t,t)] genericAdj2 n l =@@ -73,6 +180,7 @@ -- | Adjacent elements of list, at indicated distance, as pairs. -- -- > adj2 1 [1..5] == [(1,2),(2,3),(3,4),(4,5)]+-- > let l = [1..5] in zip l (tail l) == adj2 1 l -- > adj2 2 [1..4] == [(1,2),(3,4)] -- > adj2 3 [1..5] == [(1,2),(4,5)] adj2 :: Int -> [t] -> [(t,t)]@@ -98,11 +206,55 @@ -- > interleave [1..3] [4..6] == [1,4,2,5,3,6] -- > interleave ".+-" "abc" == ".a+b-c" -- > interleave [1..3] [] == []-interleave :: [b] -> [b] -> [b]+interleave :: [a] -> [a] -> [a] interleave p q = let u (i,j) = [i,j] in concatMap u (zip p q) +-- | Interleave list of lists. Allows lists to be of non-equal lenghts.+--+-- > interleave_set ["abcd","efgh","ijkl"] == "aeibfjcgkdhl"+-- > interleave_set ["abc","defg","hijkl"] == "adhbeicfjgkl"+interleave_set :: [[a]] -> [a]+interleave_set = concat . transpose++{-+import Safe {- safe -}++interleave_set l =+ case mapMaybe headMay l of+ [] -> []+ r -> r ++ interleave_set (mapMaybe tailMay l)+-}++-- | De-interleave /n/ lists.+--+-- > deinterleave 2 ".a+b-c" == [".+-","abc"]+-- > deinterleave 3 "aeibfjcgkdhl" == ["abcd","efgh","ijkl"]+deinterleave :: Int -> [a] -> [[a]]+deinterleave n = transpose . S.chunksOf n++-- | Special case for two-part deinterleaving.+--+-- > deinterleave2 ".a+b-c" == (".+-","abc")+deinterleave2 :: [t] -> ([t], [t])+deinterleave2 =+ let f l =+ case l of+ p:q:l' -> (p,q) : f l'+ _ -> []+ in unzip . f++{-+deinterleave2 =+ let f p q l =+ case l of+ [] -> (reverse p,reverse q)+ [a] -> (reverse (a:p),reverse q)+ a:b:l' -> rec (a:p) (b:q) l'+ in f [] []+-}+ -- | Variant that continues with the longer input. -- -- > interleave_continue ".+-" "abc" == ".a+b-c"@@ -121,15 +273,31 @@ interleave_rotations :: Int -> Int -> [b] -> [b] interleave_rotations i j s = interleave (rotate_left i s) (rotate_left j s) +generic_histogram :: (Ord a,Integral i) => [a] -> [(a,i)]+generic_histogram x =+ let g = group (sort x)+ in zip (map head g) (map genericLength g)++histogram_by :: Ord a => (a -> a -> Bool) -> [a] -> [(a,Int)]+histogram_by f x =+ let g = groupBy f (sort x)+ in zip (map head g) (map length g)+ -- | Count occurences of elements in list. ----- > histogram "hohoh" == [('h',3),('o',2)]-histogram :: (Ord a,Integral i) => [a] -> [(a,i)]-histogram x =- let g = group (sort x)- n = map genericLength g- in zip (map head g) n+-- > map histogram ["","hohoh"] == [[],[('h',3),('o',2)]]+histogram :: Ord a => [a] -> [(a,Int)]+histogram = histogram_by (==) +duplicates_by :: Ord a => (a -> a -> Bool) -> [a] -> [a]+duplicates_by f = map fst . filter (\(_,n) -> n > 1) . histogram_by f++-- | Elements that appear more than once in the input.+--+-- > map duplicates ["duplicates","redundant"] == ["","dn"]+duplicates :: Ord a => [a] -> [a]+duplicates = duplicates_by (==)+ -- | List segments of length /i/ at distance /j/. -- -- > segments 2 1 [1..5] == [[1,2],[2,3],[3,4],[4,5]]@@ -164,27 +332,79 @@ -- > cycles 3 [1..9] == [[1,4,7],[2,5,8],[3,6,9]] -- > cycles 4 [1..8] == [[1,5],[2,6],[3,7],[4,8]] cycles :: Int -> [a] -> [[a]]-cycles n = transpose . chunksOf n+cycles n = transpose . S.chunksOf n +-- | Variant of 'filter' that has a predicate to halt processing,+-- ie. 'filter' of 'takeWhile'.+--+-- > filter_halt (even . fst) ((< 5) . snd) (zip [1..] [0..])+filter_halt :: (a -> Bool) -> (a -> Bool) -> [a] -> [a]+filter_halt sel end = filter sel . takeWhile end++-- | Replace all /p/ with /q/ in /s/.+--+-- > replace "_x_" "-X-" "an _x_ string" == "an -X- string"+-- > replace "ab" "cd" "ab ab cd ab" == "cd cd cd cd"+replace :: Eq a => [a] -> [a] -> [a] -> [a]+replace p q s =+ let n = length p+ in case s of+ [] -> []+ c:s' -> if p `isPrefixOf` s+ then q ++ replace p q (drop n s)+ else c : replace p q s'++-- | Replace the /i/th value at /ns/ with /x/.+--+-- > replace_at "test" 2 'n' == "tent"+replace_at :: Integral i => [a] -> i -> a -> [a]+replace_at ns i x =+ let f j y = if i == j then x else y+ in zipWith f [0..] ns+ -- * Association lists --- | Given accesors for /key/ and /value/ collate input.+-- | Equivalent to 'groupBy' '==' 'on' /f/. ----- > let r = [('A',"a"),('B',"bd"),('C',"ce"),('D',"f")]--- > in collate_on fst snd (zip "ABCBCD" "abcdef")-collate_on :: (Eq k,Ord k) => (a -> k) -> (a -> v) -> [a] -> [(k,[v])]-collate_on f g =+-- > let r = [[(1,'a'),(1,'b')],[(2,'c')],[(3,'d'),(3,'e')],[(4,'f')]]+-- > in group_on fst (zip [1,1,2,3,3,4] "abcdef") == r+group_on :: Eq x => (a -> x) -> [a] -> [[a]]+group_on f = map (map snd) . groupBy ((==) `on` fst) . map (\x -> (f x,x))++-- | Given accesors for /key/ and /value/ collate adjacent values.+collate_on_adjacent :: (Eq k,Ord k) => (a -> k) -> (a -> v) -> [a] -> [(k,[v])]+collate_on_adjacent f g = let h l = case l of- [] -> error "collate_on"+ [] -> error "collate_on_adjacent" l0:_ -> (f l0,map g l)- in map h . groupBy ((==) `on` f) . sortBy (compare `on` f)+ in map h . group_on f +-- | 'collate_on_adjacent' of 'fst' and 'snd'.+--+-- > collate_adjacent (zip "TDD" "xyz") == [('T',"x"),('D',"yz")]+collate_adjacent :: Ord a => [(a,b)] -> [(a,[b])]+collate_adjacent = collate_on_adjacent fst snd++-- | 'sortOn' prior to 'collate_on_adjacent'.+--+-- > let r = [('A',"a"),('B',"bd"),('C',"ce"),('D',"f")]+-- > in collate_on fst snd (zip "ABCBCD" "abcdef") == r+collate_on :: Ord k => (a -> k) -> (a -> v) -> [a] -> [(k,[v])]+collate_on f g = collate_on_adjacent f g . sortOn f+ -- | 'collate_on' of 'fst' and 'snd'. --+-- > collate (zip "TDD" "xyz") == [('D',"yz"),('T',"x")] -- > collate (zip [1,2,1] "abc") == [(1,"ac"),(2,"b")] collate :: Ord a => [(a,b)] -> [(a,[b])] collate = collate_on fst snd +-- | Reverse of 'collate', inverse if order is not considered.+--+-- > uncollate [(1,"ac"),(2,"b")] == zip [1,1,2] "acb"+uncollate :: [(k,[v])] -> [(k,v)]+uncollate = concatMap (\(k,v) -> zip (repeat k) v)+ -- | Make /assoc/ list with given /key/. -- -- > with_key 'a' [1..3] == [('a',1),('a',2),('a',3)]@@ -208,12 +428,18 @@ e:r -> (e,reverse r) _ -> error "dx_d'" --- | Integrate, ie. pitch class segment to interval sequence.+-- | Apply flip of /f/ between elements of /l/. --+-- > d_dx_by (,) "abcd" == [('b','a'),('c','b'),('d','c')]+d_dx_by :: (t -> t -> u) -> [t] -> [u]+d_dx_by f l = if null l then [] else zipWith f (tail l) l++-- | Integrate, 'd_dx_by' '-', ie. pitch class segment to interval sequence.+-- -- > d_dx [5,6,8,11] == [1,2,3] -- > d_dx [] == [] d_dx :: (Num a) => [a] -> [a]-d_dx l = if null l then [] else zipWith (-) (tail l) l+d_dx = d_dx_by (-) -- | Elements of /p/ not in /q/. --@@ -250,18 +476,80 @@ [i] -> i _ -> error "elem_index_unique" --- | Basis of 'find_bounds'. There is an option to consider the last--- element specially, and if equal to the last span is given.-find_bounds' :: Bool -> (t -> s -> Ordering) -> [(t,t)] -> s -> Maybe (t,t)-find_bounds' scl f l x =+-- | Lookup that errors and prints message.+lookup_err_msg :: (Eq k,Show k) => String -> k -> [(k,v)] -> v+lookup_err_msg err k = fromMaybe (error (err ++ ": " ++ show k)) . lookup k++-- | Error variant.+lookup_err :: Eq k => k -> [(k,v)] -> v+lookup_err n = fromMaybe (error "lookup") . lookup n++-- | 'lookup' variant with default value.+lookup_def :: Eq k => k -> v -> [(k,v)] -> v+lookup_def k d = fromMaybe d . lookup k++-- | Reverse lookup.+--+-- > reverse_lookup 'c' [] == Nothing+-- > reverse_lookup 'c' (zip [0..4] ['a'..]) == Just 2+reverse_lookup :: Eq b => b -> [(a,b)] -> Maybe a+reverse_lookup k = fmap fst . find ((== k) . snd)++{-+reverse_lookup :: Eq b => b -> [(a,b)] -> Maybe a+reverse_lookup key ls =+ case ls of+ [] -> Nothing+ (x,y):ls' -> if key == y then Just x else reverse_lookup key ls'+-}+++-- | Basis of 'find_bounds_scl', indicates if /x/ is to the left or+-- right of the list, and it to the right whether equal or not.+-- 'Right' values will be correct if the list is not ascending,+-- however 'Left' values only make sense for ascending ranges.+--+-- > map (find_bounds' compare [(0,1),(1,2)]) [-1,0,1,2,3]+find_bounds' :: (t -> s -> Ordering) -> [(t,t)] -> s -> Either ((t,t),Ordering) (t,t)+find_bounds' f l x = let g (p,q) = f p x /= GT && f q x == GT- h (p,q) = f p x /= GT && f q x /= LT- h' = if scl then h else g in case l of- [] -> Nothing- [e] -> if h' e then Just e else Nothing- e:l' -> if g e then Just e else find_bounds' scl f l' x+ [] -> error "find_bounds': nil"+ [(p,q)] -> if g (p,q) then Right (p,q) else Left ((p,q),f q x)+ (p,q):l' -> if f p x == GT+ then Left ((p,q),GT)+ else if g (p,q) then Right (p,q) else find_bounds' f l' x +decide_nearest' :: Ord o => (p -> o) -> (p,p) -> p+decide_nearest' f (p,q) = if f p < f q then p else q++-- | Decide if value is nearer the left or right value of a range.+decide_nearest :: (Num o,Ord o) => o -> (o, o) -> o+decide_nearest x = decide_nearest' (abs . (x -))++-- | Find the number that is nearest the requested value in an+-- ascending list of numbers.+--+-- > map (find_nearest_err [0,3.5,4,7]) [-1,1,3,5,7,9] == [0,0,3.5,4,7,7]+find_nearest_err :: (Num n,Ord n) => [n] -> n -> n+find_nearest_err l x =+ case find_bounds' compare (adj2 1 l) x of+ Left ((p,_),GT) -> p+ Left ((_,q),_) -> q+ Right (p,q) -> decide_nearest x (p,q)++find_nearest :: (Num n,Ord n) => [n] -> n -> Maybe n+find_nearest l x = if null l then Nothing else Just (find_nearest_err l x)++-- | Basis of 'find_bounds'. There is an option to consider the last+-- element specially, and if equal to the last span is given.+find_bounds_scl :: Bool -> (t -> s -> Ordering) -> [(t,t)] -> s -> Maybe (t,t)+find_bounds_scl scl f l x =+ case find_bounds' f l x of+ Right r -> Just r+ Left (r,EQ) -> if scl then Just r else Nothing+ _ -> Nothing+ -- | Find adjacent elements of list that bound element under given -- comparator. --@@ -269,8 +557,18 @@ -- > ;r = [Nothing,Just (1,2),Just (3,4),Just (4,5)]} -- > in map f [0,1,3.5,5] == r find_bounds :: Bool -> (t -> s -> Ordering) -> [t] -> s -> Maybe (t,t)-find_bounds scl f l = find_bounds' scl f (adj2 1 l)+find_bounds scl f l = find_bounds_scl scl f (adj2 1 l) +-- | Special case of 'dropRight'.+--+-- > map drop_last ["","?","remove"] == ["","","remov"]+drop_last :: [t] -> [t]+drop_last l =+ case l of+ [] -> []+ [_] -> []+ e:l' -> e : drop_last l'+ -- | Variant of 'drop' from right of list. -- -- > dropRight 1 [1..9] == [1..8]@@ -283,6 +581,18 @@ dropWhileRight :: (a -> Bool) -> [a] -> [a] dropWhileRight p = reverse . dropWhile p . reverse +-- | 'take' from right.+--+-- > take_right 3 "taking" == "ing"+take_right :: Int -> [a] -> [a]+take_right n = reverse . take n . reverse++-- | 'takeWhile' from right.+--+-- > take_while_right Data.Char.isDigit "A440" == "440"+take_while_right :: (a -> Bool) -> [a] -> [a]+take_while_right p = reverse . takeWhile p . reverse+ -- | Apply /f/ at first element, and /g/ at all other elements. -- -- > at_head negate id [1..5] == [-1,2,3,4,5]@@ -302,13 +612,20 @@ [i] -> [g i] i:x' -> f i : at_last f g x' --- | Separate list into an initial list and a last element tuple.+-- | Separate list into an initial list and perhaps the last element tuple. --+-- > separate_last' [] == ([],Nothing)+separate_last' :: [a] -> ([a],Maybe a)+separate_last' x =+ case reverse x of+ [] -> ([],Nothing)+ e:x' -> (reverse x',Just e)++-- | Error on null input.+-- -- > separate_last [1..5] == ([1..4],5) separate_last :: [a] -> ([a],a)-separate_last x =- let e:x' = reverse x- in (reverse x',e)+separate_last = fmap (fromMaybe (error "separate_last")) . separate_last' -- | Replace directly repeated elements with 'Nothing'. --@@ -320,6 +637,22 @@ e:l' -> Just e : map (const Nothing) l' in concatMap f . group +-- | 'zipWith' of list and it's own tail.+--+-- > zip_with_adj (,) "abcde" == [('a','b'),('b','c'),('c','d'),('d','e')]+zip_with_adj :: (a -> a -> b) -> [a] -> [b]+zip_with_adj f xs = zipWith f xs (tail xs)++-- | Type-specialised 'zip_with_adj'.+compare_adjacent_by :: (a -> a -> Ordering) -> [a] -> [Ordering]+compare_adjacent_by = zip_with_adj++-- | 'compare_adjacent_by' of 'compare'.+--+-- > compare_adjacent [0,1,3,2] == [LT,LT,GT]+compare_adjacent :: Ord a => [a] -> [Ordering]+compare_adjacent = compare_adjacent_by compare+ -- | 'Data.List.groupBy' does not make adjacent comparisons, it -- compares each new element to the start of the group. This function -- is the adjacent variant.@@ -337,23 +670,42 @@ then (x:r0) : r' else [x] : r +-- | Reduce sequences of consecutive values to ranges.+--+-- > group_ranges [-1,0,3,4,5,8,9,12] == [(-1,0),(3,5),(8,9),(12,12)]+-- > group_ranges [3,2,3,4,3] == [(3,3),(2,4),(3,3)]+group_ranges :: (Num t, Eq t) => [t] -> [(t,t)]+group_ranges =+ let f l = (head l,last l)+ in map f . adjacent_groupBy (\p q -> p + 1 == q)+ -- | 'groupBy' on /structure/ of 'Maybe', ie. all 'Just' compare equal. -- -- > let r = [[Just 1],[Nothing,Nothing],[Just 4,Just 5]] -- > in group_just [Just 1,Nothing,Nothing,Just 4,Just 5] == r group_just :: [Maybe a] -> [[Maybe a]]-group_just = groupBy ((==) `on` isJust)+group_just = group_on isJust -- | Predicate to determine if all elements of the list are '=='.+--+-- > all_equal "aaa" == True+all_equal :: Eq a => [a] -> Bool+all_equal l =+ case l of+ [] -> True+ [_] -> True+ x:xs -> all id (map (== x) xs)++-- | Variant using 'nub'. all_eq :: Eq n => [n] -> Bool all_eq = (== 1) . length . nub --- | 'groupBy' of 'sortBy'.+-- | 'group_on' of 'sortOn'. -- -- > let r = [[('1','a'),('1','c')],[('2','d')],[('3','b'),('3','e')]] -- > in sort_group_on fst (zip "13123" "abcde") == r sort_group_on :: Ord b => (a -> b) -> [a] -> [[a]]-sort_group_on f = groupBy ((==) `on` f) . sortBy (compare `on` f)+sort_group_on f = group_on f . sortOn f -- | Maybe cons element onto list. --@@ -374,20 +726,24 @@ EQ -> g p q r -> r --- | Invert 'Ordering'.-ordering_invert :: Ordering -> Ordering-ordering_invert o =- case o of- LT -> GT- EQ -> EQ- GT -> LT+-- | Sequence of comparison functions, continue comparing until not EQ.+--+-- > compare (1,0) (0,1) == GT+-- > n_stage_compare [compare `on` snd,compare `on` fst] (1,0) (0,1) == LT+n_stage_compare :: [Compare_F a] -> Compare_F a+n_stage_compare l p q =+ case l of+ [] -> EQ+ f:l' -> case f p q of+ EQ -> n_stage_compare l' p q+ r -> r -- | Sort sequence /a/ based on ordering of sequence /b/. -- -- > sort_to "abc" [1,3,2] == "acb" -- > sort_to "adbce" [1,4,2,3,5] == "abcde" sort_to :: Ord i => [e] -> [i] -> [e]-sort_to e = map fst . sortBy (compare `on` snd) . zip e+sort_to e = map fst . sortOn snd . zip e -- | 'flip' of 'sort_to'. --@@ -399,12 +755,20 @@ sort_by_two_stage :: (Ord b,Ord c) => (a -> b) -> (a -> c) -> [a] -> [a] sort_by_two_stage f g = sortBy (two_stage_compare (compare `on` f) (compare `on` g)) +-- | 'sortBy' of 'n_stage_compare'.+sort_by_n_stage :: Ord b => [a -> b] -> [a] -> [a]+sort_by_n_stage f = sortBy (n_stage_compare (map (compare `on`) f))+ -- | Given a comparison function, merge two ascending lists. -- -- > mergeBy compare [1,3,5] [2,4] == [1..5] merge_by :: Compare_F a -> [a] -> [a] -> [a] merge_by = O.mergeBy +-- | 'merge_by' 'compare' 'on'.+merge_on :: Ord x => (a -> x) -> [a] -> [a] -> [a]+merge_on f = merge_by (compare `on` f)+ -- | 'O.mergeBy' of 'two_stage_compare'. merge_by_two_stage :: Ord b => (a -> b) -> Compare_F c -> (a -> c) -> [a] -> [a] -> [a] merge_by_two_stage f cmp g = O.mergeBy (two_stage_compare (compare `on` f) (cmp `on` g))@@ -449,8 +813,291 @@ GT -> r : recur p q' in recur +-- | First non-ascending pair of elements.+find_non_ascending :: (a -> a -> Ordering) -> [a] -> Maybe (a,a)+find_non_ascending cmp xs =+ case xs of+ p:q:xs' -> if cmp p q == GT then Just (p,q) else find_non_ascending cmp (q:xs')+ _ -> Nothing++-- | 'isNothing' of 'find_non_ascending'.+is_ascending_by :: (a -> a -> Ordering) -> [a] -> Bool+is_ascending_by cmp = isNothing . find_non_ascending cmp++-- | 'is_ascending_by' 'compare'.+is_ascending :: Ord a => [a] -> Bool+is_ascending = is_ascending_by compare++-- | Variant of `elem` that operates on a sorted list, halting.+-- This is 'O.member'.+--+-- > 16 `elem_ordered` [1,3 ..] == False+-- > 16 `elem` [1,3 ..] == undefined+elem_ordered :: Ord t => t -> [t] -> Bool+elem_ordered = O.member++-- | Variant of `elemIndex` that operates on a sorted list, halting.+--+-- > 16 `elemIndex_ordered` [1,3 ..] == Nothing+-- > 16 `elemIndex_ordered` [0,1,4,9,16,25,36,49,64,81,100] == Just 4+elemIndex_ordered :: Ord t => t -> [t] -> Maybe Int+elemIndex_ordered e =+ let recur k l =+ case l of+ [] -> Nothing+ x:l' -> if e == x+ then Just k+ else if x > e+ then Nothing+ else recur (k + 1) l'+ in recur 0++-- | Keep right variant of 'zipWith', where unused rhs values are returned.+--+-- > zip_with_kr (,) [1..3] ['a'..'e'] == ([(1,'a'),(2,'b'),(3,'c')],"de")+zip_with_kr :: (a -> b -> c) -> [a] -> [b] -> ([c],[b])+zip_with_kr f =+ let go r p q =+ case (p,q) of+ (i:p',j:q') -> go (f i j : r) p' q'+ _ -> (reverse r,q)+ in go []++-- | A 'zipWith' variant that always consumes an element from the left+-- hand side (lhs), but only consumes an element from the right hand+-- side (rhs) if the zip function is 'Right' and not if 'Left'.+-- There's also a secondary function to continue if the rhs ends+-- before the lhs.+zip_with_perhaps_rhs :: (a -> b -> Either c c) -> (a -> c) -> [a] -> [b] -> [c]+zip_with_perhaps_rhs f g lhs rhs =+ case (lhs,rhs) of+ ([],_) -> []+ (_,[]) -> map g lhs+ (p:lhs',q:rhs') -> case f p q of+ Left r -> r : zip_with_perhaps_rhs f g lhs' rhs+ Right r -> r : zip_with_perhaps_rhs f g lhs' rhs'++-- | Fill gaps in a sorted association list, range is inclusive at both ends.+--+-- > let r = [(1,'a'),(2,'x'),(3,'x'),(4,'x'),(5,'b'),(6,'x'),(7,'c'),(8,'x'),(9,'x')]+-- > in fill_gaps_ascending' 'x' (1,9) (zip [1,5,7] "abc") == r+fill_gaps_ascending :: (Enum n, Ord n) => t -> (n,n) -> [(n,t)] -> [(n,t)]+fill_gaps_ascending def_e (l,r) =+ let f i (j,e) = if j > i then Left (i,def_e) else Right (j,e)+ g i = (i,def_e)+ in zip_with_perhaps_rhs f g [l .. r]++-- | Direct definition.+fill_gaps_ascending' :: (Num n,Enum n, Ord n) => t -> (n,n) -> [(n,t)] -> [(n,t)]+fill_gaps_ascending' def (l,r) =+ let recur n x =+ if n > r+ then []+ else case x of+ [] -> zip [n .. r] (repeat def)+ (m,e):x' -> if n < m+ then (n,def) : recur (n + 1) x+ else (m,e) : recur (n + 1) x'+ in recur l++-- | 'minimum' and 'maximum' in one pass.+--+-- > minmax "minimumandmaximum" == ('a','x')+minmax :: Ord t => [t] -> (t,t)+minmax inp =+ case inp of+ [] -> error "minmax: null"+ x:xs -> let mm p (l,r) = (min p l,max p r) in foldr mm (x,x) xs+ -- * Bimap -- | Apply /f/ to both elements of a two-tuple, ie. 'bimap' /f/ /f/. bimap1 :: (t -> u) -> (t,t) -> (u,u) bimap1 f (p,q) = (f p,f q)++-- | Append /k/ to the right of /l/ until result has /n/ places.+--+-- > map (pad_right '0' 2 . return) ['0' .. '9']+-- > pad_right '0' 12 "1101" == "110100000000"+-- > map (pad_right ' '3) ["S","E-L"] == ["S ","E-L"]+pad_right :: a -> Int -> [a] -> [a]+pad_right k n l = take n (l ++ repeat k)++-- | Append /k/ to the left of /l/ until result has /n/ places.+--+-- > map (pad_left '0' 2 . return) ['0' .. '9']+pad_left :: a -> Int -> [a] -> [a]+pad_left k n l = replicate (n - length l) k ++ l++-- * Embedding++-- | Locate first (leftmost) embedding of /q/ in /p/.+-- Return partial indices for failure at 'Left'.+--+-- > embedding ("embedding","ming") == Right [1,6,7,8]+-- > embedding ("embedding","mind") == Left [1,6,7]+embedding :: Eq t => ([t],[t]) -> Either [Int] [Int]+embedding =+ let recur n r (p,q) =+ case (p,q) of+ (_,[]) -> Right (reverse r)+ ([],_) -> Left (reverse r)+ (x:p',y:q') ->+ let n' = n + 1+ r' = if x == y then n : r else r+ in recur n' r' (p',if x == y then q' else q)+ in recur 0 []++embedding_err :: Eq t => ([t],[t]) -> [Int]+embedding_err = either (error "embedding_err") id . embedding++-- | Does /q/ occur in sequence, though not necessarily adjacently, in /p/.+--+-- > is_embedding [1 .. 9] [1,3,7] == True+-- > is_embedding "embedding" "ming" == True+-- > is_embedding "embedding" "mind" == False+is_embedding :: Eq t => [t] -> [t] -> Bool+is_embedding p q = isRight (embedding (p,q))++all_embeddings_m :: (Eq t,L.MonadLogic m) => [t] -> [t] -> m [Int]+all_embeddings_m p q =+ let q_n = length q+ recur p' q' n k = -- n = length k+ if n == q_n+ then return (reverse k)+ else do (m,c) <- L.msum (map return p')+ let k0:_ = k+ c':_ = q'+ L.guard (c == c' && (null k || m > k0))+ let _:p'' = p'+ _:q'' = q'+ recur p'' q'' (n + 1) (m : k)+ in recur (zip [0..] p) q 0 []++-- | Enumerate indices for all embeddings of /q/ in /p/.+--+-- > all_embeddings "all_embeddings" "leg" == [[1,4,12],[1,7,12],[2,4,12],[2,7,12]]+all_embeddings :: Eq t => [t] -> [t] -> [[Int]]+all_embeddings p = L.observeAll . all_embeddings_m p++-- * Un-list++-- | Unpack one element list.+unlist1 :: [t] -> Maybe t+unlist1 l =+ case l of+ [e] -> Just e+ _ -> Nothing++-- | Erroring variant.+unlist1_err :: [t] -> t+unlist1_err = fromMaybe (error "unlist1") . unlist1++-- * Traversable++-- | Replace elements at 'Traversable' with result of joining with elements from list.+--+-- > let t = Node 0 [Node 1 [Node 2 [],Node 3 []],Node 4 []]+-- > putStrLn $ drawTree (fmap show t)+-- > let u = (adopt_shape (\_ x -> x) "abcde" t)+-- > putStrLn $ drawTree (fmap return u)+adopt_shape :: T.Traversable t => (a -> b -> c) -> [b] -> t a -> t c+adopt_shape jn l =+ let f (i:j) k = (j,jn k i)+ f [] _ = error "adopt_shape: rhs ends"+ in snd . T.mapAccumL f l++-- | Variant of 'adopt_shape' that considers only 'Just' elements at 'Traversable'.+--+-- > let {s = "a(b(cd)ef)ghi"+-- > ;t = group_tree (begin_end_cmp_eq '(' ')') s}+-- > in adopt_shape_m (,) [1..13] t+adopt_shape_m :: T.Traversable t => (a -> b-> c) -> [b] -> t (Maybe a) -> t (Maybe c)+adopt_shape_m jn l =+ let f (i:j) k = case k of+ Nothing -> (i:j,Nothing)+ Just k' -> (j,Just (jn k' i))+ f [] _ = error "adopt_shape_m: rhs ends"+ in snd . T.mapAccumL f l++-- * Tree++{- | Given an 'Ordering' predicate where 'LT' opens a group, 'GT'+closes a group, and 'EQ' continues current group, construct tree+from list.++> let {l = "a {b {c d} e f} g h i"+> ;t = group_tree ((==) '{',(==) '}') l}+> in catMaybes (flatten t) == l++> let {d = putStrLn . drawTree . fmap show}+> in d (group_tree ((==) '(',(==) ')') "a(b(cd)ef)ghi")++-}+group_tree :: (a -> Bool,a -> Bool) -> [a] -> Tree (Maybe a)+group_tree (open_f,close_f) =+ let unit e = Node (Just e) []+ nil = Node Nothing []+ insert_e (Node t l) e = Node t (e:l)+ reverse_n (Node t l) = Node t (reverse l)+ do_push (r,z) e =+ case z of+ h:z' -> (r,insert_e h (unit e) : z')+ [] -> (unit e : r,[])+ do_open (r,z) = (r,nil:z)+ do_close (r,z) =+ case z of+ h0:h1:z' -> (r,insert_e h1 (reverse_n h0) : z')+ h:z' -> (reverse_n h : r,z')+ [] -> (r,z)+ go st x =+ case x of+ [] -> Node Nothing (reverse (fst st))+ e:x' -> if open_f e+ then go (do_push (do_open st) e) x'+ else if close_f e+ then go (do_close (do_push st e)) x'+ else go (do_push st e) x'+ in go ([],[])++-- * Indexing++-- | Remove element at index.+--+-- > remove_ix 5 "remove" == "remov"+-- > remove_ix 5 "short" == undefined+remove_ix :: Int -> [a] -> [a]+remove_ix k l = let (p,q) = splitAt k l in p ++ tail q++operate_ixs :: Bool -> [Int] -> [a] -> [a]+operate_ixs mode k =+ let sel = if mode then notElem else elem+ f (n,e) = if n `sel` k then Nothing else Just e+ in mapMaybe f . zip [0..]++-- > select_ixs [1,3] "select" == "ee"+select_ixs :: [Int] -> [a] -> [a]+select_ixs = operate_ixs True++-- > remove_ixs [1,3,5] "remove" == "rmv"+remove_ixs :: [Int] -> [a] -> [a]+remove_ixs = operate_ixs False++-- | Replace element at /i/ in /p/ by application of /f/.+--+-- > replace_ix negate 1 [1..3] == [1,-2,3]+replace_ix :: (a -> a) -> Int -> [a] -> [a]+replace_ix f i p =+ let (q,r:s) = splitAt i p+ in q ++ (f r : s)++-- | Cyclic indexing function.+--+-- > map (at_cyclic "cycle") [0..9] == "cyclecycle"+at_cyclic :: [a] -> Int -> a+at_cyclic l n =+ let m = Map.fromList (zip [0..] l)+ k = Map.size m+ n' = n `mod` k+ in fromMaybe (error "cyc_at") (Map.lookup n' m)+
+ Music/Theory/Map.hs view
@@ -0,0 +1,17 @@+-- | Map functions.+module Music.Theory.Map where++import qualified Data.Map as M {- containers -}+import Data.Maybe {- base -}++-- | Erroring 'M.lookup'.+map_lookup_err :: Ord k => k -> M.Map k c -> c+map_lookup_err k = fromMaybe (error "M.lookup") . M.lookup k++-- | 'flip' of 'M.lookup'.+map_ix :: Ord k => M.Map k c -> k -> Maybe c+map_ix = flip M.lookup++-- | 'flip' of 'map_lookup_err'.+map_ix_err :: Ord k => M.Map k c -> k -> c+map_ix_err = flip map_lookup_err
Music/Theory/Math.hs view
@@ -5,10 +5,14 @@ import Data.Ratio {- base -} import Numeric {- base -} +import qualified Music.Theory.Math.Convert as T+ -- | Real (alias for 'Double'). type R = Double -- | <http://reference.wolfram.com/mathematica/ref/FractionalPart.html>+--+-- > integral_and_fractional_parts 1.5 == (1,0.5) integral_and_fractional_parts :: (Integral i, RealFrac t) => t -> (i,t) integral_and_fractional_parts n = if n >= 0@@ -26,11 +30,40 @@ fractional_part :: RealFrac a => a -> a fractional_part = snd . integer_and_fractional_parts +-- | 'floor' of 'T.real_to_double'.+real_floor :: (Real r,Integral i) => r -> i+real_floor = floor . T.real_to_double++-- | Type specialised 'real_floor'.+real_floor_int :: Real r => r -> Int+real_floor_int = real_floor++-- | 'round' of 'T.real_to_double'.+real_round :: (Real r,Integral i) => r -> i+real_round = round . T.real_to_double++-- | Type specialised 'real_round'.+real_round_int :: Real r => r -> Int+real_round_int = real_round++-- | Is /r/ zero to /k/ decimal places.+--+-- > map (flip zero_to_precision 0.00009) [4,5] == [True,False]+-- > zero_to_precision 4 1.00009 == False+zero_to_precision :: Real r => Int -> r -> Bool+zero_to_precision k r = real_floor_int (r * (fromIntegral ((10::Int) ^ k))) == 0++-- | Is /r/ whole to /k/ decimal places.+--+-- > map (flip whole_to_precision 1.00009) [4,5] == [True,False]+whole_to_precision :: Real r => Int -> r -> Bool+whole_to_precision k = zero_to_precision k . fractional_part . T.real_to_double+ -- | <http://reference.wolfram.com/mathematica/ref/SawtoothWave.html> -- -- > plotTable1 (map sawtooth_wave [-2.0,-1.99 .. 2.0]) sawtooth_wave :: RealFrac a => a -> a-sawtooth_wave n = n - fromInteger (floor n)+sawtooth_wave n = n - floor_f n -- | Pretty printer for 'Rational' that elides denominators of @1@. --@@ -60,7 +93,7 @@ rational_simplifies (n,d) = gcd n d /= 1 -- | 'numerator' and 'denominator' of rational.-rational_nd :: Integral t => Ratio t -> (t,t)+rational_nd :: Ratio t -> (t,t) rational_nd r = (numerator r,denominator r) -- | Rational as a whole number, or 'Nothing'.@@ -71,6 +104,19 @@ rational_whole_err :: Integral a => Ratio a -> a rational_whole_err = fromMaybe (error "rational_whole") . rational_whole +-- | Show rational to /n/ decimal places.+--+-- > let r = approxRational pi 1e-100+-- > r == 884279719003555 / 281474976710656+-- > show_rational_decimal 12 r == "3.141592653590"+show_rational_decimal :: Int -> Rational -> String+show_rational_decimal n r =+ let d = round (abs r * 10^n)+ s = show (d :: Integer)+ s' = replicate (n - length s + 1) '0' ++ s+ (h, f) = splitAt (length s' - n) s'+ in (if r < 0 then "-" else "") ++ h ++ "." ++ f+ -- | Variant of 'showFFloat'. The 'Show' instance for floats resorts -- to exponential notation very readily. --@@ -78,6 +124,10 @@ realfloat_pp :: RealFloat a => Int -> a -> String realfloat_pp k n = showFFloat (Just k) n "" +-- | Show /r/ as float to /k/ places.+real_pp :: Real t => Int -> t -> String+real_pp k t = showFFloat (Just k) (T.real_to_double t) ""+ -- | Type specialised 'realfloat_pp'. float_pp :: Int -> Float -> String float_pp = realfloat_pp@@ -96,3 +146,62 @@ LT -> '-' : show (abs n) EQ -> "" GT -> '+' : show n++-- | 'fromInteger' . 'floor'.+floor_f :: (RealFrac a, Num b) => a -> b+floor_f = fromInteger . floor++-- | Round /b/ to nearest multiple of /a/.+--+-- > map (round_to 0.25) [0,0.1 .. 1] == [0.0,0.0,0.25,0.25,0.5,0.5,0.5,0.75,0.75,1.0,1.0]+-- > map (round_to 25) [0,10 .. 100] == [0,0,25,25,50,50,50,75,75,100,100]+round_to :: RealFrac n => n -> n -> n+round_to a b = if a == 0 then b else floor_f ((b / a) + 0.5) * a++-- * One-indexed++-- | One-indexed 'mod' function.+--+-- > map (`oi_mod` 5) [1..10] == [1,2,3,4,5,1,2,3,4,5]+oi_mod :: Integral a => a -> a -> a+oi_mod n m = ((n - 1) `mod` m) + 1++-- | One-indexed 'divMod' function.+--+-- > map (`oi_divMod` 5) [1,3 .. 9] == [(0,1),(0,3),(0,5),(1,2),(1,4)]+oi_divMod :: Integral t => t -> t -> (t, t)+oi_divMod n m = let (i,j) = (n - 1) `divMod` m in (i,j + 1)++-- * I = integral++-- | Integral square root function.+--+-- > map i_square_root [0,1,4,9,16,25,36,49,64,81,100] == [0 .. 10]+-- > map i_square_root [4 .. 16] == [2,2,2,2,2,3,3,3,3,3,3,3,4]+i_square_root :: Integral t => t -> t+i_square_root n =+ let babylon a =+ let b = quot (a + quot n a) 2+ in if a > b then babylon b else a+ in case compare n 0 of+ GT -> babylon n+ EQ -> 0+ _ -> error "i_square_root: negative?"++-- * Interval++-- | (0,1) = {x | 0 < x < 1}+in_open_interval :: Ord a => (a, a) -> a -> Bool+in_open_interval (p,q) n = p < n && n < q++-- | [0,1] = {x | 0 ≤ x ≤ 1}+in_closed_interval :: Ord a => (a, a) -> a -> Bool+in_closed_interval (p,q) n = p <= n && n <= q++-- | (p,q] (0,1] = {x | 0 < x ≤ 1}+in_left_half_open_interval :: Ord a => (a, a) -> a -> Bool+in_left_half_open_interval (p,q) n = p < n && n <= q++-- | [p,q) [0,1) = {x | 0 ≤ x < 1}+in_right_half_open_interval :: Ord a => (a, a) -> a -> Bool+in_right_half_open_interval (p,q) n = p <= n && n < q
+ Music/Theory/Math/Convert.hs view
@@ -0,0 +1,1121 @@+{- | Specialised type conversions, see mk/mk-convert.hs++> map int_to_word8 [-1,0,255,256] == [255,0,255,0]+> map int_to_word8_maybe [-1,0,255,256] == [Nothing,Just 0,Just 255,Nothing]++> map integer_to_int64_maybe [-2 ^ 63 - 1,2 ^ 63] == [Nothing,Nothing]+> map integer_to_word64_maybe [2 ^64 - 1,2 ^ 64] == [Just 18446744073709551615,Nothing]++> map int16_to_float [-1,0,1] == [-1,0,1]++-}+module Music.Theory.Math.Convert where++import Data.Int {- base -}+import Data.Word {- base -}++-- | Type specialised 'realToFrac'+real_to_float :: Real t => t -> Float+real_to_float = realToFrac++-- | Type specialised 'realToFrac'+real_to_double :: Real t => t -> Double+real_to_double = realToFrac++-- | Type specialised 'realToFrac'+double_to_float :: Double -> Float+double_to_float = realToFrac++-- | Type specialised 'realToFrac'+float_to_double :: Float -> Double+float_to_double = realToFrac++-- AUTOGEN (see mk/mk-convert.hs)++-- | Type specialised 'fromIntegral'+word8_to_word16 :: Word8 -> Word16+word8_to_word16 = fromIntegral++-- | Type specialised 'fromIntegral'+word8_to_word32 :: Word8 -> Word32+word8_to_word32 = fromIntegral++-- | Type specialised 'fromIntegral'+word8_to_word64 :: Word8 -> Word64+word8_to_word64 = fromIntegral++-- | Type specialised 'fromIntegral'+word8_to_int8 :: Word8 -> Int8+word8_to_int8 = fromIntegral++-- | Type specialised 'fromIntegral'+word8_to_int16 :: Word8 -> Int16+word8_to_int16 = fromIntegral++-- | Type specialised 'fromIntegral'+word8_to_int32 :: Word8 -> Int32+word8_to_int32 = fromIntegral++-- | Type specialised 'fromIntegral'+word8_to_int64 :: Word8 -> Int64+word8_to_int64 = fromIntegral++-- | Type specialised 'fromIntegral'+word8_to_int :: Word8 -> Int+word8_to_int = fromIntegral++-- | Type specialised 'fromIntegral'+word8_to_integer :: Word8 -> Integer+word8_to_integer = fromIntegral++-- | Type specialised 'fromIntegral'+word8_to_float :: Word8 -> Float+word8_to_float = fromIntegral++-- | Type specialised 'fromIntegral'+word8_to_double :: Word8 -> Double+word8_to_double = fromIntegral++-- | Type specialised 'fromIntegral'+word16_to_word8 :: Word16 -> Word8+word16_to_word8 = fromIntegral++-- | Type specialised 'fromIntegral'+word16_to_word32 :: Word16 -> Word32+word16_to_word32 = fromIntegral++-- | Type specialised 'fromIntegral'+word16_to_word64 :: Word16 -> Word64+word16_to_word64 = fromIntegral++-- | Type specialised 'fromIntegral'+word16_to_int8 :: Word16 -> Int8+word16_to_int8 = fromIntegral++-- | Type specialised 'fromIntegral'+word16_to_int16 :: Word16 -> Int16+word16_to_int16 = fromIntegral++-- | Type specialised 'fromIntegral'+word16_to_int32 :: Word16 -> Int32+word16_to_int32 = fromIntegral++-- | Type specialised 'fromIntegral'+word16_to_int64 :: Word16 -> Int64+word16_to_int64 = fromIntegral++-- | Type specialised 'fromIntegral'+word16_to_int :: Word16 -> Int+word16_to_int = fromIntegral++-- | Type specialised 'fromIntegral'+word16_to_integer :: Word16 -> Integer+word16_to_integer = fromIntegral++-- | Type specialised 'fromIntegral'+word16_to_float :: Word16 -> Float+word16_to_float = fromIntegral++-- | Type specialised 'fromIntegral'+word16_to_double :: Word16 -> Double+word16_to_double = fromIntegral++-- | Type specialised 'fromIntegral'+word32_to_word8 :: Word32 -> Word8+word32_to_word8 = fromIntegral++-- | Type specialised 'fromIntegral'+word32_to_word16 :: Word32 -> Word16+word32_to_word16 = fromIntegral++-- | Type specialised 'fromIntegral'+word32_to_word64 :: Word32 -> Word64+word32_to_word64 = fromIntegral++-- | Type specialised 'fromIntegral'+word32_to_int8 :: Word32 -> Int8+word32_to_int8 = fromIntegral++-- | Type specialised 'fromIntegral'+word32_to_int16 :: Word32 -> Int16+word32_to_int16 = fromIntegral++-- | Type specialised 'fromIntegral'+word32_to_int32 :: Word32 -> Int32+word32_to_int32 = fromIntegral++-- | Type specialised 'fromIntegral'+word32_to_int64 :: Word32 -> Int64+word32_to_int64 = fromIntegral++-- | Type specialised 'fromIntegral'+word32_to_int :: Word32 -> Int+word32_to_int = fromIntegral++-- | Type specialised 'fromIntegral'+word32_to_integer :: Word32 -> Integer+word32_to_integer = fromIntegral++-- | Type specialised 'fromIntegral'+word32_to_float :: Word32 -> Float+word32_to_float = fromIntegral++-- | Type specialised 'fromIntegral'+word32_to_double :: Word32 -> Double+word32_to_double = fromIntegral++-- | Type specialised 'fromIntegral'+word64_to_word8 :: Word64 -> Word8+word64_to_word8 = fromIntegral++-- | Type specialised 'fromIntegral'+word64_to_word16 :: Word64 -> Word16+word64_to_word16 = fromIntegral++-- | Type specialised 'fromIntegral'+word64_to_word32 :: Word64 -> Word32+word64_to_word32 = fromIntegral++-- | Type specialised 'fromIntegral'+word64_to_int8 :: Word64 -> Int8+word64_to_int8 = fromIntegral++-- | Type specialised 'fromIntegral'+word64_to_int16 :: Word64 -> Int16+word64_to_int16 = fromIntegral++-- | Type specialised 'fromIntegral'+word64_to_int32 :: Word64 -> Int32+word64_to_int32 = fromIntegral++-- | Type specialised 'fromIntegral'+word64_to_int64 :: Word64 -> Int64+word64_to_int64 = fromIntegral++-- | Type specialised 'fromIntegral'+word64_to_int :: Word64 -> Int+word64_to_int = fromIntegral++-- | Type specialised 'fromIntegral'+word64_to_integer :: Word64 -> Integer+word64_to_integer = fromIntegral++-- | Type specialised 'fromIntegral'+word64_to_float :: Word64 -> Float+word64_to_float = fromIntegral++-- | Type specialised 'fromIntegral'+word64_to_double :: Word64 -> Double+word64_to_double = fromIntegral++-- | Type specialised 'fromIntegral'+int8_to_word8 :: Int8 -> Word8+int8_to_word8 = fromIntegral++-- | Type specialised 'fromIntegral'+int8_to_word16 :: Int8 -> Word16+int8_to_word16 = fromIntegral++-- | Type specialised 'fromIntegral'+int8_to_word32 :: Int8 -> Word32+int8_to_word32 = fromIntegral++-- | Type specialised 'fromIntegral'+int8_to_word64 :: Int8 -> Word64+int8_to_word64 = fromIntegral++-- | Type specialised 'fromIntegral'+int8_to_int16 :: Int8 -> Int16+int8_to_int16 = fromIntegral++-- | Type specialised 'fromIntegral'+int8_to_int32 :: Int8 -> Int32+int8_to_int32 = fromIntegral++-- | Type specialised 'fromIntegral'+int8_to_int64 :: Int8 -> Int64+int8_to_int64 = fromIntegral++-- | Type specialised 'fromIntegral'+int8_to_int :: Int8 -> Int+int8_to_int = fromIntegral++-- | Type specialised 'fromIntegral'+int8_to_integer :: Int8 -> Integer+int8_to_integer = fromIntegral++-- | Type specialised 'fromIntegral'+int8_to_float :: Int8 -> Float+int8_to_float = fromIntegral++-- | Type specialised 'fromIntegral'+int8_to_double :: Int8 -> Double+int8_to_double = fromIntegral++-- | Type specialised 'fromIntegral'+int16_to_word8 :: Int16 -> Word8+int16_to_word8 = fromIntegral++-- | Type specialised 'fromIntegral'+int16_to_word16 :: Int16 -> Word16+int16_to_word16 = fromIntegral++-- | Type specialised 'fromIntegral'+int16_to_word32 :: Int16 -> Word32+int16_to_word32 = fromIntegral++-- | Type specialised 'fromIntegral'+int16_to_word64 :: Int16 -> Word64+int16_to_word64 = fromIntegral++-- | Type specialised 'fromIntegral'+int16_to_int8 :: Int16 -> Int8+int16_to_int8 = fromIntegral++-- | Type specialised 'fromIntegral'+int16_to_int32 :: Int16 -> Int32+int16_to_int32 = fromIntegral++-- | Type specialised 'fromIntegral'+int16_to_int64 :: Int16 -> Int64+int16_to_int64 = fromIntegral++-- | Type specialised 'fromIntegral'+int16_to_int :: Int16 -> Int+int16_to_int = fromIntegral++-- | Type specialised 'fromIntegral'+int16_to_integer :: Int16 -> Integer+int16_to_integer = fromIntegral++-- | Type specialised 'fromIntegral'+int16_to_float :: Int16 -> Float+int16_to_float = fromIntegral++-- | Type specialised 'fromIntegral'+int16_to_double :: Int16 -> Double+int16_to_double = fromIntegral++-- | Type specialised 'fromIntegral'+int32_to_word8 :: Int32 -> Word8+int32_to_word8 = fromIntegral++-- | Type specialised 'fromIntegral'+int32_to_word16 :: Int32 -> Word16+int32_to_word16 = fromIntegral++-- | Type specialised 'fromIntegral'+int32_to_word32 :: Int32 -> Word32+int32_to_word32 = fromIntegral++-- | Type specialised 'fromIntegral'+int32_to_word64 :: Int32 -> Word64+int32_to_word64 = fromIntegral++-- | Type specialised 'fromIntegral'+int32_to_int8 :: Int32 -> Int8+int32_to_int8 = fromIntegral++-- | Type specialised 'fromIntegral'+int32_to_int16 :: Int32 -> Int16+int32_to_int16 = fromIntegral++-- | Type specialised 'fromIntegral'+int32_to_int64 :: Int32 -> Int64+int32_to_int64 = fromIntegral++-- | Type specialised 'fromIntegral'+int32_to_int :: Int32 -> Int+int32_to_int = fromIntegral++-- | Type specialised 'fromIntegral'+int32_to_integer :: Int32 -> Integer+int32_to_integer = fromIntegral++-- | Type specialised 'fromIntegral'+int32_to_float :: Int32 -> Float+int32_to_float = fromIntegral++-- | Type specialised 'fromIntegral'+int32_to_double :: Int32 -> Double+int32_to_double = fromIntegral++-- | Type specialised 'fromIntegral'+int64_to_word8 :: Int64 -> Word8+int64_to_word8 = fromIntegral++-- | Type specialised 'fromIntegral'+int64_to_word16 :: Int64 -> Word16+int64_to_word16 = fromIntegral++-- | Type specialised 'fromIntegral'+int64_to_word32 :: Int64 -> Word32+int64_to_word32 = fromIntegral++-- | Type specialised 'fromIntegral'+int64_to_word64 :: Int64 -> Word64+int64_to_word64 = fromIntegral++-- | Type specialised 'fromIntegral'+int64_to_int8 :: Int64 -> Int8+int64_to_int8 = fromIntegral++-- | Type specialised 'fromIntegral'+int64_to_int16 :: Int64 -> Int16+int64_to_int16 = fromIntegral++-- | Type specialised 'fromIntegral'+int64_to_int32 :: Int64 -> Int32+int64_to_int32 = fromIntegral++-- | Type specialised 'fromIntegral'+int64_to_int :: Int64 -> Int+int64_to_int = fromIntegral++-- | Type specialised 'fromIntegral'+int64_to_integer :: Int64 -> Integer+int64_to_integer = fromIntegral++-- | Type specialised 'fromIntegral'+int64_to_float :: Int64 -> Float+int64_to_float = fromIntegral++-- | Type specialised 'fromIntegral'+int64_to_double :: Int64 -> Double+int64_to_double = fromIntegral++-- | Type specialised 'fromIntegral'+int_to_word8 :: Int -> Word8+int_to_word8 = fromIntegral++-- | Type specialised 'fromIntegral'+int_to_word16 :: Int -> Word16+int_to_word16 = fromIntegral++-- | Type specialised 'fromIntegral'+int_to_word32 :: Int -> Word32+int_to_word32 = fromIntegral++-- | Type specialised 'fromIntegral'+int_to_word64 :: Int -> Word64+int_to_word64 = fromIntegral++-- | Type specialised 'fromIntegral'+int_to_int8 :: Int -> Int8+int_to_int8 = fromIntegral++-- | Type specialised 'fromIntegral'+int_to_int16 :: Int -> Int16+int_to_int16 = fromIntegral++-- | Type specialised 'fromIntegral'+int_to_int32 :: Int -> Int32+int_to_int32 = fromIntegral++-- | Type specialised 'fromIntegral'+int_to_int64 :: Int -> Int64+int_to_int64 = fromIntegral++-- | Type specialised 'fromIntegral'+int_to_integer :: Int -> Integer+int_to_integer = fromIntegral++-- | Type specialised 'fromIntegral'+int_to_float :: Int -> Float+int_to_float = fromIntegral++-- | Type specialised 'fromIntegral'+int_to_double :: Int -> Double+int_to_double = fromIntegral++-- | Type specialised 'fromIntegral'+integer_to_word8 :: Integer -> Word8+integer_to_word8 = fromIntegral++-- | Type specialised 'fromIntegral'+integer_to_word16 :: Integer -> Word16+integer_to_word16 = fromIntegral++-- | Type specialised 'fromIntegral'+integer_to_word32 :: Integer -> Word32+integer_to_word32 = fromIntegral++-- | Type specialised 'fromIntegral'+integer_to_word64 :: Integer -> Word64+integer_to_word64 = fromIntegral++-- | Type specialised 'fromIntegral'+integer_to_int8 :: Integer -> Int8+integer_to_int8 = fromIntegral++-- | Type specialised 'fromIntegral'+integer_to_int16 :: Integer -> Int16+integer_to_int16 = fromIntegral++-- | Type specialised 'fromIntegral'+integer_to_int32 :: Integer -> Int32+integer_to_int32 = fromIntegral++-- | Type specialised 'fromIntegral'+integer_to_int64 :: Integer -> Int64+integer_to_int64 = fromIntegral++-- | Type specialised 'fromIntegral'+integer_to_int :: Integer -> Int+integer_to_int = fromIntegral++-- | Type specialised 'fromIntegral'+integer_to_float :: Integer -> Float+integer_to_float = fromIntegral++-- | Type specialised 'fromIntegral'+integer_to_double :: Integer -> Double+integer_to_double = fromIntegral++-- | Type specialised 'fromIntegral'+word8_to_word16_maybe :: Word8 -> Maybe Word16+word8_to_word16_maybe n =+ if n < fromIntegral (minBound::Word16) ||+ n > fromIntegral (maxBound::Word16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word8_to_word32_maybe :: Word8 -> Maybe Word32+word8_to_word32_maybe n =+ if n < fromIntegral (minBound::Word32) ||+ n > fromIntegral (maxBound::Word32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word8_to_word64_maybe :: Word8 -> Maybe Word64+word8_to_word64_maybe n =+ if n < fromIntegral (minBound::Word64) ||+ n > fromIntegral (maxBound::Word64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word8_to_int8_maybe :: Word8 -> Maybe Int8+word8_to_int8_maybe n =+ if n < fromIntegral (minBound::Int8) ||+ n > fromIntegral (maxBound::Int8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word8_to_int16_maybe :: Word8 -> Maybe Int16+word8_to_int16_maybe n =+ if n < fromIntegral (minBound::Int16) ||+ n > fromIntegral (maxBound::Int16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word8_to_int32_maybe :: Word8 -> Maybe Int32+word8_to_int32_maybe n =+ if n < fromIntegral (minBound::Int32) ||+ n > fromIntegral (maxBound::Int32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word8_to_int64_maybe :: Word8 -> Maybe Int64+word8_to_int64_maybe n =+ if n < fromIntegral (minBound::Int64) ||+ n > fromIntegral (maxBound::Int64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word8_to_int_maybe :: Word8 -> Maybe Int+word8_to_int_maybe n =+ if n < fromIntegral (minBound::Int) ||+ n > fromIntegral (maxBound::Int)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word16_to_word8_maybe :: Word16 -> Maybe Word8+word16_to_word8_maybe n =+ if n < fromIntegral (minBound::Word8) ||+ n > fromIntegral (maxBound::Word8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word16_to_word32_maybe :: Word16 -> Maybe Word32+word16_to_word32_maybe n =+ if n < fromIntegral (minBound::Word32) ||+ n > fromIntegral (maxBound::Word32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word16_to_word64_maybe :: Word16 -> Maybe Word64+word16_to_word64_maybe n =+ if n < fromIntegral (minBound::Word64) ||+ n > fromIntegral (maxBound::Word64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word16_to_int8_maybe :: Word16 -> Maybe Int8+word16_to_int8_maybe n =+ if n < fromIntegral (minBound::Int8) ||+ n > fromIntegral (maxBound::Int8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word16_to_int16_maybe :: Word16 -> Maybe Int16+word16_to_int16_maybe n =+ if n < fromIntegral (minBound::Int16) ||+ n > fromIntegral (maxBound::Int16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word16_to_int32_maybe :: Word16 -> Maybe Int32+word16_to_int32_maybe n =+ if n < fromIntegral (minBound::Int32) ||+ n > fromIntegral (maxBound::Int32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word16_to_int64_maybe :: Word16 -> Maybe Int64+word16_to_int64_maybe n =+ if n < fromIntegral (minBound::Int64) ||+ n > fromIntegral (maxBound::Int64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word16_to_int_maybe :: Word16 -> Maybe Int+word16_to_int_maybe n =+ if n < fromIntegral (minBound::Int) ||+ n > fromIntegral (maxBound::Int)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word32_to_word8_maybe :: Word32 -> Maybe Word8+word32_to_word8_maybe n =+ if n < fromIntegral (minBound::Word8) ||+ n > fromIntegral (maxBound::Word8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word32_to_word16_maybe :: Word32 -> Maybe Word16+word32_to_word16_maybe n =+ if n < fromIntegral (minBound::Word16) ||+ n > fromIntegral (maxBound::Word16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word32_to_word64_maybe :: Word32 -> Maybe Word64+word32_to_word64_maybe n =+ if n < fromIntegral (minBound::Word64) ||+ n > fromIntegral (maxBound::Word64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word32_to_int8_maybe :: Word32 -> Maybe Int8+word32_to_int8_maybe n =+ if n < fromIntegral (minBound::Int8) ||+ n > fromIntegral (maxBound::Int8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word32_to_int16_maybe :: Word32 -> Maybe Int16+word32_to_int16_maybe n =+ if n < fromIntegral (minBound::Int16) ||+ n > fromIntegral (maxBound::Int16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word32_to_int32_maybe :: Word32 -> Maybe Int32+word32_to_int32_maybe n =+ if n < fromIntegral (minBound::Int32) ||+ n > fromIntegral (maxBound::Int32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word32_to_int64_maybe :: Word32 -> Maybe Int64+word32_to_int64_maybe n =+ if n < fromIntegral (minBound::Int64) ||+ n > fromIntegral (maxBound::Int64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word32_to_int_maybe :: Word32 -> Maybe Int+word32_to_int_maybe n =+ if n < fromIntegral (minBound::Int) ||+ n > fromIntegral (maxBound::Int)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word64_to_word8_maybe :: Word64 -> Maybe Word8+word64_to_word8_maybe n =+ if n < fromIntegral (minBound::Word8) ||+ n > fromIntegral (maxBound::Word8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word64_to_word16_maybe :: Word64 -> Maybe Word16+word64_to_word16_maybe n =+ if n < fromIntegral (minBound::Word16) ||+ n > fromIntegral (maxBound::Word16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word64_to_word32_maybe :: Word64 -> Maybe Word32+word64_to_word32_maybe n =+ if n < fromIntegral (minBound::Word32) ||+ n > fromIntegral (maxBound::Word32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word64_to_int8_maybe :: Word64 -> Maybe Int8+word64_to_int8_maybe n =+ if n < fromIntegral (minBound::Int8) ||+ n > fromIntegral (maxBound::Int8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word64_to_int16_maybe :: Word64 -> Maybe Int16+word64_to_int16_maybe n =+ if n < fromIntegral (minBound::Int16) ||+ n > fromIntegral (maxBound::Int16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word64_to_int32_maybe :: Word64 -> Maybe Int32+word64_to_int32_maybe n =+ if n < fromIntegral (minBound::Int32) ||+ n > fromIntegral (maxBound::Int32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word64_to_int64_maybe :: Word64 -> Maybe Int64+word64_to_int64_maybe n =+ if n < fromIntegral (minBound::Int64) ||+ n > fromIntegral (maxBound::Int64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+word64_to_int_maybe :: Word64 -> Maybe Int+word64_to_int_maybe n =+ if n < fromIntegral (minBound::Int) ||+ n > fromIntegral (maxBound::Int)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int8_to_word8_maybe :: Int8 -> Maybe Word8+int8_to_word8_maybe n =+ if n < fromIntegral (minBound::Word8) ||+ n > fromIntegral (maxBound::Word8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int8_to_word16_maybe :: Int8 -> Maybe Word16+int8_to_word16_maybe n =+ if n < fromIntegral (minBound::Word16) ||+ n > fromIntegral (maxBound::Word16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int8_to_word32_maybe :: Int8 -> Maybe Word32+int8_to_word32_maybe n =+ if n < fromIntegral (minBound::Word32) ||+ n > fromIntegral (maxBound::Word32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int8_to_word64_maybe :: Int8 -> Maybe Word64+int8_to_word64_maybe n =+ if n < fromIntegral (minBound::Word64) ||+ n > fromIntegral (maxBound::Word64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int8_to_int16_maybe :: Int8 -> Maybe Int16+int8_to_int16_maybe n =+ if n < fromIntegral (minBound::Int16) ||+ n > fromIntegral (maxBound::Int16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int8_to_int32_maybe :: Int8 -> Maybe Int32+int8_to_int32_maybe n =+ if n < fromIntegral (minBound::Int32) ||+ n > fromIntegral (maxBound::Int32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int8_to_int64_maybe :: Int8 -> Maybe Int64+int8_to_int64_maybe n =+ if n < fromIntegral (minBound::Int64) ||+ n > fromIntegral (maxBound::Int64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int8_to_int_maybe :: Int8 -> Maybe Int+int8_to_int_maybe n =+ if n < fromIntegral (minBound::Int) ||+ n > fromIntegral (maxBound::Int)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int16_to_word8_maybe :: Int16 -> Maybe Word8+int16_to_word8_maybe n =+ if n < fromIntegral (minBound::Word8) ||+ n > fromIntegral (maxBound::Word8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int16_to_word16_maybe :: Int16 -> Maybe Word16+int16_to_word16_maybe n =+ if n < fromIntegral (minBound::Word16) ||+ n > fromIntegral (maxBound::Word16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int16_to_word32_maybe :: Int16 -> Maybe Word32+int16_to_word32_maybe n =+ if n < fromIntegral (minBound::Word32) ||+ n > fromIntegral (maxBound::Word32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int16_to_word64_maybe :: Int16 -> Maybe Word64+int16_to_word64_maybe n =+ if n < fromIntegral (minBound::Word64) ||+ n > fromIntegral (maxBound::Word64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int16_to_int8_maybe :: Int16 -> Maybe Int8+int16_to_int8_maybe n =+ if n < fromIntegral (minBound::Int8) ||+ n > fromIntegral (maxBound::Int8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int16_to_int32_maybe :: Int16 -> Maybe Int32+int16_to_int32_maybe n =+ if n < fromIntegral (minBound::Int32) ||+ n > fromIntegral (maxBound::Int32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int16_to_int64_maybe :: Int16 -> Maybe Int64+int16_to_int64_maybe n =+ if n < fromIntegral (minBound::Int64) ||+ n > fromIntegral (maxBound::Int64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int16_to_int_maybe :: Int16 -> Maybe Int+int16_to_int_maybe n =+ if n < fromIntegral (minBound::Int) ||+ n > fromIntegral (maxBound::Int)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int32_to_word8_maybe :: Int32 -> Maybe Word8+int32_to_word8_maybe n =+ if n < fromIntegral (minBound::Word8) ||+ n > fromIntegral (maxBound::Word8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int32_to_word16_maybe :: Int32 -> Maybe Word16+int32_to_word16_maybe n =+ if n < fromIntegral (minBound::Word16) ||+ n > fromIntegral (maxBound::Word16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int32_to_word32_maybe :: Int32 -> Maybe Word32+int32_to_word32_maybe n =+ if n < fromIntegral (minBound::Word32) ||+ n > fromIntegral (maxBound::Word32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int32_to_word64_maybe :: Int32 -> Maybe Word64+int32_to_word64_maybe n =+ if n < fromIntegral (minBound::Word64) ||+ n > fromIntegral (maxBound::Word64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int32_to_int8_maybe :: Int32 -> Maybe Int8+int32_to_int8_maybe n =+ if n < fromIntegral (minBound::Int8) ||+ n > fromIntegral (maxBound::Int8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int32_to_int16_maybe :: Int32 -> Maybe Int16+int32_to_int16_maybe n =+ if n < fromIntegral (minBound::Int16) ||+ n > fromIntegral (maxBound::Int16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int32_to_int64_maybe :: Int32 -> Maybe Int64+int32_to_int64_maybe n =+ if n < fromIntegral (minBound::Int64) ||+ n > fromIntegral (maxBound::Int64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int32_to_int_maybe :: Int32 -> Maybe Int+int32_to_int_maybe n =+ if n < fromIntegral (minBound::Int) ||+ n > fromIntegral (maxBound::Int)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int64_to_word8_maybe :: Int64 -> Maybe Word8+int64_to_word8_maybe n =+ if n < fromIntegral (minBound::Word8) ||+ n > fromIntegral (maxBound::Word8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int64_to_word16_maybe :: Int64 -> Maybe Word16+int64_to_word16_maybe n =+ if n < fromIntegral (minBound::Word16) ||+ n > fromIntegral (maxBound::Word16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int64_to_word32_maybe :: Int64 -> Maybe Word32+int64_to_word32_maybe n =+ if n < fromIntegral (minBound::Word32) ||+ n > fromIntegral (maxBound::Word32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int64_to_word64_maybe :: Int64 -> Maybe Word64+int64_to_word64_maybe n =+ if n < fromIntegral (minBound::Word64) ||+ n > fromIntegral (maxBound::Word64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int64_to_int8_maybe :: Int64 -> Maybe Int8+int64_to_int8_maybe n =+ if n < fromIntegral (minBound::Int8) ||+ n > fromIntegral (maxBound::Int8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int64_to_int16_maybe :: Int64 -> Maybe Int16+int64_to_int16_maybe n =+ if n < fromIntegral (minBound::Int16) ||+ n > fromIntegral (maxBound::Int16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int64_to_int32_maybe :: Int64 -> Maybe Int32+int64_to_int32_maybe n =+ if n < fromIntegral (minBound::Int32) ||+ n > fromIntegral (maxBound::Int32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int64_to_int_maybe :: Int64 -> Maybe Int+int64_to_int_maybe n =+ if n < fromIntegral (minBound::Int) ||+ n > fromIntegral (maxBound::Int)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int_to_word8_maybe :: Int -> Maybe Word8+int_to_word8_maybe n =+ if n < fromIntegral (minBound::Word8) ||+ n > fromIntegral (maxBound::Word8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int_to_word16_maybe :: Int -> Maybe Word16+int_to_word16_maybe n =+ if n < fromIntegral (minBound::Word16) ||+ n > fromIntegral (maxBound::Word16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int_to_word32_maybe :: Int -> Maybe Word32+int_to_word32_maybe n =+ if n < fromIntegral (minBound::Word32) ||+ n > fromIntegral (maxBound::Word32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int_to_word64_maybe :: Int -> Maybe Word64+int_to_word64_maybe n =+ if n < fromIntegral (minBound::Word64) ||+ n > fromIntegral (maxBound::Word64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int_to_int8_maybe :: Int -> Maybe Int8+int_to_int8_maybe n =+ if n < fromIntegral (minBound::Int8) ||+ n > fromIntegral (maxBound::Int8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int_to_int16_maybe :: Int -> Maybe Int16+int_to_int16_maybe n =+ if n < fromIntegral (minBound::Int16) ||+ n > fromIntegral (maxBound::Int16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int_to_int32_maybe :: Int -> Maybe Int32+int_to_int32_maybe n =+ if n < fromIntegral (minBound::Int32) ||+ n > fromIntegral (maxBound::Int32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+int_to_int64_maybe :: Int -> Maybe Int64+int_to_int64_maybe n =+ if n < fromIntegral (minBound::Int64) ||+ n > fromIntegral (maxBound::Int64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+integer_to_word8_maybe :: Integer -> Maybe Word8+integer_to_word8_maybe n =+ if n < fromIntegral (minBound::Word8) ||+ n > fromIntegral (maxBound::Word8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+integer_to_word16_maybe :: Integer -> Maybe Word16+integer_to_word16_maybe n =+ if n < fromIntegral (minBound::Word16) ||+ n > fromIntegral (maxBound::Word16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+integer_to_word32_maybe :: Integer -> Maybe Word32+integer_to_word32_maybe n =+ if n < fromIntegral (minBound::Word32) ||+ n > fromIntegral (maxBound::Word32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+integer_to_word64_maybe :: Integer -> Maybe Word64+integer_to_word64_maybe n =+ if n < fromIntegral (minBound::Word64) ||+ n > fromIntegral (maxBound::Word64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+integer_to_int8_maybe :: Integer -> Maybe Int8+integer_to_int8_maybe n =+ if n < fromIntegral (minBound::Int8) ||+ n > fromIntegral (maxBound::Int8)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+integer_to_int16_maybe :: Integer -> Maybe Int16+integer_to_int16_maybe n =+ if n < fromIntegral (minBound::Int16) ||+ n > fromIntegral (maxBound::Int16)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+integer_to_int32_maybe :: Integer -> Maybe Int32+integer_to_int32_maybe n =+ if n < fromIntegral (minBound::Int32) ||+ n > fromIntegral (maxBound::Int32)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+integer_to_int64_maybe :: Integer -> Maybe Int64+integer_to_int64_maybe n =+ if n < fromIntegral (minBound::Int64) ||+ n > fromIntegral (maxBound::Int64)+ then Nothing+ else Just (fromIntegral n)++-- | Type specialised 'fromIntegral'+integer_to_int_maybe :: Integer -> Maybe Int+integer_to_int_maybe n =+ if n < fromIntegral (minBound::Int) ||+ n > fromIntegral (maxBound::Int)+ then Nothing+ else Just (fromIntegral n)
+ Music/Theory/Math/OEIS.hs view
@@ -0,0 +1,27 @@+-- | The On-Line Encyclopedia of Integer Sequences, <http://oeis.org/>+module Music.Theory.Math.OEIS where++-- | <http://oeis.org/A000290>+--+-- The squares of the non-negative integers.+--+-- > import Data.List+-- > [0,1,4,9,16,25,36,49,64,81,100] `isInfixOf` a000290+a000290 :: Integral n => [n]+a000290 = let square n = n * n in map square [0..]++-- | <http://oeis.org/A002267>+a002267 :: Num n => [n]+a002267 = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 41, 47, 59, 71]++-- | <http://oeis.org/A126709>+--+-- Loh-Shu magic square, attributed to the legendary Fu Xi (Fuh-Hi).+a126709 :: Num n => [n]+a126709 = [4, 9, 2, 3, 5, 7, 8, 1, 6]++-- | <http://oeis.org/A126710>+--+-- Jaina inscription of the twelfth or thirteenth century, Khajuraho, India.+a126710 :: Num n => [n]+a126710 = [7, 12, 1, 14, 2, 13, 8, 11, 16, 3, 10, 5, 9, 6, 15, 4]
Music/Theory/Maybe.hs view
@@ -1,7 +1,11 @@ -- | Extensions to "Data.Maybe". module Music.Theory.Maybe where --- import Data.Maybe {- base -}+import Data.Maybe {- base -}++-- | Variant with error text.+from_just :: String -> Maybe a -> a+from_just err = fromMaybe (error err) -- | Variant of unzip. --
Music/Theory/Meter/Barlow_1987.hs view
@@ -42,7 +42,7 @@ else r -- | Specialised variant of 'fromIntegral'.-to_r :: (Integral n,Show n) => n -> R+to_r :: Integral n => n -> R to_r = fromIntegral -- | Variant on 'div' with input constraints.@@ -91,7 +91,7 @@ -- | The first /n/th primes, reversed. -- -- > reverse_primes 14 == [43,41,37,31,29,23,19,17,13,11,7,5,3,2]-reverse_primes :: (Integral n,Show n) => n -> [n]+reverse_primes :: Integral n => n -> [n] reverse_primes n = reverse (genericTake n primes) -- | Generate prime stratification for /n/.
Music/Theory/Metric/Polansky_1996.hs view
@@ -116,7 +116,7 @@ -- -- > olm_general (abs_dif (-)) [0,2,4,1,0] [2,3,0,4,1] == 1.25 -- > olm_general (abs_dif (-)) [1,5,12,2,9,6] [7,6,4,9,8,1] == 4.6-olm_general :: (Fractional a,Enum a,Fractional n) => Interval a n -> [a] -> [a] -> n+olm_general :: Fractional n => Interval a n -> [a] -> [a] -> n olm_general f p q = let r = zipWith (-) (d_dx f p) (d_dx f q) z = sum (map abs r)@@ -151,7 +151,7 @@ -- -- > olm (abs_dif dif_r) (abs_ix_dif dif_r) (const 1) [1,5,12,2,9,6] [7,6,4,9,8,1] == 4.6 -- > olm (abs_dif dif_r) (abs_ix_dif dif_r) maximum [1,5,12,2,9,6] [7,6,4,9,8,1] == 0.46-olm :: (Fractional a,Enum a) => Psi a -> Delta n a -> ([a] -> a) -> [n] -> [n] -> a+olm :: Fractional a => Psi a -> Delta n a -> ([a] -> a) -> [n] -> [n] -> a olm psi delta maxint m n = let l = length m l' = fromIntegral l - 1@@ -162,23 +162,23 @@ -- > olm_no_delta [0,2,4,1,0] [2,3,0,4,1] == 1.25 -- > olm_no_delta [1,6,2,5,11] [3,15,13,2,9] == 4.5-olm_no_delta :: (Real a,Real n,Enum n,Fractional n) => [a] -> [a] -> n+olm_no_delta :: (Real a,Real n,Fractional n) => [a] -> [a] -> n olm_no_delta = olm (abs_dif dif_r) (abs_ix_dif dif_r) (const 1) -- > olm_no_delta_squared [0,2,4,1,0] [2,3,0,4,1] == sum (map sqrt [3,5,7,8]) / 4-olm_no_delta_squared :: (Enum a,Floating a) => [a] -> [a] -> a+olm_no_delta_squared :: Floating a => [a] -> [a] -> a olm_no_delta_squared = olm (sqrt_abs_dif (-)) (sqr_abs_ix_dif (-)) (const 1) second_order :: (Num n) => ([n] -> [n] -> t) -> [n] -> [n] -> t second_order f p q = f (d_dx_abs (-) p) (d_dx_abs (-) q) -- > olm_no_delta_second_order [0,2,4,1,0] [2,3,0,4,1] == 1.0-olm_no_delta_second_order :: (Real a,Enum a,Fractional a) => [a] -> [a] -> a+olm_no_delta_second_order :: (Real a,Fractional a) => [a] -> [a] -> a olm_no_delta_second_order = second_order olm_no_delta -- p.301 erroneously gives this as sum (map sqrt [2,0,1]) / 3 -- > olm_no_delta_squared_second_order [0,2,4,1,0] [2,3,0,4,1] == sum (map sqrt [4,0,3]) / 3-olm_no_delta_squared_second_order :: (Enum a,Floating a) => [a] -> [a] -> a+olm_no_delta_squared_second_order :: Floating a => [a] -> [a] -> a olm_no_delta_squared_second_order = second_order olm_no_delta_squared -- | Second order binomial coefficient, p.307@@ -199,7 +199,7 @@ -- > ord_hist [LT,GT,GT] == (1,0,2) ord_hist :: Integral t => [Ordering] -> (t,t,t) ord_hist x =- let h = L.histogram x+ let h = L.generic_histogram x f n = fromMaybe 0 (lookup n h) in (f LT,f EQ,f GT) @@ -279,7 +279,7 @@ let g = abs . sum . d_dx f in abs (g p - g q) / fromIntegral (length p - 1) -ocm_zcm :: (Fractional n, Num a) => Interval a n -> [a] -> [a] -> (n, n, [n])+ocm_zcm :: Fractional n => Interval a n -> [a] -> [a] -> (n, n, [n]) ocm_zcm f p q = let p' = concat (C.half_matrix_f f p) q' = concat (C.half_matrix_f f q)@@ -293,7 +293,7 @@ -- -- > ocm (abs_dif (-)) [1,6,2,5,11] [3,15,13,2,9] == 5.2 -- > ocm (abs_dif (-)) [1,5,12,2,9,6] [7,6,4,9,8,1] == 3.6-ocm :: (Fractional a,Enum a,Fractional n) => Interval a n -> [a] -> [a] -> n+ocm :: Fractional n => Interval a n -> [a] -> [a] -> n ocm f p q = let (z,c,_) = ocm_zcm f p q in z / c@@ -302,7 +302,7 @@ -- -- > ocm_absolute_scaled (abs_dif (-)) [1,6,2,5,11] [3,15,13,2,9] == 0.4 -- > ocm_absolute_scaled (abs_dif (-)) [1,5,12,2,9,6] [7,6,4,9,8,1] == 54/(15*11)-ocm_absolute_scaled :: (Ord a,Fractional a,Enum a,Ord n,Fractional n) => Interval a n -> [a] -> [a] -> n+ocm_absolute_scaled :: (Ord n,Fractional n) => Interval a n -> [a] -> [a] -> n ocm_absolute_scaled f p q = let (z,c,m) = ocm_zcm f p q in z / (c * maximum m)
+ Music/Theory/Monad.hs view
@@ -0,0 +1,10 @@+-- | Monad functions.+module Music.Theory.Monad where++repeatM_ :: (Monad m) => m a -> m ()+repeatM_ = sequence_ . repeat++iterateM_ :: (Monad m) => st -> (st -> m st) -> m ()+iterateM_ st f = do+ st' <- f st+ iterateM_ st' f
+ Music/Theory/Ord.hs view
@@ -0,0 +1,38 @@+-- | 'Ordering' functions+module Music.Theory.Ord where++-- | Specialised 'fromEnum'.+ord_to_int :: Ordering -> Int+ord_to_int = fromEnum++-- | Specialised 'toEnum'.+int_to_ord :: Int -> Ordering+int_to_ord = toEnum++-- | Invert 'Ordering'.+--+-- > map ord_invert [LT,EQ,GT] == [GT,EQ,LT]+ord_invert :: Ordering -> Ordering+ord_invert x =+ case x of+ LT -> GT+ EQ -> EQ+ GT -> LT++-- | Given 'Ordering', re-order pair,+order_pair :: Ordering -> (t,t) -> (t,t)+order_pair o (x,y) =+ case o of+ LT -> (x,y)+ EQ -> (x,y)+ GT -> (y,x)++-- | Sort a pair of equal type values using given comparison function.+--+-- > sort_pair compare ('b','a') == ('a','b')+sort_pair :: (t -> t -> Ordering) -> (t,t) -> (t,t)+sort_pair fn (x,y) = order_pair (fn x y) (x,y)++-- | Variant where the comparison function may not compute a value.+sort_pair_m :: (t -> t -> Maybe Ordering) -> (t,t) -> Maybe (t,t)+sort_pair_m fn (x,y) = fmap (`order_pair` (x,y)) (fn x y)
+ Music/Theory/Parse.hs view
@@ -0,0 +1,16 @@+module Music.Theory.Parse where++import Data.Maybe {- base -}++import qualified Text.ParserCombinators.Parsec as P {- parsec -}++-- | A 'Char' parser.+type P a = P.GenParser Char () a++-- | Boolean 'P' for given 'Char'.+is_char :: Char -> P Bool+is_char = fmap isJust . P.optionMaybe . P.char++-- | Parse 'Integral'.+parse_int :: Integral i => P i+parse_int = fmap (fromInteger . read) (P.many1 P.digit)
Music/Theory/Permutations.hs view
@@ -39,7 +39,7 @@ -- -- > let p = permutation [1..4] [4,3,2,1] -- > in apply_permutation p [1..4] == [4,3,2,1]-apply_permutation :: (Eq a) => P.Permute -> [a] -> [a]+apply_permutation :: P.Permute -> [a] -> [a] apply_permutation f p = map (p !!) (P.elems f) -- | Composition of 'apply_permutation' and 'from_cycles'.@@ -48,7 +48,7 @@ -- > apply_permutation_c [[0,2],[1],[3,4]] [1..5] == [3,2,1,5,4] -- > apply_permutation_c [[0,1,4],[2,3]] [1..5] == [2,5,4,3,1] -- > apply_permutation_c [[0,1,3],[2,4]] [1..5] == [2,4,5,1,3]-apply_permutation_c :: (Eq a) => [[Int]] -> [a] -> [a]+apply_permutation_c :: [[Int]] -> [a] -> [a] apply_permutation_c = apply_permutation . from_cycles -- | True if the inverse of /p/ is /p/.@@ -155,4 +155,8 @@ map P.cycles (permutations_n 3) map P.cycles (permutations_n 4) partition not (map non_invertible (permutations_n 4))++import Data.List {- base -}+putStrLn $ unlines $ map unwords $ permutations ["A0","A1","B0"]+ -}
Music/Theory/Permutations/List.hs view
@@ -1,14 +1,16 @@ -- | List permutation functions. module Music.Theory.Permutations.List where -import qualified Math.Combinatorics.Multiset as C-import qualified Music.Theory.Permutations as P+import Data.List {- base -}+import qualified Math.Combinatorics.Multiset as C {- multiset-comb -} +import qualified Music.Theory.Permutations as P {- hmt -}+ -- | Generate all permutations. -- -- > permutations [0,3] == [[0,3],[3,0]] -- > length (permutations [1..5]) == P.n_permutations 5-permutations :: (Eq a) => [a] -> [[a]]+permutations :: [a] -> [[a]] permutations i = let f p = P.apply_permutation p i in map f (P.permutations_n (length i))@@ -18,3 +20,20 @@ -- > multiset_permutations [0,1,1] == [[0,1,1],[1,1,0],[1,0,1]] multiset_permutations :: (Ord a) => [a] -> [[a]] multiset_permutations = C.permutations . C.fromList++factorial :: (Enum a, Num a) => a -> a+factorial n = product [1..n]++-- | Calculate number of permutations of a multiset.+--+-- > let r = factorial 11 `div` product (map factorial [1,4,4,2])+-- > in multiset_permutations_n "MISSISSIPPI" == r+--+-- > multiset_permutations_n "MISSISSIPPI" == 34650+-- > length (multiset_permutations "MISSISSIPPI") == 34650+multiset_permutations_n :: Ord a => [a] -> Int+multiset_permutations_n x =+ let occ = map length . group . sort+ n = factorial (length x)+ d = product $ map factorial $ occ x+ in n `div` d
Music/Theory/Permutations/Morris_1984.hs view
@@ -8,6 +8,7 @@ import Data.Char {- base -} import Data.List {- base -} import Data.List.Split {- split -}+import Data.Maybe {- base -} import qualified Music.Theory.List as T {- hmt -} import qualified Music.Theory.Permutations as T {- hmt -}@@ -76,11 +77,14 @@ swap_all :: [a] -> [a] swap_all = flatten_pairs . map swap_pair . T.adj2 2 +numeric_spelling_tbl :: [(Char,Int)]+numeric_spelling_tbl = zip "1234567890ETABCD" [1 .. 16]+ -- | Parse abbreviated 'Hold' notation, characters are hexedecimal. ----- > to_abbrev "38A" == [3,8,10]+-- > to_abbrev "380ETA" == [3,8,10,11,12,13] to_abbrev :: String -> [Int]-to_abbrev = map digitToInt+to_abbrev = map (fromMaybe (error "to_abbrev") . flip lookup numeric_spelling_tbl) -- | Given a 'Hold' notation, generate permutation cycles. --@@ -99,6 +103,14 @@ else Left n : rec (m + 1) l' in rec 1 +-- | Given two sequences, derive the one-indexed "hold" list.+--+-- > derive_holds ("12345","13254") == [1]+derive_holds :: (Eq a,Enum n,Num n) => ([a],[a]) -> [n]+derive_holds (p,q) =+ let f n (i,j) = if i == j then Just n else Nothing+ in catMaybes (zipWith f [1..] (zip p q))+ -- | Two-tuple to two element list. pair_to_list :: (t,t) -> [t] pair_to_list (p,q) = [p,q]@@ -120,14 +132,14 @@ -- | Apply abbreviated 'Hold' notation, given cardinality. -- -- > swap_abbrev 8 [3,8] [2,1,4,3,6,5,8,7] == [1,2,4,6,3,8,5,7]-swap_abbrev :: Eq a => Int -> [Int] -> [a] -> [a]+swap_abbrev :: Int -> [Int] -> [a] -> [a] swap_abbrev k a = let c = to_zero_indexed (swaps_to_cycles (gen_swaps k a)) p = T.from_cycles c in T.apply_permutation p -- | Apply a 'Change'.-apply_change :: Eq a => Int -> Change -> [a] -> [a]+apply_change :: Int -> Change -> [a] -> [a] apply_change k p l = case p of Swap_All -> swap_all l@@ -140,7 +152,7 @@ -- > ,[[1,2,3,4,5],[2,1,3,4,5],[2,3,1,4,5],[3,2,4,1,5],[3,4,2,5,1] -- > ,[4,3,2,5,1],[4,2,3,1,5],[2,4,1,3,5],[2,1,4,3,5],[1,2,4,3,5]]) -- > in apply_method cambridgeshire_slow_course_doubles [1..5] == r-apply_method :: Eq a => Method -> [a] -> ([a],[[a]])+apply_method :: Method -> [a] -> ([a],[[a]]) apply_method m l = let k = length l f z e = (apply_change k e z,z)@@ -165,9 +177,7 @@ -- * Methods --- | Cambridgeshire Slow Course Doubles.------ <https://rsw.me.uk/blueline/methods/view/Cambridgeshire_Slow_Course_Doubles>+-- | <https://rsw.me.uk/blueline/methods/view/Cambridgeshire_Slow_Course_Doubles> -- -- > length (closed_method cambridgeshire_slow_course_doubles [1..5]) == 3 cambridgeshire_slow_course_doubles :: Method@@ -195,9 +205,7 @@ let a = ("7.1.5.123.7.345.7",Just "127") in parse_method a --- | Cambridge Surprise Major.------ <https://rsw.me.uk/blueline/methods/view/Cambridge_Surprise_Major>+-- | <https://rsw.me.uk/blueline/methods/view/Cambridge_Surprise_Major> -- -- > length (closed_method cambridge_surprise_major [1..8]) == 7 cambridge_surprise_major :: Method@@ -205,12 +213,19 @@ let a = ("-38-14-1258-36-14-58-16-78",Just "12") in parse_method a --- | Smithsonian Surprise Royal.------ <https://rsw.me.uk/blueline/methods/view/Smithsonian_Surprise_Royal>+-- | <https://rsw.me.uk/blueline/methods/view/Smithsonian_Surprise_Royal> ----- > length (closed_method smithsonian_surprise_royal [1..10]) == 9+-- > let m = closed_method smithsonian_surprise_royal [1..10]+-- > (length m,nub (map length m),sum (map length m)) == (9,[40],360) smithsonian_surprise_royal :: Method smithsonian_surprise_royal =- let a = ("-3A-14-5A-16-347A-18-1456-5A-16-7A",Just "12")+ let a = ("-30-14-50-16-3470-18-1456-50-16-70",Just "12") in parse_method a++-- | <https://rsw.me.uk/blueline/methods/view/Ecumenical_Surprise_Maximus>+--+-- > let m = closed_method ecumenical_surprise_maximus [1..12]+-- > (length m,nub (map length m),sum (map length m)) == (11,[48],528)+ecumenical_surprise_maximus :: Method+ecumenical_surprise_maximus =+ parse_method ("x3Tx14x5Tx16x7Tx1238x149Tx50x16x7Tx18.90.ET",Just "12")
Music/Theory/Pitch.hs view
@@ -4,12 +4,45 @@ import Data.Char {- base -} import Data.Function {- base -} import Data.List {- base -}+import Data.Maybe {- base -}+import Text.Printf {- base -} import qualified Music.Theory.List as T {- hmt -} import qualified Music.Theory.Math as T {- hmt -}-import Music.Theory.Pitch.Note {- hmt -}-import Music.Theory.Pitch.Spelling {- hmt -}+import qualified Music.Theory.Pitch.Note as T {- hmt -} +-- * Octave & pitch-class (generic)++-- | 'Octave' and 'PitchClass' duple.+type Octave_PitchClass i = (i,i)++-- | Normalise 'Octave_PitchClass' value, ie. ensure pitch-class is in (0,11).+octave_pitchclass_nrm :: Integral i => Octave_PitchClass i -> Octave_PitchClass i+octave_pitchclass_nrm (o,pc) =+ if pc > 11+ then octave_pitchclass_nrm (o+1,pc-12)+ else if pc < 0+ then octave_pitchclass_nrm (o-1,pc+12)+ else (o,pc)++-- | Transpose 'Octave_PitchClass' value.+octave_pitchclass_trs :: Integral i => i -> Octave_PitchClass i -> Octave_PitchClass i+octave_pitchclass_trs n (o,pc) =+ let pc' = fromIntegral pc+ k = pc' + n+ (i,j) = k `divMod` 12+ in (fromIntegral o + fromIntegral i,fromIntegral j)++-- | 'Octave_PitchClass' value to integral /midi/ note number.+octave_pitchclass_to_midi :: Integral i => Octave_PitchClass i -> i+octave_pitchclass_to_midi (o,pc) = 60 + ((o - 4) * 12) + pc++-- | Inverse of 'octave_pitchclass_to_midi'.+midi_to_octave_pitchclass :: Integral i => i -> Octave_PitchClass i+midi_to_octave_pitchclass n = (n - 12) `divMod` 12++-- * Octave & PitchClass+ -- | Pitch classes are modulo twelve integers. type PitchClass = Int @@ -17,30 +50,93 @@ type Octave = Int -- | 'Octave' and 'PitchClass' duple.-type Octave_PitchClass i = (i,i) type OctPC = (Octave,PitchClass) +-- | Translate from generic octave & pitch-class duple.+to_octpc :: (Integral pc, Integral oct) => (oct,pc) -> OctPC+to_octpc (oct,pc) = (fromIntegral oct,fromIntegral pc)++-- | Normalise 'OctPC'.+--+-- > octpc_nrm (4,16) == (5,4)+octpc_nrm :: OctPC -> OctPC+octpc_nrm = octave_pitchclass_nrm++-- | Transpose 'OctPC'.+--+-- > octpc_trs 7 (4,9) == (5,4)+-- > octpc_trs (-11) (4,9) == (3,10)+octpc_trs :: Int -> OctPC -> OctPC+octpc_trs = octave_pitchclass_trs++-- | Enumerate range, inclusive.+--+-- > octpc_range ((3,8),(4,1)) == [(3,8),(3,9),(3,10),(3,11),(4,0),(4,1)]+octpc_range :: (OctPC,OctPC) -> [OctPC]+octpc_range (l,r) =+ let (l',r') = (octpc_to_midi l,octpc_to_midi r)+ in map midi_to_octpc [l' .. r']++-- * Midi note number++-- | Midi note number+type Midi = Int++-- | 'OctPC' value to integral /midi/ note number.+--+-- > map octpc_to_midi [(0,0),(2,6),(4,9),(9,0)] == [12,42,69,120]+-- > map octpc_to_midi [(0,9),(8,0)] == [21,108]+octpc_to_midi :: OctPC -> Midi+octpc_to_midi = octave_pitchclass_to_midi++-- | Inverse of 'octpc_to_midi'.+--+-- > map midi_to_octpc [40,69] == [(2,4),(4,9)]+midi_to_octpc :: Midi -> OctPC+midi_to_octpc = midi_to_octave_pitchclass++-- * Octave & fractional pitch-class++-- | Fractional midi note number.+type FMidi = Double++-- | Fractional octave pitch-class (octave is integral, pitch-class is fractional).+type FOctPC = (Int,Double)++-- | 'fromIntegral' of 'octpc_to_midi'.+octpc_to_fmidi :: (Integral i,Num n) => Octave_PitchClass i -> n+octpc_to_fmidi = fromIntegral . octave_pitchclass_to_midi++-- | Fractional midi to fractional octave pitch-class.+--+-- > fmidi_to_foctpc 69.5 == (4,9.5)+fmidi_to_foctpc :: RealFrac f => f -> (Octave,f)+fmidi_to_foctpc n = let o = (floor n - 12) `div` 12 in (o,n - (fromIntegral (o + 1) * 12))++-- | Octave of fractional midi note number.+fmidi_octave :: RealFrac f => f -> Octave+fmidi_octave = fst . fmidi_to_foctpc++foctpc_to_fmidi :: RealFrac f => (Octave,f) -> f+foctpc_to_fmidi (o,pc) = (fromIntegral (o + 1) * 12) + pc++-- | Move fractional midi note number to indicated octave.+--+-- > map (fmidi_in_octave 1) [59.5,60.5] == [35.5,24.5]+fmidi_in_octave :: RealFrac f => Octave -> f -> f+fmidi_in_octave o m = let (_,pc) = fmidi_to_foctpc m in foctpc_to_fmidi (o,pc)++-- * Pitch+ -- | Common music notation pitch value.-data Pitch = Pitch {note :: Note_T- ,alteration :: Alteration_T+data Pitch = Pitch {note :: T.Note_T+ ,alteration :: T.Alteration_T ,octave :: Octave} deriving (Eq,Show) instance Ord Pitch where compare = pitch_compare --- | Generalised pitch, given by a generalised alteration.-data Pitch' = Pitch' Note_T Alteration_T' Octave- deriving (Eq,Show)---- | Pretty printer for 'Pitch''.-pitch'_pp :: Pitch' -> String-pitch'_pp (Pitch' n (_,a) o) = show n ++ a ++ show o---- | 'Pitch'' printed without octave.-pitch'_class_pp :: Pitch' -> String-pitch'_class_pp = T.dropWhileRight isDigit . pitch'_pp- -- | Simplify 'Pitch' to standard 12ET by deleting quarter tones. -- -- > let p = Pitch A QuarterToneSharp 4@@ -48,25 +144,25 @@ pitch_clear_quarter_tone :: Pitch -> Pitch pitch_clear_quarter_tone p = let Pitch n a o = p- in Pitch n (alteration_clear_quarter_tone a) o+ in Pitch n (T.alteration_clear_quarter_tone a) o -- | 'Pitch' to 'Octave' and 'PitchClass' notation. -- -- > pitch_to_octpc (Pitch F Sharp 4) == (4,6) pitch_to_octpc :: Integral i => Pitch -> Octave_PitchClass i-pitch_to_octpc = midi_to_octpc . pitch_to_midi+pitch_to_octpc = midi_to_octave_pitchclass . pitch_to_midi -- | Is 'Pitch' 12-ET. pitch_is_12et :: Pitch -> Bool-pitch_is_12et = alteration_is_12et . alteration+pitch_is_12et = T.alteration_is_12et . alteration -- | 'Pitch' to midi note number notation. -- -- > pitch_to_midi (Pitch A Natural 4) == 69 pitch_to_midi :: Integral i => Pitch -> i pitch_to_midi (Pitch n a o) =- let a' = alteration_to_diff_err a- n' = note_to_pc n+ let a' = T.alteration_to_diff_err a+ n' = T.note_to_pc n o' = fromIntegral o in 12 + o' * 12 + n' + a' @@ -75,17 +171,17 @@ -- > pitch_to_fmidi (Pitch A QuarterToneSharp 4) == 69.5 pitch_to_fmidi :: Fractional n => Pitch -> n pitch_to_fmidi (Pitch n a o) =- let a' = alteration_to_fdiff a+ let a' = T.alteration_to_fdiff a o' = fromIntegral o- n' = fromInteger (note_to_pc n)+ n' = fromInteger (T.note_to_pc n) in 12 + o' * 12 + n' + a' -- | Extract 'PitchClass' of 'Pitch' ----- > pitch_to_pc (Pitch A Natural 4) == 9--- > pitch_to_pc (Pitch F Sharp 4) == 6+-- > map pitch_to_pc [Pitch A Natural 4,Pitch F Sharp 4] == [9,6]+-- > map pitch_to_pc [Pitch C Flat 4,Pitch B Sharp 5] == [11,0] pitch_to_pc :: Pitch -> PitchClass-pitch_to_pc (Pitch n a _) = note_to_pc n + alteration_to_diff_err a+pitch_to_pc (Pitch n a _) = (T.note_to_pc n + T.alteration_to_diff_err a) `mod` 12 -- | 'Pitch' comparison, implemented via 'pitch_to_fmidi'. --@@ -95,93 +191,131 @@ let f = pitch_to_fmidi :: Pitch -> Double in compare `on` f --- | Given 'Spelling' function translate from 'OctPC' notation to--- 'Pitch'.-octpc_to_pitch :: Integral i => Spelling i -> Octave_PitchClass i -> Pitch-octpc_to_pitch sp (o,pc) =- let (n,a) = sp pc- in Pitch n a (fromIntegral o)---- | Normalise 'OctPC' value, ie. ensure 'PitchClass' is in (0,11).------ > octpc_nrm (4,16) == (5,4)-octpc_nrm :: Integral i => Octave_PitchClass i -> Octave_PitchClass i-octpc_nrm (o,pc) =- if pc > 11- then octpc_nrm (o+1,pc-12)- else if pc < 0- then octpc_nrm (o-1,pc+12)- else (o,pc)---- | Transpose 'OctPC' value.------ > octpc_trs 7 (4,9) == (5,4)--- > octpc_trs (-11) (4,9) == (3,10)-octpc_trs :: Integral i => i -> Octave_PitchClass i -> Octave_PitchClass i-octpc_trs n (o,pc) =- let pc' = fromIntegral pc- k = pc' + n- (i,j) = k `divMod` 12- in (fromIntegral o + fromIntegral i,fromIntegral j)---- | 'OctPC' value to integral /midi/ note number.------ > octpc_to_midi (4,9) == 69-octpc_to_midi :: Integral i => Octave_PitchClass i -> i-octpc_to_midi (o,pc) = 60 + ((fromIntegral o - 4) * 12) + pc+-- * Spelling --- | 'fromIntegral' of 'octpc_to_midi'.-octpc_to_fmidi :: (Integral i,Num n) => Octave_PitchClass i -> n-octpc_to_fmidi = fromIntegral . octpc_to_midi+-- | Function to spell a 'PitchClass'.+type Spelling n = n -> (T.Note_T,T.Alteration_T) --- | Inverse of 'octpc_to_midi'.------ > midi_to_octpc 69 == (4,9)-midi_to_octpc :: Integral i => i -> Octave_PitchClass i-midi_to_octpc n = (n - 12) `divMod` 12+-- | Variant of 'Spelling' for incomplete functions.+type Spelling_M i = i -> Maybe (T.Note_T,T.Alteration_T) --- | Enumerate range, inclusive.+-- | Given 'Spelling' function translate from 'OctPC' notation to 'Pitch'. ----- > octpc_range ((3,8),(4,1)) == [(3,8),(3,9),(3,10),(3,11),(4,0),(4,1)]-octpc_range :: (OctPC,OctPC) -> [OctPC]-octpc_range (l,r) =- let (l',r') = (octpc_to_midi l,octpc_to_midi r)- in map midi_to_octpc [l' .. r']+-- > octpc_to_pitch T.pc_spell_sharp (4,6) == Pitch T.F T.Sharp 4+octpc_to_pitch :: Integral i => Spelling i -> Octave_PitchClass i -> Pitch+octpc_to_pitch sp (o,pc) =+ let (n,a) = sp pc+ in Pitch n a (fromIntegral o) -- | Midi note number to 'Pitch'. -- -- > let r = ["C4","E♭4","F♯4"] -- > in map (pitch_pp . midi_to_pitch pc_spell_ks) [60,63,66] == r midi_to_pitch :: Integral i => Spelling i -> i -> Pitch-midi_to_pitch sp = octpc_to_pitch sp . midi_to_octpc+midi_to_pitch sp = octpc_to_pitch sp . midi_to_octave_pitchclass +-- | Print fractional midi note number as ET12 pitch with cents detune in parentheses.+--+-- > fmidi_et12_cents_pp 66.5 == "F♯4(+50)"+fmidi_et12_cents_pp :: Spelling PitchClass -> Double -> String+fmidi_et12_cents_pp sp =+ let f (m,c) =+ let d = T.num_diff_str (round c :: Int)+ d' = if null d then "" else "(" ++ d ++ ")"+ in pitch_pp (midi_to_pitch sp m) ++ d'+ in f . midi_detune_normalise . fmidi_to_midi_detune+ -- | Fractional midi note number to 'Pitch'. ----- > import Music.Theory.Pitch.Spelling--- > pitch_pp (fmidi_to_pitch pc_spell_ks 65.5) == "F𝄲4"--- > pitch_pp (fmidi_to_pitch pc_spell_ks 66.5) == "F𝄰4"--- > pitch_pp (fmidi_to_pitch pc_spell_ks 67.5) == "A𝄭4"--- > pitch_pp (fmidi_to_pitch pc_spell_ks 69.5) == "B𝄭4"-fmidi_to_pitch :: RealFrac n => Spelling Int -> n -> Pitch+-- > fmidi_to_pitch pc_spell_ks 69.25 == Nothing+fmidi_to_pitch :: RealFrac n => Spelling PitchClass -> n -> Maybe Pitch fmidi_to_pitch sp m = let m' = round m (Pitch n a o) = midi_to_pitch sp m' q = m - fromIntegral m'- in case alteration_edit_quarter_tone q a of- Nothing -> error "fmidi_to_pitch"- Just a' -> Pitch n a' o+ in case T.alteration_edit_quarter_tone q a of+ Nothing -> Nothing+ Just a' -> Just (Pitch n a' o) +-- | Erroring variant.+--+-- > import Music.Theory.Pitch.Spelling+-- > pitch_pp (fmidi_to_pitch_err pc_spell_ks 65.5) == "F𝄲4"+-- > pitch_pp (fmidi_to_pitch_err pc_spell_ks 66.5) == "F𝄰4"+-- > pitch_pp (fmidi_to_pitch_err pc_spell_ks 67.5) == "A𝄭4"+-- > pitch_pp (fmidi_to_pitch_err pc_spell_ks 69.5) == "B𝄭4"+fmidi_to_pitch_err :: (Show n,RealFrac n) => Spelling Int -> n -> Pitch+fmidi_to_pitch_err sp m = fromMaybe (error (show ("fmidi_to_pitch",m))) (fmidi_to_pitch sp m)+ -- | Composition of 'pitch_to_fmidi' and then 'fmidi_to_pitch'. -- -- > import Music.Theory.Pitch.Name as T -- > import Music.Theory.Pitch.Spelling as T -- -- > pitch_tranpose T.pc_spell_ks 2 T.ees5 == T.f5-pitch_tranpose :: RealFrac n => Spelling Int -> n -> Pitch -> Pitch+pitch_tranpose :: (RealFrac n,Show n) => Spelling Int -> n -> Pitch -> Pitch pitch_tranpose sp n p = let m = pitch_to_fmidi p- in fmidi_to_pitch sp (m + n)+ in fmidi_to_pitch_err sp (m + n) +-- | Displacement of /q/ into octave of /p/.+fmidi_in_octave_of :: RealFrac f => f -> f -> f+fmidi_in_octave_of p = fmidi_in_octave (fmidi_octave p)++-- | Octave displacement of /m2/ that is nearest /m1/.+--+-- > let {p = octpc_to_fmidi (2,1);q = map octpc_to_fmidi [(4,11),(4,0),(4,1)]}+-- > in map (fmidi_in_octave_nearest p) q == [35,36,37]+fmidi_in_octave_nearest :: RealFrac n => n -> n -> n+fmidi_in_octave_nearest m1 m2 =+ let m2' = fmidi_in_octave (fmidi_octave m1) m2+ m2'' = [m2' - 12,m2',m2' + 12]+ d = map (abs . (m1 -)) m2''+ z = sortOn snd (zip m2'' d)+ in fst (head z)++-- | Displacement of /q/ into octave above /p/.+--+-- > fmidi_in_octave_of 69 51 == 63+-- > fmidi_in_octave_nearest 69 51 == 63+-- > fmidi_in_octave_above 69 51 == 75+fmidi_in_octave_above :: RealFrac a => a -> a -> a+fmidi_in_octave_above p q = let r = fmidi_in_octave_nearest p q in if r < p then r + 12 else r++-- | Displacement of /q/ into octave below /p/.+--+-- > fmidi_in_octave_of 69 85 == 61+-- > fmidi_in_octave_nearest 69 85 == 73+-- > fmidi_in_octave_below 69 85 == 61+fmidi_in_octave_below :: RealFrac a => a -> a -> a+fmidi_in_octave_below p q = let r = fmidi_in_octave_nearest p q in if r > p then r - 12 else r++cps_in_octave' :: Floating f => (f -> f -> f) -> f -> f -> f+cps_in_octave' f p = fmidi_to_cps . f (cps_to_fmidi p) . cps_to_fmidi++-- | CPS form of 'fmidi_in_octave_nearest'.+--+-- > map cps_octave [440,256] == [4,4]+-- > round (cps_in_octave_nearest 440 256) == 512+cps_in_octave_nearest :: (Floating f,RealFrac f) => f -> f -> f+cps_in_octave_nearest = cps_in_octave' fmidi_in_octave_nearest++-- | Raise or lower the frequency /q/ by octaves until it is in the+-- octave starting at /p/.+--+-- > cps_in_octave_above 55.0 392.0 == 98.0+cps_in_octave_above :: (Ord a, Fractional a) => a -> a -> a+cps_in_octave_above p =+ let go q = if q > p * 2 then go (q / 2) else if q < p then go (q * 2) else q+ in go++-- > cps_in_octave_above' 55.0 392.0 == 97.99999999999999+cps_in_octave_above' :: (Floating f,RealFrac f) => f -> f -> f+cps_in_octave_above' = cps_in_octave' fmidi_in_octave_above++cps_in_octave_below :: (Floating f,RealFrac f) => f -> f -> f+cps_in_octave_below = cps_in_octave' fmidi_in_octave_below+ -- | Set octave of /p2/ so that it nearest to /p1/. -- -- > import Music.Theory.Pitch.Name as T@@ -190,13 +324,9 @@ -- > in map (pitch_pp_iso . f) [T.b4,T.c4,T.cis4] == r pitch_in_octave_nearest :: Pitch -> Pitch -> Pitch pitch_in_octave_nearest p1 p2 =- let o1 = octave p1- p2' = map (\n -> p2 {octave = n}) [o1 - 1,o1,o1 + 1]- m1 = pitch_to_fmidi p1 :: Double- m2 = map (pitch_to_fmidi) p2'- d = map (abs . (m1 -)) m2- z = sortBy (compare `on` snd) (zip p2' d)- in fst (head z)+ let f = pitch_to_fmidi :: Pitch -> Double+ o = fmidi_octave (fmidi_in_octave_nearest (f p1) (f p2))+ in p2 {octave = o} -- | Raise 'Note_T' of 'Pitch', account for octave transposition. --@@ -225,8 +355,8 @@ pitch_rewrite_threequarter_alteration :: Pitch -> Pitch pitch_rewrite_threequarter_alteration (Pitch n a o) = case a of- ThreeQuarterToneFlat -> pitch_note_lower (Pitch n QuarterToneSharp o)- ThreeQuarterToneSharp -> pitch_note_raise (Pitch n QuarterToneFlat o)+ T.ThreeQuarterToneFlat -> pitch_note_lower (Pitch n T.QuarterToneSharp o)+ T.ThreeQuarterToneSharp -> pitch_note_raise (Pitch n T.QuarterToneFlat o) _ -> Pitch n a o -- | Apply function to 'octave' of 'PitchClass'.@@ -237,22 +367,46 @@ -- * Frequency (CPS) --- | /Midi/ note number to cycles per second.+-- | /Midi/ note number to cycles per second, given frequency of ISO A4.+midi_to_cps_f0 :: (Integral i,Floating f) => f -> i -> f+midi_to_cps_f0 f0 = fmidi_to_cps_f0 f0 . fromIntegral++-- | 'midi_to_cps_f0' 440. -- -- > map midi_to_cps [60,69] == [261.6255653005986,440.0] midi_to_cps :: (Integral i,Floating f) => i -> f-midi_to_cps = fmidi_to_cps . fromIntegral+midi_to_cps = midi_to_cps_f0 440 --- | Fractional /midi/ note number to cycles per second.+-- | Fractional /midi/ note number to cycles per second, given frequency of ISO A4.+fmidi_to_cps_f0 :: Floating a => a -> a -> a+fmidi_to_cps_f0 f0 i = f0 * (2 ** ((i - 69) * (1 / 12)))++-- | 'fmidi_to_cps_f0' 440. -- -- > map fmidi_to_cps [69,69.1] == [440.0,442.5488940698553] fmidi_to_cps :: Floating a => a -> a-fmidi_to_cps i = 440 * (2 ** ((i - 69) * (1 / 12)))+fmidi_to_cps = fmidi_to_cps_f0 440 --- | 'fmidi_to_cps' of 'pitch_to_fmidi'.+-- | 'fmidi_to_cps' of 'pitch_to_fmidi', given frequency of ISO A4.+pitch_to_cps_f0 :: Floating n => n -> Pitch -> n+pitch_to_cps_f0 f0 = fmidi_to_cps_f0 f0 . pitch_to_fmidi++-- | 'pitch_to_cps_f0' 440. pitch_to_cps :: Floating n => Pitch -> n-pitch_to_cps = fmidi_to_cps . pitch_to_fmidi+pitch_to_cps = pitch_to_cps_f0 440 +-- | Frequency (cps = cycles per second) to fractional /midi/ note+-- number, given frequency of ISO A4 (mnn = 69).+cps_to_fmidi_f0 :: Floating a => a -> a -> a+cps_to_fmidi_f0 f0 a = (logBase 2 (a * (1 / f0)) * 12) + 69++-- | 'cps_to_fmidi_f0' @440@.+--+-- > cps_to_fmidi 440 == 69+-- > cps_to_fmidi (fmidi_to_cps 60.25) == 60.25+cps_to_fmidi :: Floating a => a -> a+cps_to_fmidi = cps_to_fmidi_f0 440+ -- | Frequency (cycles per second) to /midi/ note number, ie. 'round' -- of 'cps_to_fmidi'. --@@ -260,40 +414,123 @@ cps_to_midi :: (Integral i,Floating f,RealFrac f) => f -> i cps_to_midi = round . cps_to_fmidi --- | Frequency (cycles per second) to fractional /midi/ note number.+-- | 'midi_to_cps_f0' of 'octpc_to_midi', given frequency of ISO A4.+octpc_to_cps_f0 :: (Integral i,Floating n) => n -> Octave_PitchClass i -> n+octpc_to_cps_f0 f0 = midi_to_cps_f0 f0 . octave_pitchclass_to_midi++-- | 'octpc_to_cps_f0' 440. ----- > cps_to_fmidi 440 == 69--- > cps_to_fmidi (fmidi_to_cps 60.25) == 60.25-cps_to_fmidi :: Floating a => a -> a-cps_to_fmidi a = (logBase 2 (a * (1 / 440)) * 12) + 69+-- > octpc_to_cps (4,9) == 440+octpc_to_cps :: (Integral i,Floating n) => Octave_PitchClass i -> n+octpc_to_cps = octpc_to_cps_f0 440 +-- | 'midi_to_octpc' of 'cps_to_midi'.+cps_to_octpc :: (Floating f,RealFrac f,Integral i) => f -> Octave_PitchClass i+cps_to_octpc = midi_to_octave_pitchclass . cps_to_midi++cps_octave :: (Floating f,RealFrac f) => f -> Octave+cps_octave = fst . cps_to_octpc++-- * MIDI detune (cents)+ -- | Midi note number with cents detune.-type Midi_Detune = (Int,Double)+type Midi_Detune' c = (Int,c) +-- | Is cents in (-50,+50].+--+-- > map cents_is_normal [-250,-75,75,250] == replicate 4 False+cents_is_normal :: (Num c, Ord c) => c -> Bool+cents_is_normal c = c > (-50) && c <= 50++-- | 'cents_is_normal' of 'snd'.+midi_detune_is_normal :: (Num c, Ord c) => Midi_Detune' c -> Bool+midi_detune_is_normal = cents_is_normal . snd++-- | In normal form the detune is in the range (-50,+50] instead of [0,100) or wider.+--+-- > map midi_detune_normalise [(60,-250),(60,-75),(60,75),(60,250)]+midi_detune_normalise :: (Ord c,Num c) => Midi_Detune' c -> Midi_Detune' c+midi_detune_normalise (m,c) =+ if c > 50+ then midi_detune_normalise (m + 1,c - 100)+ else if c > (-50)+ then (m,c)+ else midi_detune_normalise (m - 1,c + 100)++-- | Inverse of 'cps_to_midi_detune', given frequency of ISO @A4@.+midi_detune_to_cps_f0 :: Real c => Double -> Midi_Detune' c -> Double+midi_detune_to_cps_f0 f0 (m,c) = fmidi_to_cps_f0 f0 (fromIntegral m + (realToFrac c / 100))++-- | Inverse of 'cps_to_midi_detune'.+--+-- > map midi_detune_to_cps [(69,0),(68,100)] == [440,440]+midi_detune_to_cps :: Real c => Midi_Detune' c -> Double+midi_detune_to_cps = midi_detune_to_cps_f0 440++-- | 'Midi_Detune' to fractional midi note number.+--+-- > midi_detune_to_fmidi (60,50.0) == 60.50+midi_detune_to_fmidi :: Real c => Midi_Detune' c -> Double+midi_detune_to_fmidi (mnn,c) = fromIntegral mnn + (realToFrac c / 100)++-- | 'Midi_Detune' to 'Pitch', detune must be precisely at a notateable Pitch.+--+-- > let p = Pitch {note = C, alteration = QuarterToneSharp, octave = 4}+-- > in midi_detune_to_pitch T.pc_spell_ks (midi_detune_nearest_24et (60,35)) == p+midi_detune_to_pitch :: Real c => Spelling Int -> Midi_Detune' c -> Pitch+midi_detune_to_pitch sp = fmidi_to_pitch_err sp . cps_to_fmidi . midi_detune_to_cps++-- | Midi note number with real-valued cents detune.+type Midi_Detune = Midi_Detune' Double++-- | Fractional midi note number to 'Midi_Detune'.+--+-- > fmidi_to_midi_detune 60.50 == (60,50.0)+fmidi_to_midi_detune :: Double -> Midi_Detune+fmidi_to_midi_detune mnn =+ let (n,c) = T.integral_and_fractional_parts mnn+ in (n,c * 100)+ -- | Frequency (in hertz) to 'Midi_Detune'. -- -- > map (fmap round . cps_to_midi_detune) [440.00,508.35] == [(69,0),(71,50)] cps_to_midi_detune :: Double -> Midi_Detune-cps_to_midi_detune f =- let (n,c) = T.integral_and_fractional_parts (cps_to_fmidi f)- in (n,c * 100)---- | Inverse of 'cps_to_midi_detune'.-midi_detune_to_cps :: Midi_Detune -> Double-midi_detune_to_cps (m,c) = fmidi_to_cps (fromIntegral m + (c / 100))+cps_to_midi_detune = fmidi_to_midi_detune . cps_to_fmidi --- | 'midi_to_cps' of 'octpc_to_midi'.+-- | Round /detune/ value to nearest multiple of @50@, normalised. ----- > octpc_to_cps (4,9) == 440-octpc_to_cps :: (Integral i,Floating n) => Octave_PitchClass i -> n-octpc_to_cps = midi_to_cps . octpc_to_midi+-- > map midi_detune_nearest_24et [(59,70),(59,80)] == [(59,50),(60,00)]+midi_detune_nearest_24et :: Midi_Detune -> Midi_Detune+midi_detune_nearest_24et (m,dt) = midi_detune_normalise (m,T.round_to 50 dt) --- | 'midi_to_octpc' of 'cps_to_midi'.-cps_to_octpc :: (Floating f,RealFrac f,Integral i) => f -> Octave_PitchClass i-cps_to_octpc = midi_to_octpc . cps_to_midi+-- * MIDI cents +-- | Midi note number with integral cents detune.+type Midi_Cents = Midi_Detune' Int++midi_detune_to_midi_cents :: Midi_Detune -> Midi_Cents+midi_detune_to_midi_cents (m,c) = (m,round c)++-- | Printed as /fmidi/ value with cents to two places. Must be normal.+--+-- > map midi_cents_pp [(60,0),(60,25)] == ["60.00","60.25"]+midi_cents_pp :: Midi_Cents -> String+midi_cents_pp (m,c) = if cents_is_normal c then printf "%d.%02d" m c else error "midi_cents_pp"+ -- * Parsers +-- | Parse possible octave from single integer.+--+-- > map (parse_octave 2) ["","4","x","11"]+parse_octave :: Num a => a -> String -> Maybe a+parse_octave def_o o =+ case o of+ [] -> Just def_o+ [n] -> if isDigit n+ then Just (fromIntegral (digitToInt n))+ else Nothing+ _ -> Nothing+ -- | Slight generalisation of ISO pitch representation. Allows octave -- to be elided, pitch names to be lower case, and double sharps -- written as @##@.@@ -304,59 +541,69 @@ -- > in mapMaybe (parse_iso_pitch_oct 4) ["C","Ab5","f##6",""] == r parse_iso_pitch_oct :: Octave -> String -> Maybe Pitch parse_iso_pitch_oct def_o s =- let nte n = let tb = zip "cdefgab" [C,D,E,F,G,A,B]- in lookup (toLower n) tb- oct o = case o of- [] -> Just def_o- [n] -> if isDigit n- then Just (fromIntegral (digitToInt n))- else Nothing- _ -> Nothing- mk n a o = case nte n of+ let mk n a o = case T.parse_note_t True n of Nothing -> Nothing- Just n' -> fmap (Pitch n' a) (oct o)+ Just n' -> fmap (Pitch n' a) (parse_octave def_o o) in case s of [] -> Nothing- n:'b':'b':o -> mk n DoubleFlat o- n:'#':'#':o -> mk n DoubleSharp o- n:'x':o -> mk n DoubleSharp o- n:'b':o -> mk n Flat o- n:'#':o -> mk n Sharp o- n:o -> mk n Natural o+ n:'b':'b':o -> mk n T.DoubleFlat o+ n:'#':'#':o -> mk n T.DoubleSharp o+ n:'x':o -> mk n T.DoubleSharp o+ n:'b':o -> mk n T.Flat o+ n:'#':o -> mk n T.Sharp o+ n:o -> mk n T.Natural o -- | Variant of 'parse_iso_pitch_oct' requiring octave. parse_iso_pitch :: String -> Maybe Pitch parse_iso_pitch = parse_iso_pitch_oct (error "parse_iso_pitch: no octave") +-- | 'error' variant.+parse_iso_pitch_err :: String -> Pitch+parse_iso_pitch_err = fromMaybe (error "parse_iso_pitch") . parse_iso_pitch+ -- * Pretty printers -- | Pretty printer for 'Pitch' (unicode, see 'alteration_symbol').+-- Option selects if 'Natural's are printed. ----- > pitch_pp (Pitch E Flat 4) == "E♭4"--- > pitch_pp (Pitch F QuarterToneSharp 3) == "F𝄲3"+-- > pitch_pp_opt (True,True) (Pitch T.E T.Natural 4) == "E♮4"+pitch_pp_opt :: (Bool,Bool) -> Pitch -> String+pitch_pp_opt (show_nat,show_oct) (Pitch n a o) =+ let a' = if a == T.Natural && not show_nat then "" else [T.alteration_symbol a]+ rem_oct_f c = isDigit c || c == '-' -- negative octave values...+ rem_oct = if show_oct then id else T.dropWhileRight rem_oct_f+ in rem_oct (show n ++ a' ++ show o)++-- | 'pitch_pp_opt' with default options, ie. (False,True).+--+-- > pitch_pp (Pitch T.E T.Natural 4) == "E4"+-- > pitch_pp (Pitch T.E T.Flat 4) == "E♭4"+-- > pitch_pp (Pitch T.F T.QuarterToneSharp 3) == "F𝄲3" pitch_pp :: Pitch -> String-pitch_pp (Pitch n a o) =- let a' = if a == Natural then "" else [alteration_symbol a]- in show n ++ a' ++ show o+pitch_pp = pitch_pp_opt (False,True) --- | 'Pitch' printed without octave.+-- | 'pitch_pp_opt' with options (False,False).+--+-- > pitch_class_pp (Pitch T.C T.ThreeQuarterToneSharp 0) == "C𝄰" pitch_class_pp :: Pitch -> String-pitch_class_pp = T.dropWhileRight isDigit . pitch_pp+pitch_class_pp = pitch_pp_opt (False,False) -- | Sequential list of /n/ pitch class names starting from /k/. --+-- > unwords (pitch_class_names_12et 0 12) == "C C♯ D E♭ E F F♯ G A♭ A B♭ B" -- > pitch_class_names_12et 11 2 == ["B","C"]-pitch_class_names_12et :: Integral n => n -> n -> [String]-pitch_class_names_12et k n =- let f = pitch_class_pp . midi_to_pitch pc_spell_ks+pitch_class_names_12et :: Integral n => Spelling n -> n -> n -> [String]+pitch_class_names_12et sp k n =+ let f = pitch_class_pp . midi_to_pitch sp in map f [60 + k .. 60 + k + n - 1] -- | Pretty printer for 'Pitch' (ISO, ASCII, see 'alteration_iso'). -- -- > pitch_pp_iso (Pitch E Flat 4) == "Eb4" -- > pitch_pp_iso (Pitch F DoubleSharp 3) == "Fx3"+-- > pitch_pp_iso (Pitch C ThreeQuarterToneSharp 4) -- error pitch_pp_iso :: Pitch -> String-pitch_pp_iso (Pitch n a o) = show n ++ alteration_iso a ++ show o+pitch_pp_iso (Pitch n a o) = show n ++ T.alteration_iso a ++ show o -- | Pretty printer for 'Pitch' (ASCII, see 'alteration_tonh'). --@@ -366,7 +613,7 @@ pitch_pp_hly :: Pitch -> String pitch_pp_hly (Pitch n a o) = let n' = map toLower (show n)- in n' ++ alteration_tonh a ++ show o+ in n' ++ T.alteration_tonh a ++ show o -- | Pretty printer for 'Pitch' (Tonhöhe, see 'alteration_tonh'). --@@ -377,9 +624,46 @@ pitch_pp_tonh (Pitch n a o) = let o' = show o in case (n,a) of- (B,Natural) -> "H" ++ o'- (B,Flat) -> "B" ++ o'- (B,DoubleFlat) -> "Heses" ++ o'- (A,Flat) -> "As" ++ o'- (E,Flat) -> "Es" ++ o'- _ -> show n ++ alteration_tonh a ++ o'+ (T.B,T.Natural) -> "H" ++ o'+ (T.B,T.Flat) -> "B" ++ o'+ (T.B,T.DoubleFlat) -> "Heses" ++ o'+ (T.A,T.Flat) -> "As" ++ o'+ (T.E,T.Flat) -> "Es" ++ o'+ _ -> show n ++ T.alteration_tonh a ++ o'++-- * 24ET++{- The 24ET pitch-class universe, with /sharp/ spellings, in octave '4'.++> length pc24et_univ == 24++> let r = "C C𝄲 C♯ C𝄰 D D𝄲 D♯ D𝄰 E E𝄲 F F𝄲 F♯ F𝄰 G G𝄲 G♯ G𝄰 A A𝄲 A♯ A𝄰 B B𝄲"+> in unwords (map pitch_class_pp pc24et_univ) == r++-}+pc24et_univ :: [Pitch]+pc24et_univ =+ let a = [T.Natural,T.QuarterToneSharp,T.Sharp,T.ThreeQuarterToneSharp]+ f (n,k) = map (\i -> Pitch n (a !! i) 4) [0 .. k - 1]+ in concatMap f (zip T.note_seq [4,4,2,4,4,4,2])++-- | 'genericIndex' into 'pc24et_univ'.+--+-- > pitch_class_pp (pc24et_to_pitch 13) == "F𝄰"+pc24et_to_pitch :: Integral i => i -> Pitch+pc24et_to_pitch = genericIndex pc24et_univ++-- * Pitch, rational alteration.++-- | Generalised pitch, given by a generalised alteration.+data Pitch_R = Pitch_R T.Note_T T.Alteration_R Octave+ deriving (Eq,Show)++-- | Pretty printer for 'Pitch_R'.+pitch_r_pp :: Pitch_R -> String+pitch_r_pp (Pitch_R n (_,a) o) = show n ++ a ++ show o++-- | 'Pitch_R' printed without octave.+pitch_r_class_pp :: Pitch_R -> String+pitch_r_class_pp = T.dropWhileRight isDigit . pitch_r_pp+
+ Music/Theory/Pitch/Chord.hs view
@@ -0,0 +1,159 @@+module Music.Theory.Pitch.Chord where++import Data.List {- base -}+import Data.Maybe {- base -}++import qualified Text.ParserCombinators.Parsec as P {- parsec -}++import qualified Music.Theory.Key as T {- hmt -}+import qualified Music.Theory.List as T {- hmt -}+import qualified Music.Theory.Pitch.Note as T {- hmt -}++type PC = (T.Note_T,T.Alteration_T)++pc_pp :: (T.Note_T, T.Alteration_T) -> [Char]+pc_pp (n,a) = T.note_pp n : T.alteration_iso a++-- | D = dominant, M = major+data Extension = D7 | M7 deriving (Eq,Show)++extension_tbl :: Num n => [(Extension, (String,n))]+extension_tbl = [(D7,("7",10)),(M7,("M7",11))]++extension_dat :: Num n => Extension -> (String,n)+extension_dat = flip T.lookup_err extension_tbl++extension_pp :: Extension -> String+extension_pp = fst . (extension_dat :: Extension -> (String,Int))++extension_to_pc :: Num n => Extension -> n+extension_to_pc = snd . extension_dat++data Chord_Type = Major | Minor+ | Augmented | Diminished+ | Diminished_7 | Half_Diminished+ | Suspended_2 | Suspended_4+ deriving (Eq,Show)++is_suspended :: Chord_Type -> Bool+is_suspended ty = ty `elem` [Suspended_2,Suspended_4]++-- | Names and pc-sets for chord types.+-- The name used here is in the first position, alternates follow.+chord_type_tbl :: Num n => [(Chord_Type,([String],[n]))]+chord_type_tbl =+ [(Major,(["","M","maj"],[0,4,7]))+ ,(Minor,(["m","min"],[0,3,7]))+ ,(Augmented,(["+","aug"],[0,4,8]))+ ,(Diminished,(["o","dim"],[0,3,6]))+ ,(Diminished_7,(["o7","dim7"],[0,3,6,9]))+ ,(Half_Diminished,(["Ø","halfdim","m7(b5)"],[0,3,6,10]))+ ,(Suspended_2,(["sus2"],[0,2,7]))+ ,(Suspended_4,(["sus4"],[0,5,7]))]++chord_type_dat :: Num n => Chord_Type -> ([String],[n])+chord_type_dat = flip T.lookup_err chord_type_tbl++chord_type_pp :: Chord_Type -> String+chord_type_pp = head . fst . (chord_type_dat :: Chord_Type -> ([String],[Int]))++chord_type_pcset :: Num n => Chord_Type -> [n]+chord_type_pcset = snd . chord_type_dat++-- (root,mode,extensions,bass)+data Chord = CH PC Chord_Type (Maybe Extension) (Maybe PC)+ deriving (Show)++chord_pcset :: Chord -> (Maybe Int,[Int])+chord_pcset (CH pc ty ex bs) =+ let get = m_error "chord_pcset" . T.note_alteration_to_pc+ pc' = get pc+ ty' = chord_type_pcset ty+ ex' = fmap extension_to_pc ex+ bs' = fmap get bs+ ch = map ((`mod` 12) . (+ pc')) (ty' ++ maybe [] return ex')+ ch' = maybe ch (flip delete ch) bs'+ in (bs',ch')++bass_pp :: PC -> String+bass_pp = ('/' :) . pc_pp++chord_pp :: Chord -> String+chord_pp (CH pc ty ex bs) =+ let (pre_ty,post_ty) = if is_suspended ty+ then (Nothing,Just ty)+ else (Just ty,Nothing)+ in concat [pc_pp pc+ ,maybe "" chord_type_pp pre_ty+ ,maybe "" extension_pp ex+ ,maybe "" chord_type_pp post_ty+ ,maybe "" bass_pp bs]++type P a = P.GenParser Char () a++m_error :: String -> Maybe a -> a+m_error txt = fromMaybe (error txt)++p_note_t :: P T.Note_T+p_note_t =+ fmap+ (m_error "p_note_t" . T.parse_note_t False)+ (P.oneOf "ABCDEFG")++p_alteration_t_iso :: P T.Alteration_T+p_alteration_t_iso =+ fmap+ (m_error "p_alteration_t_iso" . T.symbol_to_alteration_iso)+ (P.oneOf "b#x")++p_pc :: P PC+p_pc = do+ n <- p_note_t+ a <- P.optionMaybe p_alteration_t_iso+ return (n,fromMaybe T.Natural a)++p_mode_m :: P T.Mode_T+p_mode_m = P.option T.Major_Mode (P.char 'm' >> return T.Minor_Mode)++p_chord_type :: P Chord_Type+p_chord_type =+ let m = P.char 'm' >> return Minor+ au = P.char '+' >> return Augmented+ dm = P.char 'o' >> return Diminished+ dm7 = P.try (P.string "o7" >> return Diminished_7)+ hdm = P.char 'Ø' >> return Half_Diminished+ sus2 = P.try (P.string "sus2" >> return Suspended_2)+ sus4 = P.try (P.string "sus4" >> return Suspended_4)+ in P.option Major (P.choice [dm7,dm,hdm,au,sus2,sus4,m])++p_extension :: P Extension+p_extension =+ let d7 = P.char '7' >> return D7+ m7 = P.try (P.string "M7" >> return M7)+ in P.choice [d7,m7]++p_bass :: P (Maybe PC)+p_bass = P.optionMaybe (P.char '/' >> p_pc)++p_chord :: P Chord+p_chord = do+ pc <- p_pc+ ty <- p_chord_type+ ex <- P.optionMaybe p_extension+ b <- p_bass+ ty' <- p_chord_type+ let ty'' = case (ty,ty') of+ (Major,Suspended_2) -> Suspended_2+ (Major,Suspended_4) -> Suspended_4+ (_,Major) -> ty -- ie. nothing+ _ -> error ("trailing type not sus2 or sus4: " ++ show ty')+ return (CH pc ty'' ex b)++-- > let ch = words "CmM7 C#o EbM7 Fo7 Gx/D C/E GØ/F Bbsus4/C E7sus2"+-- > let c = map parse_chord ch+-- > map chord_pp c == ch+-- > map chord_pcset c+parse_chord :: String -> Chord+parse_chord =+ either (\e -> error ("parse_chord failed\n" ++ show e)) id .+ P.parse p_chord ""
Music/Theory/Pitch/Note.hs view
@@ -1,28 +1,41 @@ -- | Common music notation note and alteration values. module Music.Theory.Pitch.Note where +import Data.Char {- base -} import Data.Maybe {- base -} --- * Note+import qualified Music.Theory.List as T {- hmt -} +-- * Note_T+ -- | Enumeration of common music notation note names (@C@ to @B@). data Note_T = C | D | E | F | G | A | B- deriving (Eq,Enum,Bounded,Ord,Show)+ deriving (Eq,Enum,Bounded,Ord,Read,Show) +-- | Note sequence as usually understood, ie. 'C' - 'B'.+note_seq :: [Note_T]+note_seq = [C .. B]++-- | Char variant of 'show'.+note_pp :: Note_T -> Char+note_pp = head . show++-- | Table of 'Note_T' and corresponding pitch-classes.+note_pc_tbl :: Num i => [(Note_T,i)]+note_pc_tbl = zip [C .. B] [0,2,4,5,7,9,11]+ -- | Transform 'Note_T' to pitch-class number. -- -- > map note_to_pc [C,E,G] == [0,4,7]-note_to_pc :: Integral i => Note_T -> i-note_to_pc n =- case n of- C -> 0- D -> 2- E -> 4- F -> 5- G -> 7- A -> 9- B -> 11+note_to_pc :: Num i => Note_T -> i+note_to_pc n = fromMaybe (error "note_to_pc") (lookup n note_pc_tbl) +-- | Inverse of 'note_to_pc'.+--+-- > mapMaybe pc_to_note [0,4,7] == [C,E,G]+pc_to_note :: (Eq i,Num i) => i -> Maybe Note_T+pc_to_note i = T.reverse_lookup i note_pc_tbl+ -- | Modal transposition of 'Note_T' value. -- -- > note_t_transpose C 2 == E@@ -32,15 +45,38 @@ n' = fromEnum (maxBound::Note_T) + 1 in toEnum ((x' + n) `mod` n') +-- | Parser from 'Char', case insensitive flag.+--+-- > mapMaybe (parse_note True) "CDEFGab" == [C,D,E,F,G,A,B]+parse_note_t :: Bool -> Char -> Maybe Note_T+parse_note_t ci c =+ let tbl = zip "CDEFGAB" [C,D,E,F,G,A,B]+ in lookup (if ci then toUpper c else c) tbl++-- | Inclusive set of 'Note_T' within indicated interval. This is not+-- equal to 'enumFromTo' which is not circular.+--+-- > note_span E B == [E,F,G,A,B]+-- > note_span B D == [B,C,D]+-- > enumFromTo B D == []+note_span :: Note_T -> Note_T -> [Note_T]+note_span n1 n2 =+ let fn x = toEnum (x `mod` 7)+ n1' = fromEnum n1+ n2' = fromEnum n2+ n2'' = if n1' > n2' then n2' + 7 else n2'+ in map fn [n1' .. n2'']+ -- * Alteration -- | Enumeration of common music notation note alterations.-data Alteration_T = DoubleFlat- | ThreeQuarterToneFlat | Flat | QuarterToneFlat- | Natural- | QuarterToneSharp | Sharp | ThreeQuarterToneSharp- | DoubleSharp- deriving (Eq,Enum,Bounded,Ord,Show)+data Alteration_T =+ DoubleFlat+ | ThreeQuarterToneFlat | Flat | QuarterToneFlat+ | Natural+ | QuarterToneSharp | Sharp | ThreeQuarterToneSharp+ | DoubleSharp+ deriving (Eq,Enum,Bounded,Ord,Show) -- | Generic form. generic_alteration_to_diff :: Integral i => Alteration_T -> Maybe i@@ -146,6 +182,18 @@ ThreeQuarterToneSharp -> Sharp _ -> x +alteration_symbol_tbl :: [(Alteration_T,Char)]+alteration_symbol_tbl =+ [(DoubleFlat,'𝄫')+ ,(ThreeQuarterToneFlat,'𝄭')+ ,(Flat,'♭')+ ,(QuarterToneFlat,'𝄳')+ ,(Natural,'♮')+ ,(QuarterToneSharp,'𝄲')+ ,(Sharp,'♯')+ ,(ThreeQuarterToneSharp,'𝄰')+ ,(DoubleSharp,'𝄪')]+ -- | Unicode has entries for /Musical Symbols/ in the range @U+1D100@ -- through @U+1D1FF@. The @3/4@ symbols are non-standard, here they -- correspond to @MUSICAL SYMBOL FLAT DOWN@ and @MUSICAL SYMBOL SHARP@@ -153,33 +201,39 @@ -- -- > map alteration_symbol [minBound .. maxBound] == "𝄫𝄭♭𝄳♮𝄲♯𝄰𝄪" alteration_symbol :: Alteration_T -> Char-alteration_symbol a = case a of- DoubleFlat -> '𝄫'- ThreeQuarterToneFlat -> '𝄭'- Flat -> '♭'- QuarterToneFlat -> '𝄳'- Natural -> '♮'- QuarterToneSharp -> '𝄲'- Sharp -> '♯'- ThreeQuarterToneSharp -> '𝄰'- DoubleSharp -> '𝄪'+alteration_symbol a = fromMaybe (error "alteration_symbol") (lookup a alteration_symbol_tbl) --- | The @ISO@ ASCII spellings for alterations. Naturals as written+-- | Inverse of 'alteration_symbol'.+--+-- > mapMaybe symbol_to_alteration "♭♮♯" == [Flat,Natural,Sharp]+symbol_to_alteration :: Char -> Maybe Alteration_T+symbol_to_alteration c = T.reverse_lookup c alteration_symbol_tbl++-- | Variant of 'symbol_to_alteration' that /also/ recognises @b@ for 'Flat'+-- and @#@ for 'Sharp' and 'x' for double sharp.+symbol_to_alteration_iso :: Char -> Maybe Alteration_T+symbol_to_alteration_iso c =+ case c of+ 'b' -> Just Flat+ '#' -> Just Sharp+ 'x' -> Just DoubleSharp+ _ -> symbol_to_alteration c++alteration_iso_tbl :: [(Alteration_T,String)]+alteration_iso_tbl =+ [(DoubleFlat,"bb")+ ,(Flat,"b")+ ,(Natural,"")+ ,(Sharp,"#")+ ,(DoubleSharp,"x")]++-- | The @ISO@ ASCII spellings for alterations. Naturals are written -- as the empty string. -- -- > mapMaybe alteration_iso_m [Flat .. Sharp] == ["b","","#"]+-- > mapMaybe alteration_iso_m [DoubleFlat,DoubleSharp] == ["bb","x"] alteration_iso_m :: Alteration_T -> Maybe String-alteration_iso_m a =- case a of- DoubleFlat -> Just "bb"- ThreeQuarterToneFlat -> Nothing- Flat -> Just "b"- QuarterToneFlat -> Nothing- Natural -> Just ""- QuarterToneSharp -> Nothing- Sharp -> Just "#"- ThreeQuarterToneSharp -> Nothing- DoubleSharp -> Just "x"+alteration_iso_m a = lookup a alteration_iso_tbl -- | The @ISO@ ASCII spellings for alterations. alteration_iso :: Alteration_T -> String@@ -206,19 +260,40 @@ ThreeQuarterToneSharp -> "isih" DoubleSharp -> "isis" --- * Generalised Alteration+-- * 12-ET --- | Generalised alteration, given as a rational semitone difference+note_alteration_to_pc :: (Note_T,Alteration_T) -> Maybe Int+note_alteration_to_pc (n,a) =+ let n_pc = note_to_pc n+ in fmap ((`mod` 12) . (+ n_pc)) (alteration_to_diff a)++-- > map note_alteration_to_pc_err [(A,DoubleSharp),(B,Sharp),(C,Flat),(C,DoubleFlat)]+note_alteration_to_pc_err :: (Note_T, Alteration_T) -> Int+note_alteration_to_pc_err = fromMaybe (error "note_alteration_to_pc") . note_alteration_to_pc++-- | Note & alteration sequence in key-signature spelling.+note_alteration_ks :: [(Note_T, Alteration_T)]+note_alteration_ks =+ [(C,Natural),(C,Sharp),(D,Natural),(E,Flat),(E,Natural),(F,Natural)+ ,(F,Sharp),(G,Natural),(A,Flat),(A,Natural),(B,Flat),(B,Natural)]++-- | Table connecting pitch class number with 'note_alteration_ks'.+pc_note_alteration_ks_tbl :: Integral i => [((Note_T,Alteration_T),i)]+pc_note_alteration_ks_tbl = zip note_alteration_ks [0..11]++-- | 'T.reverse_lookup' of 'pc_note_alteration_ks_tbl'.+pc_to_note_alteration_ks :: Integral i => i -> Maybe (Note_T,Alteration_T)+pc_to_note_alteration_ks i = T.reverse_lookup i pc_note_alteration_ks_tbl++-- * Rational Alteration++-- | Alteration given as a rational semitone difference -- and a string representation of the alteration.-type Alteration_T' = (Rational,String)+type Alteration_R = (Rational,String) --- | Transform 'Alteration_T' to 'Alteration_T''.+-- | Transform 'Alteration_T' to 'Alteration_R'. -- -- > let r = [(-1,"♭"),(0,"♮"),(1,"♯")] -- > in map alteration_t' [Flat,Natural,Sharp] == r-alteration_t' :: Alteration_T -> Alteration_T'-alteration_t' a = (alteration_to_fdiff a,[alteration_symbol a])---- | Function to spell a 'PitchClass'.-type Spelling n = n -> (Note_T,Alteration_T)-+alteration_r :: Alteration_T -> Alteration_R+alteration_r a = (alteration_to_fdiff a,[alteration_symbol a])
+ Music/Theory/Pitch/Note/Name.hs view
@@ -0,0 +1,88 @@+-- | Constants names for notes. /eses/ indicates double+-- flat, /eseh/ three quarter tone flat, /es/ flat, /eh/ quarter tone+-- flat, /ih/ quarter tone sharp, /is/ sharp, /isih/ three quarter+-- tone sharp and /isis/ double sharp.+module Music.Theory.Pitch.Note.Name where++import Music.Theory.Pitch.Note++ceses,deses,eeses,feses,geses,aeses,beses :: (Note_T,Alteration_T)+ceses = (C,DoubleFlat)+deses = (D,DoubleFlat)+eeses = (E,DoubleFlat)+feses = (F,DoubleFlat)+geses = (G,DoubleFlat)+aeses = (A,DoubleFlat)+beses = (B,DoubleFlat)++ceseh,deseh,eeseh,feseh,geseh,aeseh,beseh :: (Note_T,Alteration_T)+ceseh = (C,ThreeQuarterToneFlat)+deseh = (D,ThreeQuarterToneFlat)+eeseh = (E,ThreeQuarterToneFlat)+feseh = (F,ThreeQuarterToneFlat)+geseh = (G,ThreeQuarterToneFlat)+aeseh = (A,ThreeQuarterToneFlat)+beseh = (B,ThreeQuarterToneFlat)++ces,des,ees,fes,ges,aes,bes :: (Note_T,Alteration_T)+ces = (C,Flat)+des = (D,Flat)+ees = (E,Flat)+fes = (F,Flat)+ges = (G,Flat)+aes = (A,Flat)+bes = (B,Flat)++ceh,deh,eeh,feh,geh,aeh,beh :: (Note_T,Alteration_T)+ceh = (C,QuarterToneFlat)+deh = (D,QuarterToneFlat)+eeh = (E,QuarterToneFlat)+feh = (F,QuarterToneFlat)+geh = (G,QuarterToneFlat)+aeh = (A,QuarterToneFlat)+beh = (B,QuarterToneFlat)++c,d,e,f,g,a,b :: (Note_T,Alteration_T)+c = (C,Natural)+d = (D,Natural)+e = (E,Natural)+f = (F,Natural)+g = (G,Natural)+a = (A,Natural)+b = (B,Natural)++cih,dih,eih,fih,gih,aih,bih :: (Note_T,Alteration_T)+cih = (C,QuarterToneSharp)+dih = (D,QuarterToneSharp)+eih = (E,QuarterToneSharp)+fih = (F,QuarterToneSharp)+gih = (G,QuarterToneSharp)+aih = (A,QuarterToneSharp)+bih = (B,QuarterToneSharp)++cis,dis,eis,fis,gis,ais,bis :: (Note_T,Alteration_T)+cis = (C,Sharp)+dis = (D,Sharp)+eis = (E,Sharp)+fis = (F,Sharp)+gis = (G,Sharp)+ais = (A,Sharp)+bis = (B,Sharp)++cisih,disih,eisih,fisih,gisih,aisih,bisih :: (Note_T,Alteration_T)+cisih = (C,ThreeQuarterToneSharp)+disih = (D,ThreeQuarterToneSharp)+eisih = (E,ThreeQuarterToneSharp)+fisih = (F,ThreeQuarterToneSharp)+gisih = (G,ThreeQuarterToneSharp)+aisih = (A,ThreeQuarterToneSharp)+bisih = (B,ThreeQuarterToneSharp)++cisis,disis,eisis,fisis,gisis,aisis,bisis :: (Note_T,Alteration_T)+cisis = (C,DoubleSharp)+disis = (D,DoubleSharp)+eisis = (E,DoubleSharp)+fisis = (F,DoubleSharp)+gisis = (G,DoubleSharp)+aisis = (A,DoubleSharp)+bisis = (B,DoubleSharp)
Music/Theory/Pitch/Spelling.hs view
@@ -1,75 +1,19 @@ -- | Spelling rules for common music notation. module Music.Theory.Pitch.Spelling where -import Music.Theory.Pitch.Note (Note_T(..),Alteration_T(..),Spelling)---- | Variant of 'Spelling' for incomplete functions.-type Spelling_M i = i -> Maybe (Note_T, Alteration_T)---- | Spelling for natural (♮) notes only.------ > map pc_spell_natural_m [0,1] == [Just (C,Natural),Nothing]-pc_spell_natural_m :: Integral i => Spelling_M i-pc_spell_natural_m pc =- case pc of- 0 -> Just (C,Natural)- 2 -> Just (D,Natural)- 4 -> Just (E,Natural)- 5 -> Just (F,Natural)- 7 -> Just (G,Natural)- 9 -> Just (A,Natural)- 11 -> Just (B,Natural)- _ -> Nothing---- | Erroring variant of 'pc_spell_natural_m'.------ > map pc_spell_natural [0,5,7] == [(C,Natural),(F,Natural),(G,Natural)]-pc_spell_natural :: Integral i => Spelling i-pc_spell_natural pc =- case pc_spell_natural_m pc of- Just p -> p- _ -> error "pc_spell_natural"---- | Use spelling from simplest key-signature. Note that this is--- ambiguous for @8@, which could be either G Sharp (♯) in /A Major/--- or A Flat (♭) in /E Flat (♭) Major/.------ > map pc_spell_ks [6,8] == [(F,Sharp),(A,Flat)]-pc_spell_ks :: Integral i => Spelling i-pc_spell_ks pc =- case pc of- 1 -> (C,Sharp) -- 2#- 3 -> (E,Flat) -- 3b- 6 -> (F,Sharp) -- 1#- 8 -> (A,Flat) -- 3b/3#- 10 -> (B,Flat) -- 1b- _ -> pc_spell_natural pc+import qualified Music.Theory.Pitch as T {- hmt -}+import qualified Music.Theory.Pitch.Spelling.Cluster as T {- hmt -}+import qualified Music.Theory.Pitch.Spelling.Key as T {- hmt -}+import qualified Music.Theory.Pitch.Spelling.Table as T {- hmt -} --- | Use always sharp (♯) spelling.------ > map pc_spell_sharp [6,8] == [(F,Sharp),(G,Sharp)]--- > Data.List.nub (map (snd . pc_spell_sharp) [1,3,6,8,10]) == [Sharp]--- > octpc_to_pitch pc_spell_sharp (4,6) == Pitch F Sharp 4-pc_spell_sharp :: Integral i => Spelling i-pc_spell_sharp pc =- case pc of- 1 -> (C,Sharp)- 3 -> (D,Sharp)- 6 -> (F,Sharp)- 8 -> (G,Sharp)- 10 -> (A,Sharp)- _ -> pc_spell_natural pc+spell_octpc_set :: [T.OctPC] -> [T.Pitch]+spell_octpc_set o =+ case T.octpc_spell_implied_key o of+ Just r -> r+ Nothing ->+ case T.spell_cluster_octpc o of+ Just r -> r+ Nothing -> map T.octpc_to_pitch_ks o --- | Use always flat (♭) spelling.------ > map pc_spell_flat [6,8] == [(G,Flat),(A,Flat)]--- > Data.List.nub (map (snd . pc_spell_flat) [1,3,6,8,10]) == [Flat]-pc_spell_flat :: Integral i => Spelling i-pc_spell_flat pc =- case pc of- 1 -> (D,Flat)- 3 -> (E,Flat)- 6 -> (G,Flat)- 8 -> (A,Flat)- 10 -> (B,Flat)- _ -> pc_spell_natural pc+spell_midi_set :: [T.Midi] -> [T.Pitch]+spell_midi_set = spell_octpc_set . map T.midi_to_octpc
Music/Theory/Pitch/Spelling/Cluster.hs view
@@ -1,128 +1,175 @@ -- | Spelling for chromatic clusters. module Music.Theory.Pitch.Spelling.Cluster where -import Data.List-import Music.Theory.Pitch-import Music.Theory.Pitch.Name+import Data.List {- base -} --- | Spelling table for chromatic clusters.+import qualified Music.Theory.List as T {- hmt -}+import qualified Music.Theory.Pitch as T {- hmt -}+import qualified Music.Theory.Pitch.Note as T {- hmt -}+import Music.Theory.Pitch.Note.Name {- hmt -}++-- | Form of cluster with smallest outer boundary interval. ----- > let f (p,q) = p == sort (map (snd . pitch_to_octpc) q)--- > in all f spell_cluster_c4_table == True-spell_cluster_c4_table :: [([PitchClass],[Pitch])]-spell_cluster_c4_table =- [([0],[c4])- ,([0,1],[c4,des4])- ,([0,1,2],[bis3,cis4,d4])- ,([0,1,2,3],[bis3,cis4,d4,ees4])- ,([0,1,2,3,10,11],[ais3,b3,c4,cis4,d4,ees4]) -- overlap...- ,([0,1,2,10],[ais3,bis3,cis4,d4])- ,([0,1,2,11],[aisis3,bis3,cis4,d4])- ,([0,1,3],[c4,des4,ees4])- ,([0,1,3,10],[bes3,c4,des4,ees4])- ,([0,1,3,11],[b3,c4,des4,ees4])- ,([0,1,10],[bes3,c4,des4])- ,([0,1,10,11],[ais3,b3,c4,des4])- ,([0,1,11],[b3,c4,des4])- ,([0,2],[c4,d4])- ,([0,2,3],[c4,d4,ees4])- ,([0,2,3,10],[bes3,c4,d4,ees4])- ,([0,2,3,11],[b3,c4,d4,ees4])- ,([0,2,11],[b3,c4,d4])- ,([0,2,10],[bes3,c4,d4])- ,([0,2,10,11],[ais3,b3,c4,d4])- ,([0,3,10,11],[ais3,b3,c4,dis4])- ,([0,3,11],[b3,c4,dis4])- ,([0,10,11],[ais3,b3,c4])- ,([0,11],[b3,c4])- ,([1],[cis4])- ,([1,2],[cis4,d4])- ,([1,2,3],[cis4,d4,ees4])- ,([1,2,3,10],[bes3,cis4,d4,ees4])- ,([1,2,3,11],[b3,cis4,d4,ees4])- ,([1,2,10],[ais3,cis4,d4])- ,([1,2,10,11],[ais3,b3,cis4,d4])- ,([1,2,11],[b3,cis4,d4])- ,([1,3,11],[b3,cis4,dis4])- ,([1,3,10,11],[ais3,b3,cis4,dis4])- ,([1,10,11],[ais3,b3,cis4])- ,([1,11],[b3,cis4])- ,([2],[d4])- ,([2,3],[d4,ees4])- ,([2,3,4],[d4,ees4,fes4])- ,([2,3,5],[d4,ees4,f4])- ,([2,3,4,5],[d4,ees4,fes4,geses4])- ,([2,3,10,11],[bes3,ces4,d4,ees4])- ,([2,3,11],[b3,d4,ees4])- ,([2,4],[d4,e4])- ,([2,4,5],[d4,e4,f4])- ,([2,5],[d4,f4])- ,([2,10,11],[ais3,b3,d4])- ,([2,11],[b3,d4])- ,([3],[ees4])- ,([3,4],[dis4,e4])- ,([3,4,5],[dis4,e4,f4])- ,([3,5],[ees4,f4])- ,([4],[e4])- ,([4,5],[e4,f4])- ,([5],[f4])- ,([5,6],[f4,ges4])- ,([5,6,7],[eis4,fis4,g4])- ,([5,6,8],[f4,ges4,aes4])- ,([5,6,9],[f4,ges4,a4])- ,([5,6,7,8],[eis4,fis4,g4,aes4])- ,([5,6,7,8,9],[eis4,fis4,g4,aes4,beses4])- ,([5,6,7,9],[eis4,fis4,g4,a4])- ,([5,6,8,9],[eis4,fis4,gis4,a4])- ,([5,7],[f4,g4])- ,([5,7,8],[f4,g4,aes4])- ,([5,7,8,9],[f4,g4,aes4,beses4])- ,([5,7,9],[f4,g4,a4])- ,([5,8],[f4,aes4])- ,([5,8,9],[f4,gis4,a4])- ,([5,9],[f4,a4])- ,([6],[fis4])- ,([6,7],[fis4,g4])- ,([6,7,8],[fis4,g4,aes4])- ,([6,7,8,9],[fis4,g4,aes4,beses4])- ,([6,7,9],[fis4,g4,a4])- ,([6,8],[fis4,gis4])- ,([6,8,9],[fis4,gis4,a4])- ,([6,9],[fis4,a4])- ,([7],[g4])- ,([7,8],[g4,aes4])- ,([7,8,9],[fisis4,gis4,a4])- ,([7,9],[g4,a4])- ,([8],[aes4])- ,([8,9],[gis4,a4])- ,([8,9,10],[gis4,a4,bes4])- ,([8,10],[aes4,bes4])- ,([9],[a4])- ,([9,10],[a4,bes4])- ,([10],[bes4])- ,([10,11],[ais4,b4])- ,([11],[b4])]+-- > cluster_normal_order [0,1,11] == [11,0,1]+cluster_normal_order :: [T.PitchClass] -> [T.PitchClass]+cluster_normal_order =+ let with_bounds x = ((last x - head x) `mod` 12,x)+ in snd . head . sort . map with_bounds . T.rotations +-- | Normal order starting in indicated octave.+--+-- > cluster_normal_order_octpc 3 [0,1,11] == [(3,11),(4,0),(4,1)]+cluster_normal_order_octpc :: T.Octave -> [T.PitchClass] -> [T.OctPC]+cluster_normal_order_octpc o pc =+ let pc_n = cluster_normal_order pc+ pc_0 = head pc_n+ in map (\x -> (if x >= pc_0 then o else o + 1,x)) pc_n++-- | True if 'sort' of cluster is not equal to 'cluster_normal_order'.+--+-- > map cluster_is_multiple_octave [[0,1,11],[1,2,3],[1,2,11]] == [True,False,True]+cluster_is_multiple_octave :: [T.PitchClass] -> Bool+cluster_is_multiple_octave x = sort x /= cluster_normal_order x++-- | Spelling table for chromatic and near-chromatic clusters,+-- pitch-classes are in cluster order.+--+-- > let f (p,q) = (p == map T.note_alteration_to_pc_err q)+-- > in all f spell_cluster_table+spell_cluster_table :: [([T.PitchClass],[(T.Note_T,T.Alteration_T)])]+spell_cluster_table =+ [([0,1,2,3],[bis,cis,d,ees])+ ,([0,1,2],[bis,cis,d])+ ,([0,1,3],[c,des,ees])+ ,([0,1],[c,des])+ ,([0,2,3],[c,d,ees])+ ,([0,2],[c,d])+ ,([0],[c])+ ,([1,2,3],[cis,d,ees])+ ,([1,2],[cis,d])+ ,([10,0,1,2],[ais,bis,cis,d])+ ,([10,0,1,3],[bes,c,des,ees])+ ,([10,0,1],[bes,c,des])+ ,([10,0,2,3],[bes,c,d,ees])+ ,([10,0,2],[bes,c,d])+ ,([10,1,2,3],[bes,cis,d,ees])+ ,([10,1,2],[ais,cis,d])+ ,([10,11,0,1,2,3],[ais,b,c,cis,d,ees]) -- overlap...+ ,([10,11,0,1],[ais,b,c,des])+ ,([10,11,0,2],[ais,b,c,d])+ ,([10,11,0,3],[ais,b,c,dis])+ ,([10,11,0],[ais,b,c])+ ,([10,11,1,2],[ais,b,cis,d])+ ,([10,11,1,3],[ais,b,cis,dis])+ ,([10,11,1],[ais,b,cis])+ ,([10,11,2,3],[bes,ces,d,ees])+ ,([10,11,2],[ais,b,d])+ ,([10,11],[ais,b])+ ,([10],[bes])+ ,([11,0,1,2],[aisis,bis,cis,d])+ ,([11,0,1,3],[b,c,des,ees])+ ,([11,0,1],[b,c,des])+ ,([11,0,2,3],[b,c,d,ees])+ ,([11,0,2],[b,c,d])+ ,([11,0,3],[b,c,dis])+ ,([11,0],[b,c])+ ,([11,1,2,3],[b,cis,d,ees])+ ,([11,1,2],[b,cis,d])+ ,([11,1,3],[b,cis,dis])+ ,([11,1],[b,cis])+ ,([11,2,3],[b,d,ees])+ ,([11,2],[b,d])+ ,([11],[b])+ ,([1],[cis])+ ,([2,3,4,5],[d,ees,fes,geses])+ ,([2,3,4],[d,ees,fes])+ ,([2,3,5],[d,ees,f])+ ,([2,3],[d,ees])+ ,([2,4,5],[d,e,f])+ ,([2,4],[d,e])+ ,([2,5],[d,f])+ ,([2],[d])+ ,([3,4,5],[dis,e,f])+ ,([3,4],[dis,e])+ ,([3,5],[ees,f])+ ,([3],[ees])+ ,([4,5],[e,f])+ ,([4],[e])+ ,([5,6,7,8,9],[eis,fis,g,aes,beses])+ ,([5,6,7,8],[eis,fis,g,aes])+ ,([5,6,7,9],[eis,fis,g,a])+ ,([5,6,7],[eis,fis,g])+ ,([5,6,8,9],[eis,fis,gis,a])+ ,([5,6,8],[f,ges,aes])+ ,([5,6,9],[f,ges,a])+ ,([5,6],[f,ges])+ ,([5,7,8,9],[f,g,aes,beses])+ ,([5,7,8],[f,g,aes])+ ,([5,7,9],[f,g,a])+ ,([5,7],[f,g])+ ,([5,8,9],[f,gis,a])+ ,([5,8],[f,aes])+ ,([5,9],[f,a])+ ,([5],[f])+ ,([6,7,8,9],[fis,g,aes,beses])+ ,([6,7,8],[fis,g,aes])+ ,([6,7,9],[fis,g,a])+ ,([6,7],[fis,g])+ ,([6,8,9],[fis,gis,a])+ ,([6,8],[fis,gis])+ ,([6,9],[fis,a])+ ,([6],[fis])+ ,([7,8,9],[fisis,gis,a])+ ,([7,8],[g,aes])+ ,([7,9],[g,a])+ ,([7],[g])+ ,([8,10],[aes,bes])+ ,([8,9,10],[gis,a,bes])+ ,([8,9],[gis,a])+ ,([8],[aes])+ ,([9,10],[a,bes])+ ,([9],[a])]++spell_cluster :: [T.PitchClass] -> Maybe [(T.Note_T,T.Alteration_T)]+spell_cluster = flip lookup spell_cluster_table++-- | Spell an arbitrary sequence of 'T.OctPC' values.+--+-- > fmap (map T.pitch_pp_iso) (spell_cluster_octpc [(3,11),(4,3),(4,11),(5,1)])+spell_cluster_octpc :: [T.OctPC] -> Maybe [T.Pitch]+spell_cluster_octpc o =+ let p = cluster_normal_order (sort (nub (map snd o)))+ na_f na =+ let na_tbl = map (\x -> (T.note_alteration_to_pc_err x,x)) na+ o_f (oct,pc) = let (n,alt) = T.lookup_err pc na_tbl in T.Pitch n alt oct+ in map o_f o+ in fmap na_f (spell_cluster p)+ -- | Spelling for chromatic clusters. Sequence must be ascending. -- Pitch class @0@ maps to 'c4', if there is no @0@ then all notes are -- in octave @4@. ----- > let f = fmap (map pitch_pp) . spell_cluster_c4+-- > let f = (fmap (map T.pitch_pp) . spell_cluster_c4) -- > in map f [[11,0],[11]] == [Just ["B3","C4"],Just ["B4"]] ----- > fmap (map pitch_pp) (spell_cluster_c4 [10,11]) == Just ["A♯4","B4"]-spell_cluster_c4 :: [PitchClass] -> Maybe [Pitch]-spell_cluster_c4 p = lookup (sort p) spell_cluster_c4_table+-- > fmap (map T.pitch_pp) (spell_cluster_c4 [10,11]) == Just ["A♯4","B4"]+spell_cluster_c4 :: [T.PitchClass] -> Maybe [T.Pitch]+spell_cluster_c4 p =+ let o_0 = if cluster_is_multiple_octave p then 3 else 4+ oct = map fst (cluster_normal_order_octpc o_0 p)+ in case spell_cluster p of+ Nothing -> Nothing+ Just na -> Just (map (\((n,alt),o) -> T.Pitch n alt o) (zip na oct)) -- | Variant of 'spell_cluster_c4' that runs 'pitch_edit_octave'. An -- octave of @4@ is the identitiy, @3@ an octave below, @5@ an octave -- above. ----- > fmap (map pitch_pp) (spell_cluster_c 3 [11,0]) == Just ["B2","C3"]--- > fmap (map pitch_pp) (spell_cluster_c 3 [10,11]) == Just ["A♯3","B3"]-spell_cluster_c :: Octave -> [PitchClass] -> Maybe [Pitch]+-- > fmap (map T.pitch_pp) (spell_cluster_c 3 [11,0]) == Just ["B2","C3"]+-- > fmap (map T.pitch_pp) (spell_cluster_c 3 [10,11]) == Just ["A♯3","B3"]+spell_cluster_c :: T.Octave -> [T.PitchClass] -> Maybe [T.Pitch] spell_cluster_c o =- fmap (map (pitch_edit_octave (+ (o - 4)))) .+ fmap (map (T.pitch_edit_octave (+ (o - 4)))) . spell_cluster_c4 -- | Variant of 'spell_cluster_c4' that runs 'pitch_edit_octave' so@@ -131,27 +178,27 @@ -- > import Data.Maybe -- -- > let {f n = if n >= 11 then 3 else 4--- > ;g = map pitch_pp .fromJust . spell_cluster_f f+-- > ;g = map T.pitch_pp .fromJust . spell_cluster_f f -- > ;r = [["B3","C4"],["B3"],["C4"],["A♯4","B4"]]} -- > in map g [[11,0],[11],[0],[10,11]] == r-spell_cluster_f :: (PitchClass -> Octave) -> [PitchClass] -> Maybe [Pitch]+spell_cluster_f :: (T.PitchClass -> T.Octave) -> [T.PitchClass] -> Maybe [T.Pitch] spell_cluster_f o_f p = let fn r = case r of [] -> []- l:_ -> let (o,n) = pitch_to_octpc l- f = (+ (o_f n - o))- in (map (pitch_edit_octave f) r)+ l:_ -> let (o,n) = T.pitch_to_octpc l+ oct_f = (+ (o_f n - o))+ in (map (T.pitch_edit_octave oct_f) r) in fmap fn (spell_cluster_c4 p) -- | Variant of 'spell_cluster_c4' that runs 'pitch_edit_octave' so -- that the left-most note is in octave /o/. ----- > fmap (map pitch_pp) (spell_cluster_left 3 [11,0]) == Just ["B3","C4"]--- > fmap (map pitch_pp) (spell_cluster_left 3 [10,11]) == Just ["A♯3","B3"]-spell_cluster_left :: Octave -> [PitchClass] -> Maybe [Pitch]+-- > fmap (map T.pitch_pp) (spell_cluster_left 3 [11,0]) == Just ["B3","C4"]+-- > fmap (map T.pitch_pp) (spell_cluster_left 3 [10,11]) == Just ["A♯3","B3"]+spell_cluster_left :: T.Octave -> [T.PitchClass] -> Maybe [T.Pitch] spell_cluster_left o p = let fn r = case r of [] -> []- l:_ -> let f = (+ (o - octave l))- in map (pitch_edit_octave f) r+ l:_ -> let oct_f = (+ (o - T.octave l))+ in map (T.pitch_edit_octave oct_f) r in fmap fn (spell_cluster_c4 p)
+ Music/Theory/Pitch/Spelling/Key.hs view
@@ -0,0 +1,33 @@+module Music.Theory.Pitch.Spelling.Key where++import qualified Music.Theory.Key as T {- hmt -}+import qualified Music.Theory.Pitch as T {- hmt -}+import qualified Music.Theory.Pitch.Note as T {- hmt -}+import qualified Music.Theory.Pitch.Spelling.Table as T {- hmt -}++pcset_spell_implied_key_f :: Integral i => [i] -> Maybe (T.Spelling i)+pcset_spell_implied_key_f x =+ case T.implied_fifths T.Major_Mode x of+ Nothing -> Nothing+ Just n -> if n == 0+ then Just T.pc_spell_natural+ else if n < 0+ then Just T.pc_spell_flat+ else Just T.pc_spell_sharp++-- > map pcset_spell_implied_key [[0,1],[4,10],[3,9],[3,11]]+pcset_spell_implied_key :: Integral i => [i] -> Maybe [(T.Note_T, T.Alteration_T)]+pcset_spell_implied_key x =+ case pcset_spell_implied_key_f x of+ Just f -> Just (map f x)+ Nothing -> Nothing++-- > map octpc_spell_implied_key [[(3,11),(4,1)],[(3,11),(4,10)]]+octpc_spell_implied_key :: [T.OctPC] -> Maybe [T.Pitch]+octpc_spell_implied_key x =+ let f o (n,a) = T.Pitch n a o+ in fmap (zipWith f (map fst x)) (pcset_spell_implied_key (map snd x))++-- > map (fmap (map T.pitch_pp_iso) . midi_spell_implied_key) [[59,61],[59,70]]+midi_spell_implied_key :: [T.Midi] -> Maybe [T.Pitch]+midi_spell_implied_key = octpc_spell_implied_key . map T.midi_to_octpc
+ Music/Theory/Pitch/Spelling/Table.hs view
@@ -0,0 +1,101 @@+-- | Simple table based spelling rules for common music notation.+module Music.Theory.Pitch.Spelling.Table where++import Data.Maybe {- base -}++import Music.Theory.Pitch {- hmt -}+import Music.Theory.Pitch.Note {- hmt -}++type Spelling_Table i = [(i,(Note_T,Alteration_T))]++-- | Spelling table for natural (♮) notes only.+pc_spell_natural_tbl :: Integral i => Spelling_Table i+pc_spell_natural_tbl =+ [(0,(C,Natural))+ ,(2,(D,Natural))+ ,(4,(E,Natural))+ ,(5,(F,Natural))+ ,(7,(G,Natural))+ ,(9,(A,Natural))+ ,(11,(B,Natural))]++-- | Spelling table for sharp (♯) notes only.+pc_spell_sharp_tbl :: Integral i => Spelling_Table i+pc_spell_sharp_tbl =+ [(1,(C,Sharp))+ ,(3,(D,Sharp))+ ,(6,(F,Sharp))+ ,(8,(G,Sharp))+ ,(10,(A,Sharp))]++-- | Spelling table for flat (♭) notes only.+pc_spell_flat_tbl :: Integral i => Spelling_Table i+pc_spell_flat_tbl =+ [(1,(D,Flat))+ ,(3,(E,Flat))+ ,(6,(G,Flat))+ ,(8,(A,Flat))+ ,(10,(B,Flat))]++-- | Spelling table from simplest key-signature. Note that this is+-- ambiguous for @8@, which could be either G Sharp (♯) in /A Major/+-- or A Flat (♭) in /E Flat (♭) Major/.+pc_spell_ks_tbl :: Integral i => Spelling_Table i+pc_spell_ks_tbl =+ [(1,(C,Sharp)) -- 2♯+ ,(3,(E,Flat)) -- 3♭+ ,(6,(F,Sharp)) -- 1♯+ ,(8,(A,Flat)) -- 3♭/3♯+ ,(10,(B,Flat))] -- 1♭++pc_spell_tbl :: Integral i => Spelling_Table i -> Spelling i+pc_spell_tbl tbl = fromMaybe (error "pc_spell_tbl") . flip lookup tbl++-- | Spell using indicated table prepended to and 'pc_spell_natural_tbl' and 'pc_spell_ks_tbl'+pc_spell_tbl_ks :: Integral i => Spelling_Table i -> Spelling i+pc_spell_tbl_ks tbl = pc_spell_tbl (tbl ++ pc_spell_natural_tbl ++ pc_spell_ks_tbl)++-- | Spelling for natural (♮) notes only.+--+-- > map pc_spell_natural_m [0,1] == [Just (C,Natural),Nothing]+pc_spell_natural_m :: Integral i => Spelling_M i+pc_spell_natural_m = flip lookup pc_spell_natural_tbl++-- | Erroring variant of 'pc_spell_natural_m'.+--+-- > map pc_spell_natural [0,5,7] == [(C,Natural),(F,Natural),(G,Natural)]+pc_spell_natural :: Integral i => Spelling i+pc_spell_natural = pc_spell_tbl pc_spell_natural_tbl++-- | Lookup 'pc_spell_ks_tbl'.+--+-- > map pc_spell_ks [6,8] == [(F,Sharp),(A,Flat)]+pc_spell_ks :: Integral i => Spelling i+pc_spell_ks = pc_spell_tbl_ks []++-- | Use always sharp (♯) spelling.+--+-- > map pc_spell_sharp [6,8] == [(F,Sharp),(G,Sharp)]+-- > Data.List.nub (map (snd . pc_spell_sharp) [1,3,6,8,10]) == [Sharp]+pc_spell_sharp :: Integral i => Spelling i+pc_spell_sharp = pc_spell_tbl (pc_spell_sharp_tbl ++ pc_spell_natural_tbl)++-- | Use always flat (♭) spelling.+--+-- > map pc_spell_flat [6,8] == [(G,Flat),(A,Flat)]+-- > Data.List.nub (map (snd . pc_spell_flat) [1,3,6,8,10]) == [Flat]+pc_spell_flat :: Integral i => Spelling i+pc_spell_flat = pc_spell_tbl (pc_spell_flat_tbl ++ pc_spell_natural_tbl)++octpc_to_pitch_ks :: Integral i => Octave_PitchClass i -> Pitch+octpc_to_pitch_ks = octpc_to_pitch pc_spell_ks++-- | 'midi_to_pitch' 'T.pc_spell_ks'.+midi_to_pitch_ks :: Integral i => i -> Pitch+midi_to_pitch_ks = midi_to_pitch pc_spell_ks++fmidi_to_pitch_ks :: (Show n,RealFrac n) => n -> Pitch+fmidi_to_pitch_ks = fmidi_to_pitch_err pc_spell_ks++midi_detune_to_pitch_ks :: Real c => Midi_Detune' c -> Pitch+midi_detune_to_pitch_ks = midi_detune_to_pitch pc_spell_ks
+ Music/Theory/Random/I_Ching.hs view
@@ -0,0 +1,192 @@+{-# Language BinaryLiterals #-}++module Music.Theory.Random.I_Ching where++import Control.Monad {- base -}+import Data.Maybe {- base -}+import System.Random {- random -}++import qualified Music.Theory.Bits as T {- hmt -}+import qualified Music.Theory.Tuple as T {- hmt -}++-- | Line, indicated as sum.+data Line = L6 | L7 | L8 | L9 deriving (Eq,Show)++{-| (sum={6,7,8,9},+ (yarrow probablity={1,3,5,7}/16,+ three-coin probablity={2,6}/16,+ name,signification,symbol))+-}+type Line_Stat = (Line,(Rational,Rational,String,String,String))++i_ching_chart :: [Line_Stat]+i_ching_chart =+ [(L6,(1/16,2/16,"old yin","yin changing into yang","---x---"))+ ,(L8,(7/16,6/16,"young yin","yin unchanging","--- ---"))+ ,(L9,(3/16,2/16,"old yang","yang changing into yin","---o---"))+ ,(L7,(5/16,6/16,"young yang","yang unchanging","-------"))]++-- | Lines L6 and L7 are unbroken (since L6 is becoming L7).+line_unbroken :: Line -> Bool+line_unbroken n = n `elem` [L6,L7]++line_from_bit :: Bool -> Line+line_from_bit b = if b then L7 else L8++-- | Seven character ASCII string for line.+line_ascii_pp :: Line -> String+line_ascii_pp n = fromMaybe (error "line_ascii_pp") (fmap T.p5_fifth (lookup n i_ching_chart))++-- | Is line (ie. sum) moving (ie. 6 or 9).+line_is_moving :: Line -> Bool+line_is_moving n = n `elem` [L6,L9]++-- | Old yin (L6) becomes yang (L7), and old yang (L9) becomes yin (L8).+line_complement :: Line -> Maybe Line+line_complement n =+ case n of+ L6 -> Just L7+ L9 -> Just L8+ _ -> Nothing++type Hexagram = [Line]++-- | Hexagrams are drawn upwards.+hexagram_pp :: Hexagram -> String+hexagram_pp = unlines . reverse . map line_ascii_pp++{- | Sequence of sum values assigned to ascending four bit numbers.++> import Music.Theory.Bits {- hmt -}+> zip (map (gen_bitseq_pp 4) [0::Int .. 15]) (map line_ascii_pp_err four_coin_sequence)++-}+four_coin_sequence :: [Line]+four_coin_sequence =+ [L6,L9,L9,L9+ ,L7,L7,L7,L7+ ,L7,L8,L8,L8+ ,L8,L8,L8,L8]++-- | Generate hexagram (ie. sequence of six lines given by sum) using 'four_coin_sequence'.+--+-- > four_coin_gen_hexagram >>= putStrLn . hexagram_pp+four_coin_gen_hexagram :: IO Hexagram+four_coin_gen_hexagram = fmap (map (four_coin_sequence !!)) (replicateM 6 (randomRIO (0,15)))++-- | 'any' of 'line_is_moving'.+hexagram_has_complement :: Hexagram -> Bool+hexagram_has_complement = any line_is_moving++-- | If 'hexagram_has_complement' then derive it.+--+-- > h <- four_coin_gen_hexagram+-- > putStrLn (hexagram_pp h)+-- > maybe (return ()) (putStrLn . hexagram_pp) (hexagram_complement h)+hexagram_complement :: Hexagram -> Maybe Hexagram+hexagram_complement h =+ let f n = fromMaybe n (line_complement n)+ in if hexagram_has_complement h then Just (map f h) else Nothing++-- | Names of hexagrams, in King Wen order.+--+-- > length hexagram_names == 64+hexagram_names :: [(String,String)]+hexagram_names =+ [("乾","qián")+ ,("坤","kūn")+ ,("屯","zhūn")+ ,("蒙","méng")+ ,("需","xū")+ ,("訟","sòng")+ ,("師","shī")+ ,("比","bǐ")+ ,("小畜","xiǎo chù")+ ,("履","lǚ")+ ,("泰","tài")+ ,("否","pǐ")+ ,("同人","tóng rén")+ ,("大有","dà yǒu")+ ,("謙","qiān")+ ,("豫","yù")+ ,("隨","suí")+ ,("蠱","gŭ")+ ,("臨","lín")+ ,("觀","guān")+ ,("噬嗑","shì kè")+ ,("賁","bì")+ ,("剝","bō")+ ,("復","fù")+ ,("無妄","wú wàng")+ ,("大畜","dà chù")+ ,("頤","yí")+ ,("大過","dà guò")+ ,("坎","kǎn")+ ,("離","lí")+ ,("咸","xián")+ ,("恆","héng")+ ,("遯","dùn")+ ,("大壯","dà zhuàng")+ ,("晉","jìn")+ ,("明夷","míng yí")+ ,("家人","jiā rén")+ ,("睽","kuí")+ ,("蹇","jiǎn")+ ,("解","xiè")+ ,("損","sǔn")+ ,("益","yì")+ ,("夬","guài")+ ,("姤","gòu")+ ,("萃","cuì")+ ,("升","shēng")+ ,("困","kùn")+ ,("井","jǐng")+ ,("革","gé")+ ,("鼎","dǐng")+ ,("震","zhèn")+ ,("艮","gèn")+ ,("漸","jiàn")+ ,("歸妹","guī mèi")+ ,("豐","fēng")+ ,("旅","lǚ")+ ,("巽","xùn")+ ,("兌","duì")+ ,("渙","huàn")+ ,("節","jié")+ ,("中孚","zhōng fú")+ ,("小過","xiǎo guò")+ ,("既濟","jì jì")+ ,("未濟","wèi jì")]++-- | Unicode hexagram characters, in King Wen order.+--+-- > import Data.List.Split {- split -}+-- > mapM_ putStrLn (chunksOf 8 hexagram_unicode_sequence)+hexagram_unicode_sequence :: [Char]+hexagram_unicode_sequence = map toEnum [0x4DC0 .. 0x4DFF]++hexagram_to_binary :: Hexagram -> Int+hexagram_to_binary = T.pack_bitseq . map line_unbroken++-- > let h = hexagram_from_binary 0b100010+-- > putStrLn (hexagram_pp h)+-- > gen_bitseq_pp 6 (hexagram_to_binary h) == "100010"+hexagram_from_binary :: Int -> Hexagram+hexagram_from_binary = map line_from_bit . T.gen_bitseq 6++-- > import Data.List {- base -}+-- > putStrLn (intersperse ' ' trigram_unicode_sequence)+trigram_unicode_sequence :: [Char]+trigram_unicode_sequence = map toEnum [0x2630 .. 0x2637]++-- > map p8_third trigram_chart == [7,6,5,4,3,2,1,0]+trigram_chart :: Num i => [(i, Char, i, Char, String, Char, String, Char)]+trigram_chart =+ [(1,'☰',0b111,'乾',"qián",'天',"NW",'馬')+ ,(2,'☱',0b110,'兌',"duì",'澤',"W",'羊')+ ,(3,'☲',0b101,'離',"lí",'火',"S",'雉')+ ,(4,'☳',0b100,'震',"zhèn",'雷',"E",'龍')+ ,(5,'☴',0b011,'巽',"xùn",'風',"SE",'雞')+ ,(6,'☵',0b010,'坎',"kǎn",'水',"N",'豕')+ ,(7,'☶',0b001,'艮',"gèn",'山',"NE",'狗')+ ,(8,'☷',0b000,'坤',"kūn",'地',"SW",'牛')]
+ Music/Theory/Read.hs view
@@ -0,0 +1,147 @@+-- | Read functions.+module Music.Theory.Read where++import Data.Char {- base -}+import Data.List {- base -}+import Data.Maybe {- base -}+import Data.Ratio {- base -}+import Numeric {- base -}++-- | Transform 'ReadS' function into precise 'Read' function.+-- Requires using all the input to produce a single token. The only+-- exception is a singular trailing white space character.+reads_to_read_precise :: ReadS t -> (String -> Maybe t)+reads_to_read_precise f s =+ case f s of+ [(r,[])] -> Just r+ [(r,[c])] -> if isSpace c then Just r else Nothing+ _ -> Nothing++-- | Error variant of 'reads_to_read_precise'.+reads_to_read_precise_err :: String -> ReadS t -> String -> t+reads_to_read_precise_err err f =+ fromMaybe (error ("reads_to_read_precise_err:" ++ err)) .+ reads_to_read_precise f++-- | 'reads_to_read_precise' of 'reads'.+-- space character.+read_maybe :: Read a => String -> Maybe a+read_maybe = reads_to_read_precise reads++-- | Variant of 'read_maybe' with default value.+--+-- > map (read_def 0) ["2","2:","2\n"] == [2,0,2]+read_def :: Read a => a -> String -> a+read_def x s = maybe x id (read_maybe s)++-- | Variant of 'read_maybe' that errors on 'Nothing'.+read_err :: Read a => String -> a+read_err s = maybe (error ("read_err: " ++ s)) id (read_maybe s)++-- | Variant of 'reads' requiring exact match, no trailing white space.+--+-- > map reads_exact ["1.5","2,5"] == [Just 1.5,Nothing]+reads_exact :: Read a => String -> Maybe a+reads_exact s =+ case reads s of+ [(r,"")] -> Just r+ _ -> Nothing++-- | Variant of 'reads_exact' that errors on failure.+reads_exact_err :: Read a => String -> String -> a+reads_exact_err err_txt str =+ let err = error ("reads: " ++ err_txt ++ ": " ++ str)+ in fromMaybe err (reads_exact str)++-- * Type specific variants++-- | Allow commas as thousand separators.+--+-- > let r = [Just 123456,Just 123456,Nothing,Just 123456789]+-- > in map read_integral_allow_commas_maybe ["123456","123,456","1234,56","123,456,789"]+read_integral_allow_commas_maybe :: Read i => String -> Maybe i+read_integral_allow_commas_maybe s =+ let c = filter ((== ',') . fst) (zip (reverse s) [0..])+ in if null c+ then read_maybe s+ else if map snd c `isPrefixOf` [3::Int,7..]+ then read_maybe (filter (not . (== ',')) s)+ else Nothing++read_integral_allow_commas_err :: (Integral i,Read i) => String -> i+read_integral_allow_commas_err s =+ let err = error ("read_integral_allow_commas: misplaced commas: " ++ s)+ in fromMaybe err (read_integral_allow_commas_maybe s)++read_int_allow_commas :: String -> Int+read_int_allow_commas = read_integral_allow_commas_err++-- | Read a ratio where the division is given by @/@ instead of @%@+-- and the integers allow commas.+--+-- > map read_ratio_with_div_err ["123,456/7","123,456,789"] == [123456/7,123456789]+read_ratio_with_div_err :: (Integral i, Read i) => String -> Ratio i+read_ratio_with_div_err s =+ let f = read_integral_allow_commas_err+ in case break (== '/') s of+ (n,'/':d) -> f n % f d+ _ -> read_integral_allow_commas_err s % 1++-- | Read 'Ratio', allow commas for thousand separators.+--+-- > read_ratio_allow_commas_err "327,680" "177,147" == 327680 / 177147+read_ratio_allow_commas_err :: (Integral i,Read i) => String -> String -> Ratio i+read_ratio_allow_commas_err n d = let f = read_integral_allow_commas_err in f n % f d++-- | Delete trailing @.@, 'read' fails for @700.@.+delete_trailing_point :: String -> String+delete_trailing_point s =+ case reverse s of+ '.':s' -> reverse s'+ _ -> s++-- | 'read_err' disallows trailing decimal points.+--+-- > map read_fractional_allow_trailing_point_err ["123.","123.4"] == [123.0,123.4]+read_fractional_allow_trailing_point_err :: Read n => String -> n+read_fractional_allow_trailing_point_err = read_err . delete_trailing_point++-- * Plain type specialisations++-- | Type specialised 'read_maybe'.+--+-- > map read_maybe_int ["2","2:","2\n"] == [Just 2,Nothing,Just 2]+read_maybe_int :: String -> Maybe Int+read_maybe_int = read_maybe++-- | Type specialised 'read_err'.+read_int :: String -> Int+read_int = read_err++-- | Type specialised 'read_maybe'.+read_maybe_double :: String -> Maybe Double+read_maybe_double = read_maybe++-- | Type specialised 'read_err'.+read_double :: String -> Double+read_double = read_err++-- | Type specialised 'read_maybe'.+--+-- > map read_maybe_rational ["1","1%2","1/2"] == [Nothing,Just (1/2),Nothing]+read_maybe_rational :: String -> Maybe Rational+read_maybe_rational = read_maybe++-- | Type specialised 'read_err'.+--+-- > read_rational "1%4"+read_rational :: String -> Rational+read_rational = read_err++-- * Numeric variants++-- | Error variant of 'readHex'.+--+-- > read_hex_err "F0B0" == 61616+read_hex_err :: (Eq n,Num n) => String -> n+read_hex_err = reads_to_read_precise_err "readHex" readHex
Music/Theory/Set/List.hs view
@@ -1,15 +1,17 @@ -- | Set operations on lists. module Music.Theory.Set.List where -import Control.Monad-import Data.List+import Control.Monad {- base -}+import Data.List {- base -} import qualified Math.Combinatorics.Multiset as M {- multiset-comb -} --- | Remove duplicate elements with 'nub' and then 'sort'.+import qualified Music.Theory.List as T {- hmt -}++-- | 'sort' then 'nub'. ----- > set_l [3,3,3,2,2,1] == [1,2,3]+-- > set [3,3,3,2,2,1] == [1,2,3] set :: (Ord a) => [a] -> [a]-set = sort . nub+set = nub . sort -- | Size of powerset of set of cardinality /n/, ie. @2@ '^' /n/. --@@ -24,6 +26,12 @@ powerset :: [a] -> [[a]] powerset = filterM (const [True,False]) +-- | Variant where result is sorted and the empty set is not given.+--+-- > powerset' [1,2,3] == [[1],[2],[3],[1,2],[1,3],[2,3],[1,2,3]]+powerset' :: Ord a => [a] -> [[a]]+powerset' = tail . T.sort_by_two_stage length id . powerset+ -- | Two element subsets. -- -- > pairs [1,2,3] == [(1,2),(1,3),(2,3)]@@ -64,9 +72,25 @@ partitions :: Eq a => [a] -> [[[a]]] partitions = map (map M.toList . M.toList) . M.partitions . M.fromListEq --- | Cartesian product of two sets.------ > let r = [('a',1),('a',2),('b',1),('b',2),('c',1),('c',2)]--- > in cartesian_product "abc" [1,2] == r+{- | Cartesian product of two sets.++> let r = [('a',1),('a',2),('b',1),('b',2),('c',1),('c',2)]+> in cartesian_product "abc" [1,2] == r++> cartesian_product "abc" "" == []++-} cartesian_product :: [a] -> [b] -> [(a,b)] cartesian_product p q = [(i,j) | i <- p, j <- q]++-- | List form of n-fold cartesian product.+--+-- > length (nfold_cartesian_product [[1..13],[1..4]]) == 52+-- > length (nfold_cartesian_product ["abc","de","fgh"]) == 3 * 2 * 3+nfold_cartesian_product :: [[a]] -> [[a]]+nfold_cartesian_product l =+ case l of+ [] -> []+ [_] -> []+ [x,y] -> [[i,j] | i <- x, j <- y]+ x:l' -> concatMap (\e -> map (e :) (nfold_cartesian_product l')) x
+ Music/Theory/Show.hs view
@@ -0,0 +1,2 @@+-- | Show functions.+module Music.Theory.Show where
+ Music/Theory/String.hs view
@@ -0,0 +1,15 @@+-- | String functions.+module Music.Theory.String where++import Data.Char {- base -}++-- | Remove @\r@.+filter_cr :: String -> String+filter_cr = filter (not . (==) '\r')++-- | Delete trailing 'Char' where 'isSpace' holds.+--+-- > delete_trailing_whitespace " str " == " str"+delete_trailing_whitespace :: String -> String+delete_trailing_whitespace = reverse . dropWhile isSpace . reverse+
Music/Theory/Tempo_Marking.hs view
@@ -79,7 +79,7 @@ -- | Lookup metronome mark in table. -- -- > mm_name metronome_table_nikko 72 == Just "Andante"-mm_name :: (Num a, Ord a) => [(String,(a,a))] -> a -> Maybe String+mm_name :: Ord a => [(String,(a,a))] -> a -> Maybe String mm_name tbl x = let f (_,(p,q)) = x >= p && x < q in fmap fst (find f tbl)
Music/Theory/Tiling/Canon.hs view
@@ -1,11 +1,13 @@ module Music.Theory.Tiling.Canon where -import Control.Monad.Logic {- logict -}-import Data.Function {- base -} import Data.List {- base -} import Data.List.Split {- split -} import Text.Printf {- base -} +import qualified Control.Monad.Logic as L {- logict -}++import qualified Music.Theory.List as T {- hmt -}+ -- | Sequence. type S = [Int] @@ -85,65 +87,67 @@ n = maximum (concat t) + 1 t3_1 (i,_,_) = i f z = let (s:_,m,o) = unzip3 z in (n,s,m,o)- in map f (groupBy ((==) `on` t3_1) e)+ in map f (T.group_on t3_1 e) -- * Construction -- | 'msum' '.' 'map' 'return'. -- -- > observeAll (fromList [1..7]) == [1..7]-fromList :: MonadPlus m => [a] -> m a-fromList = msum . map return+fromList :: L.MonadPlus m => [a] -> m a+fromList = L.msum . map return -- | Search for /perfect/ tilings of the sequence 'S' using -- multipliers from /m/ to degree /n/ with /k/ parts.-perfect_tilings_m :: MonadPlus m => [S] -> [Int] -> Int -> Int -> m T+perfect_tilings_m :: L.MonadPlus m => [S] -> [Int] -> Int -> Int -> m T perfect_tilings_m s m n k = let rec p q = if length q == k then return (sort q) else do m' <- fromList m- guard (m' `notElem` p)+ L.guard (m' `notElem` p) s' <- fromList s let i = n - (maximum s' * m') - 1 o <- fromList [0..i] let s'' = e_to_seq (s',m',o) q' = concat q- guard (all (`notElem` q') s'')+ L.guard (all (`notElem` q') s'') rec (m':p) (s'':q) in rec [] [] --- | 't_normal' of 'observeAll' of 'perfect_tilings_m'.------ > perfect_tilings [[0,1]] [1..3] 6 3 == []------ > let r = [[[0,7,14],[1,5,9],[2,4,6],[3,8,13],[10,11,12]]]--- > in perfect_tilings [[0,1,2]] [1,2,4,5,7] 15 5 == r------ > length (perfect_tilings [[0,1,2]] [1..12] 15 5) == 1------ > let r = [[[0,1],[2,5],[3,7],[4,6]]--- > ,[[0,1],[2,6],[3,5],[4,7]]--- > ,[[0,2],[1,4],[3,7],[5,6]]]--- > in perfect_tilings [[0,1]] [1..4] 8 4 == r------ > let r = [[[0,1],[2,5],[3,7],[4,9],[6,8]]--- > ,[[0,1],[2,7],[3,5],[4,8],[6,9]]--- > ,[[0,2],[1,4],[3,8],[5,9],[6,7]]--- > ,[[0,2],[1,5],[3,6],[4,9],[7,8]]--- > ,[[0,3],[1,6],[2,4],[5,9],[7,8]]]--- > in perfect_tilings [[0,1]] [1..5] 10 5 == r------ Johnson 2004, p.2------ > let r = [[0,6,12],[1,8,15],[2,11,20],[3,5,7],[4,9,14],[10,13,16],[17,18,19]]--- > in perfect_tilings [[0,1,2]] [1,2,3,5,6,7,9] 21 7 == [r]------ > let r = [[0,10,20],[1,9,17],[2,4,6],[3,7,11],[5,12,19],[8,13,18],[14,15,16]]--- > in perfect_tilings [[0,1,2]] [1,2,4,5,7,8,10] 21 7 == [t_retrograde r]+{- | 't_normal' of 'L.observeAll' of 'perfect_tilings_m'.++> perfect_tilings [[0,1]] [1..3] 6 3 == []++> let r = [[[0,7,14],[1,5,9],[2,4,6],[3,8,13],[10,11,12]]]+> in perfect_tilings [[0,1,2]] [1,2,4,5,7] 15 5 == r++> length (perfect_tilings [[0,1,2]] [1..12] 15 5) == 1++> let r = [[[0,1],[2,5],[3,7],[4,6]]+> ,[[0,1],[2,6],[3,5],[4,7]]+> ,[[0,2],[1,4],[3,7],[5,6]]]+> in perfect_tilings [[0,1]] [1..4] 8 4 == r++> let r = [[[0,1],[2,5],[3,7],[4,9],[6,8]]+> ,[[0,1],[2,7],[3,5],[4,8],[6,9]]+> ,[[0,2],[1,4],[3,8],[5,9],[6,7]]+> ,[[0,2],[1,5],[3,6],[4,9],[7,8]]+> ,[[0,3],[1,6],[2,4],[5,9],[7,8]]]+> in perfect_tilings [[0,1]] [1..5] 10 5 == r++Johnson 2004, p.2++> let r = [[0,6,12],[1,8,15],[2,11,20],[3,5,7],[4,9,14],[10,13,16],[17,18,19]]+> in perfect_tilings [[0,1,2]] [1,2,3,5,6,7,9] 21 7 == [r]++> let r = [[0,10,20],[1,9,17],[2,4,6],[3,7,11],[5,12,19],[8,13,18],[14,15,16]]+> in perfect_tilings [[0,1,2]] [1,2,4,5,7,8,10] 21 7 == [t_retrograde r]++-} perfect_tilings :: [S] -> [Int] -> Int -> Int -> [T] perfect_tilings s m n =- nub . sort . map t_normal . observeAll . perfect_tilings_m s m n+ nub . sort . map t_normal . L.observeAll . perfect_tilings_m s m n -- * Display
Music/Theory/Time/Bel1990/R.hs view
@@ -11,184 +11,7 @@ Centre National de la Recherche Scientifique, 1992. /GRTC 458/ (<http://www.lpl.univ-aix.fr/~belbernard/music/2algorithms.pdf>) -For patterns without tempo indications, the two notations should give-equivalent phase diagrams, for instance (Bel 1990, §11, p.24):--> > bel_ascii_pp "ab{ab,cde}cd"->-> Bel(R): "ab{ab,cde}cd", Dur: 7->-> a _ b _ a _ _ b _ _ c _ d _-> c _ d _ e _ --and:--> > bel_ascii_pp "{a{bc,def},ghijk}"->-> Bel(R): "{a{bc,def},ghijk}", Dur: 5->-> a _ _ _ _ _ _ _ _ _ b _ _ _ _ _ _ _ _ _ _ _ _ _ _ c _ _ _ _ _ _ _ _ _ _ _ _ _ _-> d _ _ _ _ _ _ _ _ _ e _ _ _ _ _ _ _ _ _ f _ _ _ _ _ _ _ _ _-> g _ _ _ _ _ _ _ h _ _ _ _ _ _ _ i _ _ _ _ _ _ _ j _ _ _ _ _ _ _ k _ _ _ _ _ _ _--The /Bel/ notation allows /n/-ary parallel structures,-ie. @{a_bcd_e,a_f_gh_,ji_a_i_}@ (Bel 1992, p.29), however /Bel(R)/-allows only binary structures. The parallel interpretation rules are-associative:--> > bel_ascii_pp "{a_bcd_e,{a_f_gh_,ji_a_i_}}"->-> Bel(R): "{a_bcd_e,{a_f_gh_,ji_a_i_}}", Dur: 7->-> a _ b c d _ e-> a _ f _ g h _-> j i _ a _ i _--/Bel(R)/ does allow unary parallel structures (see 'Iso'), which can-be used to /isolate/ tempo changes:--> > bel_ascii_pp "ab{*2cd}ef{*2/3gh}ij"->-> Bel(R): "ab{*2cd}ef{*2/3gh}ij", Dur: 10->-> a _ b _ c d e _ f _ g _ _ h _ _ i _ j _--Patterns with tempo indications have completely different meanings in-/Bel/ and /Bel(R)/, though in both cases parallel nodes delimit the-scope of tempo markings.--/Bel(R)/ replaces the @\/n@ notation for explicit tempo marks with a-@*n@ notation to indicate a tempo multiplier, and a set of bracketing-notations to specify interpretation rules for parallel (concurrent)-temporal structures.--The tempo indication @\/1@ in the expression @ab{\/1ab,cde}cd@-(Bel 1990, p.24) requires that the inner @ab@ have the same tempo as-the outer @ab@, which is implicitly @\/1@. Setting the tempo of one-part of a parallel structure requires assigning a tempo to the other-part in order that the two parts have equal duration. Here the tempo-assigned to @cde@ is @\/1.5@, but since fractional tempi are not-allowed the expression is re-written as @\/2ab{\/2ab,\/3cde}\/2cd@.--Importantly the explicit tempo indications make it possible to write-syntactically correct expressions in /Bel/ that do not have a coherent-interpretation, ie. @{\/1ab,\/1cde}@. Determining if a coherent set-of tempos can be assigned, and assigning these tempos, is the object-of the interpretation system.--In comparison, all syntactically valid /Bel(R)/ strings have an-interpretation. The expression @{*1ab,*1cde}@ is trivially equal to-@{ab,cde}@, and tempo marks in parallel parts do not interact:--> > bel_ascii_pp "{a*2b,*3c/2d/3e}"->-> Bel(R): "{a*2b,*3c*1/2d*1/3e}", Dur: 3->-> a _ _ _ _ _ b _ _-> c d _ e _ _ _ _ _--Here @a@ is twice the duration of @b@, and @e@ is three times the-duration of @d@, which is twice the duration of @c@ (in /Bel(R)/ @\/n@-is equivalent to @*1\/n@). The duration of any /Bel(R)/ expression-can be calculated directly, given an initial 'Tempo':--> bel_dur 1 (bel_char_parse "a*2b") == 3/2-> bel_dur 1 (bel_char_parse "*3c/2d/3e") == 3--Therefore in the composite expression the left part is slowed by a-factor of two to align with the right part.--The /Bel/ string @ab{\/1ab,cde}cd@ can be re-written in /Bel(R)/ as-either @ab~{ab,cde}cd@ or @ab(ab,cde)cd@. The absolute tempo-indication is replaced by notations giving alternate modes of-interpretation for the parallel structure.--In the first case the @~@ indicates the /opposite/ of the normal rule-for parallel nodes. The normal rule is the same as for /Bel/ and is-that the duration of the whole is equal to duration of the longer of-the two parts. The @~@ inverts this so that the whole has the-duration of the shorter of the two parts, and the longer part is-scaled to have equal duration.--In the second case the parentheses @()@ replacing the braces @{}@-indicates that the duration of the whole is equal to the duration of-the left side, and that the right is to be scaled. Similarly, a @~@-preceding parentheses indicates the duration of the whole should be-the duration of the right side, and the left scaled.--> > bel_ascii_pp "ab~{ab,cde}cd"->-> Bel(R): "ab~{ab,cde}cd", Dur: 6->-> a _ _ b _ _ a _ _ b _ _ c _ _ d _ _-> c _ d _ e _ --There is one other parallel mode that has no equivalent in /Bel/-notation. It is a mode that does not scale either part, leaving a-/hole/ at the end of the shorter part, and is indicated by square-brackets:--> > bel_ascii_pp "ab[ab,cde]cd"->-> Bel(R): "ab[ab,cde]cd", Dur: 7->-> a b a b c d-> c d e --The /Bel/ string @\/2abc\/3de@ (Bel 1992, p.53) can be written as-@*2abc*1/2*3de@, or equivalently as @*2abc*3/2de@:--> > bel_ascii_pp "*2abc*3/2de"->-> Bel(R): "*2abc*3/2de", Dur: 13/6->-> a _ _ b _ _ c _ _ d _ e _--It can also be written using the shorthand notation for rest-sequences, where an integer /n/ indicates a sequence of /n/ rests, as:--> > bel_ascii_pp "(9,abc)(4,de)"->-> Bel(R): "(---------,abc)(----,de)", Dur: 13->-> - - - - - - - - - - - - --> a _ _ b _ _ c _ _ d _ e _--In the /Bel/ string @{ab{/3abc,de},fghijk}@ (Bel 1992, p.20) the tempo-indication does not change the inter-relation of the parts but rather-scales the parallel node altogether, and can be re-written in /Bel(R)/-notation as:--> > bel_ascii_pp "{ab*3{abc,de},fghijk}"->-> Bel(R): "{ab*3{abc,de},fghijk}", Dur: 6->-> a _ _ _ _ _ b _ _ _ _ _ a _ b _ c _-> d _ _ e _ _-> f _ _ g _ _ h _ _ i _ _ j _ _ k _ _--Curiously the following example (Bel 1990, p. 24) does not correspond-to the phase diagram given:--> > bel_ascii_pp "{i{ab,cde},jk}"->-> Bel(R): "{i{ab,cde},jk}", Dur: 4->-> i _ a _ _ b _ _-> c _ d _ e _-> j _ _ _ k _ _ _--The paper assigns tempi of @\/6@ to both @i@ and @ab@, which in-/Bel(R)/ could be written:--> > bel_ascii_pp "{i~{ab,cde},jk}"->-> Bel(R): "{i~{ab,cde},jk}", Dur: 3->-> i _ _ _ _ _ a _ _ _ _ _ b _ _ _ _ _-> c _ _ _ d _ _ _ e _ _ _-> j _ _ _ _ _ _ _ _ k _ _ _ _ _ _ _ _-+For details see <http://rd.slavepianos.org/t/hmt-texts>. -} module Music.Theory.Time.Bel1990.R where@@ -359,7 +182,7 @@ -- | Merge two ascending 'L_Bel'. lbel_merge :: L_Bel a -> L_Bel a -> L_Bel a-lbel_merge = T.merge_by (compare `on` lterm_time)+lbel_merge = T.merge_on lterm_time -- | Set of unique 'Tempo' at 'L_Bel'. lbel_tempi :: L_Bel a -> [Tempo]@@ -391,14 +214,14 @@ -- | Unique 'Voice's at 'L_Bel'. lbel_voices :: L_Bel a -> [Voice] lbel_voices =- sortBy (compare `on` reverse) .+ sortOn reverse . nub . map (\((_,_,v),_) -> voice_normalise v) -- | The duration of 'L_Bel'. lbel_duration :: L_Bel a -> Time lbel_duration b =- let l = last (groupBy ((==) `on` lterm_time) b)+ let l = last (T.group_on lterm_time b) in maximum (map (\((st,tm,_),_) -> st + recip tm) l) -- | Locate an 'L_Term' that is active at the indicated 'Time' and in@@ -512,7 +335,7 @@ -- -- > P.parse p_nrests "" "3" p_nrests :: P (Bel a)-p_nrests = liftM nrests p_integer+p_nrests = liftM nrests p_non_negative_integer -- | Parse 'Continue' 'Term'. --@@ -538,40 +361,41 @@ p_char_node :: P (Bel Char) p_char_node = liftM Node p_char_term --- | Parse positive 'Integer'.+-- | Parse non-negative 'Integer'. ----- > P.parse p_integer "" "3"-p_integer :: P Integer-p_integer = liftM read (P.many1 P.digit)+-- > P.parse p_non_negative_integer "" "3"+p_non_negative_integer :: P Integer+p_non_negative_integer = liftM read (P.many1 P.digit) --- | Parse positive 'Rational'.+-- | Parse non-negative 'Rational'. ----- > P.parse (p_rational `P.sepBy` (P.char ',')) "" "3%5,2/3"-p_rational :: P Rational-p_rational = do- n <- p_integer+-- > P.parse (p_non_negative_rational `P.sepBy` (P.char ',')) "" "3%5,2/3"+p_non_negative_rational :: P Rational+p_non_negative_rational = do+ n <- p_non_negative_integer _ <- P.oneOf "%/"- d <- p_integer+ d <- p_non_negative_integer return (n % d) --- | Parse positive 'Double'.+-- | Parse non-negative 'Double'. ----- > P.parse p_double "" "3.5"--- > P.parse (p_double `P.sepBy` (P.char ',')) "" "3.5,7.2,1.0"-p_double :: P Double-p_double = do+-- > P.parse p_non_negative_double "" "3.5"+-- > P.parse (p_non_negative_double `P.sepBy` (P.char ',')) "" "3.5,7.2,1.0"+p_non_negative_double :: P Double+p_non_negative_double = do a <- P.many1 P.digit _ <- P.char '.' b <- P.many1 P.digit return (read (a ++ "." ++ b)) --- | Parse positive number as 'Rational'.+-- | Parse non-negative number as 'Rational'. ----- > P.parse (p_number `P.sepBy` (P.char ',')) "" "7%2,3.5,3"-p_number :: P Rational-p_number = P.choice [P.try p_rational- ,P.try (liftM toRational p_double)- ,P.try (liftM toRational p_integer)]+-- > P.parse (p_non_negative_number `P.sepBy` (P.char ',')) "" "7%2,3.5,3"+p_non_negative_number :: P Rational+p_non_negative_number =+ P.choice [P.try p_non_negative_rational+ ,P.try (liftM toRational p_non_negative_double)+ ,P.try (liftM toRational p_non_negative_integer)] -- | Parse 'Mul'. --@@ -579,7 +403,7 @@ p_mul :: P (Bel a) p_mul = do op <- P.oneOf "*/"- n <- p_number+ n <- p_non_negative_number let n' = case op of '*' -> n '/' -> recip n
Music/Theory/Time/Notation.hs view
@@ -1,21 +1,67 @@ module Music.Theory.Time.Notation where +import Data.List.Split {- split -} import Text.Printf {- base -} -- | Fractional seconds. type FSEC = Double -- | Minutes, seconds as @(min,sec)@+type MinSec n = (n,n)++-- | Type specialised. type MINSEC = (Int,Int) -- | Minutes, seconds, centi-seconds as @(min,sec,csec)@+type MinCsec n = (n,n,n)++-- | Type specialised. type MINCSEC = (Int,Int,Int) +-- | 'divMod' by @60@.+--+-- > sec_to_minsec 123 == (2,3)+sec_to_minsec :: Integral n => n -> MinSec n+sec_to_minsec = flip divMod 60++-- | Inverse of 'sec_minsec'.+--+-- > minsec_to_sec (2,3) == 123+minsec_to_sec :: Num n => MinSec n -> n+minsec_to_sec (m,s) = m * 60 + s++minsec_binop :: Integral t => (t -> t -> t) -> MinSec t -> MinSec t -> MinSec t+minsec_binop f p q = sec_to_minsec (f (minsec_to_sec p) (minsec_to_sec q))++-- | 'minsec_binop' '-', assumes /q/ precedes /p/.+--+-- > minsec_sub (2,35) (1,59) == (0,36)+minsec_sub :: Integral n => MinSec n -> MinSec n -> MinSec n+minsec_sub = minsec_binop (-)++-- | 'minsec_binop' 'subtract', assumes /p/ precedes /q/.+--+-- > minsec_diff (1,59) (2,35) == (0,36)+minsec_diff :: Integral n => MinSec n -> MinSec n -> MinSec n+minsec_diff = minsec_binop subtract++-- | 'minsec_binop' '+'.+--+-- > minsec_add (1,59) (2,35) == (4,34)+minsec_add :: Integral n => MinSec n -> MinSec n -> MinSec n+minsec_add = minsec_binop (+)++-- | 'foldl' of 'minsec_add'+--+-- > minsec_sum [(1,59),(2,35),(4,34)] == (9,08)+minsec_sum :: Integral n => [MinSec n] -> MinSec n+minsec_sum = foldl minsec_add (0,0)+ -- | Fractional seconds to @(min,sec)@. -- -- > map fsec_to_minsec [59.49,60,60.51] == [(0,59),(1,0),(1,1)] fsec_to_minsec :: FSEC -> MINSEC-fsec_to_minsec tm = round tm `divMod` 60+fsec_to_minsec = sec_to_minsec . round -- | 'MINSEC' pretty printer. --@@ -23,21 +69,59 @@ minsec_pp :: MINSEC -> String minsec_pp (m,s) = printf "%02d:%02d" m s --- | Fractional seconds to @(min,sec,csec)@.+-- * 'MinSec' parser.+minsec_parse :: (Num n,Read n) => String -> MinSec n+minsec_parse x =+ case splitOn ":" x of+ [m,s] -> (read m,read s)+ _ -> error "parse_minsec"++-- | Fractional seconds to @(min,sec,csec)@, csec value is 'round'ed. -- -- > map fsec_to_mincsec [1,1.5,4/3] == [(0,1,0),(0,1,50),(0,1,33)] fsec_to_mincsec :: FSEC -> MINCSEC fsec_to_mincsec tm = let tm' = floor tm- (m,s) = tm' `divMod` 60+ (m,s) = sec_to_minsec tm' cs = round ((tm - fromIntegral tm') * 100) in (m,s,cs) +-- | Inverse of 'fsec_mincsec'.+mincsec_to_fsec :: Real n => MinCsec n -> FSEC+mincsec_to_fsec (m,s,cs) = realToFrac m * 60 + realToFrac s + (realToFrac cs / 100)++-- > map (mincsec_to_csec . fsec_to_mincsec) [1,6+2/3,123.45] == [100,667,12345]+mincsec_to_csec :: Num n => MinCsec n -> n+mincsec_to_csec (m,s,cs) = m * 60 * 100 + s * 100 + cs++-- | Centi-seconds to 'MinCsec'.+--+-- > map csec_to_mincsec [123,12345] == [(0,1,23),(2,3,45)]+csec_to_mincsec :: Integral n => n -> MinCsec n+csec_to_mincsec csec =+ let (m,cs) = csec `divMod` 6000+ (s,cs') = cs `divMod` 100+ in (m,s,cs')++-- | 'MINCSEC' pretty printer, concise mode omits centiseconds when zero.+--+-- > map (mincsec_pp_opt True . fsec_to_mincsec) [1,60.5] == ["00:01","01:00.50"]+mincsec_pp_opt :: Bool -> MINCSEC -> String+mincsec_pp_opt concise (m,s,cs) =+ if concise && cs == 0+ then printf "%02d:%02d" m s+ else printf "%02d:%02d.%02d" m s cs+ -- | 'MINCSEC' pretty printer. ----- > map (mincsec_pp . fsec_to_mincsec) [1,4/3] == ["00:01.00","00:01.33"]+-- > let r = ["00:01.00","00:06.67","02:03.45"]+-- > map (mincsec_pp . fsec_to_mincsec) [1,6+2/3,123.45] == r mincsec_pp :: MINCSEC -> String-mincsec_pp (m,s,cs) = printf "%02d:%02d.%02d" m s cs+mincsec_pp = mincsec_pp_opt False +mincsec_binop :: Integral t => (t -> t -> t) -> MinCsec t -> MinCsec t -> MinCsec t+mincsec_binop f p q = csec_to_mincsec (f (mincsec_to_csec p) (mincsec_to_csec q))++-- | Given printer, pretty print time span. span_pp :: (t -> String) -> (t,t) -> String span_pp f (t1,t2) = concat [f t1," - ",f t2]
Music/Theory/Time/Seq.hs view
@@ -6,13 +6,13 @@ import qualified Data.List.Ordered as O {- data-ordlist -} import qualified Data.Map as M {- containers -} import Data.Maybe {- base -}-import Data.Monoid {- base -} import Data.Ratio {- base -} import Safe {- safe -} import Music.Theory.Function {- hmt -} import qualified Music.Theory.List as T {- hmt -} import qualified Music.Theory.Math as T {- hmt -}+import qualified Music.Theory.Ord as T {- hmt -} import qualified Music.Theory.Tuple as T {- hmt -} -- * Types@@ -26,16 +26,16 @@ -- | Inter-offset sequence. The duration is the interval /before/ the -- value. To indicate the duration of the final value /a/ must have--- an /nil/ (end of sequence) value.+-- a /nil/ (end of sequence) value. type Iseq t a = [(t,a)] -- | Pattern sequence. The duration is a triple of /logical/, -- /sounding/ and /forward/ durations. type Pseq t a = [((t,t,t),a)] --- | Time-point sequence. To express holes /a/ must have a /empty/+-- | Time-point sequence. To express holes /a/ must have an /empty/ -- value. To indicate the duration of the final value /a/ must have--- an /nil/ (end of sequence) value.+-- a /nil/ (end of sequence) value. type Tseq t a = [(t,a)] -- | Window sequence. The temporal field is (/time/,/duration/).@@ -69,6 +69,20 @@ wseq_tspan :: Num t => Wseq t a -> (t,t) wseq_tspan = seq_tspan fst (uncurry (+)) +-- | Start time of sequence.+--+-- > wseq_start [((1,2),'a')] == 1+-- > wseq_start [] == 0+wseq_start :: Num t => Wseq t a -> t+wseq_start = fst . wseq_tspan++-- | End time of sequence.+--+-- > wseq_end [((1,2),'a')] == 3+-- > wseq_end (useq_to_wseq 0 (1,"linear")) == 6+wseq_end :: Num t => Wseq t a -> t+wseq_end = snd . wseq_tspan+ -- * Duration dseq_dur :: Num t => Dseq t a -> t@@ -94,15 +108,52 @@ -- * Window --- | Keep only elements in the indicated temporal window.+-- | Prefix of sequence where the start time precedes or is at the+-- indicate time.+wseq_until :: Ord t => t -> Wseq t a -> Wseq t a+wseq_until tm = takeWhile (\((t0,_),_) -> t0 <= tm)++-- | Keep only elements that are entirely contained within the indicated+-- temporal window, which is inclusive at the left & right+-- edges, ie. [t0,t1]. Halts processing at end of window. -- -- > let r = [((5,1),'e'),((6,1),'f'),((7,1),'g'),((8,1),'h')]--- > in wseq_twindow (5,9) (zip (zip [1..10] (repeat 1)) ['a'..]) == r+-- > in wseq_twindow (5,9) (zip (zip [1..] (repeat 1)) ['a'..]) == r+--+-- > wseq_twindow (1,2) [((1,1),'a'),((1,2),'b')] == [((1,1),'a')] wseq_twindow :: (Num t, Ord t) => (t,t) -> Wseq t a -> Wseq t a wseq_twindow (w0,w1) = let f (st,du) = w0 <= st && (st + du) <= w1- in wseq_tfilter f+ in wseq_tfilter f . wseq_until w1 +-- | Select nodes that are active at indicated time, comparison is+-- inclusive at left and exclusive at right. Halts processing at end+-- of window.+--+-- > let sq = [((1,1),'a'),((1,2),'b')]+-- > in map (wseq_at sq) [1,2] == [sq,[((1,2),'b')]]+--+-- > wseq_at (zip (zip [1..] (repeat 1)) ['a'..]) 3 == [((3,1),'c')]+wseq_at :: (Num t,Ord t) => Wseq t a -> t -> Wseq t a+wseq_at sq tm =+ let sel ((t0,t1),_) = t0 <= tm && tm < (t0 + t1)+ end ((t0,_),_) = t0 <= tm+ in filter sel (takeWhile end sq)++-- | Select nodes that are active within the indicated window, comparison is+-- inclusive at left and exclusive at right. Halts processing at end+-- of window.+--+-- > let sq = [((0,2),'a'),((0,4),'b'),((2,4),'c')]+-- > in wseq_at_window sq (1,3) == sq+--+-- > wseq_at_window (zip (zip [1..] (repeat 1)) ['a'..]) (3,4) == [((3,1),'c'),((4,1),'d')]+wseq_at_window :: (Num t, Ord t) => Wseq t a -> (t,t) -> Wseq t a+wseq_at_window sq (w0,w1) =+ let f (t0,t1) t = t0 <= t && t < t1+ g (st,du) = let w = (st,st + du) in f w w0 || f w w1+ in wseq_tfilter g (wseq_until w1 sq)+ -- * Append dseq_append :: Dseq t a -> Dseq t a -> Dseq t a@@ -140,11 +191,24 @@ g (t,p) (_,q) = (t,f p q) in T.merge_by_resolve g cmp +-- | Compare first by start time, then by duration.+w_compare :: Ord t => ((t,t),a) -> ((t,t),a) -> Ordering+w_compare ((t1,d1),_) ((t2,d2),_) =+ case compare t1 t2 of+ EQ -> compare d1 d2+ r -> r++-- | Merge considering only start times. wseq_merge :: Ord t => Wseq t a -> Wseq t a -> Wseq t a wseq_merge = O.mergeBy (compare `on` (fst . fst)) +-- | Merge set considering both start times & durations.+wseq_merge_set :: Ord t => [Wseq t a] -> Wseq t a+wseq_merge_set = T.merge_set_by w_compare+ -- * Lookup +-- | Locate nodes to the left and right of indicated time. tseq_lookup_window_by :: (t -> t -> Ordering) -> Tseq t e -> t -> (Maybe (t,e),Maybe (t,e)) tseq_lookup_window_by cmp = let recur l sq t =@@ -276,7 +340,7 @@ seq_partition :: Ord v => (a -> v) -> [(t,a)] -> [(v,[(t,a)])] seq_partition voice sq = let assign m (t,a) = M.insertWith (++) (voice a) [(t,a)] m- from_map = sortBy (compare `on` fst) .+ from_map = sortOn fst . map (\(v,l) -> (v,reverse l)) . M.toList in from_map (foldl assign M.empty sq)@@ -379,6 +443,9 @@ -- -- > let r = [(0,"a"),(1,"bc"),(2,"de"),(3,"f")] -- > in tseq_group (zip [0,1,1,2,2,3] ['a'..]) == r+--+-- > tseq_group [(1,'a'),(1,'b')] == [(1,"ab")]+-- > tseq_group [(1,'a'),(2,'b'),(2,'c')] == [(1,"a"),(2,"bc")] tseq_group :: (Eq t,Num t) => Tseq t a -> Tseq t [a] tseq_group = group_f (==) @@ -432,35 +499,66 @@ -- * Wseq +-- | Sort 'Wseq' by start time, 'Wseq' ought never to be out of+-- order.+--+-- > wseq_sort [((3,1),'a'),((1,3),'b')] == [((1,3),'b'),((3,1),'a')]+wseq_sort :: Ord t => Wseq t a -> Wseq t a+wseq_sort = sortBy (compare `on` (fst . fst))+ -- | Transform 'Wseq' to 'Tseq' by discaring durations. wseq_discard_dur :: Wseq t a -> Tseq t a wseq_discard_dur = let f ((t,_),e) = (t,e) in map f --- | Edit durations to ensure that notes don't overlap. If the same--- note is played simultaneously delete shorter note. If a note--- extends into a later note shorten duration (apply /d_fn/ to iot).+wseq_overlap_f :: (Eq e,Ord t,Num t) =>+ (e -> e -> Bool) -> (t -> t) -> ((t,t),e) -> Wseq t e -> Maybe (Wseq t e)+wseq_overlap_f eq_fn dur_fn ((t,d),a) sq =+ case find (eq_fn a . snd) sq of+ Nothing -> Nothing+ Just ((t',d'),a') ->+ if t == t'+ then if d <= d'+ then Just sq -- delete LHS+ else Just (((t,d),a) : delete ((t',d'),a') sq) -- delete RHS+ else if t' < t + d+ then Just (((t,dur_fn (t' - t)),a) : sq) -- truncate LHS+ else Nothing++-- | Determine if sequence has overlapping equal nodes.+wseq_has_overlaps :: (Ord t, Num t, Eq e) => (e -> e -> Bool) -> Wseq t e -> Bool+wseq_has_overlaps eq_fn =+ let recur sq =+ case sq of+ [] -> False+ h:sq' ->+ case wseq_overlap_f eq_fn id h sq' of+ Nothing -> recur sq'+ Just _ -> True+ in recur+++{- | Edit durations to ensure that nodes don't overlap. If equal nodes+ begin simultaneously delete the shorter node. If a node+ extends into a later node shorten the initial duration (apply /dur_fn/ to iot).++> let sq = [((0,1),'a'),((0,5),'a'),((1,5),'a'),((3,1),'a')]+> let r = [((0,1),'a'),((1,2),'a'),((3,1),'a')]+> wseq_has_overlaps (==) sq == True+> wseq_remove_overlaps (==) id sq == r+> wseq_has_overlaps (==) (wseq_remove_overlaps (==) id sq) == False++-} wseq_remove_overlaps :: (Eq e,Ord t,Num t) =>- (e -> e -> Bool) -> (t -> t) ->- Wseq t e -> Wseq t e-wseq_remove_overlaps eq_fn d_fn =- let go sq =- case sq of- [] -> []- ((t,d),a):sq' ->- case find (eq_fn a . snd) sq' of- Nothing -> ((t,d),a) : go sq'- Just ((t',d'),a') ->- if t == t'- then if d <= d'- then -- delete LHS- go sq'- else -- delete RHS- ((t,d),a) :- go (delete ((t',d'),a') sq')- else if t' < t + d- then ((t,d_fn (t' - t)),a) : go sq'- else ((t,d),a) : go sq'- in go+ (e -> e -> Bool) -> (t -> t) -> Wseq t e -> Wseq t e+wseq_remove_overlaps eq_fn dur_fn =+ let recur sq =+ case sq of+ [] -> []+ h:sq' ->+ case wseq_overlap_f eq_fn dur_fn h sq' of+ Nothing -> h : recur sq'+ Just sq'' -> recur sq''+ in recur -- | Unjoin elements (assign equal time stamps to all elements). seq_unjoin :: [(t,[e])] -> [(t,e)]@@ -470,87 +568,149 @@ wseq_unjoin :: Wseq t [e] -> Wseq t e wseq_unjoin = seq_unjoin --- * On/Off+-- | Shift (displace) onset times by /i/.+--+-- > wseq_shift 3 [((1,2),'a')] == [((4,2),'a')]+wseq_shift :: Num t => t -> Wseq t a -> Wseq t a+wseq_shift i = wseq_tmap_st (+ i) --- | Container for values that have /on/ and /off/ modes.-data On_Off a = On a | Off a deriving (Eq,Show)+-- | Shift q to end of p and append.+--+-- > wseq_append [((1,2),'a')] [((1,2),'b')] == [((1,2),'a'),((4,2),'b')]+wseq_append :: Num t => Wseq t a -> Wseq t a -> Wseq t a+wseq_append p q = p ++ wseq_shift (wseq_end p) q --- | Structural comparison at 'On_Off', 'On' compares less than 'Off'.-cmp_on_off :: On_Off a -> On_Off b -> Ordering-cmp_on_off p q =+-- | 'foldl1' of 'wseq_append'+--+-- > wseq_concat [[((1,2),'a')],[((1,2),'b')]] == [((1,2),'a'),((4,2),'b')]+wseq_concat :: Num t => [Wseq t a] -> Wseq t a+wseq_concat = foldl1 wseq_append++-- * Begin/End++-- | Container to mark the /begin/ and /end/ of a value.+data Begin_End a = Begin a | End a deriving (Eq,Show)++-- | Functor instance.+begin_end_map :: (t -> u) -> Begin_End t -> Begin_End u+begin_end_map f x =+ case x of+ Begin a -> Begin (f a)+ End a -> End (f a)++-- | Structural comparison at 'Begin_End', 'Begin' compares less than 'End'.+cmp_begin_end :: Begin_End a -> Begin_End b -> Ordering+cmp_begin_end p q = case (p,q) of- (On _,Off _) -> LT- (On _,On _) -> EQ- (Off _,Off _) -> EQ- (Off _,On _) -> GT+ (Begin _,End _) -> LT+ (Begin _,Begin _) -> EQ+ (End _,End _) -> EQ+ (End _,Begin _) -> GT -- | Translate container types.-either_to_on_off :: Either a a -> On_Off a-either_to_on_off p =+either_to_begin_end :: Either a a -> Begin_End a+either_to_begin_end p = case p of- Left a -> On a- Right a -> Off a+ Left a -> Begin a+ Right a -> End a -- | Translate container types.-on_off_to_either :: On_Off a -> Either a a-on_off_to_either p =+begin_end_to_either :: Begin_End a -> Either a a+begin_end_to_either p = case p of- On a -> Left a- Off a -> Right a+ Begin a -> Left a+ End a -> Right a --- | Convert 'Wseq' to 'Tseq' transforming elements to 'On' and 'Off'--- parts. When merging, /off/ elements precede /on/ elements at equal--- times.+begin_end_partition :: [Begin_End a] -> ([a],[a])+begin_end_partition =+ let f e (p,q) = case e of+ Begin x -> (x:p,q)+ End x -> (p,x:q)+ in foldr f ([],[])++-- | Add or delete element from accumulated state.+begin_end_track :: Eq a => [a] -> Begin_End a -> [a]+begin_end_track st e =+ case e of+ Begin x -> x : st+ End x -> delete x st++-- | Convert 'Wseq' to 'Tseq' transforming elements to 'Begin_End'.+-- When merging, /end/ elements precede /begin/ elements at equal times. -- -- > let {sq = [((0,5),'a'),((2,2),'b')]--- > ;r = [(0,On 'a'),(2,On 'b'),(4,Off 'b'),(5,Off 'a')]}--- > in wseq_on_off sq == r+-- > ;r = [(0,Begin 'a'),(2,Begin 'b'),(4,End 'b'),(5,End 'a')]}+-- > in wseq_begin_end sq == r -- -- > let {sq = [((0,1),'a'),((1,1),'b'),((2,1),'c')]--- > ;r = [(0,On 'a'),(1,Off 'a')--- > ,(1,On 'b'),(2,Off 'b')--- > ,(2,On 'c'),(3,Off 'c')]}--- > in wseq_on_off sq == r-wseq_on_off :: (Num t, Ord t) => Wseq t a -> Tseq t (On_Off a)-wseq_on_off sq =- let f ((t,d),a) = [(t,On a),(t + d,Off a)]+-- > ;r = [(0,Begin 'a'),(1,End 'a')+-- > ,(1,Begin 'b'),(2,End 'b')+-- > ,(2,Begin 'c'),(3,End 'c')]}+-- > in wseq_begin_end sq == r+wseq_begin_end :: (Num t, Ord t) => Wseq t a -> Tseq t (Begin_End a)+wseq_begin_end sq =+ let f ((t,d),a) = [(t,Begin a),(t + d,End a)] g l = case l of [] -> []- e:l' -> tseq_merge_by (T.ordering_invert .: cmp_on_off) e (g l')+ e:l' -> tseq_merge_by (T.ord_invert .: cmp_begin_end) e (g l') in g (map f sq) --- | 'on_off_to_either' of 'wseq_on_off'.-wseq_on_off_either :: (Num t, Ord t) => Wseq t a -> Tseq t (Either a a)-wseq_on_off_either = tseq_map on_off_to_either . wseq_on_off+-- | 'begin_end_to_either' of 'wseq_begin_end'.+wseq_begin_end_either :: (Num t, Ord t) => Wseq t a -> Tseq t (Either a a)+wseq_begin_end_either = tseq_map begin_end_to_either . wseq_begin_end --- | Variant that applies /on/ and /off/ functions to nodes.+-- | Variant that applies /begin/ and /end/ functions to nodes. -- -- > let {sq = [((0,5),'a'),((2,2),'b')] -- > ;r = [(0,'A'),(2,'B'),(4,'b'),(5,'a')]}--- > in wseq_on_off_f Data.Char.toUpper id sq == r-wseq_on_off_f :: (Ord t,Num t) => (a -> b) -> (a -> b) -> Wseq t a -> Tseq t b-wseq_on_off_f f g = tseq_map (either f g) . wseq_on_off_either+-- > in wseq_begin_end_f Data.Char.toUpper id sq == r+wseq_begin_end_f :: (Ord t,Num t) => (a -> b) -> (a -> b) -> Wseq t a -> Tseq t b+wseq_begin_end_f f g = tseq_map (either f g) . wseq_begin_end_either --- | Inverse of 'wseq_on_off' given a predicate function for locating--- the /off/ node of an /on/ node.+-- | Result for each time-point the triple (begin-list,end-list,hold-list).+-- The elements of the end-list have been deleted from the hold list.+tseq_begin_end_accum :: Eq a => Tseq t [Begin_End a] -> Tseq t ([a],[a],[a])+tseq_begin_end_accum =+ let f st (t,x) =+ let (b,e) = begin_end_partition x+ st' = foldl begin_end_track st x+ in (st',(t,(b,e,st \\ e)))+ in snd . mapAccumL f []++tseq_accumulate :: Eq a => Tseq t [Begin_End a] -> Tseq t [a]+tseq_accumulate =+ let f st (t,e) =+ let g st' = (st',(t,st'))+ in g (foldl begin_end_track st e)+ in snd . mapAccumL f []++-- | The transition sequence of /active/ elements. ----- > let {sq = [(0,On 'a'),(2,On 'b'),(4,Off 'b'),(5,Off 'a')]+-- > let w = [((0,3),'a'),((1,2),'b'),((2,1),'c'),((3,3),'d')]+-- > wseq_accumulate w == [(0,"a"),(1,"ba"),(2,"cba"),(3,"d"),(6,"")]+wseq_accumulate :: (Eq a,Ord t,Num t) => Wseq t a -> Tseq t [a]+wseq_accumulate = tseq_accumulate . tseq_group . wseq_begin_end++-- | Inverse of 'wseq_begin_end' given a predicate function for locating+-- the /end/ node of a /begin/ node.+--+-- > let {sq = [(0,Begin 'a'),(2,Begin 'b'),(4,End 'b'),(5,End 'a')] -- > ;r = [((0,5),'a'),((2,2),'b')]}--- > in tseq_on_off_to_wseq (==) sq == r-tseq_on_off_to_wseq :: Num t => (a -> a -> Bool) -> Tseq t (On_Off a) -> Wseq t a-tseq_on_off_to_wseq cmp =+-- > in tseq_begin_end_to_wseq (==) sq == r+tseq_begin_end_to_wseq :: Num t => (a -> a -> Bool) -> Tseq t (Begin_End a) -> Wseq t a+tseq_begin_end_to_wseq cmp = let cmp' x e = case e of- Off x' -> cmp x x'+ End x' -> cmp x x' _ -> False f e r = case seq_find (cmp' e) r of- Nothing -> error "tseq_on_off_to_wseq: no matching off?"+ Nothing -> error "tseq_begin_end_to_wseq: no matching end?" Just (t,_) -> t go sq = case sq of [] -> []- (_,Off _) : sq' -> go sq'- (t,On e) : sq' -> let t' = f e sq' in ((t,t' - t),e) : go sq'+ (_,End _) : sq' -> go sq'+ (t,Begin e) : sq' -> let t' = f e sq' in ((t,t' - t),e) : go sq' in go -- * Interop@@ -558,6 +718,9 @@ useq_to_dseq :: Useq t a -> Dseq t a useq_to_dseq (t,e) = zip (repeat t) e +useq_to_wseq :: Num t => t -> Useq t a -> Wseq t a+useq_to_wseq t0 = dseq_to_wseq t0 . useq_to_dseq+ -- | The conversion requires a start time and a /nil/ value used as an -- /eof/ marker. Productive given indefinite input sequence. --@@ -574,8 +737,8 @@ a' = a ++ [nil] in zip t a' --- | Variant where the /nil/ is take as the last element of the--- sequence.+-- | Variant where the /nil/ value is taken from the last element of+-- the sequence. -- -- > let r = zip [0,1,3,6,8,9] "abcdee" -- > in dseq_to_tseq_last 0 (zip [1,2,3,2,1] "abcde") == r@@ -595,7 +758,8 @@ in wseq_zip t d a -- | The last element of 'Tseq' is required to be an /eof/ marker that--- has no duration and is not represented in the 'Dseq'.+-- has no duration and is not represented in the 'Dseq'. A 'nil'+-- value is required in case the 'Tseq' does not begin at @0@. -- -- > let r = zip [1,2,3,2,1] "abcde" -- > in tseq_to_dseq undefined (zip [0,1,3,6,8,9] "abcde|") == r@@ -689,6 +853,30 @@ (z',r) = T.dx_d' z tm in (z',zip r el) in mapAccumL f++-- * Cycle++wseq_cycle' :: Num t => Wseq t a -> [Wseq t a]+wseq_cycle' sq =+ let (_,et) = wseq_tspan sq+ t_sq = iterate (+ et) 0+ in map (\x -> wseq_tmap (\(t,d) -> (x + t,d)) sq) t_sq++-- | Only finite 'Wseq' can be cycled, the resulting Wseq is infinite.+--+-- > take 5 (wseq_cycle [((0,1),'a'),((3,3),'b')])+wseq_cycle :: Num t => Wseq t a -> Wseq t a+wseq_cycle = concat . wseq_cycle'++-- | Variant cycling only /n/ times.+--+-- > wseq_cycle_n 3 [((0,1),'a'),((3,3),'b')]+wseq_cycle_n :: Num t => Int -> Wseq t a -> Wseq t a+wseq_cycle_n n = concat . take n . wseq_cycle'++-- | 'wseq_until' of 'wseq_cycle'.+wseq_cycle_until :: (Num t,Ord t) => t -> Wseq t a -> Wseq t a+wseq_cycle_until et = wseq_until et . wseq_cycle -- * Type specialised map
Music/Theory/Time_Signature.hs view
@@ -1,6 +1,7 @@ -- | Time Signatures. module Music.Theory.Time_Signature where +import Data.Function {- base -} import Data.Ratio {- base -} import Music.Theory.Duration@@ -37,6 +38,7 @@ (1,1) -> [whole_note] (2,2) -> [whole_note] (4,4) -> [whole_note]+ (8,8) -> [whole_note] (5,4) -> [whole_note,quarter_note] (3,2) -> [dotted_whole_note] (6,4) -> [dotted_whole_note]@@ -59,10 +61,14 @@ ts_rq :: Time_Signature -> RQ ts_rq (n,d) = (4 * n) % d +-- | 'compare' 'on' 'ts_rq'.+ts_compare :: Time_Signature -> Time_Signature -> Ordering+ts_compare = compare `on` ts_rq+ -- | 'Time_Signature' derived from whole note duration in 'RQ' form. -- -- > map rq_to_ts [4,3/2,7/4,6] == [(4,4),(3,8),(7,16),(6,4)]-rq_to_ts :: Rational -> Time_Signature+rq_to_ts :: RQ -> Time_Signature rq_to_ts rq = let n = numerator rq d = denominator rq * 4@@ -74,6 +80,7 @@ -- > ts_divisions (3,8) == [1/2,1/2,1/2] -- > ts_divisions (2,2) == [2,2] -- > ts_divisions (1,1) == [4]+-- > ts_divisions (7,4) == [1,1,1,1,1,1,1] ts_divisions :: Time_Signature -> [RQ] ts_divisions (i,j) = let k = fromIntegral i
Music/Theory/Tuning.hs view
@@ -1,15 +1,19 @@ -- | Tuning theory module Music.Theory.Tuning where -import Data.Fixed {- base -}+import Data.Fixed (mod') {- base -} import Data.List {- base -}+import qualified Data.Map as M {- containers -} import Data.Maybe {- base -} import Data.Ratio {- base -} import Safe {- safe -} import qualified Music.Theory.Either as T {- hmt -} import qualified Music.Theory.List as T {- hmt -}+import qualified Music.Theory.Map as T {- hmt -} import qualified Music.Theory.Pitch as T {- hmt -}+import qualified Music.Theory.Set.List as T {- hmt -}+import qualified Music.Theory.Tuple as T {- hmt -} -- * Types @@ -22,35 +26,38 @@ -- | A tuning specified 'Either' as a sequence of exact ratios, or as -- a sequence of possibly inexact 'Cents'.-data Tuning = Tuning {ratios_or_cents :: Either [Rational] [Cents]- ,octave_ratio :: Rational}+--+-- In both cases, the values are given in relation to the first degree+-- of the scale, which for ratios is 1 and for cents 0.+data Tuning = Tuning {tn_ratios_or_cents :: Either [Rational] [Cents]+ ,tn_octave_ratio :: Rational} deriving (Eq,Show) -- | Divisions of octave. ----- > divisions ditone == 12-divisions :: Tuning -> Int-divisions = either length length . ratios_or_cents+-- > tn_divisions (equal_temperament 12) == 12+tn_divisions :: Tuning -> Int+tn_divisions = either length length . tn_ratios_or_cents -- | 'Maybe' exact ratios of 'Tuning'.-ratios :: Tuning -> Maybe [Rational]-ratios = T.fromLeft . ratios_or_cents+tn_ratios :: Tuning -> Maybe [Rational]+tn_ratios = T.fromLeft . tn_ratios_or_cents -- | 'error'ing variant.-ratios_err :: Tuning -> [Rational]-ratios_err = fromMaybe (error "ratios") . ratios+tn_ratios_err :: Tuning -> [Rational]+tn_ratios_err = fromMaybe (error "ratios") . tn_ratios -- | Possibly inexact 'Cents' of tuning.-cents :: Tuning -> [Cents]-cents = either (map ratio_to_cents) id . ratios_or_cents+tn_cents :: Tuning -> [Cents]+tn_cents = either (map ratio_to_cents) id . tn_ratios_or_cents -- | 'map' 'round' '.' 'cents'.-cents_i :: Integral i => Tuning -> [i]-cents_i = map round . cents+tn_cents_i :: Integral i => Tuning -> [i]+tn_cents_i = map round . tn_cents -- | Variant of 'cents' that includes octave at right.-cents_octave :: Tuning -> [Cents]-cents_octave t = cents t ++ [ratio_to_cents (octave_ratio t)]+tn_cents_octave :: Tuning -> [Cents]+tn_cents_octave t = tn_cents t ++ [ratio_to_cents (tn_octave_ratio t)] -- | Convert from interval in cents to frequency ratio. --@@ -59,30 +66,64 @@ cents_to_ratio n = 2 ** (n / 1200) -- | Possibly inexact 'Approximate_Ratio's of tuning.-approximate_ratios :: Tuning -> [Approximate_Ratio]-approximate_ratios =+tn_approximate_ratios :: Tuning -> [Approximate_Ratio]+tn_approximate_ratios = either (map approximate_ratio) (map cents_to_ratio) .- ratios_or_cents+ tn_ratios_or_cents -- | Cyclic form, taking into consideration 'octave_ratio'.-approximate_ratios_cyclic :: Tuning -> [Approximate_Ratio]-approximate_ratios_cyclic t =- let r = approximate_ratios t- m = realToFrac (octave_ratio t)+tn_approximate_ratios_cyclic :: Tuning -> [Approximate_Ratio]+tn_approximate_ratios_cyclic t =+ let r = tn_approximate_ratios t+ m = realToFrac (tn_octave_ratio t) g = iterate (* m) 1 f n = map (* n) r in concatMap f g +-- | Iterate the function /f/ /n/ times, the inital value is /x/.+--+-- > recur_n 5 (* 2) 1 == 32+-- > take (5 + 1) (iterate (* 2) 1) == [1,2,4,8,16,32]+recur_n :: Integral n => n -> (t -> t) -> t -> t+recur_n n f x = if n < 1 then x else recur_n (n - 1) f (f x)++-- | Convert a (signed) number of octaves difference of given ratio to a ratio.+--+-- > map (oct_diff_to_ratio 2) [-3 .. 3] == [1/8,1/4,1/2,1,2,4,8]+-- > map (oct_diff_to_ratio (9/8)) [-3 .. 3] == [512/729,64/81,8/9,1/1,9/8,81/64,729/512]+oct_diff_to_ratio :: Integral a => Ratio a -> Int -> Ratio a+oct_diff_to_ratio r n = if n >= 0 then recur_n n (* r) 1 else recur_n (negate n) (/ r) 1++-- | Lookup function that allows both negative & multiple octave indices.+--+-- > let map_zip f l = zip l (map f l)+-- > map_zip (tn_ratios_lookup werckmeister_vi) [-24 .. 24]+tn_ratios_lookup :: Tuning -> Int -> Maybe Rational+tn_ratios_lookup t n =+ let (o,pc) = n `divMod` tn_divisions t+ o_ratio = oct_diff_to_ratio (tn_octave_ratio t) o+ in fmap (\r -> o_ratio * (r !! pc)) (tn_ratios t)++-- | Lookup function that allows both negative & multiple octave indices.+--+-- > map_zip (tn_approximate_ratios_lookup werckmeister_v) [-24 .. 24]+tn_approximate_ratios_lookup :: Tuning -> Int -> Approximate_Ratio+tn_approximate_ratios_lookup t n =+ let (o,pc) = n `divMod` tn_divisions t+ o_ratio = fromRational (oct_diff_to_ratio (tn_octave_ratio t) o)+ in o_ratio * ((tn_approximate_ratios t) !! pc)+ -- | 'Maybe' exact ratios reconstructed from possibly inexact 'Cents' -- of 'Tuning'. --+-- > :l Music.Theory.Tuning.Werckmeister -- > let r = [1,17/16,9/8,13/11,5/4,4/3,7/5,3/2,11/7,5/3,16/9,15/8]--- > in reconstructed_ratios 1e-2 werckmeister_iii == Just r-reconstructed_ratios :: Double -> Tuning -> Maybe [Rational]-reconstructed_ratios epsilon =+-- > tn_reconstructed_ratios 1e-2 werckmeister_iii == Just r+tn_reconstructed_ratios :: Double -> Tuning -> Maybe [Rational]+tn_reconstructed_ratios epsilon = fmap (map (reconstructed_ratio epsilon)) . T.fromRight .- ratios_or_cents+ tn_ratios_or_cents -- | Convert from a 'Floating' ratio to /cents/. --@@ -100,15 +141,17 @@ approximate_ratio = fromRational -- | 'approximate_ratio_to_cents' '.' 'approximate_ratio'.-ratio_to_cents :: Rational -> Cents-ratio_to_cents = approximate_ratio_to_cents . approximate_ratio+--+-- > map (\n -> (n,round (ratio_to_cents (fold_ratio_to_octave_err (n % 1))))) [1..21]+ratio_to_cents :: Integral i => Ratio i -> Cents+ratio_to_cents = approximate_ratio_to_cents . realToFrac -- | Construct an exact 'Rational' that approximates 'Cents' to within -- /epsilon/. -- -- > map (reconstructed_ratio 1e-5) [0,700,1200] == [1,442/295,2] ----- > ratio_to_cents (442/295) == 699.9976981706734+-- > ratio_to_cents (442/295) == 699.9976981706735 reconstructed_ratio :: Double -> Cents -> Rational reconstructed_ratio epsilon c = approxRational (cents_to_ratio c) epsilon @@ -197,16 +240,17 @@ equal_temperament_72 :: Tuning equal_temperament_72 = equal_temperament (72::Int) +-- | 96-tone equal temperament.+equal_temperament_96 :: Tuning+equal_temperament_96 = equal_temperament (96::Int)+ -- * Harmonic series --- | Raise or lower the frequency /q/ by octaves until it is in the--- octave starting at /p/.+-- | Harmonic series to /n/th partial, with indicated octave. ----- > fold_cps_to_octave_of 55 392 == 98-fold_cps_to_octave_of :: (Ord a, Fractional a) => a -> a -> a-fold_cps_to_octave_of p =- let f q = if q > p * 2 then f (q / 2) else if q < p then f (q * 2) else q- in f+-- > harmonic_series 17 2+harmonic_series :: Integer -> Rational -> Tuning+harmonic_series n o = Tuning (Left [1 .. n%1]) o -- | Harmonic series on /n/. harmonic_series_cps :: (Num t, Enum t) => t -> [t]@@ -236,27 +280,44 @@ partial :: (Num a, Enum a) => a -> Int -> a partial f1 k = harmonic_series_cps f1 `at` (k - 1) +fold_ratio_to_octave' :: Integral i => Ratio i -> Ratio i+fold_ratio_to_octave' =+ let rec_f n = if n >= 2 then rec_f (n / 2) else if n < 1 then rec_f (n * 2) else n+ in rec_f++-- | Error if input is less than or equal to zero.+--+-- > map fold_ratio_to_octave_err [2/3,3/4] == [4/3,3/2]+fold_ratio_to_octave_err :: Integral i => Ratio i -> Ratio i+fold_ratio_to_octave_err n =+ if n <= 0+ then error "fold_ratio_to_octave"+ else fold_ratio_to_octave' n+ -- | Fold ratio until within an octave, ie. @1@ '<' /n/ '<=' @2@. ----- > map fold_ratio_to_octave [2/3,3/4] == [4/3,3/2]-fold_ratio_to_octave :: Integral i => Ratio i -> Ratio i-fold_ratio_to_octave n =- if n >= 2- then fold_ratio_to_octave (n / 2)- else if n < 1- then fold_ratio_to_octave (n * 2)- else n+-- > map fold_ratio_to_octave [0,1] == [Nothing,Just 1]+fold_ratio_to_octave :: Integral i => Ratio i -> Maybe (Ratio i)+fold_ratio_to_octave n = if n <= 0 then Nothing else Just (fold_ratio_to_octave' n) +-- | Sun of numerator & denominator.+ratio_nd_sum :: Num a => Ratio a -> a+ratio_nd_sum r = numerator r + denominator r++min_by :: Ord a => (t -> a) -> t -> t -> t+min_by f p q = if f p <= f q then p else q+ -- | The interval between two pitches /p/ and /q/ given as ratio -- multipliers of a fundamental is /q/ '/' /p/. The classes over such -- intervals consider the 'fold_ratio_to_octave' of both /p/ to /q/ -- and /q/ to /p/. -- -- > map ratio_interval_class [2/3,3/2,3/4,4/3] == [3/2,3/2,3/2,3/2]+-- > map ratio_interval_class [7/6,12/7] == [7/6,7/6] ratio_interval_class :: Integral i => Ratio i -> Ratio i ratio_interval_class i =- let f = fold_ratio_to_octave- in max (f i) (f (recip i))+ let f = fold_ratio_to_octave_err+ in min_by ratio_nd_sum (f i) (f (recip i)) -- | Derivative harmonic series, based on /k/th partial of /f1/. --@@ -267,31 +328,31 @@ -- > in map round (take 15 d) == r harmonic_series_cps_derived :: (Ord a, Fractional a, Enum a) => Int -> a -> [a] harmonic_series_cps_derived k f1 =- let f0 = fold_cps_to_octave_of f1 (partial f1 k)+ let f0 = T.cps_in_octave_above f1 (partial f1 k) in harmonic_series_cps f0 --- | Harmonic series to /n/th harmonic (folded).+-- | Harmonic series to /n/th harmonic (folded, duplicated removed). ----- > harmonic_series_folded 17 == [1,17/16,9/8,5/4,11/8,3/2,13/8,7/4,15/8]+-- > harmonic_series_folded_r 17 == [1,17/16,9/8,5/4,11/8,3/2,13/8,7/4,15/8] -- -- > let r = [0,105,204,386,551,702,841,969,1088]--- > in map (round . ratio_to_cents) (harmonic_series_folded 17) == r-harmonic_series_folded :: Integer -> [Rational]-harmonic_series_folded n =- nub (sort (map fold_ratio_to_octave [1 .. n%1]))+-- > in map (round . ratio_to_cents) (harmonic_series_folded_r 17) == r+harmonic_series_folded_r :: Integer -> [Rational]+harmonic_series_folded_r n = nub (sort (map fold_ratio_to_octave_err [1 .. n%1])) -- | 'ratio_to_cents' variant of 'harmonic_series_folded'.------ > map round (harmonic_series_folded_c 21) == [0,105,204,298,386,471,551,702,841,969,1088] harmonic_series_folded_c :: Integer -> [Cents]-harmonic_series_folded_c = map ratio_to_cents . harmonic_series_folded+harmonic_series_folded_c = map ratio_to_cents . harmonic_series_folded_r +harmonic_series_folded :: Integer -> Rational -> Tuning+harmonic_series_folded n o = Tuning (Left (harmonic_series_folded_r n)) o+ -- | @12@-tone tuning of first @21@ elements of the harmonic series. -- -- > cents_i harmonic_series_folded_21 == [0,105,204,298,386,471,551,702,841,969,1088] -- > divisions harmonic_series_folded_21 == 11 harmonic_series_folded_21 :: Tuning-harmonic_series_folded_21 = Tuning (Left (harmonic_series_folded 21)) 2+harmonic_series_folded_21 = harmonic_series_folded 21 2 -- * Cents @@ -362,6 +423,20 @@ -- which may be distant from the note sounded. type Midi_Tuning_F = Int -> T.Midi_Detune +-- | Variant for tunings that are incomplete.+type Sparse_Midi_Tuning_F = Int -> Maybe T.Midi_Detune++-- | Variant for sparse tunings that require state.+type Sparse_Midi_Tuning_ST_F st = st -> Int -> (st,Maybe T.Midi_Detune)++-- | Lift 'Midi_Tuning_F' to 'Sparse_Midi_Tuning_F'.+lift_tuning_f :: Midi_Tuning_F -> Sparse_Midi_Tuning_F+lift_tuning_f tn_f = Just . tn_f++-- | Lift 'Sparse_Midi_Tuning_F' to 'Sparse_Midi_Tuning_ST_F'.+lift_sparse_tuning_f :: Sparse_Midi_Tuning_F -> Sparse_Midi_Tuning_ST_F st+lift_sparse_tuning_f tn_f st k = (st,tn_f k)+ -- | (t,c,k) where t=tuning (must have 12 divisions of octave), -- c=cents deviation (ie. constant detune offset), k=midi offset -- (ie. value to be added to incoming midi note number).@@ -369,27 +444,175 @@ -- | 'Midi_Tuning_F' for 'D12_Midi_Tuning'. ----- > import Music.Theory.Tuning.Gann--- > let f = d12_midi_tuning_f (la_monte_young,-74.7,-3)--- > octpc_to_midi (-1,11) == 11--- > map (round . midi_detune_to_cps . f) [62,63,69] == [293,298,440]+-- > let f = d12_midi_tuning_f (equal_temperament 12,0,0)+-- > map f [0..127] == zip [0..127] (repeat 0) d12_midi_tuning_f :: D12_Midi_Tuning -> Midi_Tuning_F d12_midi_tuning_f (t,c_diff,k) n = let (_,pc) = T.midi_to_octpc (n + k)- dt = zipWith (-) (cents t) [0,100 .. 1200]- in (n,(dt `at` pc) + c_diff)+ dt = zipWith (-) (tn_cents t) [0,100 .. 1200]+ in if tn_divisions t /= 12+ then error "d12_midi_tuning_f: not d12"+ else case dt `atMay` pc of+ Nothing -> error "d12_midi_tuning_f: pc?"+ Just c -> (n,c + c_diff) --- | (t,f0,k) where t=tuning, f0=fundamental frequency, k=midi note--- number for f0, n=gamut+-- | (t,f0,k,g) where t=tuning, f0=fundamental frequency, k=midi note+-- number for f0, g=gamut type CPS_Midi_Tuning = (Tuning,Double,Int,Int) --- | 'Midi_Tuning_F' for 'CPS_Midi_Tuning'.-cps_midi_tuning_f :: CPS_Midi_Tuning -> Midi_Tuning_F+-- | 'Midi_Tuning_F' for 'CPS_Midi_Tuning'. The function is sparse, it is only+-- valid for /g/ values from /k/.+--+-- > let f = cps_midi_tuning_f (equal_temperament 72,T.midi_to_cps 59,59,72 * 4)+-- > map f [59 .. 59 + 72]+cps_midi_tuning_f :: CPS_Midi_Tuning -> Sparse_Midi_Tuning_F cps_midi_tuning_f (t,f0,k,g) n =- let r = approximate_ratios_cyclic t+ let r = tn_approximate_ratios_cyclic t m = take g (map (T.cps_to_midi_detune . (* f0)) r)- in m `at` (n - k)+ in m `atMay` (n - k) --- Local Variables:--- truncate-lines:t--- End:+-- * Midi tuning tables.++-- | Midi-note-number -> CPS table, possibly sparse.+type MNN_CPS_Table = [(Int,Double)]++-- | Generates 'MNN_CPS_Table' given 'Midi_Tuning_F' with keys for all valid @MNN@.+--+-- > import Sound.SC3.Plot+-- > plot_p2_ln [map (fmap round) (gen_cps_tuning_tbl f)]+gen_cps_tuning_tbl :: Sparse_Midi_Tuning_F -> MNN_CPS_Table+gen_cps_tuning_tbl tn_f =+ let f n = case tn_f n of+ Just r -> Just (n,T.midi_detune_to_cps r)+ Nothing -> Nothing+ in mapMaybe f [0 .. 127]++-- * Derived (secondary) tuning table (DTT) lookup.++-- | Given an 'MNN_CPS_Table' /tbl/, a list of @CPS@ /c/, and a @MNN@ /m/+-- find the @CPS@ in /c/ that is nearest to the @CPS@ in /t/ for /m/.+dtt_lookup :: (Eq k, Num v, Ord v) => [(k,v)] -> [v] -> k -> (Maybe v,Maybe v)+dtt_lookup tbl cps n =+ let f = lookup n tbl+ in (f,fmap (T.find_nearest_err cps) f)++-- | Require table be non-sparse.+dtt_lookup_err :: (Eq k, Num v, Ord v) => [(k,v)] -> [v] -> k -> (k,v,v)+dtt_lookup_err tbl cps n =+ case dtt_lookup tbl cps n of+ (Just f,Just g) -> (n,f,g)+ _ -> error "dtt_lookup"++-- | Given two tuning tables generate the @dtt@ table.+gen_dtt_lookup_tbl :: MNN_CPS_Table -> MNN_CPS_Table -> MNN_CPS_Table+gen_dtt_lookup_tbl t0 t1 =+ let ix = [0..127]+ cps = sort (map (T.p3_third . dtt_lookup_err t0 (map snd t1)) ix)+ in zip ix cps++gen_dtt_lookup_f :: MNN_CPS_Table -> MNN_CPS_Table -> Midi_Tuning_F+gen_dtt_lookup_f t0 t1 =+ let m = M.fromList (gen_dtt_lookup_tbl t0 t1)+ in T.cps_to_midi_detune . T.map_ix_err m++-- * Euler-Fokker genus <http://www.huygens-fokker.org/microtonality/efg.html>++-- | Normal form, value with occurences count (ie. exponent in notation above).+type EFG i = [(i,Int)]++-- | Degree of EFG, ie. sum of exponents.+--+-- > efg_degree [(3,3),(7,2)] == 3 + 2+efg_degree :: EFG i -> Int+efg_degree = sum . map snd++-- | Number of tones of EFG, ie. product of increment of exponents.+--+-- > efg_tones [(3,3),(7,2)] == (3 + 1) * (2 + 1)+efg_tones :: EFG i -> Int+efg_tones = product . map ((+ 1) . snd)++-- | Collate a genus given as a multiset into standard form, ie. histogram.+--+-- > efg_collate [3,3,3,7,7] == [(3,3),(7,2)]+efg_collate :: Ord i => [i] -> EFG i+efg_collate = T.histogram . sort++{- | Factors of EFG given with co-ordinate of grid location.++> efg_factors [(3,3)]++> let r = [([0,0],[]),([0,1],[7]),([0,2],[7,7])+> ,([1,0],[3]),([1,1],[3,7]),([1,2],[3,7,7])+> ,([2,0],[3,3]),([2,1],[3,3,7]),([2,2],[3,3,7,7])+> ,([3,0],[3,3,3]),([3,1],[3,3,3,7]),([3,2],[3,3,3,7,7])]+> in efg_factors [(3,3),(7,2)] == r++-}+efg_factors :: EFG i -> [([Int],[i])]+efg_factors efg =+ let k = map (\(_,n) -> [0 .. n]) efg+ k' = if length efg == 1+ then concatMap (map return) k+ else T.nfold_cartesian_product k+ z = map fst efg+ f ix = (ix,concat (zipWith (\n m -> replicate n (z !! m)) ix [0..]))+ in map f k'++{- | Ratios of EFG, taking /n/ as the 1:1 ratio, with indices, folded into one octave.++> let r = sort $ map snd $ efg_ratios 7 [(3,3),(7,2)]+> r == [1/1,9/8,8/7,9/7,21/16,189/128,3/2,27/16,12/7,7/4,27/14,63/32]+> map (round . ratio_to_cents) r == [0,204,231,435,471,675,702,906,933,969,1137,1173]++ 0: 1/1 C 0.000 cents+ 1: 9/8 D 203.910 cents+ 2: 8/7 D+ 231.174 cents+ 3: 9/7 E+ 435.084 cents+ 4: 21/16 F- 470.781 cents+ 5: 189/128 G- 674.691 cents+ 6: 3/2 G 701.955 cents+ 7: 27/16 A 905.865 cents+ 8: 12/7 A+ 933.129 cents+ 9: 7/4 Bb- 968.826 cents+ 10: 27/14 B+ 1137.039 cents+ 11: 63/32 C- 1172.736 cents+ 12: 2/1 C 1200.000 cents++> let r' = sort $ map snd $ efg_ratios 5 [(5,2),(7,3)]+> r' == [1/1,343/320,35/32,49/40,5/4,343/256,7/5,49/32,8/5,1715/1024,7/4,245/128]+> map (round . ratio_to_cents) r' == [0,120,155,351,386,506,583,738,814,893,969,1124]++> let r'' = sort $ map snd $ efg_ratios 3 [(3,1),(5,1),(7,1)]+> r'' == [1/1,35/32,7/6,5/4,4/3,35/24,5/3,7/4]+> map (round . ratio_to_cents) r'' == [0,155,267,386,498,653,884,969]++> let c0 = [0,204,231,435,471,675,702,906,933,969,1137,1173,1200]+> let c1 = [0,120,155,351,386,506,583,738,814,893,969,1124,1200]+> let c2 = [0,155,267,386,498,653,884,969,1200]+> let f (c',y) = map (\x -> (x,y,x,y + 10)) c'+> map f (zip [c0,c1,c2] [0,20,40])++-}+efg_ratios :: Real r => Rational -> EFG r -> [([Int],Rational)]+efg_ratios n =+ let to_r = fold_ratio_to_octave_err . (/ n) . toRational . product+ f (ix,i) = (ix,to_r i)+ in map f . efg_factors++{- | Generate a line drawing, as a set of (x0,y0,x1,y1) 4-tuples.+ h=row height, m=distance of vertical mark from row edge, k=distance between rows++> let e = [[3,3,3],[3,3,5],[3,5,5],[3,5,7],[3,7,7],[5,5,5],[5,5,7],[3,3,7],[5,7,7],[7,7,7]]+> let e = [[3,3,3],[5,5,5],[7,7,7],[3,3,5],[3,5,5],[5,5,7],[5,7,7],[3,7,7],[3,3,7],[3,5,7]]+> let e' = map efg_collate e+> efg_diagram_set (round,25,4,75) e'++-}+efg_diagram_set :: (Enum n,Real n) => (Cents -> n,n,n,n) -> [EFG n] -> [(n,n,n,n)]+efg_diagram_set (to_f,h,m,k) e =+ let f = (++ [1200]) . sort . map (to_f . ratio_to_cents . snd) . efg_ratios 1+ g (c,y) = let y' = y + h+ b = [(0,y,1200,y),(0,y',1200,y')]+ in b ++ map (\x -> (x,y + m,x,y' - m)) c+ in concatMap g (zip (map f e) [0,k ..])
− Music/Theory/Tuning/Alves.hs
@@ -1,25 +0,0 @@--- | Bill Alves.-module Music.Theory.Tuning.Alves where--import Music.Theory.Tuning {- hmt -}---- | Ratios for 'harrison_ditone'.------ > let c = [0,114,204,294,408,498,612,702,816,906,996,1110]--- > in map (round . ratio_to_cents) harrison_ditone_r == c-harrison_ditone_r :: [Rational]-harrison_ditone_r =- [1,2187/2048 {- 256/243 -}- ,9/8,32/27- ,81/64- ,4/3,729/512- ,3/2,6561/4096 {- 128/81 -}- ,27/16,16/9- ,243/128]---- | Ditone/pythagorean tuning,--- see <http://www.billalves.com/porgitaro/ditonesettuning.html>------ > cents_i harrison_ditone == [0,114,204,294,408,498,612,702,816,906,996,1110]-harrison_ditone :: Tuning-harrison_ditone = Tuning (Left harrison_ditone_r) 2
Music/Theory/Tuning/Alves_1997.hs view
@@ -13,6 +13,9 @@ -- | HMC /slendro/ tuning. -- -- > cents_i alves_slendro == [0,231,498,765,996]+--+-- > scl <- scl_load "slendro_alves"+-- > cents_i (scale_tuning 0.01 scl) == cents_i alves_slendro alves_slendro :: Tuning alves_slendro = Tuning (Left alves_slendro_r) 2 @@ -24,6 +27,9 @@ -- | HMC /pelog bem/ tuning. -- -- > cents_i alves_pelog_bem == [0,231,316,702,814]+--+-- > scl <- scl_load "pelog_alves"+-- > cents_i (scale_tuning 0.01 scl) == [0,231,316,471,702,814,969] alves_pelog_bem :: Tuning alves_pelog_bem = Tuning (Left alves_pelog_bem_r) 2 @@ -32,7 +38,7 @@ alves_pelog_barang_r :: [Rational] alves_pelog_barang_r = [1,5/4,21/16,105/64,7/4] --- | HMC /pelog 2,3,4,6,7/ tuning.+-- | HMC /pelog barang/ tuning. -- -- > cents_i alves_pelog_barang == [0,386,471,857,969] alves_pelog_barang :: Tuning@@ -43,7 +49,7 @@ alves_pelog_23467_r :: [Rational] alves_pelog_23467_r = [1,5/4,21/16,3/2,7/4] --- | HMC /pelog barang/ tuning.+-- | HMC /pelog 2,3,4,6,7/ tuning. -- -- > cents_i alves_pelog_23467 == [0,386,471,702,969] alves_pelog_23467 :: Tuning
+ Music/Theory/Tuning/DB.hs view
@@ -0,0 +1,62 @@+-- | DB of locally defined tunings, but for ordinary use see "Music.Theory.Tuning.Scala".+module Music.Theory.Tuning.DB where++import Data.List {- base -}++import Music.Theory.Tuning++import Music.Theory.Tuning.Alves_1997+import Music.Theory.Tuning.Gann_1993+import Music.Theory.Tuning.Polansky_1978+import Music.Theory.Tuning.Polansky_1985c++import Music.Theory.Tuning.DB.Alves+import Music.Theory.Tuning.DB.Gann+import Music.Theory.Tuning.DB.Microtonal_Synthesis+import Music.Theory.Tuning.DB.Riley+import Music.Theory.Tuning.DB.Werckmeister++-- | (last-name,first-name,title,year,hmt/tuning,scala/name)+type Named_Tuning = (String,String,String,String,Tuning,String)++named_tuning_t :: Named_Tuning -> Tuning+named_tuning_t (_,_,_,_,t,_) = t++tuning_db :: [Named_Tuning]+tuning_db =+ [("Aaron","Pietro","","1523",pietro_aaron_1523,"meanquar")+ ,("Alves","Bill","Slendro","",alves_slendro,"slendro_alves")+ ,("Alves","Bill","Pelog/Bem","",alves_pelog_bem,"")+ ,("Alves","Bill","Pelog/Barang","",alves_pelog_barang,"")+ ,("Gann","Kyle","Superparticular","1992",gann_superparticular,"gann_super")+ ,("Harrison","Lou","Ditone","",harrison_ditone,"")+ ,("Harrison","Lou","16-tone","",lou_harrison_16,"harrison_16")+ ,("Johnston","Ben","MTP","1977",ben_johnston_mtp_1977,"")+ ,("Johnston","Ben","25-tone","",ben_johnston_25,"johnston_25")+ ,("Kirnberger","Johann Philipp","III","",kirnberger_iii,"kirnberger")+ ,("Malcolm","Alexander","Monochord","1721",five_limit_tuning,"malcolm")+ ,("Partch","Harry","43-tone","",partch_43,"partch_43")+ ,("Polansky","Larry","Piano Study #5","1985",ps5_jpr,"polansky_ps")+ ,("Polansky","Larry","Psaltery","1978",psaltery_o,"")+ ,("Riley","Terry","Harp of New Albion","",riley_albion,"riley_albion")+ ,("Tsuda","Mayumi","13-limit","",mayumi_tsuda,"tsuda13")+ ,("Vallotti","","","1754",vallotti,"vallotti")+ ,("Werckmeister","Andreas","Werckmeister III","",werckmeister_iii,"werck3")+ ,("Werckmeister","Andreas","Werckmeister IV","",werckmeister_iv,"werck4")+ ,("Werckmeister","Andreas","Werckmeister V","",werckmeister_v,"werck5")+ ,("Werckmeister","Andreas","Werckmeister VI","",werckmeister_vi,"werck6")+ ,("Young","La Monte","The Well-Tuned Piano","",lmy_wtp,"young-lm_piano")+ ,("Young","Thomas","","1799",thomas_young_1799,"young2")+ ,("Zarlino","Gioseffo","","1588",zarlino_1588,"zarlino2")+ ,("","","JI/12 7-limit","",septimal_tritone_just_intonation,"ji_12")+ ,("","","ET/12","",equal_temperament_12,"")+ ,("","","ET/19","",equal_temperament_19,"")+ ,("","","ET/31","",equal_temperament_31,"")+ ,("","","ET/53","",equal_temperament_53,"")+ ,("","","ET/72","",equal_temperament_72,"")+ ,("","","ET/96","",equal_temperament_96,"")+ ,("","","Pythagorean/12","",pythagorean_12,"pyth_12")+ ]++tuning_db_lookup_scl :: String -> Maybe Tuning+tuning_db_lookup_scl nm = fmap named_tuning_t (find (\(_,_,_,_,_,scl) -> scl == nm) tuning_db)
+ Music/Theory/Tuning/DB/Alves.hs view
@@ -0,0 +1,26 @@+-- | Bill Alves.+module Music.Theory.Tuning.DB.Alves where++import Music.Theory.Tuning {- hmt -}++-- | Ratios for 'harrison_ditone'.+--+-- > let c = [0,114,204,294,408,498,612,702,816,906,996,1110]+-- > in map (round . ratio_to_cents) harrison_ditone_r == c+harrison_ditone_r :: [Rational]+harrison_ditone_r =+ [1,2187/2048 {- 256/243 -}+ ,9/8,32/27+ ,81/64+ ,4/3,729/512+ ,3/2,6561/4096 {- 128/81 -}+ ,27/16,16/9+ ,243/128]++-- | Ditone/pythagorean tuning,+-- see <http://www.billalves.com/porgitaro/ditonesettuning.html>+--+-- > tn_divisions harrison_ditone == 12+-- > tn_cents_i harrison_ditone == [0,114,204,294,408,498,612,702,816,906,996,1110]+harrison_ditone :: Tuning+harrison_ditone = Tuning (Left harrison_ditone_r) 2
+ Music/Theory/Tuning/DB/Gann.hs view
@@ -0,0 +1,130 @@+-- | Kyle Gann.+module Music.Theory.Tuning.DB.Gann where++import Music.Theory.Tuning {- hmt -}++-- * Historical++-- | Cents for 'pietro_aaron_1523'.+--+-- > let c = [0,76,193,310,386,503,580,697,773,890,1007,1083]+-- > in map round pietro_aaron_1523_c == c+--+-- > map ((+ 60) . (/ 100)) pietro_aaron_1523_c+pietro_aaron_1523_c :: [Cents]+pietro_aaron_1523_c =+ [0,76.0+ ,193.2,310.3+ ,386.3+ ,503.4,579.5+ ,696.8,772.6+ ,889.7,1006.8+ ,1082.9]++-- | Pietro Aaron (1523) meantone temperament, see+-- <http://www.kylegann.com/histune.html>+--+-- > cents_i pietro_aaron_1523 == [0,76,193,310,386,503,580,697,773,890,1007,1083]+--+-- > import Music.Theory.Tuning.Scala+-- > scl <- scl_load "meanquar"+-- > cents_i (scale_tuning 0.01 scl) == [0,76,193,310,386,503,579,697,773,890,1007,1083]+pietro_aaron_1523 :: Tuning+pietro_aaron_1523 = Tuning (Right pietro_aaron_1523_c) 2++-- | Cents for 'thomas_young_1799'.+--+-- > let c = [0,94,196,298,392,500,592,698,796,894,1000,1092]+-- > in map round thomas_young_1799_c == c+thomas_young_1799_c :: [Cents]+thomas_young_1799_c =+ [0,93.9+ ,195.8,297.8+ ,391.7+ ,499.9,591.9+ ,697.9,795.8+ ,893.8,999.8+ ,1091.8]++-- | Thomas Young (1799), Well Temperament, <http://www.kylegann.com/histune.html>.+--+-- > cents_i thomas_young_1799 == [0,94,196,298,392,500,592,698,796,894,1000,1092]+--+-- > scl <- scl_load "young2"+-- > cents_i (scale_tuning 0.01 scl) == cents_i thomas_young_1799+thomas_young_1799 :: Tuning+thomas_young_1799 = Tuning (Right thomas_young_1799_c) 2++-- | Ratios for 'zarlino'.+--+-- > length zarlino_1588_r == 16+zarlino_1588_r :: [Rational]+zarlino_1588_r = [1/1,25/24,10/9,9/8,32/27,6/5,5/4,4/3,25/18,45/32,3/2,25/16,5/3,16/9,9/5,15/8]++-- | Gioseffo Zarlino, 1588, see <http://www.kylegann.com/tuning.html>.+--+-- > divisions zarlino_1588 == 16+-- > cents_i zarlino_1588 == [0,71,182,204,294,316,386,498,569,590,702,773,884,996,1018,1088]+--+-- > scl <- scl_load "zarlino2"+-- > cents_i (scale_tuning 0.01 scl) == cents_i zarlino_1588+zarlino_1588 :: Tuning+zarlino_1588 = Tuning (Left zarlino_1588_r) 2++-- * 20th Century++-- | Ratios for 'ben_johnston_mtp_1977'.+--+-- > let c = [0,105,204,298,386,471,551,702,841,906,969,1088]+-- > in map (round . ratio_to_cents) ben_johnston_mtp_1977_r == c+ben_johnston_mtp_1977_r :: [Rational]+ben_johnston_mtp_1977_r =+ [1,17/16+ ,9/8,19/16+ ,5/4+ ,21/16,11/8+ ,3/2,13/8+ ,27/16,7/4+ ,15/8]++-- | Ben Johnston's \"Suite for Microtonal Piano\" (1977), see+-- <http://www.kylegann.com/tuning.html>+--+-- > cents_i ben_johnston_mtp_1977 == [0,105,204,298,386,471,551,702,841,906,969,1088]+ben_johnston_mtp_1977 :: Tuning+ben_johnston_mtp_1977 = Tuning (Left ben_johnston_mtp_1977_r) 2++-- * Gann++-- | Ratios for 'gann_arcana_xvi'.+gann_arcana_xvi_r :: [Rational]+gann_arcana_xvi_r =+ [1/1,21/20,16/15,9/8,7/6,6/5,11/9,5/4,21/16,4/3,27/20,7/5+ ,22/15,3/2,55/36,8/5,44/27,5/3,42/25,7/4,9/5,11/6,15/8,88/45]++-- | Kyle Gann, _Arcana XVI_, see <http://www.kylegann.com/Arcana.html>.+--+-- > let r = [0,84,112,204,267,316,347,386,471,498,520,583,663,702,734,814,845,884,898,969,1018,1049,1088,1161]+-- > in cents_i gann_arcana_xvi == r+gann_arcana_xvi :: Tuning+gann_arcana_xvi = Tuning (Left gann_arcana_xvi_r) 2++-- | Ratios for 'gann_superparticular'.+gann_superparticular_r :: [Rational]+gann_superparticular_r =+ [1/1,11/10,10/9,9/8,8/7,7/6,6/5,5/4,9/7,4/3+ ,11/8,7/5,10/7,3/2+ ,11/7,14/9,8/5,5/3,12/7,7/4,16/9,9/5]++-- | Kyle Gann, _Superparticular_, see <http://www.kylegann.com/Super.html>.+--+-- > divisions gann_superparticular == 22+--+-- > let r = [0,165,182,204,231,267,316,386,435,498,551,583,617,702+-- > ,782,765,814,884,933,969,996,1018]+-- > in cents_i gann_superparticular == r+--+-- > scl <- scl_load "gann_super"+-- > cents_i (scale_tuning 0.01 scl) == cents_i gann_superparticular+gann_superparticular :: Tuning+gann_superparticular = Tuning (Left gann_superparticular_r) 2
+ Music/Theory/Tuning/DB/Microtonal_Synthesis.hs view
@@ -0,0 +1,230 @@+-- | <http://www.microtonal-synthesis.com/scales.html>+module Music.Theory.Tuning.DB.Microtonal_Synthesis where++import Music.Theory.Tuning {- hmt -}++-- | Ratios for 'pythagorean'.+pythagorean_12_r :: [Rational]+pythagorean_12_r =+ [1,2187/2048 {- 256/243 -}+ ,9/8,32/27+ ,81/64+ ,4/3,729/512+ ,3/2,6561/4096 {- 128/81 -}+ ,27/16,16/9+ ,243/128]++-- | Pythagorean tuning, <http://www.microtonal-synthesis.com/scale_pythagorean.html>.+--+-- > cents_i pythagorean_12 == [0,114,204,294,408,498,612,702,816,906,996,1110]+--+-- > scl <- scl_load "pyth_12"+-- > cents_i (scale_tuning 0.1 scl) == cents_i pythagorean_12+pythagorean_12 :: Tuning+pythagorean_12 = Tuning (Left pythagorean_12_r) 2++-- | Ratios for 'five_limit_tuning'.+--+-- > let c = [0,112,204,316,386,498,590,702,814,884,996,1088]+-- > in map (round . ratio_to_cents) five_limit_tuning_r == c+five_limit_tuning_r :: [Rational]+five_limit_tuning_r =+ [1,16/15+ ,9/8,6/5+ ,5/4+ ,4/3,45/32 {- 64/45 -}+ ,3/2,8/5+ ,5/3,16/9 {- 9/5 -}+ ,15/8]++-- | Five-limit tuning (five limit just intonation), Alexander Malcolm's Monochord (1721).+--+-- > cents_i five_limit_tuning == [0,112,204,316,386,498,590,702,814,884,996,1088]+--+-- > scl <- scl_load "malcolm"+-- > cents_i (scale_tuning 0.1 scl) == cents_i five_limit_tuning+five_limit_tuning :: Tuning+five_limit_tuning = Tuning (Left five_limit_tuning_r) 2++-- | Ratios for 'septimal_tritone_just_intonation'.+--+-- > let c = [0,112,204,316,386,498,583,702,814,884,1018,1088]+-- > in map (round . ratio_to_cents) septimal_tritone_just_intonation == c+septimal_tritone_just_intonation_r :: [Rational]+septimal_tritone_just_intonation_r =+ [1,16/15+ ,9/8,6/5+ ,5/4+ ,4/3,7/5+ ,3/2,8/5+ ,5/3,9/5+ ,15/8]++-- | Septimal tritone Just Intonation, see+-- <http://www.microtonal-synthesis.com/scale_just_intonation.html>+--+-- > let c = [0,112,204,316,386,498,583,702,814,884,1018,1088]+-- > in cents_i septimal_tritone_just_intonation == c+--+-- > scl <- scl_load "ji_12"+-- > cents_i (scale_tuning 0.1 scl) == cents_i septimal_tritone_just_intonation+septimal_tritone_just_intonation :: Tuning+septimal_tritone_just_intonation = Tuning (Left septimal_tritone_just_intonation_r) 2++-- | Ratios for 'seven_limit_just_intonation'.+--+-- > let c = [0,112,204,316,386,498,583,702,814,884,969,1088]+-- > in map (round . ratio_to_cents) seven_limit_just_intonation == c+seven_limit_just_intonation_r :: [Rational]+seven_limit_just_intonation_r =+ [1,16/15+ ,9/8,6/5+ ,5/4+ ,4/3,7/5+ ,3/2,8/5+ ,5/3,7/4+ ,15/8]++-- | Seven limit Just Intonation.+--+-- > cents_i seven_limit_just_intonation == [0,112,204,316,386,498,583,702,814,884,969,1088]+seven_limit_just_intonation :: Tuning+seven_limit_just_intonation = Tuning (Left seven_limit_just_intonation_r) 2++-- | Approximate ratios for 'kirnberger_iii'.+--+-- > let c = [0,90,193,294,386,498,590,697,792,890,996,1088]+-- > in map (round.to_cents) kirnberger_iii_ar == c+kirnberger_iii_ar :: [Approximate_Ratio]+kirnberger_iii_ar =+ [1,256/243+ ,sqrt 5 / 2,32/27+ ,5/4+ ,4/3,45/32+ ,5 ** 0.25,128/81+ ,(5 ** 0.75)/2,16/9+ ,15/8]++-- | <http://www.microtonal-synthesis.com/scale_kirnberger.html>.+--+-- > cents_i kirnberger_iii == [0,90,193,294,386,498,590,697,792,890,996,1088]+--+-- > scl <- scl_load "kirnberger"+-- > cents_i (scale_tuning 0.1 scl) == cents_i kirnberger_iii+kirnberger_iii :: Tuning+kirnberger_iii = Tuning (Right (map approximate_ratio_to_cents kirnberger_iii_ar)) 2++-- > let c = [0,94,196,298,392,502,592,698,796,894,1000,1090]+-- > in map round vallotti_c == c+vallotti_c :: [Cents]+vallotti_c =+ [0.0,94.135+ ,196.09,298.045+ ,392.18+ ,501.955,592.18+ ,698.045,796.09+ ,894.135,1000.0+ ,1090.225]++-- | Vallotti & Young scale (Vallotti version), see+-- <http://www.microtonal-synthesis.com/scale_vallotti_young.html>.+--+-- > cents_i vallotti == [0,94,196,298,392,502,592,698,796,894,1000,1090]+--+-- > scl <- scl_load "vallotti"+-- > cents_i (scale_tuning 0.1 scl) == cents_i vallotti+vallotti :: Tuning+vallotti = Tuning (Right vallotti_c) 2++-- > let c = [0,128,139,359,454,563,637,746,841,911,1072,1183]+-- > in map (round . ratio_to_cents) mayumi_tsuda == c+mayumi_tsuda_r :: [Rational]+mayumi_tsuda_r =+ [1,14/13+ ,13/12,16/13+ ,13/10+ ,18/13,13/9+ ,20/13,13/8+ ,22/13,13/7+ ,208/105]++-- | Mayumi Tsuda 13-limit Just Intonation scale,+-- <http://www.microtonal-synthesis.com/scale_reinhard.html>.+--+-- > cents_i mayumi_tsuda == [0,128,139,359,454,563,637,746,841,911,1072,1183]+--+-- > scl <- scl_load "tsuda13"+-- > cents_i (scale_tuning 0.1 scl) == cents_i mayumi_tsuda+mayumi_tsuda :: Tuning+mayumi_tsuda = Tuning (Left mayumi_tsuda_r) 2++-- | Ratios for 'lou_harrison_16'.+--+-- > length lou_harrison_16_r == 16+--+-- > let c = [0,112,182,231,267,316,386,498,603,702,814,884,933,969,1018,1088]+-- > in map (round . ratio_to_cents) lou_harrison_16_r == c+lou_harrison_16_r :: [Rational]+lou_harrison_16_r =+ [1,16/15+ ,10/9,8/7+ ,7/6,6/5,5/4+ ,4/3+ ,17/12+ ,3/2+ ,8/5,5/3,12/7+ ,7/4,9/5,15/8]++-- | Lou Harrison 16 tone Just Intonation scale, see+-- <http://www.microtonal-synthesis.com/scale_harrison_16.html>+--+-- > let r = [0,112,182,231,267,316,386,498,603,702,814,884,933,969,1018,1088]+-- > in cents_i lou_harrison_16 == r+--+-- > import Music.Theory.Tuning.Scala+-- > scl <- scl_load "harrison_16"+-- > cents_i (scale_tuning 0.1 scl) == cents_i lou_harrison_16+lou_harrison_16 :: Tuning+lou_harrison_16 = Tuning (Left lou_harrison_16_r) 2++-- | Ratios for 'partch_43'.+partch_43_r :: [Rational]+partch_43_r =+ [1,81/80,33/32,21/20,16/15,12/11,11/10,10/9,9/8,8/7+ ,7/6,32/27,6/5,11/9,5/4,14/11,9/7+ ,21/16,4/3,27/20+ ,11/8,7/5,10/7,16/11+ ,40/27,3/2,32/21,14/9,11/7,8/5,18/11,5/3,27/16,12/7+ ,7/4,16/9,9/5,20/11,11/6,15/8,40/21,64/33,160/81]++-- | Harry Partch 43 tone scale, see+-- <http://www.microtonal-synthesis.com/scale_partch.html>+--+-- > cents_i partch_43 == [0,22,53,84,112,151,165+-- > ,182,204,231,267,294,316+-- > ,347,386,418,435+-- > ,471,498,520,551,583,617,649+-- > ,680,702,729,765,782,814,853,884,906,933+-- > ,969,996,1018,1035,1049,1088,1116,1147,1178]+--+-- > scl <- scl_load "partch_43"+-- > cents_i (scale_tuning 0.1 scl) == cents_i partch_43+partch_43 :: Tuning+partch_43 = Tuning (Left partch_43_r) 2++-- | Ratios for 'ben_johnston_25'.+ben_johnston_25_r :: [Rational]+ben_johnston_25_r =+ [1/1,25/24,135/128,16/15,10/9+ ,9/8,75/64,6/5,5/4,81/64+ ,32/25,4/3,27/20,45/32,36/25+ ,3/2,25/16,8/5,5/3,27/16+ ,225/128,16/9,9/5,15/8,48/25]++-- | Ben Johnston 25 note just enharmonic scale, see+-- <http://www.microtonal-synthesis.com/scale_johnston_25.html>+--+-- > scl <- scl_load "johnston_25"+-- > cents_i (scale_tuning 0.1 scl) == cents_i ben_johnston_25+ben_johnston_25 :: Tuning+ben_johnston_25 = Tuning (Left ben_johnston_25_r) 2
+ Music/Theory/Tuning/DB/Riley.hs view
@@ -0,0 +1,22 @@+-- | Terry Riley.+module Music.Theory.Tuning.DB.Riley where++import Music.Theory.Tuning {- hmt -}++-- | Ratios for 'riley_albion'.+--+-- > let r = [0,112,204,316,386,498,610,702,814,884,996,1088]+-- > in map (round . ratio_to_cents) riley_albion_r == r+riley_albion_r :: [Rational]+riley_albion_r = [1/1,16/15,9/8,6/5,5/4,4/3,64/45,3/2,8/5,5/3,16/9,15/8]++-- | Riley's five-limit tuning as used in _The Harp of New Albion_,+-- see <http://www.ex-tempore.org/Volx1/hudson/hudson.htm>.+--+-- > cents_i riley_albion == [0,112,204,316,386,498,610,702,814,884,996,1088]+--+-- > import Music.Theory.Tuning.Scala+-- > scl <- scl_load "riley_albion"+-- > cents_i (scale_tuning 0.01 scl) == cents_i riley_albion+riley_albion :: Tuning+riley_albion = Tuning (Left riley_albion_r) 2
+ Music/Theory/Tuning/DB/Werckmeister.hs view
@@ -0,0 +1,117 @@+-- | Andreas Werckmeister (1645-1706).+module Music.Theory.Tuning.DB.Werckmeister where++import Music.Theory.Tuning {- hmt -}++-- | Approximate ratios for 'werckmeister_iii'.+--+-- > let c = [0,90,192,294,390,498,588,696,792,888,996,1092]+-- > in map (round . ratio_to_cents) werckmeister_iii_ar == c+werckmeister_iii_ar :: [Approximate_Ratio]+werckmeister_iii_ar =+ let c0 = 2 ** (1/2)+ c1 = 2 ** (1/4)+ c2 = 8 ** (1/4)+ in [1,256/243+ ,64/81 * c0,32/27+ ,256/243 * c1+ ,4/3,1024/729+ ,8/9 * c2,128/81+ ,1024/729 * c1,16/9+ ,128/81 * c1]++-- | Cents for 'werckmeister_iii'.+werckmeister_iii_ar_c :: [Cents]+werckmeister_iii_ar_c = map approximate_ratio_to_cents werckmeister_iii_ar++-- | Werckmeister III, Andreas Werckmeister (1645-1706)+--+-- > cents_i werckmeister_iii == [0,90,192,294,390,498,588,696,792,888,996,1092]+--+-- > import Music.Theory.Tuning.Scala+-- > scl <- scl_load "werck3"+-- > cents_i (scale_tuning 0.01 scl) == cents_i werckmeister_iii+werckmeister_iii :: Tuning+werckmeister_iii = Tuning (Right werckmeister_iii_ar_c) 2++-- | Approximate ratios for 'werckmeister_iv'.+--+-- > let c = [0,82,196,294,392,498,588,694,784,890,1004,1086]+-- > in map (round . ratio_to_cents) werckmeister_iv_ar == c+werckmeister_iv_ar :: [Approximate_Ratio]+werckmeister_iv_ar =+ let c0 = 2 ** (1/3)+ c1 = 4 ** (1/3)+ in [1,16384/19683 * c0+ ,8/9 * c0,32/27+ ,64/81 * c1+ ,4/3,1024/729+ ,32/27 * c0,8192/6561 * c0+ ,256/243 * c1,9/(4*c0)+ ,4096/2187]++-- | Cents for 'werckmeister_iv'.+werckmeister_iv_c :: [Cents]+werckmeister_iv_c = map approximate_ratio_to_cents werckmeister_iv_ar++-- | Werckmeister IV, Andreas Werckmeister (1645-1706)+--+-- > cents_i werckmeister_iv == [0,82,196,294,392,498,588,694,784,890,1004,1086]+--+-- > scl <- scl_load "werck4"+-- > cents_i (scale_tuning 0.01 scl) == cents_i werckmeister_iv+werckmeister_iv :: Tuning+werckmeister_iv = Tuning (Right werckmeister_iv_c) 2++-- | Approximate ratios for 'werckmeister_v'.+--+-- > let c = [0,96,204,300,396,504,600,702,792,900,1002,1098]+-- > in map (round . ratio_to_cents) werckmeister_v_ar == c+werckmeister_v_ar :: [Approximate_Ratio]+werckmeister_v_ar =+ let c0 = 2 ** (1/4)+ c1 = 2 ** (1/2)+ c2 = 8 ** (1/4)+ in [1,8/9 * c0+ ,9/8,c0+ ,8/9 * c1+ ,9/8 * c0,c1+ ,3/2,128/81+ ,c2,3/c2+ ,4/3 * c1]++-- | Cents for 'werckmeister_v'.+werckmeister_v_c :: [Cents]+werckmeister_v_c = map approximate_ratio_to_cents werckmeister_v_ar++-- | Werckmeister V, Andreas Werckmeister (1645-1706)+--+-- > cents_i werckmeister_v == [0,96,204,300,396,504,600,702,792,900,1002,1098]+--+-- > scl <- scl_load "werck5"+-- > cents_i (scale_tuning 0.01 scl) == cents_i werckmeister_v+werckmeister_v :: Tuning+werckmeister_v = Tuning (Right werckmeister_v_c) 2++-- | Ratios for 'werckmeister_vi', with supposed correction of 28/25 to 49/44.+--+-- > let c = [0,91,186,298,395,498,595,698,793,893,1000,1097]+-- > in map (round . ratio_to_cents) werckmeister_vi_r == c+werckmeister_vi_r :: [Rational]+werckmeister_vi_r =+ [1,98/93+ ,49/44 {- 28/25 -},196/165+ ,49/39+ ,4/3,196/139+ ,196/131,49/31+ ,196/117,98/55+ ,49/26]++-- | Werckmeister VI, Andreas Werckmeister (1645-1706)+--+-- > cents_i werckmeister_vi == [0,91,186,298,395,498,595,698,793,893,1000,1097]+--+-- > scl <- scl_load "werck6"+-- > cents_i (scale_tuning 0.01 scl) == cents_i werckmeister_vi+werckmeister_vi :: Tuning+werckmeister_vi = Tuning (Left werckmeister_vi_r) 2
Music/Theory/Tuning/ET.hs view
@@ -6,46 +6,59 @@ import Data.Ratio {- base -} import Text.Printf {- base -} -import Music.Theory.List {- hmt -}+import qualified Music.Theory.List as T {- hmt -} import Music.Theory.Pitch {- hmt -} import Music.Theory.Pitch.Note {- hmt -}-import Music.Theory.Pitch.Spelling {- hmt -}+import Music.Theory.Pitch.Spelling.Table {- hmt -} import Music.Theory.Tuning {- hmt -} -- | 'octpc_to_pitch' and 'octpc_to_cps'.+octpc_to_pitch_cps_f0 :: (Floating n) => n -> OctPC -> (Pitch,n)+octpc_to_pitch_cps_f0 f0 x = (octpc_to_pitch pc_spell_ks x,octpc_to_cps_f0 f0 x)++-- | 'octpc_to_pitch' and 'octpc_to_cps'. octpc_to_pitch_cps :: (Floating n) => OctPC -> (Pitch,n)-octpc_to_pitch_cps x = (octpc_to_pitch pc_spell_ks x,octpc_to_cps x)+octpc_to_pitch_cps = octpc_to_pitch_cps_f0 440 -- | 12-tone equal temperament table equating 'Pitch' and frequency--- over range of human hearing, where @A4@ = @440@hz.+-- over range of human hearing, where @A4@ has given frequency. --+-- > tbl_12et_f0 415+tbl_12et_f0 :: Double -> [(Pitch,Double)]+tbl_12et_f0 f0 =+ let z = [(o,pc) | o <- [0..10], pc <- [0..11]]+ in map (octpc_to_pitch_cps_f0 f0) z++-- | 'tbl_12et_f0' @440@hz.+-- -- > length tbl_12et == 132--- > let min_max l = (minimum l,maximum l)--- > min_max (map (round . snd) tbl_12et) == (16,31609)+-- > minmax (map (round . snd) tbl_12et) == (16,31609) tbl_12et :: [(Pitch,Double)]-tbl_12et =- let z = [(o,pc) | o <- [0..10], pc <- [0..11]]- in map octpc_to_pitch_cps z+tbl_12et = tbl_12et_f0 440 --- | 24-tone equal temperament variant of 'tbl_12et'.+-- | 24-tone equal temperament variant of 'tbl_12et_f0'.+tbl_24et_f0 :: Double -> [(Pitch,Double)]+tbl_24et_f0 f0 =+ let f x = let p = fmidi_to_pitch_err pc_spell_ks x+ p' = pitch_rewrite_threequarter_alteration p+ in (p',fmidi_to_cps_f0 f0 x)+ in map f [12,12.5 .. 143.5]++-- | 'tbl_24et_f0' @440@. -- -- > length tbl_24et == 264--- > min_max (map (round . snd) tbl_24et) == (16,32535)+-- > minmax (map (round . snd) tbl_24et) == (16,32535) tbl_24et :: [(Pitch,Double)]-tbl_24et =- let f x = let p = fmidi_to_pitch pc_spell_ks x- p' = pitch_rewrite_threequarter_alteration p- in (p',fmidi_to_cps x)- in map f [12,12.5 .. 143.5]+tbl_24et = tbl_24et_f0 440 -- | Given an @ET@ table (or like) find bounds of frequency. ----- > let r = Just (at_pair octpc_to_pitch_cps ((3,11),(4,0)))+-- import qualified Music.Theory.Tuple as T+--+-- > let r = Just (T.t2_map octpc_to_pitch_cps ((3,11),(4,0))) -- > in bounds_et_table tbl_12et 256 == r bounds_et_table :: Ord s => [(t,s)] -> s -> Maybe ((t,s),(t,s))-bounds_et_table tbl =- let f (_,p) = compare p- in find_bounds True f tbl+bounds_et_table = T.find_bounds True (compare . snd) -- | 'bounds_et_table' of 'tbl_12et'. --@@ -55,6 +68,8 @@ -- | Tuple indicating nearest 'Pitch' to /frequency/ with @ET@ -- frequency, and deviation in hertz and 'Cents'.+--+-- (cps,nearest-pitch,cps-of-nearest-pitch,cps-deviation,cents-deviation) type HS_R p = (Double,p,Double,Double,Cents) -- | /n/-decimal places.@@ -76,12 +91,14 @@ hs_r_pitch_pp :: Int -> HS_R Pitch -> [String] hs_r_pitch_pp = hs_r_pp pitch_pp --- | Form 'HS_R' for /frequency/ by consulting table.------ > let {f = 256--- > ;f' = octpc_to_cps (4,0)--- > ;r = (f,Pitch C Natural 4,f',f-f',fratio_to_cents (f/f'))}--- > in nearest_et_table_tone tbl_12et 256 == r+{- | Form 'HS_R' for /frequency/ by consulting table.++> let {f = 256+> ;f' = octpc_to_cps (4,0)+> ;r = (f,Pitch C Natural 4,f',f-f',fratio_to_cents (f/f'))}+> in nearest_et_table_tone tbl_12et 256 == r++-} nearest_et_table_tone :: [(p,Double)] -> Double -> HS_R p nearest_et_table_tone tbl f = case bounds_et_table tbl f of@@ -138,7 +155,7 @@ -- > let {f = pitch'_pp . fst . pitch_72et -- > ;r = "Bb4 Bb+4 Bb>4 Bv4 B<4 B-4 B4 B+4 B>4 B^4"} -- > in unwords (map f (zip (repeat 70) [0..9])) == r-pitch_72et :: (Int,Int) -> (Pitch',Double)+pitch_72et :: (Int,Int) -> (Pitch_R,Double) pitch_72et (x,n) = let p = midi_to_pitch pc_spell_ks x t = note p@@ -150,7 +167,7 @@ _ -> error "pitch_72et: alteration?" a' = alteration_72et_monzo n' x' = fromIntegral x + (fromIntegral n / 6)- r = (Pitch' t' (fromIntegral n' % 12,a') (octave p),fmidi_to_cps x')+ r = (Pitch_R t' (fromIntegral n' % 12,a') (octave p),fmidi_to_cps x') r' = if n > 3 then pitch_72et (x + 1,n - 6) else if n < (-3)@@ -165,7 +182,7 @@ -- -- > length tbl_72et == 792 -- > min_max (map (round . snd) tbl_72et) == (16,33167)-tbl_72et :: [(Pitch',Double)]+tbl_72et :: [(Pitch_R,Double)] tbl_72et = let f n = map pitch_72et (zip (replicate 6 n) [0..5]) in concatMap f [12 .. 143]@@ -177,7 +194,7 @@ -- -- > let {f = take 2 . hs_r_pp pitch'_pp 1 . nearest_72et_tone . snd} -- > in mapM_ (print . unwords . f) tbl_72et-nearest_72et_tone :: Double -> HS_R Pitch'+nearest_72et_tone :: Double -> HS_R Pitch_R nearest_72et_tone = nearest_et_table_tone tbl_72et -- * Detune@@ -185,7 +202,7 @@ -- | 'Pitch' with 12-ET/24-ET tuning deviation given in 'Cents'. type Pitch_Detune = (Pitch,Cents) --- | Exract 'Pitch_Detune' from 'HS_R'.+-- | Extract 'Pitch_Detune' from 'HS_R'. hsr_to_pitch_detune :: HS_R Pitch -> Pitch_Detune hsr_to_pitch_detune (_,p,_,_,c) = (p,c) @@ -223,26 +240,20 @@ ratio_to_pitch_detune_24et = ratio_to_pitch_detune nearest_24et_tone pitch_detune_in_octave_nearest :: Pitch -> Pitch_Detune -> Pitch_Detune-pitch_detune_in_octave_nearest p1 (p2,d2) =- let p2' = pitch_in_octave_nearest p1 p2- in (p2',d2)+pitch_detune_in_octave_nearest p1 (p2,d2) = (pitch_in_octave_nearest p1 p2,d2) -- | Markdown pretty-printer for 'Pitch_Detune'. pitch_detune_md :: Pitch_Detune -> String-pitch_detune_md (p,c) =- pitch_pp p ++ cents_diff_md (round c :: Integer)+pitch_detune_md (p,c) = pitch_pp p ++ cents_diff_md (round c :: Integer) -- | HTML pretty-printer for 'Pitch_Detune'. pitch_detune_html :: Pitch_Detune -> String-pitch_detune_html (p,c) =- pitch_pp p ++ cents_diff_html (round c :: Integer)+pitch_detune_html (p,c) = pitch_pp p ++ cents_diff_html (round c :: Integer) -- | No-octave variant of 'pitch_detune_md'. pitch_class_detune_md :: Pitch_Detune -> String-pitch_class_detune_md (p,c) =- pitch_class_pp p ++ cents_diff_md (round c :: Integer)+pitch_class_detune_md (p,c) = pitch_class_pp p ++ cents_diff_md (round c :: Integer) -- | No-octave variant of 'pitch_detune_html'. pitch_class_detune_html :: Pitch_Detune -> String-pitch_class_detune_html (p,c) =- pitch_class_pp p ++ cents_diff_html (round c :: Integer)+pitch_class_detune_html (p,c) = pitch_class_pp p ++ cents_diff_html (round c :: Integer)
+ Music/Theory/Tuning/Euler.hs view
@@ -0,0 +1,138 @@+-- | Euler plane diagrams as /dot/ language graph.+module Music.Theory.Tuning.Euler where++import Data.List {- base -}+import Data.Ratio {- base -}++import qualified Music.Theory.List as T {- hmt -}+import qualified Music.Theory.Math as T {- hmt -}+import qualified Music.Theory.Pitch.Note as T {- hmt -}+import qualified Music.Theory.Tuning as T {- hmt -}+import qualified Music.Theory.Tuple as T {- hmt -}++-- | 'T.fold_ratio_to_octave' of '*'.+rat_mul :: Rational -> Rational -> Rational+rat_mul r = T.fold_ratio_to_octave_err . (* r)++-- | 'T.fold_ratio_to_octave' of '/'.+rat_div :: Rational -> Rational -> Rational+rat_div p q = T.fold_ratio_to_octave_err (p / q)++-- | /n/ = length, /m/ equals multiplier, /r/ = initial ratio.+--+-- > tun_seq 5 (3/2) 1 == [1/1,3/2,9/8,27/16,81/64]+tun_seq :: Int -> Rational -> Rational -> [Rational]+tun_seq n m = take n . iterate (rat_mul m)++mod12 :: Integral a => a -> a+mod12 n = n `mod` 12++-- | 'T.ratio_to_cents' rounded to nearest multiple of 100, modulo 12.+--+-- > map (ratio_to_pc 0) [1,4/3,3/2,2] == [0,5,7,0]+ratio_to_pc :: Int -> Rational -> Int+ratio_to_pc n = mod12 . (+ n) . round . (/ 100) . T.ratio_to_cents++all_pairs :: [t] -> [u] -> [(t,u)]+all_pairs p q = [(x,y) | x <- p, y <- q]++-- | Give all pairs from (l2,l1) and (l3,l2) that are at interval ratios r1 and r2 respectively.+euler_align_rat :: T.T2 Rational -> T.T3 [Rational] -> T.T2 [T.T2 Rational]+euler_align_rat (r1,r2) (l1,l2,l3) =+ let f r (p,q) = rat_mul p r == q+ in (filter (f r1) (all_pairs l2 l1)+ ,filter (f r2) (all_pairs l3 l2))++-- | Pretty printer for pitch class.+--+-- > unwords (map pc_pp [0..11]) == "C♮ C♯ D♮ E♭ E♮ F♮ F♯ G♮ A♭ A♮ B♭ B♮"+pc_pp :: (Integral i,Show i) => i -> String+pc_pp x =+ case T.pc_to_note_alteration_ks x of+ Just (n,a) -> [T.note_pp n,T.alteration_symbol a]+ Nothing -> error (show ("pc_pp",x))++cents_pp :: Rational -> String+cents_pp = show . (round :: Double -> Integer) . T.ratio_to_cents++-- > rat_label (0,False) 1 == "C♮\\n1:1"+-- > rat_label (3,True) (7/4) == "C♯=969\\n7:4"+rat_label :: (Int,Bool) -> Rational -> String+rat_label (k,with_cents) r =+ if r < 1 || r >= 2+ then error (show ("rat_label",r))+ else concat [pc_pp (ratio_to_pc k r)+ ,if with_cents+ then '=' : cents_pp r+ else ""+ ,"\\n",T.ratio_pp r]++-- > rat_id (5/4) == "R_5_4"+rat_id :: Rational-> String+rat_id r = "R_" ++ show (numerator r) ++ "_" ++ show (denominator r)++rat_edge_label :: (Rational, Rational) -> String+rat_edge_label (p,q) = concat [" (",T.ratio_pp (rat_div p q),")"]++-- | Zip start-middle-end.+--+-- > zip_sme (0,1,2) "abcd" == [(0,'a'),(1,'b'),(1,'c'),(2,'d')]+zip_sme :: (t,t,t) -> [u] -> [(t,u)]+zip_sme (s,m,e) xs =+ case xs of+ x0:x1:xs' -> (s,x0) : (m,x1) : T.at_last (\x -> (m,x)) (\x -> (e,x)) xs'+ _ -> error "zip_sme: not SME list"++type Euler_Plane t = ([[t]],[(t,t)])++euler_plane_to_dot :: (t -> String,t -> String,(t,t) -> String) -> Euler_Plane t -> [String]+euler_plane_to_dot (n_id,n_pp,e_pp) (h,v) =+ let mk_lab_term x =concat [" [label=\"",x,"\"];"]+ node_to_dot x = concat [n_id x,mk_lab_term (n_pp x)]+ subgraph_edges x = intercalate " -- " (map n_id x) ++ ";"+ edge_to_dot (lhs,rhs) = concat [n_id lhs," -- ",n_id rhs,mk_lab_term (e_pp (lhs,rhs))]+ subgraphs_to_dot (ty,x) = concat ["{rank=",ty,"; ",unwords (map n_id x),"}"]+ in ["graph g {"+ ,"graph [layout=\"dot\",rankdir=\"TB\",nodesep=0.5];"+ ,"edge [fontsize=\"8\",fontname=\"century schoolbook\"];"+ ,"node [shape=\"plaintext\",fontsize=\"10\",fontname=\"century schoolbook\"];"] +++ map node_to_dot (concat h) +++ map subgraph_edges h +++ map edge_to_dot v +++ map subgraphs_to_dot (zip_sme ("min","same","max") h) +++ ["}"]++euler_plane_to_dot_rat :: (Int, Bool) -> Euler_Plane Rational -> [String]+euler_plane_to_dot_rat opt = euler_plane_to_dot (rat_id,rat_label opt,rat_edge_label)++{-++let j5 =+ let {l1 = tun_seq 3 (3%2) (5%3)+ ;l2 = tun_seq 5 (3%2) (16%9)+ ;l3 = tun_seq 4 (3%2) (64%45)+ ;(c1,c2) = euler_align_rat (5%8,5%4) (l1,l2,l3)}+ in ([l1,l2,l3],c1 ++ c2)++let j5' =+ let {f = T.fold_ratio_to_octave_err+ ;l1 = tun_seq 4 (3/2) (f (1 * 2/3 * 5/4))+ ;l2 = tun_seq 5 (3/2) (f (1 * 2/3 * 2/3))+ ;l3 = tun_seq 3 (3/2) (f (1 * 2/3 * 4/5))+ ;(c1,c2) = euler_align_rat (5/4,5/4) (l1,l2,l3)}+ in ([l1,l2,l3],c1 ++ c2)++let j7 =+ let {l1 = tun_seq 4 (3%2) (5%4)+ ;l2 = tun_seq 5 (3%2) (4%3)+ ;l3 = tun_seq 3 (3%2) (14%9)+ ;(c1,c2) = euler_align_rat (5%4,4%7) (l1,l2,l3)}+ in ([l1,l2,l3],c1 ++ c2)++let dir = "/home/rohan/sw/hmt/data/dot/"+let f = unlines . euler_plane_to_dot_rat (0,False)+writeFile (dir ++ "euler-j5-a.dot") (f j5)+writeFile (dir ++ "euler-j5-b.dot") (f j5')+writeFile (dir ++ "euler-j7.dot") (f j7)++-}
− Music/Theory/Tuning/Gann.hs
@@ -1,141 +0,0 @@--- | Kyle Gann.-module Music.Theory.Tuning.Gann where--import Music.Theory.Tuning {- hmt -}---- * Historical---- | Cents for 'pietro_aaron_1523'.------ > let c = [0,76,193,310,386,503,580,697,773,890,1007,1083]--- > in map round pietro_aaron_1523_c == c-pietro_aaron_1523_c :: [Cents]-pietro_aaron_1523_c =- [0,76.0- ,193.2,310.3- ,386.3- ,503.4,579.5- ,696.8,772.6- ,889.7,1006.8- ,1082.9]---- | Pietro Aaron (1523) meantone temperament, see--- <http://www.kylegann.com/histune.html>------ > cents_i pietro_aaron_1523 == [0,76,193,310,386,503,580,697,773,890,1007,1083]-pietro_aaron_1523 :: Tuning-pietro_aaron_1523 = Tuning (Right pietro_aaron_1523_c) 2---- | Andreas Werckmeister (1645-1706), <http://www.kylegann.com/histune.html>.-werckmeister_iii_c :: [Cents]-werckmeister_iii_c =- [0,90.225- ,192.18,294.135- ,390.225- ,498.045,588.27- ,696.09,792.18- ,888.27,996.09- ,1092.18]---- | Cents for 'thomas_young_1799'.------ > let c = [0,94,196,298,392,500,592,698,796,894,1000,1092]--- > in map round thomas_young_1799_c == c-thomas_young_1799_c :: [Cents]-thomas_young_1799_c =- [0,93.9- ,195.8,297.8- ,391.7- ,499.9,591.9- ,697.9,795.8- ,893.8,999.8- ,1091.8]---- | Thomas Young (1799), Well Temperament, <http://www.kylegann.com/histune.html>.------ > cents_i thomas_young_1799 == [0,94,196,298,392,500,592,698,796,894,1000,1092]-thomas_young_1799 :: Tuning-thomas_young_1799 = Tuning (Right thomas_young_1799_c) 2---- | Ratios for 'zarlino'.-zarlino_r :: [Rational]-zarlino_r = [1/1,25/24,10/9,9/8,32/27,6/5,5/4,4/3,25/18,45/32,3/2,25/16,5/3,16/9,9/5,15/8]---- | Gioseffo Zarlino, 1588, see <http://www.kylegann.com/tuning.html>.------ > divisions zarlino == 16--- > cents_i zarlino == [0,71,182,204,294,316,386,498,569,590,702,773,884,996,1018,1088]-zarlino :: Tuning-zarlino = Tuning (Left zarlino_r) 2---- * 20th Century---- | Ratios for 'la_monte_young'.------ > let c = [0,177,204,240,471,444,675,702,738,969,942,1173]--- > in map (round . ratio_to_cents) la_monte_young_r == c-la_monte_young_r :: [Rational]-la_monte_young_r =- [1,567/512- ,9/8,147/128- ,21/16- ,1323/1024,189/128- ,3/2,49/32- ,7/4,441/256- ,63/32]---- | La Monte Young's \"The Well-Tuned Piano\", see--- <http://www.kylegann.com/wtp.html>.------ > cents_i la_monte_young == [0,177,204,240,471,444,675,702,738,969,942,1173]-la_monte_young :: Tuning-la_monte_young = Tuning (Left la_monte_young_r) 2---- | Ratios for 'ben_johnston'.------ > let c = [0,105,204,298,386,471,551,702,841,906,969,1088]--- > in map (round . ratio_to_cents) ben_johnston_r == c-ben_johnston_r :: [Rational]-ben_johnston_r =- [1,17/16- ,9/8,19/16- ,5/4- ,21/16,11/8- ,3/2,13/8- ,27/16,7/4- ,15/8]---- | Ben Johnston's \"Suite for Microtonal Piano\" (1977), see--- <http://www.kylegann.com/tuning.html>------ > cents_i ben_johnston == [0,105,204,298,386,471,551,702,841,906,969,1088]-ben_johnston :: Tuning-ben_johnston = Tuning (Left ben_johnston_r) 2---- * Gann---- | Ratios for 'gann_arcana_xvi'.-gann_arcana_xvi_r :: [Rational]-gann_arcana_xvi_r =- [1/1,21/20,16/15,9/8,7/6,6/5,11/9,5/4,21/16,4/3,27/20,7/5- ,22/15,3/2,55/36,8/5,44/27,5/3,42/25,7/4,9/5,11/6,15/8,88/45]---- | Kyle Gann, _Arcana XVI_, see <http://www.kylegann.com/Arcana.html>.------ > let r = [0,84,112,204,267,316,347,386,471,498,520,583,663,702,734,814,845,884,898,969,1018,1049,1088,1161]--- > in cents_i gann_arcana_xvi == r-gann_arcana_xvi :: Tuning-gann_arcana_xvi = Tuning (Left gann_arcana_xvi_r) 2---- | Ratios for 'gann_superparticular'.-gann_superparticular_r :: [Rational]-gann_superparticular_r = [1/1,11/10,10/9,9/8,8/7,7/6,6/5,5/4,9/7,4/3,11/8,7/5,10/7,3/2,11/7,14/9,8/5,5/3,12/7,7/4,16/9,9/5]---- | Kyle Gann, _Superparticular_, see <http://www.kylegann.com/Super.html>.------ > divisions gann_superparticular == 22------ > let r = [0,165,182,204,231,267,316,386,435,498,551,583,617,702,782,765,814,884,933,969,996,1018]--- > in cents_i gann_superparticular == r-gann_superparticular :: Tuning-gann_superparticular = Tuning (Left gann_superparticular_r) 2
+ Music/Theory/Tuning/Gann_1993.hs view
@@ -0,0 +1,139 @@+-- | Kyle Gann. "La Monte Young's The Well-Tuned Piano".+-- /Perspectives of New Music/, 31(1):134--162, Winter 1993.+module Music.Theory.Tuning.Gann_1993 where++import Data.List {- base -}+import Data.Maybe {- base -}++import qualified Music.Theory.List as T {- hmt -}+import qualified Music.Theory.Pitch as T {- hmt -}+import qualified Music.Theory.Tuning as T {- hmt -}+import qualified Music.Theory.Tuning.Euler as T {- hmt -}++{- | Ratios for 'lmy_wtp'. lmy = La Monte Young. wtp = Well-Tuned Piano.++> let c = [0,177,204,240,471,444,675,702,738,969,942,1173]+> in map (round . T.ratio_to_cents) lmy_wtp_r == c++-}+lmy_wtp_r :: [Rational]+lmy_wtp_r =+ [1,567/512+ ,9/8,147/128+ ,21/16+ ,1323/1024,189/128+ ,3/2,49/32+ ,7/4,441/256+ ,63/32]++-- | The pitch-class of the key associated with each ratio of the tuning.+--+-- > mapMaybe lmy_wtp_ratio_to_pc [1,1323/1024,7/4] == [3,8,0]+lmy_wtp_ratio_to_pc :: Rational -> Maybe T.PitchClass+lmy_wtp_ratio_to_pc r = fmap (T.mod12 . (+ 3)) (elemIndex r lmy_wtp_r)++lmy_wtp_ratio_to_pc_err :: Rational -> T.PitchClass+lmy_wtp_ratio_to_pc_err = fromMaybe (error "lmy_wtp_ratio_to_pc") . lmy_wtp_ratio_to_pc++-- | The list of all non-unison ascending intervals possible in 'lmy_wtp_r'.+--+-- > length lmy_wtp_univ == 66+lmy_wtp_univ :: [(Rational,(T.PitchClass,T.PitchClass))]+lmy_wtp_univ =+ let f (p,q) = if p < q+ then Just (T.ratio_interval_class (p/q)+ ,(lmy_wtp_ratio_to_pc_err p+ ,lmy_wtp_ratio_to_pc_err q))+ else Nothing+ in mapMaybe f (T.all_pairs lmy_wtp_r lmy_wtp_r)++{- | Collated and sorted 'lmy_wtp_univ'.++> let r_cents_pp = show . round . T.ratio_to_cents++> import qualified Music.Theory.Math as T {- hmt -}++> let f (r,i) = concat [T.ratio_pp r," = "+> ,r_cents_pp r," = #"+> ,show (length i)," = "+> ,unwords (map show i)]++> putStrLn $ unlines $ map f lmy_wtp_uniq++3:2 = 702 = #9 = (3,10) (4,9) (5,10) (6,11) (6,1) (7,0) (7,2) (8,1) (9,2)+7:4 = 969 = #7 = (3,0) (5,2) (6,7) (7,10) (8,9) (11,0) (1,2)+7:6 = 267 = #6 = (4,8) (5,7) (6,2) (7,11) (9,1) (10,0)+9:7 = 435 = #4 = (4,1) (5,0) (6,9) (11,2)+9:8 = 204 = #6 = (3,5) (4,2) (6,8) (7,9) (11,1) (0,2)+21:16 = 471 = #6 = (3,7) (5,9) (6,0) (7,1) (8,2) (10,2)+27:14 = 1137 = #2 = (4,6) (9,11)+27:16 = 906 = #3 = (4,7) (8,11) (9,0)+49:32 = 738 = #3 = (3,11) (5,1) (6,10)+49:36 = 534 = #1 = (5,11)+63:32 = 1173 = #5 = (3,2) (4,5) (8,7) (9,10) (1,0)+49:48 = 36 = #2 = (5,6) (10,11)+81:56 = 639 = #1 = (4,11)+81:64 = 408 = #1 = (4,0)+147:128 = 240 = #3 = (3,6) (5,8) (10,1)+189:128 = 675 = #3 = (3,9) (4,10) (8,0)+441:256 = 942 = #2 = (3,1) (8,10)+567:512 = 177 = #1 = (3,4)+1323:1024 = 444 = #1 = (3,8)++-}+lmy_wtp_uniq :: [(Rational,[(T.PitchClass,T.PitchClass)])]+lmy_wtp_uniq = sortOn (T.ratio_nd_sum . fst) $ T.collate_on fst snd $ lmy_wtp_univ++{- | Gann, 1993, p.137.++> cents_i lmy_wtp == [0,177,204,240,471,444,675,702,738,969,942,1173]++> import Data.List {- base -}+> import Music.Theory.Tuning.Scala {- hmt -}+> scl <- scl_load "young-lm_piano"+> cents_i (scale_to_tuning 0.01 scl) == cents_i lmy_wtp++> let f = d12_midi_tuning_f (lmy_wtp,-74.7,-3)+> import qualified Music.Theory.Pitch as T+> T.octpc_to_midi (-1,11) == 11+> map (round . T.midi_detune_to_cps . f) [62,63,69] == [293,298,440]+> map (fmap round . T.midi_detune_normalise . f) [0 .. 127]++-}+lmy_wtp :: T.Tuning+lmy_wtp = T.Tuning (Left lmy_wtp_r) 2++-- | Ratios for 'lmy_wtp_1964.+lmy_wtp_1964_r :: [Rational]+lmy_wtp_1964_r =+ let n = [1,279,9,147,21,93,189,3,49,7,31,63]+ d = [1,256,8,128,16,64,128,2,32,4,16,32]+ in zipWith (/) n d++{- | La Monte Young's initial 1964 tuning for \"The Well-Tuned Piano\" (Gann, 1993, p.141).++> cents_i lmy_wtp_1964 == [0,149,204,240,471,647,675,702,738,969,1145,1173]++> import Music.Theory.Tuning.Scala+> let nm = ("young-lm_piano_1964","LaMonte Young's Well-Tuned Piano (1964)")+> let scl = tuning_to_scale nm lmy_wtp_1964+> putStr $ unlines $ scale_pp scl++-}+lmy_wtp_1964 :: T.Tuning+lmy_wtp_1964 = T.Tuning (Left lmy_wtp_1964_r) 2++{- | Euler diagram for 'lmy_wtp'.++let dir = "/home/rohan/sw/hmt/data/dot/"+let f = unlines . T.euler_plane_to_dot_rat (3,True)+writeFile (dir ++ "euler-wtp.dot") (f lmy_wtp_euler)++-}+lmy_wtp_euler :: T.Euler_Plane Rational+lmy_wtp_euler =+ let {l1 = T.tun_seq 4 (3/2) (49/32)+ ;l2 = T.tun_seq 5 (3/2) (7/4)+ ;l3 = T.tun_seq 3 (3/2) (1/1)+ ;(c1,c2) = T.euler_align_rat (7/4,7/4) (l1,l2,l3)}+ in ([l1,l2,l3],c1 ++ c2)
+ Music/Theory/Tuning/Load.hs view
@@ -0,0 +1,78 @@+-- | Functions to load a tuning definition and transform it into a sparse tuning function.+module Music.Theory.Tuning.Load where++import System.Random {- random -}++import qualified Music.Theory.Array.CSV as T+import qualified Music.Theory.Pitch as T+import qualified Music.Theory.Tuning as T+import qualified Music.Theory.Tuning.Scala as T++-- | Load possibly sparse and possibly one-to-many+-- (midi-note-number,cps-frequency) table from CSV file.+--+-- > load_cps_tbl "/home/rohan/dr.csv"+load_cps_tbl :: FilePath -> IO [(Int,Double)]+load_cps_tbl nm = do+ tbl <- T.csv_table_read_def id nm+ let f e = case e of+ [p,q] -> (read p,read q)+ _ -> error "load_cps_tbl"+ return (map f tbl)++-- | Load scala scl file as 'T.Tuning'.+load_tuning_scl :: String -> IO T.Tuning+load_tuning_scl = fmap (T.scale_to_tuning 0.01) . T.scl_load++-- | Load scala file and apply 'T.cps_midi_tuning_f'.+load_tuning_cps :: (String,Double,Int) -> IO T.Sparse_Midi_Tuning_F+load_tuning_cps (nm,f0,k) =+ let f tn = T.cps_midi_tuning_f (tn,f0,k,128-k)+ in fmap f (load_tuning_scl nm)++-- | Load scala file and apply 'T.d12_midi_tuning_f'.+load_tuning_d12 :: (String,Double,Int) -> IO T.Sparse_Midi_Tuning_F+load_tuning_d12 (nm,dt,k) =+ let f tn = T.lift_tuning_f (T.d12_midi_tuning_f (tn,dt,k))+ in fmap f (load_tuning_scl nm)++-- | Lookup first matching element in table.+load_tuning_tbl :: (String,Double,Int) -> IO T.Sparse_Midi_Tuning_F+load_tuning_tbl (nm,dt,k) =+ let from_cps = T.cps_to_midi_detune . flip T.cps_shift_cents dt+ f tbl mnn = fmap from_cps (lookup (mnn + k) tbl)+ in fmap f (load_cps_tbl nm)++type Choose_f st t = [t] -> st-> (t,st)++-- | Randomly choose from elements in table, equal weighting.+default_choose_f :: RandomGen g => Choose_f g t+default_choose_f l g =+ let (i,g') = randomR (0,length l - 1) g+ in (l !! i,g')++-- | Load tuning table with stateful selection function for one-to-many entries.+load_tuning_tbl_st :: Choose_f st (Int,Double) -> (String,Double,Int) -> IO (T.Sparse_Midi_Tuning_ST_F st)+load_tuning_tbl_st choose_f (nm,dt,k) =+ let from_cps = T.cps_to_midi_detune . flip T.cps_shift_cents dt+ f tbl g mnn = case filter ((== (mnn + k)) . fst) tbl of+ [] -> (g,Nothing)+ l -> let ((_,e),g') = choose_f l g+ in (g',Just (from_cps e))+ in fmap f (load_cps_tbl nm)++load_tuning_ty :: String -> (String,Double,Int) -> IO T.Sparse_Midi_Tuning_F+load_tuning_ty ty opt =+ case ty of+ "cps" -> load_tuning_cps opt+ "d12" -> load_tuning_d12 opt+ "tbl" -> load_tuning_tbl opt+ _ -> error "cps|d12|tbl"++load_tuning_st_ty :: String -> (String,Double,Int) -> IO (T.Sparse_Midi_Tuning_ST_F StdGen)+load_tuning_st_ty ty opt =+ case ty of+ "cps" -> fmap T.lift_sparse_tuning_f (load_tuning_cps opt)+ "d12" -> fmap T.lift_sparse_tuning_f (load_tuning_d12 opt)+ "tbl" -> load_tuning_tbl_st default_choose_f opt+ _ -> error "cps|d12|tbl"
Music/Theory/Tuning/Meyer_1929.hs view
@@ -3,8 +3,9 @@ -- University of Missouri, 1929. p.22 module Music.Theory.Tuning.Meyer_1929 where -import Data.List-import Data.Ratio+import Data.List {- base -}+import Data.Ratio {- base -}+ import qualified Music.Theory.Tuning as T -- | Odd numbers to /n/.@@ -17,17 +18,17 @@ -- -- > row 7 == [1,5/4,3/2,7/4] row :: Integral i => i -> [Ratio i]-row = sort . map T.fold_ratio_to_octave . odd_to . (% 1)+row = sort . map T.fold_ratio_to_octave_err . odd_to . (% 1) -- | Generate initial column for /n/. -- -- > column 7 == [1,8/5,4/3,8/7] column :: Integral i => i -> [Ratio i]-column = map (T.fold_ratio_to_octave . recip) . row+column = map (T.fold_ratio_to_octave_err . recip) . row -- | 'T.fold_to_octave' '.' '*'. in_oct_mul :: Integral i => Ratio i -> Ratio i -> Ratio i-in_oct_mul i j = T.fold_ratio_to_octave (i * j)+in_oct_mul i j = T.fold_ratio_to_octave_err (i * j) -- | Given /row/ and /column/ generate matrix value at /(i,j)/. --
− Music/Theory/Tuning/Microtonal_Synthesis.hs
@@ -1,205 +0,0 @@--- | <http://www.microtonal-synthesis.com/scales.html>-module Music.Theory.Tuning.Microtonal_Synthesis where--import Music.Theory.Tuning {- hmt -}---- | Ratios for 'pythagorean'.------ > let c = [0,90,204,294,408,498,612,702,792,906,996,1110]--- > in map (round . ratio_to_cents) pythagorean_r == c-pythagorean_r :: [Rational]-pythagorean_r =- [1,256/243 {- 2187/2048 -}- ,9/8,32/27- ,81/64- ,4/3,729/512- ,3/2,128/81 {- 6561/4096 -}- ,27/16,16/9- ,243/128]---- | Pythagorean tuning, <http://www.microtonal-synthesis.com/scale_pythagorean.html>.------ > divisions pythagorean == 12--- > cents_i pythagorean == [0,90,204,294,408,498,612,702,792,906,996,1110]-pythagorean :: Tuning-pythagorean = Tuning (Left pythagorean_r) 2---- | Ratios for 'five_limit_tuning'.------ > let c = [0,112,204,316,386,498,590,702,814,884,996,1088]--- > in map (round . ratio_to_cents) five_limit_tuning_r == c-five_limit_tuning_r :: [Rational]-five_limit_tuning_r =- [1,16/15- ,9/8,6/5- ,5/4- ,4/3,45/32 {- 64/45 -}- ,3/2,8/5- ,5/3,16/9 {- 9/5 -}- ,15/8]---- | Five-limit tuning (five limit just intonation).------ > cents_i five_limit_tuning == [0,112,204,316,386,498,590,702,814,884,996,1088]-five_limit_tuning :: Tuning-five_limit_tuning = Tuning (Left five_limit_tuning_r) 2---- | Ratios for 'septimal_tritone_just_intonation'.------ > let c = [0,112,204,316,386,498,583,702,814,884,1018,1088]--- > in map (round . ratio_to_cents) septimal_tritone_just_intonation == c-septimal_tritone_just_intonation_r :: [Rational]-septimal_tritone_just_intonation_r =- [1,16/15- ,9/8,6/5- ,5/4- ,4/3,7/5- ,3/2,8/5- ,5/3,9/5- ,15/8]---- | Septimal tritone Just Intonation, see--- <http://www.microtonal-synthesis.com/scale_just_intonation.html>------ > cents_i septimal_tritone_just_intonation == [0,112,204,316,386,498,583,702,814,884,1018,1088]-septimal_tritone_just_intonation :: Tuning-septimal_tritone_just_intonation = Tuning (Left septimal_tritone_just_intonation_r) 2---- | Ratios for 'seven_limit_just_intonation'.------ > let c = [0,112,204,316,386,498,583,702,814,884,969,1088]--- > in map (round . ratio_to_cents) seven_limit_just_intonation == c-seven_limit_just_intonation_r :: [Rational]-seven_limit_just_intonation_r =- [1,16/15- ,9/8,6/5- ,5/4- ,4/3,7/5- ,3/2,8/5- ,5/3,7/4- ,15/8]---- | Seven limit Just Intonation.------ > cents_i seven_limit_just_intonation == [0,112,204,316,386,498,583,702,814,884,969,1088]-seven_limit_just_intonation :: Tuning-seven_limit_just_intonation = Tuning (Left seven_limit_just_intonation_r) 2---- | Approximate ratios for 'kirnberger_iii'.------ > let c = [0,90,193,294,386,498,590,697,792,890,996,1088]--- > in map (round.to_cents) kirnberger_iii_ar == c-kirnberger_iii_ar :: [Approximate_Ratio]-kirnberger_iii_ar =- [1,256/243- ,sqrt 5 / 2,32/27- ,5/4- ,4/3,45/32- ,5 ** 0.25,128/81- ,(5 ** 0.75)/2,16/9- ,15/8]---- | <http://www.microtonal-synthesis.com/scale_kirnberger.html>.------ > cents_i kirnberger_iii == [0,90,193,294,386,498,590,697,792,890,996,1088]-kirnberger_iii :: Tuning-kirnberger_iii = Tuning (Right (map approximate_ratio_to_cents kirnberger_iii_ar)) 2---- > let c = [0,94,196,298,392,502,592,698,796,894,1000,1090]--- > in map round vallotti_c == c-vallotti_c :: [Cents]-vallotti_c =- [0.0,94.135- ,196.09,298.045- ,392.18- ,501.955,592.18- ,698.045,796.09- ,894.135,1000.0- ,1090.225]---- | Vallotti & Young scale (Vallotti version), see--- <http://www.microtonal-synthesis.com/scale_vallotti_young.html>.------ > cents_i vallotti == [0,94,196,298,392,502,592,698,796,894,1000,1090]-vallotti :: Tuning-vallotti = Tuning (Right vallotti_c) 2---- > let c = [0,128,139,359,454,563,637,746,841,911,1072,1183]--- > in map (round . ratio_to_cents) mayumi_reinhard == c-mayumi_reinhard_r :: [Rational]-mayumi_reinhard_r =- [1,14/13- ,13/12,16/13- ,13/10- ,18/13,13/9- ,20/13,13/8- ,22/13,13/7- ,208/105]---- | Mayumi Reinhard 13-limit Just Intonation scale,--- <http://www.microtonal-synthesis.com/scale_reinhard.html>.------ > cents_i mayumi_reinhard == [0,128,139,359,454,563,637,746,841,911,1072,1183]-mayumi_reinhard :: Tuning-mayumi_reinhard = Tuning (Left mayumi_reinhard_r) 2---- | Ratios for 'lou_harrison_16'.------ > length lou_harrison_16_r == 16------ > let c = [0,112,182,231,267,316,386,498,603,702,814,884,933,969,1018,1088]--- > in map (round . ratio_to_cents) lou_harrison_16_r == c-lou_harrison_16_r :: [Rational]-lou_harrison_16_r =- [1,16/15- ,10/9,8/7- ,7/6,6/5,5/4- ,4/3- ,17/12- ,3/2- ,8/5,5/3,12/7- ,7/4,9/5,15/8]---- | Lou Harrison 16 tone Just Intonation scale, see--- <http://www.microtonal-synthesis.com/scale_harrison_16.html>------ > let r = [0,112,182,231,267,316,386,498,603,702,814,884,933,969,1018,1088]--- > in cents_i lou_harrison_16 == r-lou_harrison_16 :: Tuning-lou_harrison_16 = Tuning (Left lou_harrison_16_r) 2---- | Ratios for 'partch_43'.-partch_43_r :: [Rational]-partch_43_r =- [1,81/80,33/32,21/20,16/15,12/11,11/10,10/9,9/8,8/7- ,7/6,32/27,6/5,11/9,5/4,14/11,9/7- ,21/16,4/3,27/20- ,11/8,7/5,10/7,16/11- ,40/27,3/2,32/21,14/9,11/7,8/5,18/11,5/3,27/16,12/7- ,7/4,16/9,9/5,20/11,11/6,15/8,40/21,64/33,160/81]---- | Harry Partch 43 tone scale, see--- <http://www.microtonal-synthesis.com/scale_partch.html>------ > cents_i partch_43 == [0,22,53,84,112,151,165--- > ,182,204,231,267,294,316--- > ,347,386,418,435--- > ,471,498,520,551,583,617,649--- > ,680,702,729,765,782,814,853,884,906,933--- > ,969,996,1018,1035,1049,1088,1116,1147,1178]-partch_43 :: Tuning-partch_43 = Tuning (Left partch_43_r) 2---- | Ratios for 'ben_johnston_25'.-ben_johnston_25_r :: [Rational]-ben_johnston_25_r =- [1/1,25/24,135/128,16/15,10/9- ,9/8,75/64,6/5,5/4,81/64- ,32/25,4/3,27/20,45/32,36/25- ,3/2,25/16,8/5,5/3,27/16- ,225/128,16/9,9/5,15/8,48/25]---- | Ben Johnston 25 note just enharmonic scale, see--- <http://www.microtonal-synthesis.com/scale_johnston_25.html>-ben_johnston_25 :: Tuning-ben_johnston_25 = Tuning (Left ben_johnston_25_r) 2
Music/Theory/Tuning/Polansky_1978.hs view
@@ -1,30 +1,46 @@--- | Larry Polansky. \"Psaltery (for Lou Harrison)\". Frog Peak Music,--- 1978.+-- | Larry Polansky. \"Psaltery (for Lou Harrison)\".+-- Frog Peak Music, 1978. module Music.Theory.Tuning.Polansky_1978 where -import Data.List+import Data.List {- base -}+ import qualified Music.Theory.Tuning as T --- | Three interlocking harmonic series on 1:5:3, by Larry Polansky in--- \"Psaltery\".------ > import qualified Music.Theory.Tuning.Scala as T--- > let fn = "/home/rohan/opt/scala/scl/polansky_ps.scl"--- > s <- T.load fn--- > T.scale_pitch_representations s == (0,50)--- > 1 : Data.Either.rights (T.scale_pitches s) == psaltery-psaltery :: [Rational]-psaltery = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,5/4,5/2,15/4,5,25/4,15/2,35/4,10,45/4,25/2,55/4,15,65/4,35/2,75/4,20,85/4,3/2,3,9/2,6,15/2,9,21/2,12,27/2,15,33/2,18,39/2,21,45/2,24,51/2]+{- | Three interlocking harmonic series on 1:5:3, by Larry Polansky in \"Psaltery\". --- | 'T.fold_ratio_to_octave' of 'psaltery'.------ > length psaltery == 51 && length psaltery_o == 21--- > psaltery_o == [1,65/64,33/32,17/16,35/32,9/8,75/64,39/32--- > ,5/4,21/16,85/64,11/8,45/32--- > ,3/2,25/16,51/32,13/8,27/16,55/32,7/4,15/8]-psaltery_o :: [Rational]-psaltery_o = nub (sort (map T.fold_ratio_to_octave psaltery))+> import qualified Music.Theory.Tuning.Scala as T+> scl <- T.scl_load "polansky_ps"+> T.pitch_representations (T.scale_pitches scl) == (0,50)+> 1 : Data.Either.rights (T.scale_pitches scl) == psaltery_r --- Local Variables:--- truncate-lines:t--- End:+-}+psaltery_r :: [Rational]+psaltery_r =+ let sq_at n = map (* n) [1..17]+ in concat [sq_at 1,sq_at (5/4),sq_at (3/2)]++{- | 'T.fold_ratio_to_octave'' of 'psaltery'.++> length psaltery_r == 51 && length psaltery_o_r == 21++> psaltery_o_r == [1,65/64,33/32,17/16,35/32,9/8,75/64,39/32+> ,5/4,21/16,85/64,11/8,45/32+> ,3/2,25/16,51/32,13/8,27/16,55/32,7/4,15/8]++-}+psaltery_o_r :: [Rational]+psaltery_o_r = nub (sort (map T.fold_ratio_to_octave_err psaltery_r))++{- | 'Tuning' derived from 'psaltery_o' with 'octave_ratio' of @2@.++> cents_i psaltery_o == [0,27,53,105,155,204,275,342,386,471,491,551,590+ ,702,773,807,841,906,938,969,1088]++> let r = [0,1200,1902,2400,2786,3102,3369,3600,3804,3986,4151,4302,4441,4569,4688,4800,4905+ ,386,1586,2288,2786,3173,3488,3755,3986,4190,4373,4538,4688,4827,4955,5075,5186,5291+ ,702,1902,2604,3102,3488,3804,4071,4302,4506,4688,4853,5004,5142,5271,5390,5502]+> in cents_i (T.scale_tuning 0.01 scl) == r++-}+psaltery_o :: T.Tuning+psaltery_o = T.Tuning (Left psaltery_o_r) 2
Music/Theory/Tuning/Polansky_1984.hs view
@@ -2,9 +2,11 @@ -- Interval Sizes in Javanese Slendro\". /Balungan/, 1(2):9-11, 1984 module Music.Theory.Tuning.Polansky_1984 where -import Data.List-import Music.Theory.Tuning+import Data.List {- base -} +import qualified Music.Theory.List as T+import qualified Music.Theory.Tuning as T+ k_manisrenga :: Fractional n => [n] k_manisrenga = [219.5,266.5,227,233.5,258.5] @@ -100,12 +102,6 @@ let f n (i,j) = i <= n && n < j in maybe "U" snd (find (f x . fst) i_categories) --- | Pad 'String' to right with spaces until at least /n/ characters.------ > map (pad 3) ["S","E-L"] == ["S ","E-L"]-pad :: Int -> String -> String-pad n s = s ++ replicate (n - length s) ' '- -- | Pretty interval category table (pp. 10-11). -- -- > i_category_table k_set ==@@ -128,7 +124,7 @@ -- > ,"S-E S L E L " -- > ,"S S E-L L L "] i_category_table :: (Ord a, Num a) => [[a]] -> [String]-i_category_table = map (intercalate " " . map (pad 3 . i_category))+i_category_table = map (intercalate " " . map (T.pad_right ' ' 3 . i_category)) -- | Rational tuning derived from 'gm_averages', p.11. --@@ -148,5 +144,5 @@ -- -- > import Music.Theory.List -- > map round (d_dx polansky_1984_c) == [231,240,223,240,231]-polansky_1984_c :: [Cents]-polansky_1984_c = map ratio_to_cents polansky_1984_r+polansky_1984_c :: [T.Cents]+polansky_1984_c = map T.ratio_to_cents polansky_1984_r
− Music/Theory/Tuning/Riley.hs
@@ -1,18 +0,0 @@--- | Terry Riley.-module Music.Theory.Tuning.Riley where--import Music.Theory.Tuning {- hmt -}---- | Ratios for 'riley_albion'.------ > let r = [0,112,204,316,386,498,610,702,814,884,996,1088]--- > in map (round . ratio_to_cents) riley_albion_r == r-riley_albion_r :: [Rational]-riley_albion_r = [1/1,16/15,9/8,6/5,5/4,4/3,64/45,3/2,8/5,5/3,16/9,15/8]---- | Riley's five-limit tuning as used in _The Harp of New Albion_,--- see <http://www.ex-tempore.org/Volx1/hudson/hudson.htm>.------ > cents_i riley_albion == [0,112,204,316,386,498,610,702,814,884,996,1088]-riley_albion :: Tuning-riley_albion = Tuning (Left riley_albion_r) 2
+ Music/Theory/Tuning/Rosenboom_1979.hs view
@@ -0,0 +1,190 @@+-- | David Rosenboom, "In the Beginning: Etude I (Trombones)", 1979+-- <http://davidrosenboom.com/media/beginning-etude-i-trombones>+--+-- kw: subharmonics, difference tones+module Music.Theory.Tuning.Rosenboom_1979 where++import Data.List {- base -}+import Data.Ratio {- base -}++import qualified Music.Theory.List as T+import qualified Music.Theory.Pitch as T+import qualified Music.Theory.Pitch.Name as T+import qualified Music.Theory.Tuning.ET as T+import qualified Music.Theory.Tuning.Scala as Scala+import qualified Music.Theory.Tuple as T++t2_to_ratio :: (Integer,Integer) -> Rational+t2_to_ratio (n,d) = n % d++-- | Tuning, ratios for each octave.+--+-- > length (concat dr_tuning_oct) == 19+-- > import qualified Music.Theory.Tuning as T+-- > map (map (T.ratio_to_cents . t2_to_ratio)) dr_tuning_oct+dr_tuning_oct :: Num n => [[(n,n)]]+dr_tuning_oct =+ [[(1,1),(4,3),(16,11),(8,5),(16,9)]+ ,[(1,1),(8,7),(4,3),(3,2),(8,5),(16,9)]+ ,[(1,1),(9,8),(5,4),(4,3),(11,8),(3,2),(8,5),(7,4)]]++-- | Tuning, actual ratios.+dr_tuning :: [Rational]+dr_tuning = concat (zipWith (\o -> map ((* o) . t2_to_ratio)) [1,2,4] dr_tuning_oct)++-- | Actual scale, in CPS.+--+-- > let r = [52,69,76,83,92,104,119,138,156,166,185,208,234,260,277,286,311,332,363]+-- > in map round dr_scale == r+dr_scale :: [Double]+dr_scale =+ let f0 = T.octpc_to_cps (1::Int,8)+ f = (* f0) . fromRational+ in map f dr_tuning++-- > putStrLn (unlines (map (unwords . T.hs_r_pitch_pp 1) dr_scale_tbl_12et))+-- > map (\(f,p,_,_,_) -> (T.pitch_to_midi p,f)) dr_scale_tbl_12et+dr_scale_tbl_12et :: [T.HS_R T.Pitch]+dr_scale_tbl_12et = map T.nearest_12et_tone dr_scale++{-++51.9 A♭1 51.9 0.0 0.0+69.2 C♯2 69.3 -0.1 -2.0+75.5 D2 73.4 2.1 48.7+83.1 E2 82.4 0.7 13.7+92.3 F♯2 92.5 -0.2 -3.9+103.8 A♭2 103.8 0.0 0.0+118.7 B♭2 116.5 2.1 31.2+138.4 C♯3 138.6 -0.2 -2.0+155.7 E♭3 155.6 0.2 2.0+166.1 E3 164.8 1.3 13.7+184.6 F♯3 185.0 -0.4 -3.9+207.7 A♭3 207.7 0.0 0.0+233.6 B♭3 233.1 0.5 3.9+259.6 C4 261.6 -2.1 -13.7+276.9 C♯4 277.2 -0.3 -2.0+285.5 D4 293.7 -8.1 -48.7+311.5 E♭4 311.1 0.4 2.0+332.2 E4 329.6 2.6 13.7+363.4 F♯4 370.0 -6.6 -31.2++-}++-- > Scala.scale_verify dr_scale_scala+-- > putStrLn $ unlines $ Scala.scale_pp dr_scale_scala+dr_scale_scala :: Scala.Scale Integer+dr_scale_scala =+ let f (r,(_,p,_,_,_)) = (T.pitch_to_midi p :: Int,r)+ sq = map f (zip dr_tuning dr_scale_tbl_12et)+ g z k = case lookup k sq of+ Nothing -> (z,(k,z))+ Just r -> (r,(k,r))+ r_seq = snd (mapAccumL g 1 [33 .. 32 + 12 * 3 - 1]) ++ [(68,8)]+ in ("dr_itb_etude_1","...",3 * 12,map (Right . snd) r_seq)++-- > putStrLn (unlines (map (unwords . T.hs_r_pitch_pp 1) dr_scale_tbl_24et))+dr_scale_tbl_24et :: [T.HS_R T.Pitch]+dr_scale_tbl_24et = map T.nearest_24et_tone dr_scale++{-++51.9 A♭1 51.9 0.0 0.0+69.2 C♯2 69.3 -0.1 -2.0+75.5 D𝄲2 75.6 -0.1 -1.3+83.1 E2 82.4 0.7 13.7+92.3 F♯2 92.5 -0.2 -3.9+103.8 A♭2 103.8 0.0 0.0+118.7 B𝄳2 120.0 -1.3 -18.8+138.4 C♯3 138.6 -0.2 -2.0+155.7 E♭3 155.6 0.2 2.0+166.1 E3 164.8 1.3 13.7+184.6 F♯3 185.0 -0.4 -3.9+207.7 A♭3 207.7 0.0 0.0+233.6 B♭3 233.1 0.5 3.9+259.6 C4 261.6 -2.1 -13.7+276.9 C♯4 277.2 -0.3 -2.0+285.5 D𝄳4 285.3 0.2 1.3+311.5 E♭4 311.1 0.4 2.0+332.2 E4 329.6 2.6 13.7+363.4 F𝄲4 359.5 3.9 18.8++-}++dr_chords :: [[T.Pitch]]+dr_chords =+ [[T.aes1,T.bes2,T.des3,T.ees4] -- S1+ ,[T.aes1,T.aes2,T.fes3,T.ees4]+ ,[T.aes1,T.bes2,T.des3,T.ees4]+ ,[T.aes1,T.bes2,T.des3,T.ees4] -- S2+ ,[T.aes1,T.ges2,T.aes3,T.ees4]+ ,[T.aes1,T.bes2,T.des3,T.ees4]+ ,[T.aes1,T.bes2,T.des3,T.ees4] -- S3+ ,[T.aes1,T.ges2,T.aes3,T.ees4]+ ,[T.aes1,T.ges2,T.aes3,T.ees4] -- S4+ ,[T.aes1,T.aes2,T.fes3,T.ees4]+ ,[T.aes1,T.fes2,T.des4,T.ees4] -- S5+ ,[T.ges2,T.aes2,T.aes3,T.d4]+ ,[T.aes1,T.d2,T.aes3,T.ees4]+ ,[T.aes2,T.fes3,T.d4] -- S6+ ,[T.aes1,T.fes2,T.des4,T.ees4]+ ,[T.aes1,T.fes2,T.des4,T.ees4] -- S7+ ,[T.aes1,T.ges2,T.aes3,T.ees4]+ ,[T.aes1,T.ges2,T.aes3,T.ees4] -- S8+ ,[T.aes1,T.d2,T.aes3,T.ees4]+ ]++-- > sum (map snd (concat dr_ratio_seq)) == 20 * 11+-- > map (sum . map snd) dr_ratio_seq == replicate 20 11+dr_ratio_seq :: Num n => [[(n,n)]]+dr_ratio_seq =+ [[(11,3),(2,2),(6,6)]+ ,[(7,2),(7,7),(6,2)]+ ,[(6,9),(2,2)]+ ,[(2,9),(11,2)]+ ,[(10,5),(10,3),(10,3)]+ ,[(10,10),(5,1)]+ ,[(5,7),(11,4)]+ ,[(11,3),(8,8)]+ ,[(8,8),(10,3)] -- p2+ ,[(10,7),(10,4)]+ ,[(10,4),(3,3),(4,4)]+ ,[(4,3),(9,7),(5,1)]+ ,[(7,7),(7,4)]+ ,[(9,9),(9,2)]+ ,[(9,7),(7,4)]+ ,[(7,3),(9,4),(7,4)]+ ,[(5,3),(4,4),(6,1),(4,3)]+ ,[(4,4),(7,7)]+ ,[(7,2),(5,8),(8,1)]+ ,[(8,1),(1,10)]+ ]++-- > import Data.Function+-- > import Data.List+-- > reverse (sortBy (compare `on` snd) dr_ratio_seq_hist)+dr_ratio_seq_hist :: (Ord n,Num n) => [((n,n),Int)]+dr_ratio_seq_hist = T.histogram (concat dr_ratio_seq)++dr_nt :: Integral i => [([i],[i])]+dr_nt =+ [([1,7,8,17],[12,13,15,17])+ ,([1,6,10,17],[6,10,9])]++-- > map (T.bimap1 (map T.pitch_pp) . dr_nt_pitch) dr_nt+dr_nt_pitch :: ([Int], [Int]) -> ([T.Pitch], [T.Pitch])+dr_nt_pitch =+ let f k = T.p5_snd (dr_scale_tbl_24et !! (k - 1))+ in T.bimap1 (map f)++{-++-- from harmonic series+hs :: Num n => [(n,n)]+hs = [(1,1),(9,8),(5,4),(11,8),(3,2),(7,4)]++-- from subharmonic series+shs :: Num n => [(n,n)]+shs = [(8,7),(16,11),(8,5),(16,9)]++-}
Music/Theory/Tuning/Scala.hs view
@@ -1,38 +1,112 @@ -- | Parser for the Scala scale file format. See -- <http://www.huygens-fokker.org/scala/scl_format.html> for details.--- This module succesfully parses all 4496 scales in v.81 of the scale+-- This module succesfully parses all 4671 scales in v.85 of the scale -- library. module Music.Theory.Tuning.Scala where -import qualified Codec.Binary.UTF8.String as U {- utf8-string -}-import qualified Data.ByteString as B {- bytestring -}-import Data.List-import Data.Ratio-import qualified Music.Theory.Tuning as T+import Control.Monad {- base -}+import Data.Either {- base -}+import Data.List {- base -}+import Data.Maybe {- base -}+import Data.Ratio {- base -} import System.Directory {- directory -}+import System.Environment {- base -} import System.FilePath {- filepath -} +import qualified Music.Theory.Directory as T {- hmt -}+import qualified Music.Theory.Either as T {- hmt -}+import qualified Music.Theory.Function as T {- hmt -}+import qualified Music.Theory.IO as T {- hmt -}+import qualified Music.Theory.List as T {- hmt -}+import qualified Music.Theory.Math as T {- hmt -}+import qualified Music.Theory.Read as T {- hmt -}+import qualified Music.Theory.String as T {- hmt -}+import qualified Music.Theory.Tuning as T {- hmt -}++-- * Pitch+ -- | A @.scl@ pitch is either in 'Cents' or is a 'Ratio'. type Pitch i = Either T.Cents (Ratio i) --- | A scale has a description, a degree, and a list of 'Pitch'es.-type Scale i = (String,i,[Pitch i])+-- | An enumeration type for @.scl@ pitch classification.+data Pitch_Type = Pitch_Cents | Pitch_Ratio deriving (Eq,Show) --- | Text description of scale.+-- | A nearness value for deriving approximate rationals.+type Epsilon = Double++-- | Derive 'Pitch_Type' from 'Pitch'.+pitch_type :: Pitch i -> Pitch_Type+pitch_type = either (const Pitch_Cents) (const Pitch_Ratio)++-- | Pitch as 'T.Cents', conversion by 'T.ratio_to_cents' if necessary.+pitch_cents :: Integral i => Pitch i -> T.Cents+pitch_cents p =+ case p of+ Left c -> c+ Right r -> T.ratio_to_cents r++-- | Pitch as 'Rational', conversion by 'T.reconstructed_ratio' if+-- necessary, hence /epsilon/.+pitch_ratio :: Epsilon -> Pitch Integer -> Rational+pitch_ratio epsilon p =+ case p of+ Left c -> T.reconstructed_ratio epsilon c+ Right r -> r++-- | A pair giving the number of 'Cents' and number of 'Ratio' pitches.+pitch_representations :: Integral t => [Pitch i] -> (t,t)+pitch_representations =+ let f (l,r) p = case p of+ Left _ -> (l + 1,r)+ Right _ -> (l,r + 1)+ in foldl f (0,0)++-- | If scale is uniform, give type.+uniform_pitch_type :: [Pitch i] -> Maybe Pitch_Type+uniform_pitch_type p =+ case pitch_representations p :: (Int,Int) of+ (0,_) -> Just Pitch_Ratio+ (_,0) -> Just Pitch_Cents+ _ -> Nothing++-- | The predominant type of the pitches for 'Scale'.+pitch_type_predominant :: [Pitch i] -> Pitch_Type+pitch_type_predominant p =+ let (c,r) = pitch_representations p :: (Int,Int)+ in if c >= r then Pitch_Cents else Pitch_Ratio++-- * Scale++-- | A scale has a name, a description, a degree, and a list of 'Pitch'es.+type Scale i = (String,String,Int,[Pitch i])++-- | The name of a scale.+scale_name :: Scale i -> String+scale_name (nm,_,_,_) = nm++-- | Text description of a scale. scale_description :: Scale i -> String-scale_description (d,_,_) = d+scale_description (_,d,_,_) = d -- | The degree of the scale (number of 'Pitch'es).-scale_degree :: Scale i -> i-scale_degree (_,n,_) = n+scale_degree :: Scale i -> Int+scale_degree (_,_,n,_) = n -- | The 'Pitch'es at 'Scale'. scale_pitches :: Scale i -> [Pitch i]-scale_pitches (_,_,p) = p+scale_pitches (_,_,_,p) = p +-- | Ensure degree and number of pitches align.+scale_verify :: Scale i -> Bool+scale_verify (_,_,n,p) = n == length p++-- | Raise error if scale doesn't verify, else 'id'.+scale_verify_err :: Scale i -> Scale i+scale_verify_err scl = if scale_verify scl then scl else error "invalid scale"+ -- | The last 'Pitch' element of the scale (ie. the /ocatve/). scale_octave :: Scale i -> Maybe (Pitch i)-scale_octave (_,_,s) =+scale_octave (_,_,_,s) = case s of [] -> Nothing _ -> Just (last s)@@ -42,155 +116,269 @@ perfect_octave :: Integral i => Scale i -> Bool perfect_octave s = scale_octave s `elem` [Just (Right 2),Just (Left 1200)] --- | A pair giving the number of 'Cents' and number of 'Ratio' pitches--- at 'Scale'.-scale_pitch_representations :: (Integral t) => Scale i -> (t,t)-scale_pitch_representations s =- let f (l,r) p = case p of- Left _ -> (l + 1,r)- Right _ -> (l,r + 1)- in foldl f (0,0) (scale_pitches s)---- | Pitch as 'T.Cents', conversion by 'T.to_cents_r' if necessary.-pitch_cents :: Pitch Integer -> T.Cents-pitch_cents p =- case p of- Left c -> c- Right r -> T.ratio_to_cents r--type Epsilon = Double---- | Pitch as 'Rational', conversion by 'T.reconstructed_ratio' if--- necessary, hence /epsilon/.-pitch_ratio :: Epsilon -> Pitch Integer -> Rational-pitch_ratio epsilon p =- case p of- Left c -> T.reconstructed_ratio epsilon c- Right r -> r+-- | Are all pitches of the same type.+is_scale_uniform :: Scale i -> Bool+is_scale_uniform = isJust . uniform_pitch_type . scale_pitches -- | Make scale pitches uniform, conforming to the most promininent -- pitch type. scale_uniform :: Epsilon -> Scale Integer -> Scale Integer-scale_uniform epsilon s =- let (d,n,p) = s- (c,r) = scale_pitch_representations s :: (Int,Int)- in if c >= r- then (d,n,map (Left . pitch_cents) p)- else (d,n,map (Right . pitch_ratio epsilon) p)+scale_uniform epsilon (nm,d,n,p) =+ case pitch_type_predominant p of+ Pitch_Cents -> (nm,d,n,map (Left . pitch_cents) p)+ Pitch_Ratio -> (nm,d,n,map (Right . pitch_ratio epsilon) p) -- | Scale as list of 'T.Cents' (ie. 'pitch_cents') with @0@ prefix.-scale_cents :: Scale Integer -> [T.Cents]+scale_cents :: Integral i => Scale i -> [T.Cents] scale_cents s = 0 : map pitch_cents (scale_pitches s) +-- | 'map' 'round' of 'scale_cents'.+scale_cents_i :: Integral i => Scale i -> [i]+scale_cents_i = map round . scale_cents+ -- | Scale as list of 'Rational' (ie. 'pitch_ratio') with @1@ prefix. scale_ratios :: Epsilon -> Scale Integer -> [Rational] scale_ratios epsilon s = 1 : map (pitch_ratio epsilon) (scale_pitches s) --- | Comment lines being with @!@.-comment_p :: String -> Bool-comment_p x =+-- | Require that 'Scale' be uniformlay of 'Ratio's.+scale_ratios_req :: Integral i => Scale i -> [Ratio i]+scale_ratios_req =+ let err = error "scale_ratios_req"+ in (1 :) . map (fromMaybe err . T.fromRight) . scale_pitches++-- | Translate 'Scale' to 'T.Tuning'. If 'Scale' is uniformly+-- rational, 'T.Tuning' is rational, else 'T.Tuning' is in 'T.Cents'.+-- 'Epsilon' is used to recover the 'Rational' octave if required.+scale_to_tuning :: Epsilon -> Scale Integer -> T.Tuning+scale_to_tuning epsilon (_,_,_,p) =+ case partitionEithers p of+ ([],r) -> let (r',o) = T.separate_last r+ in T.Tuning (Left (1 : r')) o+ _ -> let (c,o) = T.separate_last p+ c' = 0 : map pitch_cents c+ o' = either (T.reconstructed_ratio epsilon) id o+ in T.Tuning (Right c') o'++-- | Convert 'T.Tuning' to 'Scale'.+--+-- > tuning_to_scale ("et12","12 tone equal temperament") (T.equal_temperament 12)+tuning_to_scale :: (String,String) -> T.Tuning -> Scale Integer+tuning_to_scale (nm,dsc) (T.Tuning p o) =+ let n = either length length p+ p' = either (map Right . tail) (map Left . tail) p ++ [Right o]+ in (nm,dsc,n,p')++{- | Are scales equal ('==') at degree and tuning data.++> db <- scl_load_db+> let r = [2187/2048,9/8,32/27,81/64,4/3,729/512,3/2,6561/4096,27/16,16/9,243/128,2/1]+> let Just py = find (scale_eq ("","",12,map Right r)) db+> scale_name py == "pyth_12"++> let c = map T.ratio_to_cents r+> let Just py' = find (scale_eqv ("","",12,map Left c)) db+> scale_name py' == "pyth_12"+-}+scale_eq :: Eq n => Scale n -> Scale n -> Bool+scale_eq (_,_,d0,p0) (_,_,d1,p1) = d0 == d1 && p0 == p1++-- | Are scales equal ('==') at degree and tuning data after 'pitch_cents'.+scale_eqv :: Integral n => Scale n -> Scale n -> Bool+scale_eqv (_,_,d0,p0) (_,_,d1,p1) =+ let f = map pitch_cents+ in d0 == d1 && f p0 == f p1++-- * Parser++-- | Comment lines begin with @!@.+is_comment :: String -> Bool+is_comment x = case x of '!':_ -> True _ -> False --- | Remove @\r@.-filter_cr :: String -> String-filter_cr = filter (not . (==) '\r')---- | Logical /or/ of list of predicates.-p_or :: [a -> Bool] -> a -> Bool-p_or p x =- case p of- [] -> False- f:p' -> f x || p_or p' x- -- | Remove to end of line @!@ comments.+--+-- > remove_eol_comments " 1 ! comment" == " 1 " remove_eol_comments :: String -> String remove_eol_comments = takeWhile (/= '!') --- | Remove comments and null lines.+-- | Remove comments and null lines and trailing comments. ----- > filter_comments ["!a","b","","c"] == ["b","c"]+-- > filter_comments ["!a","b","","c","d!e"] == ["b","c","d"] filter_comments :: [String] -> [String]-filter_comments = map remove_eol_comments .- filter (not . p_or [comment_p,null])---- | Delete trailing @.@, 'read' fails for @700.@.-delete_trailing_point :: String -> String-delete_trailing_point s =- case reverse s of- '.':s' -> reverse s'- _ -> s+filter_comments =+ map remove_eol_comments .+ filter (not . T.predicate_any [is_comment,null]) --- | Pitches are either cents (with decimal point) or ratios (with @/@).+-- | Pitches are either cents (with decimal point, possibly trailing) or ratios (with @/@). ----- > map pitch ["700.0","3/2","2"] == [Left 700,Right (3/2),Right 2]-pitch :: (Read i,Integral i) => String -> Pitch i-pitch p =+-- > map parse_pitch ["700.0","350.","3/2","2"] == [Left 700,Left 350,Right (3/2),Right 2]+parse_pitch :: (Read i,Integral i) => String -> Pitch i+parse_pitch p = if '.' `elem` p- then Left (read (delete_trailing_point p))- else case break (== '/') p of- (n,'/':d) -> Right (read n % read d)- _ -> Right (read p % 1)+ then Left (T.read_fractional_allow_trailing_point_err p)+ else Right (T.read_ratio_with_div_err p) -- | Pitch lines may contain commentary.-pitch_ln :: (Read i, Integral i) => String -> Pitch i-pitch_ln x =+parse_pitch_ln :: (Read i, Integral i) => String -> Pitch i+parse_pitch_ln x = case words x of- p:_ -> pitch p- _ -> error (show ("pitch",words x))+ p:_ -> parse_pitch p+ _ -> error (show ("parse_pitch_ln",words x)) -- | Parse @.scl@ file.-parse :: (Read i, Integral i) => String -> Scale i-parse s =- case filter_comments (lines (filter_cr s)) of- t:n:p -> (t,read n,map pitch_ln p)+parse_scl :: (Read i, Integral i) => String -> String -> Scale i+parse_scl nm s =+ case filter_comments (lines (T.filter_cr s)) of+ t:n:p -> let scl = (nm,T.delete_trailing_whitespace t,T.read_err n,map parse_pitch_ln p)+ in scale_verify_err scl _ -> error "parse" --- | Load @.scl@ file.+-- * IO++-- | Read the environment variable @SCALA_SCL_DIR@, which is a+-- sequence of directories used to locate scala files on. ----- > s <- load "/home/rohan/data/scala/81/scl/xenakis_chrom.scl"--- > scale_pitch_representations s == (6,1)--- > scale_ratios 1e-3 s == [1,21/20,29/23,179/134,280/187,11/7,100/53,2]-load :: (Read i, Integral i) => FilePath -> IO (Scale i)-load fn = do- b <- B.readFile fn- let s = U.decode (B.unpack b)- return (parse s)+-- > setEnv "SCALA_DIST_DIR" "/home/rohan/data/scala/85/scl"+scl_get_dir :: IO [String]+scl_get_dir = fmap splitSearchPath (getEnv "SCALA_SCL_DIR") --- | Subset of files in /dir/ with an extension in /ext/.-dir_subset :: [String] -> FilePath -> IO [FilePath]-dir_subset ext dir = do- let f nm = takeExtension nm `elem` ext- c <- getDirectoryContents dir- return (map (dir </>) (sort (filter f c)))+-- | Lookup the @SCALA_SCL_DIR@ environment variable, which must exist, and derive the filepath.+-- It is an error if the name has a file extension.+--+-- > mapM scl_derive_filename ["young-lm_piano","et12"]+scl_derive_filename :: FilePath -> IO FilePath+scl_derive_filename nm = do+ dir <- scl_get_dir+ when (null dir) (error "scl_derive_filename: SCALA_SCL_DIR: nil")+ when (hasExtension nm) (error "scl_derive_filename: name has extension")+ T.path_scan_err dir (nm <.> "scl") --- | Load all @.scl@ files at /dir/.+-- | If the name is an absolute file path and has a @.scl@ extension,+-- then return it, else run 'scl_derive_filename'. ----- > db <- load_dir "/home/rohan/data/scala/81/scl"--- > length db == 4496--- > length (filter ((== 0) . scale_degree) db) == 0--- > length (filter (== Just (Right 2)) (map scale_octave db)) == 3855+-- > scl_resolve_name "young-lm_piano"+-- > scl_resolve_name "/home/rohan/data/scala/85/scl/young-lm_piano.scl"+-- > scl_resolve_name "/home/rohan/data/scala/85/scl/unknown-tuning.scl"+scl_resolve_name :: String -> IO FilePath+scl_resolve_name nm =+ let ex_f x = if x then return nm else error "scl_resolve_name: file does not exist"+ in if isAbsolute nm && takeExtension nm == ".scl"+ then doesFileExist nm >>= ex_f+ else scl_derive_filename nm++-- | Load @.scl@ file, runs 'resolve_scl'. ----- > let r = [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24--- > ,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44--- > ,45,46,47,48,49,50,51,53,54,55,56,57,58,59,60,61,62,63,64--- > ,65,66,67,68,69,70,71,72,74,75,77,78,79,80,81,84,87,88--- > ,90,91,92,95,96,99,100,101,105,110,112,117,118,130,140,171--- > ,180,271,311,342,366,441,612]--- > in nub (sort (map scale_degree db)) == r+-- > s <- scl_load "xenakis_chrom"+-- > pitch_representations (scale_pitches s) == (6,1)+-- > scale_ratios 1e-3 s == [1,21/20,29/23,179/134,280/187,11/7,100/53,2]+scl_load :: (Read i, Integral i) => String -> IO (Scale i)+scl_load nm = do+ fn <- scl_resolve_name nm+ s <- T.read_file_iso_8859_1 fn+ return (parse_scl (takeBaseName nm) s)++-- | 'scale_to_tuning' of 'scl_load'.+scl_load_tuning :: Epsilon -> String -> IO T.Tuning+scl_load_tuning epsilon = fmap (scale_to_tuning epsilon) . scl_load++{- | Load all @.scl@ files at /dir/.++> dir <- scl_get_dir+> dir == ["/home/rohan/data/scala/85/scl","/home/rohan/sw/hmt/data/scl"]+> let [scl_85_dir,ext_dir] = dir+> db <- scl_load_dir scl_85_dir+> length db == 4671+> length (filter ((== 0) . scale_degree) db) == 0+> length (filter ((/= 1) . head . scale_ratios 1e-3) db) == 0+> length (filter ((/= 0) . head . scale_cents) db) == 0+> length (filter (== Just (Right 2)) (map scale_octave db)) == 4003+> length (filter is_scale_uniform db) == 2816++> let na = filter (not . T.is_ascending . scale_cents) db+> length na == 121+> mapM_ (putStrLn . unlines . scale_stat) na++> import qualified Music.Theory.List as T+> import Sound.SC3.Plot+> plot_p2_stp [T.histogram (map scale_degree db)]++> import Data.List++> let r = ["Xenakis's Byzantine Liturgical mode, 5 + 19 + 6 parts"+> ,"Xenakis's Byzantine Liturgical mode, 12 + 11 + 7 parts"+> ,"Xenakis's Byzantine Liturgical mode, 7 + 16 + 7 parts"]+> in filter (isInfixOf "Xenakis") (map scale_description db) == r++> let r = ["LaMonte Young, tuning of For Guitar '58. 1/1 March '92, inv.of Mersenne lute 1"+> ,"LaMonte Young's Well-Tuned Piano"]+> in filter (isInfixOf "LaMonte Young") (map scale_description db) == r++> length (filter (not . perfect_octave) db) == 663++-}+scl_load_dir :: (Read i, Integral i) => FilePath -> IO [Scale i]+scl_load_dir d = T.dir_subset [".scl"] d >>= mapM scl_load++-- | Load Scala data base at 'scl_get_dir'. ----- > let r = ["Xenakis's Byzantine Liturgical mode, 5 + 19 + 6 parts"--- > ,"Xenakis's Byzantine Liturgical mode, 12 + 11 + 7 parts"--- > ,"Xenakis's Byzantine Liturgical mode, 7 + 16 + 7 parts"]--- > in filter (isInfixOf "Xenakis") (map scale_description db) == r+-- > db <- scl_load_db+-- > mapM_ (putStrLn.unlines.scale_stat) (filter (not . perfect_octave) db)+scl_load_db :: (Read i, Integral i) => IO [Scale i]+scl_load_db = do+ dir <- scl_get_dir+ r <- mapM scl_load_dir dir+ return (concat r)++-- * PP++scale_stat :: (Integral i,Show i) => Scale i -> [String]+scale_stat s =+ let ty = uniform_pitch_type (scale_pitches s)+ in ["scale-name : " ++ scale_name s+ ,"scale-description : " ++ scale_description s+ ,"scale-degree : " ++ show (scale_degree s)+ ,"scale-type : " ++ maybe "non-uniform" show ty+ ,"perfect-octave : " ++ show (perfect_octave s)+ ,"scale-cents-i : " ++ show (scale_cents_i s)+ ,if ty == Just Pitch_Ratio+ then "scale-ratios : " ++ intercalate "," (map T.rational_pp (scale_ratios_req s))+ else ""]++-- | Pretty print 'Pitch' in @Scala@ format.+pitch_pp :: Show i => Pitch i -> String+pitch_pp p =+ case p of+ Left c -> show c+ Right r -> show (numerator r) ++ "/" ++ show (denominator r)++-- | Pretty print 'Scale' in @Scala@ format. ----- > length (filter (not . perfect_octave) db) == 544+-- > s <- scl_load "et19"+-- > s <- scl_load "young-lm_piano"+-- > putStr $ unlines $ scale_pp s+scale_pp :: Show i => Scale i -> [String]+scale_pp (nm,dsc,k,p) =+ ["! " ++ nm ++ ".scl"+ ,"!"+ ,dsc+ ,show k+ ,"!"] ++ map pitch_pp p++-- * DIST++-- | @scala@ distribution directory, given at @SCALA_DIST_DIR@. ----- > mapM_ (putStrLn.scale_description) (filter (not . perfect_octave) db)-load_dir :: (Read i, Integral i) => FilePath -> IO [Scale i]-load_dir d = dir_subset [".scl"] d >>= mapM load+-- > fmap (== "/home/rohan/opt/build/scala-22-pc64-linux") dist_get_dir+dist_get_dir :: IO String+dist_get_dir = getEnv "SCALA_DIST_DIR" --- Local Variables:--- truncate-lines:t--- End:+-- | Load file from 'dist_get_dir'.+--+-- > s <- load_dist_file "intnam.par"+-- > length s == 473+load_dist_file :: FilePath -> IO [String]+load_dist_file nm = do+ d <- dist_get_dir+ fmap lines (readFile (d </> nm))
+ Music/Theory/Tuning/Scala/Interval.hs view
@@ -0,0 +1,62 @@+-- | Parser for the @intnam.par@ file.+module Music.Theory.Tuning.Scala.Interval where++import Data.Char {- base -}+import Data.List {- base -}++import qualified Music.Theory.Read as T {- hmt -}+import qualified Music.Theory.Tuning.Scala as T++-- | Interval and name, ie. (3/2,"perfect fifth")+type INTERVAL = (Rational,String)++-- | Length prefixed list of 'INTERVAL'.+type INTNAM = (Int,[INTERVAL])++-- | Lookup ratio in 'INTNAM'.+--+-- > db <- load_intnam+-- > intnam_search_ratio db (3/2) == Just (3/2,"perfect fifth")+-- > intnam_search_ratio db (2/3) == Nothing+-- > intnam_search_ratio db (4/3) == Just (4/3,"perfect fourth")+-- > map (intnam_search_ratio db) [3/2,4/3,7/4,7/6,9/7,12/7,14/9]+-- > intnam_search_ratio db (31/16) == Just (31/16,"31st harmonic")+intnam_search_ratio :: INTNAM -> Rational -> Maybe INTERVAL+intnam_search_ratio (_,i) x = find ((== x) . fst) i++-- | Lookup interval name in 'INTNAM', ci = case-insensitive.+--+-- > db <- load_intnam+-- > intnam_search_description_ci db "didymus"+intnam_search_description_ci :: INTNAM -> String -> [INTERVAL]+intnam_search_description_ci (_,i) x =+ let downcase = map toLower+ x' = downcase x+ in filter (isInfixOf x' . downcase . snd) i++-- * Parser++parse_intnam_entry :: [String] -> INTERVAL+parse_intnam_entry w =+ case w of+ r:w' -> (T.read_ratio_with_div_err r,unwords w')+ _ -> error "parse_intnam_entry"++parse_intnam :: [String] -> INTNAM+parse_intnam l =+ case l of+ _:n:i -> let n' = read n :: Int+ i' = map (parse_intnam_entry . words) i+ in if n' == length i' then (n',i') else error "parse_intnam"+ _ -> error "parse_intnam"++-- * IO++-- | 'parse_intnam' of 'T.load_dist_file' of "intnam.par".+--+-- > intnam <- load_intnam+-- > fst intnam == length (snd intnam)+load_intnam :: IO INTNAM+load_intnam = do+ l <- T.load_dist_file "intnam.par"+ return (parse_intnam (T.filter_comments l))
+ Music/Theory/Tuning/Scala/Mode.hs view
@@ -0,0 +1,117 @@+-- | Parser for the @modename.par@ file.+module Music.Theory.Tuning.Scala.Mode where++import Data.Char {- base -}+import Data.List {- base -}+import Data.Maybe {- base -}++import qualified Music.Theory.Function as T+import qualified Music.Theory.List as T+import qualified Music.Theory.Tuning.Scala as T++-- | (start-degree,intervals,description)+type MODE = (Int,[Int],String)++mode_starting_degree :: MODE -> Int+mode_starting_degree (d,_,_) = d++mode_intervals :: MODE -> [Int]+mode_intervals (_,i,_) = i++mode_description :: MODE -> String+mode_description (_,_,d) = d++mode_degree :: MODE -> Int+mode_degree = sum . mode_intervals++-- | (mode-count,_,mode-list)+type MODENAM = (Int,Int,[MODE])++modenam_modes :: MODENAM -> [MODE]+modenam_modes (_,_,m) = m++-- | Search for mode by interval list.+modenam_search_seq :: MODENAM -> [Int] -> [MODE]+modenam_search_seq (_,_,m) x = filter ((== x) . mode_intervals) m++-- | Expect /one/ result.+--+-- > mn <- load_modenam+-- > let sq = putStrLn . unlines . mode_stat . fromJust . modenam_search_seq1 mn+-- > sq [2,2,1,2,2,2,1]+-- > sq [2,1,2,2,1,2,2]+-- > sq [2,1,2,2,1,3,1]+-- > sq (replicate 6 2)+-- > sq [1,2,1,2,1,2,1,2]+-- > sq [2,1,2,1,2,1,2,1]+-- > sq (replicate 12 1)+modenam_search_seq1 :: MODENAM -> [Int] -> Maybe MODE+modenam_search_seq1 mn = T.unlist1 . modenam_search_seq mn++-- | Search for mode by description text.+--+-- > map (modenam_search_description mn) ["Messiaen","Xenakis","Raga"]+modenam_search_description :: MODENAM -> String -> [MODE]+modenam_search_description (_,_,m) x = filter (isInfixOf x . mode_description) m++-- | Pretty printer.+mode_stat :: MODE -> [String]+mode_stat (d,i,s) =+ ["mode-start-degree : " ++ show d+ ,"mode-intervals : " ++ intercalate "," (map show i)+ ,"mode-degree : " ++ show (sum i)+ ,"mode-description : " ++ s]++-- * Parser++-- | Bracketed integers are a non-implicit starting degree.+--+-- > map non_implicit_degree ["4","[4]"] == [Nothing,Just 4]+non_implicit_degree :: String -> Maybe Int+non_implicit_degree s =+ case T.unbracket s of+ Just ('[',s',']') -> Just (read s')+ _ -> Nothing++is_non_implicit_degree :: String -> Bool+is_non_implicit_degree = isJust . non_implicit_degree++is_integer :: String -> Bool+is_integer = all isDigit++parse_modenam_entry :: [String] -> MODE+parse_modenam_entry w =+ let (n0:n,c) = span (T.predicate_or is_non_implicit_degree is_integer) w+ in case non_implicit_degree n0 of+ Nothing -> (0,map read (n0:n),unwords c)+ Just d -> (d,map read n,unwords c)++-- | Lines ending with @\@ continue to next line.+join_long_lines :: [String] -> [String]+join_long_lines l =+ case l of+ p:q:l' -> case T.separate_last' p of+ (p',Just '\\') -> join_long_lines ((p' ++ q) : l')+ _ -> p : join_long_lines (q : l')+ _ -> l++parse_modenam :: [String] -> MODENAM+parse_modenam l =+ case l of+ n:x:m -> let n' = read n :: Int+ x' = read x :: Int+ m' = map (parse_modenam_entry . words) m+ in if n' == length m' then (n',x',m') else error "parse_modenam"+ _ -> error "parse_modenam"++-- * IO++-- | 'parse_modenam' of 'T.load_dist_file' of @modenam.par@.+--+-- > mn <- load_modenam+-- > let (n,x,m) = mn+-- > n == 2125 && x == 15 && length m == n+load_modenam :: IO MODENAM+load_modenam = do+ l <- T.load_dist_file "modenam.par"+ return (parse_modenam (T.filter_comments (join_long_lines l)))
+ Music/Theory/Tuning/Sethares_1994.hs view
@@ -0,0 +1,39 @@+-- | William A. Sethares.+-- "Adaptive Tunings for Musical Scales".+-- /Journal of the Acoustical Society of America/, 96(1), July 1994.+--+-- <http://sethares.engr.wisc.edu/consemi.html>+module Music.Theory.Tuning.Sethares_1994 where++import qualified Music.Theory.Tuning as T++-- > import Sound.SC3.Plot+-- > plotTable1 (map (\f -> d (220,1) (f,1)) [220 .. 440])+d :: (Floating n, Ord n) => (n,n) -> (n,n) -> n+d (f1,v1) (f2,v2) =+ let d_star = 0.24+ s1 = 0.0207+ s2 = 18.96+ c1 = 5+ c2 = -5+ a1 = -3.51+ a2 = -5.75+ s = d_star / (s1 * min f1 f2 + s2)+ f_dif = abs (f2 - f1)+ e1 = c1 * exp (a1 * s * f_dif)+ e2 = c2 * exp (a2 * s * f_dif)+ in v1 * v2 * (e1 + e2)++-- > plotTable fig_1+fig_1 :: (Floating n,Enum n,Ord n) => [[n]]+fig_1 =+ let f0 = [125,250,500,1000,2000]+ r_seq = map T.cents_to_ratio [0 .. 1200]+ in map (\f -> map (\r -> d (f,1) (f * r,1)) r_seq) f0++-- > let a_seq = take 7 (iterate (* 0.88) 1.0)+-- > let gen f0 = zipWith (\r a -> (f0 * r,a)) [1 .. 7] a_seq+-- > let r_seq = map T.cents_to_ratio [0,1 .. 1200]+-- > plotTable1 (let f0 = 880 in map (\r -> d_h (gen f0) (gen (f0 * r))) r_seq)+d_h :: (Floating n, Ord n) => [(n,n)] -> [(n,n)] -> n+d_h s1 s2 = sum [d p q | p <- s1, q <- s2]
− Music/Theory/Tuning/Werckmeister.hs
@@ -1,105 +0,0 @@--- | Andreas Werckmeister (1645-1706).-module Music.Theory.Tuning.Werckmeister where--import Music.Theory.Tuning {- hmt -}---- | Approximate ratios for 'werckmeister_iii'.------ > let c = [0,90,192,294,390,498,588,696,792,888,996,1092]--- > in map (round . ratio_to_cents) werckmeister_iii_ar == c-werckmeister_iii_ar :: [Approximate_Ratio]-werckmeister_iii_ar =- let c0 = 2 ** (1/2)- c1 = 2 ** (1/4)- c2 = 8 ** (1/4)- in [1,256/243- ,64/81 * c0,32/27- ,256/243 * c1- ,4/3,1024/729- ,8/9 * c2,128/81- ,1024/729 * c1,16/9- ,128/81 * c1]---- | Cents for 'werckmeister_iii'.-werckmeister_iii_ar_c :: [Cents]-werckmeister_iii_ar_c = map approximate_ratio_to_cents werckmeister_iii_ar---- | Werckmeister III, Andreas Werckmeister (1645-1706)------ > cents_i werckmeister_iii == [0,90,192,294,390,498,588,696,792,888,996,1092]-werckmeister_iii :: Tuning-werckmeister_iii = Tuning (Right werckmeister_iii_ar_c) 2---- | Approximate ratios for 'werckmeister_iv'.------ > let c = [0,82,196,294,392,498,588,694,784,890,1004,1086]--- > in map (round . ratio_to_cents) werckmeister_iv_ar == c-werckmeister_iv_ar :: [Approximate_Ratio]-werckmeister_iv_ar =- let c0 = 2 ** (1/3)- c1 = 4 ** (1/3)- in [1,16384/19683 * c0- ,8/9 * c0,32/27- ,64/81 * c1- ,4/3,1024/729- ,32/27 * c0,8192/6561 * c0- ,256/243 * c1,9/(4*c0)- ,4096/2187]---- | Cents for 'werckmeister_iv'.-werckmeister_iv_c :: [Cents]-werckmeister_iv_c = map approximate_ratio_to_cents werckmeister_iv_ar---- | Werckmeister IV, Andreas Werckmeister (1645-1706)------ > cents_i werckmeister_iv == [0,82,196,294,392,498,588,694,784,890,1004,1086]-werckmeister_iv :: Tuning-werckmeister_iv = Tuning (Right werckmeister_iv_c) 2---- | Approximate ratios for 'werckmeister_v'.------ > let c = [0,96,204,300,396,504,600,702,792,900,1002,1098]--- > in map (round . ratio_to_cents) werckmeister_v_ar == c-werckmeister_v_ar :: [Approximate_Ratio]-werckmeister_v_ar =- let c0 = 2 ** (1/4)- c1 = 2 ** (1/2)- c2 = 8 ** (1/4)- in [1,8/9 * c0- ,9/8,c0- ,8/9 * c1- ,9/8 * c0,c1- ,3/2,128/81- ,c2,3/c2- ,4/3 * c1]---- | Cents for 'werckmeister_v'.-werckmeister_v_c :: [Cents]-werckmeister_v_c = map approximate_ratio_to_cents werckmeister_v_ar---- | Werckmeister V, Andreas Werckmeister (1645-1706)------ > cents_i werckmeister_v == [0,96,204,300,396,504,600,702,792,900,1002,1098]-werckmeister_v :: Tuning-werckmeister_v = Tuning (Right werckmeister_v_c) 2---- | Ratios for 'werckmeister_vi'.------ > let c = [0,91,196,298,395,498,595,698,793,893,1000,1097]--- > in map (round . ratio_to_cents) werckmeister_vi_r == c-werckmeister_vi_r :: [Rational]-werckmeister_vi_r =- [1,98/93- ,28/25,196/165- ,49/39- ,4/3,196/139- ,196/131,49/31- ,196/117,98/55- ,49/26]---- | Werckmeister VI, Andreas Werckmeister (1645-1706)------ > cents_i werckmeister_vi == [0,91,196,298,395,498,595,698,793,893,1000,1097]-werckmeister_vi :: Tuning-werckmeister_vi = Tuning (Left werckmeister_vi_r) 2-
Music/Theory/Tuple.hs view
@@ -6,9 +6,7 @@ -- Heterogenous tuples (products) are prefixed @p2_@ etc. module Music.Theory.Tuple where -import Data.Monoid {- base -}---- * P2 (2 product)+-- * P2 (2-product) p2_swap :: (s,t) -> (t,s) p2_swap (i,j) = (j,i)@@ -18,11 +16,11 @@ -- | Uniform two-tuple. type T2 a = (a,a) -t2 :: [t] -> T2 t-t2 l = case l of {[p,q] -> (p,q);_ -> error "t2"}+t2_from_list :: [t] -> T2 t+t2_from_list l = case l of {[p,q] -> (p,q);_ -> error "t2_from_list"} -t2_list :: T2 a -> [a]-t2_list (i,j) = [i,j]+t2_to_list :: T2 a -> [a]+t2_to_list (i,j) = [i,j] t2_swap :: T2 t -> T2 t t2_swap = p2_swap@@ -48,7 +46,7 @@ t2_sort :: Ord t => (t,t) -> (t,t) t2_sort (p,q) = (min p q,max p q) --- * P3 (3 product)+-- * P3 (3-product) -- | Left rotation. --@@ -69,9 +67,12 @@ type T3 a = (a,a,a) -t3 :: [t] -> T3 t-t3 l = case l of {[p,q,r] -> (p,q,r);_ -> error "t3"}+t3_from_list :: [t] -> T3 t+t3_from_list l = case l of {[p,q,r] -> (p,q,r);_ -> error "t3_from_list"} +t3_to_list :: T3 a -> [a]+t3_to_list (i,j,k) = [i,j,k]+ t3_rotate_left :: T3 t -> T3 t t3_rotate_left = p3_rotate_left @@ -89,8 +90,6 @@ t3_zipWith :: (p -> q -> r) -> T3 p -> T3 q -> T3 r t3_zipWith f (p,q,r) (p',q',r') = (f p p',f q q',f r r')-t3_list :: T3 a -> [a]-t3_list (i,j,k) = [i,j,k] t3_infix :: (a -> a -> a) -> T3 a -> a t3_infix f (i,j,k) = (i `f` j) `f` k@@ -98,7 +97,7 @@ t3_join :: T3 [a] -> [a] t3_join = t3_infix (++) --- * P4 (4 product)+-- * P4 (4-product) p4_fst :: (a,b,c,d) -> a p4_fst (a,_,_,_) = a@@ -116,11 +115,11 @@ type T4 a = (a,a,a,a) -t4 :: [t] -> T4 t-t4 l = case l of {[p,q,r,s] -> (p,q,r,s); _ -> error "t4"}+t4_from_list :: [t] -> T4 t+t4_from_list l = case l of {[p,q,r,s] -> (p,q,r,s); _ -> error "t4_from_list"} -t4_list :: T4 t -> [t]-t4_list (p,q,r,s) = [p,q,r,s]+t4_to_list :: T4 t -> [t]+t4_to_list (p,q,r,s) = [p,q,r,s] t4_fst :: T4 t -> t t4_fst = p4_fst@@ -146,7 +145,7 @@ t4_join :: T4 [a] -> [a] t4_join = t4_infix (++) --- * P5 (5 product)+-- * P5 (5-product) p5_fst :: (a,b,c,d,e) -> a p5_fst (a,_,_,_,_) = a@@ -163,15 +162,25 @@ p5_fifth :: (a,b,c,d,e) -> e p5_fifth (_,_,_,_,e) = e +p5_from_list :: (t -> t1, t -> t2, t -> t3, t -> t4, t -> t5) -> [t] -> (t1,t2,t3,t4,t5)+p5_from_list (f1,f2,f3,f4,f5) l =+ case l of+ [c1,c2,c3,c4,c5] -> (f1 c1,f2 c2,f3 c3,f4 c4,f5 c5)+ _ -> error "p5_from_list"+++p5_to_list :: (t1 -> t, t2 -> t, t3 -> t, t4 -> t, t5 -> t) -> (t1, t2, t3, t4, t5) -> [t]+p5_to_list (f1,f2,f3,f4,f5) (c1,c2,c3,c4,c5) = [f1 c1,f2 c2,f3 c3,f4 c4,f5 c5]+ -- * T5 (5-tuple, regular) type T5 a = (a,a,a,a,a) -t5 :: [t] -> T5 t-t5 l = case l of {[p,q,r,s,t] -> (p,q,r,s,t); _ -> error "t5"}+t5_from_list :: [t] -> T5 t+t5_from_list l = case l of {[p,q,r,s,t] -> (p,q,r,s,t); _ -> error "t5_from_list"} -t5_list :: T5 t -> [t]-t5_list (p,q,r,s,t) = [p,q,r,s,t]+t5_to_list :: T5 t -> [t]+t5_to_list (p,q,r,s,t) = [p,q,r,s,t] t5_map :: (p -> q) -> T5 p -> T5 q t5_map f (p,q,r,s,t) = (f p,f q,f r,f s,f t)@@ -194,7 +203,7 @@ t5_join :: T5 [a] -> [a] t5_join = t5_infix (++) --- * P6 (6 product)+-- * P6 (6-product) p6_fst :: (a,b,c,d,e,f) -> a p6_fst (a,_,_,_,_,_) = a@@ -218,11 +227,11 @@ type T6 a = (a,a,a,a,a,a) -t6 :: [t] -> T6 t-t6 l = case l of {[p,q,r,s,t,u] -> (p,q,r,s,t,u);_ -> error "t6"}+t6_from_list :: [t] -> T6 t+t6_from_list l = case l of {[p,q,r,s,t,u] -> (p,q,r,s,t,u);_ -> error "t6_from_list"} -t6_list :: T6 t -> [t]-t6_list (p,q,r,s,t,u) = [p,q,r,s,t,u]+t6_to_list :: T6 t -> [t]+t6_to_list (p,q,r,s,t,u) = [p,q,r,s,t,u] t6_map :: (p -> q) -> T6 p -> T6 q t6_map f (p,q,r,s,t,u) = (f p,f q,f r,f s,f t,f u)@@ -231,8 +240,8 @@ type T7 a = (a,a,a,a,a,a,a) -t7_list :: T7 t -> [t]-t7_list (p,q,r,s,t,u,v) = [p,q,r,s,t,u,v]+t7_to_list :: T7 t -> [t]+t7_to_list (p,q,r,s,t,u,v) = [p,q,r,s,t,u,v] t7_map :: (p -> q) -> T7 p -> T7 q t7_map f (p,q,r,s,t,u,v) = (f p,f q,f r,f s,f t,f u,f v)@@ -241,18 +250,70 @@ type T8 a = (a,a,a,a,a,a,a,a) -t8_list :: T8 t -> [t]-t8_list (p,q,r,s,t,u,v,w) = [p,q,r,s,t,u,v,w]+t8_to_list :: T8 t -> [t]+t8_to_list (p,q,r,s,t,u,v,w) = [p,q,r,s,t,u,v,w] t8_map :: (p -> q) -> T8 p -> T8 q t8_map f (p,q,r,s,t,u,v,w) = (f p,f q,f r,f s,f t,f u,f v,f w) +-- * P8 (8-product)++p8_third :: (a,b,c,d,e,f,g,h) -> c+p8_third (_,_,c,_,_,_,_,_) = c+ -- * T9 (9-tuple, regular) type T9 a = (a,a,a,a,a,a,a,a,a) -t9_list :: T9 t -> [t]-t9_list (p,q,r,s,t,u,v,w,x) = [p,q,r,s,t,u,v,w,x]+t9_to_list :: T9 t -> [t]+t9_to_list (p,q,r,s,t,u,v,w,x) = [p,q,r,s,t,u,v,w,x] t9_map :: (p -> q) -> T9 p -> T9 q t9_map f (p,q,r,s,t,u,v,w,x) = (f p,f q,f r,f s,f t,f u,f v,f w,f x)++-- * T10 (10-tuple, regular)++type T10 a = (a,a,a,a,a,a,a,a,a,a)++t10_to_list :: T10 t -> [t]+t10_to_list (p,q,r,s,t,u,v,w,x,y) = [p,q,r,s,t,u,v,w,x,y]++t10_map :: (p -> q) -> T10 p -> T10 q+t10_map f (p,q,r,s,t,u,v,w,x,y) = (f p,f q,f r,f s,f t,f u,f v,f w,f x,f y)++-- * T11 (11-tuple, regular)++type T11 a = (a,a,a,a,a,a,a,a,a,a,a)++t11_to_list :: T11 t -> [t]+t11_to_list (p,q,r,s,t,u,v,w,x,y,z) = [p,q,r,s,t,u,v,w,x,y,z]++t11_map :: (p -> q) -> T11 p -> T11 q+t11_map f (p,q,r,s,t,u,v,w,x,y,z) = (f p,f q,f r,f s,f t,f u,f v,f w,f x,f y,f z)++-- * T12 (12-tuple, regular)++type T12 t = (t,t,t,t,t,t,t,t,t,t,t,t)++t12_to_list :: T12 t -> [t]+t12_to_list (p,q,r,s,t,u,v,w,x,y,z,a) = [p,q,r,s,t,u,v,w,x,y,z,a]++t12_from_list :: [t] -> T12 t+t12_from_list l =+ case l of+ [p,q,r,s,t,u,v,w,x,y,z,a] -> (p,q,r,s,t,u,v,w,x,y,z,a)+ _ -> error "t12_from_list"++-- | 'foldr1' of 't12_to_list'.+--+-- > t12_foldr1 (+) (1,2,3,4,5,6,7,8,9,10,11,12) == 78+t12_foldr1 :: (t -> t -> t) -> T12 t -> t+t12_foldr1 f = foldr1 f . t12_to_list++-- | 'sum' of 't12_to_list'.+--+-- > t12_sum (1,2,3,4,5,6,7,8,9,10,11,12) == 78+t12_sum :: Num n => T12 n -> n+t12_sum t =+ let (n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12) = t+ in n1 + n2 + n3 + n4 + n5 + n6 + n7 + n8 + n9 + n10 + n11 + n12
Music/Theory/Unicode.hs view
@@ -1,15 +1,56 @@ -- | <http://www.unicode.org/charts/PDF/U1D100.pdf>+--+-- These symbols are in <http://www.gnu.org/software/freefont/>,+-- debian=ttf-freefont. module Music.Theory.Unicode where -type Unicode_Table = [(Int,String)]+import Data.List {- base -}+import Numeric {- base -} --- > putStrLn (map (toEnum . fst) (concat unicode))+import qualified Text.CSV.Lazy.String as C {- lazy-csv -}++import qualified Music.Theory.IO as T {- hmt -}+import qualified Music.Theory.List as T {- hmt -}+import qualified Music.Theory.Read as T {- hmt -}++-- * Non-music++-- | Unicode non breaking hypen character.+--+-- > non_breaking_hypen == '‑'+non_breaking_hypen :: Char+non_breaking_hypen = toEnum 0x2011++-- | Unicode non breaking space character.+--+-- > non_breaking_space == ' '+non_breaking_space :: Char+non_breaking_space = toEnum 0x00A0++-- * Music++type Unicode_Index = Int+type Unicode_Range = (Unicode_Index,Unicode_Index)+type Unicode_Point = (Unicode_Index,String)+type Unicode_Table = [Unicode_Point]++-- > putStrLn$ map (toEnum . fst) (concat unicode) unicode :: [Unicode_Table] unicode = [accidentals,notes,rests,clefs] +-- > putStrLn$ concatMap (unicode_table_hs . flip unicode_table_block tbl) accidentals_rng_set+accidentals_rng_set :: [Unicode_Range]+accidentals_rng_set = [(0x266D,0x266F),(0x1D12A,0x1D133)]++-- | UNICODE accidental symbols.+--+-- > let r = "♭♮♯𝄪𝄫𝄬𝄭𝄮𝄯𝄰𝄱𝄲𝄳" in map (toEnum . fst) accidentals == r accidentals :: Unicode_Table accidentals =- [(0x1D12A,"MUSICAL SYMBOL DOUBLE SHARP")+ [(0x266D,"MUSIC FLAT SIGN")+ ,(0x266E,"MUSIC NATURAL SIGN")+ ,(0x266F,"MUSIC SHARP SIGN")+ ,(0x1D12A,"MUSICAL SYMBOL DOUBLE SHARP") ,(0x1D12B,"MUSICAL SYMBOL DOUBLE FLAT") ,(0x1D12C,"MUSICAL SYMBOL FLAT UP") ,(0x1D12D,"MUSICAL SYMBOL FLAT DOWN")@@ -20,6 +61,13 @@ ,(0x1D132,"MUSICAL SYMBOL QUARTER TONE SHARP") ,(0x1D133,"MUSICAL SYMBOL QUARTER TONE FLAT")] +-- > putStrLn$ unicode_table_hs (unicode_table_block notes_rng tbl)+notes_rng :: Unicode_Range+notes_rng = (0x1D15C,0x1D164)++-- | UNICODE note duration symbols.+--+-- > let r = "𝅜𝅝𝅗𝅥𝅘𝅥𝅘𝅥𝅮𝅘𝅥𝅯𝅘𝅥𝅰𝅘𝅥𝅱𝅘𝅥𝅲" in map (toEnum . fst) notes == r notes :: Unicode_Table notes = [(0x1D15C,"MUSICAL SYMBOL BREVE")@@ -32,6 +80,13 @@ ,(0x1D163,"MUSICAL SYMBOL SIXTY-FOURTH NOTE") ,(0x1D164,"MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE")] +-- > putStrLn$ unicode_table_hs (unicode_table_block rests_rng tbl)+rests_rng :: Unicode_Range+rests_rng = (0x1D13B,0x1D142)++-- | UNICODE rest symbols.+--+-- > let r = "𝄻𝄼𝄽𝄾𝄿𝅀𝅁𝅂" in map (toEnum . fst) rests == r rests :: Unicode_Table rests = [(0x1D13B,"MUSICAL SYMBOL WHOLE REST")@@ -43,6 +98,17 @@ ,(0x1D141,"MUSICAL SYMBOL SIXTY-FOURTH REST") ,(0x1D142,"MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH REST")] +-- > map toEnum [0x1D15E,0x1D16D,0x1D16D] == "𝅗𝅥𝅭𝅭"+augmentation_dot :: Unicode_Point+augmentation_dot = (0x1D16D, "MUSICAL SYMBOL COMBINING AUGMENTATION DOT")++-- > putStrLn$ unicode_table_hs (unicode_table_block clefs_rng tbl)+clefs_rng :: Unicode_Range+clefs_rng = (0x1D11E,0x1D126)++-- | UNICODE clef symbols.+--+-- > let r = "𝄞𝄟𝄠𝄡𝄢𝄣𝄤𝄥𝄦" in map (toEnum . fst) clefs == r clefs :: Unicode_Table clefs = [(0x1D11E,"MUSICAL SYMBOL G CLEF")@@ -54,3 +120,120 @@ ,(0x1D124,"MUSICAL SYMBOL F CLEF OTTAVA BASSA") ,(0x1D125,"MUSICAL SYMBOL DRUM CLEF-1") ,(0x1D126,"MUSICAL SYMBOL DRUM CLEF-2")]++-- > putStrLn$ unicode_table_hs (unicode_table_block tbl notehead_rng)+notehead_rng :: Unicode_Range+notehead_rng = (0x1D143,0x1D15B)++-- | UNICODE notehead symbols.+--+-- > let r = "𝅃𝅄𝅅𝅆𝅇𝅈𝅉𝅊𝅋𝅌𝅍𝅎𝅏𝅐𝅑𝅒𝅓𝅔𝅕𝅖𝅗𝅘𝅙𝅚𝅛" in map (toEnum . fst) noteheads == r+noteheads :: Unicode_Table+noteheads =+ [(0x1d143,"MUSICAL SYMBOL X NOTEHEAD")+ ,(0x1d144,"MUSICAL SYMBOL PLUS NOTEHEAD")+ ,(0x1d145,"MUSICAL SYMBOL CIRCLE X NOTEHEAD")+ ,(0x1d146,"MUSICAL SYMBOL SQUARE NOTEHEAD WHITE")+ ,(0x1d147,"MUSICAL SYMBOL SQUARE NOTEHEAD BLACK")+ ,(0x1d148,"MUSICAL SYMBOL TRIANGLE NOTEHEAD UP WHITE")+ ,(0x1d149,"MUSICAL SYMBOL TRIANGLE NOTEHEAD UP BLACK")+ ,(0x1d14a,"MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT WHITE")+ ,(0x1d14b,"MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT BLACK")+ ,(0x1d14c,"MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT WHITE")+ ,(0x1d14d,"MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT BLACK")+ ,(0x1d14e,"MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN WHITE")+ ,(0x1d14f,"MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN BLACK")+ ,(0x1d150,"MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT WHITE")+ ,(0x1d151,"MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT BLACK")+ ,(0x1d152,"MUSICAL SYMBOL MOON NOTEHEAD WHITE")+ ,(0x1d153,"MUSICAL SYMBOL MOON NOTEHEAD BLACK")+ ,(0x1d154,"MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN WHITE")+ ,(0x1d155,"MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN BLACK")+ ,(0x1d156,"MUSICAL SYMBOL PARENTHESIS NOTEHEAD")+ ,(0x1d157,"MUSICAL SYMBOL VOID NOTEHEAD")+ ,(0x1d158,"MUSICAL SYMBOL NOTEHEAD BLACK")+ ,(0x1d159,"MUSICAL SYMBOL NULL NOTEHEAD")+ ,(0x1d15a,"MUSICAL SYMBOL CLUSTER NOTEHEAD WHITE")+ ,(0x1d15b,"MUSICAL SYMBOL CLUSTER NOTEHEAD BLACK")]++-- > map toEnum [0x1D143,0x1D165] == "𝅃𝅥"+stem :: Unicode_Point+stem = (0x1D165, "MUSICAL SYMBOL COMBINING STEM")++-- > putStrLn$ unicode_table_hs (unicode_table_block dynamics_rng tbl)+dynamics_rng :: Unicode_Range+dynamics_rng = (0x1D18C,0x1D193)++-- > map (toEnum . fst) dynamics == "𝆌𝆍𝆎𝆏𝆐𝆑𝆒𝆓"+dynamics :: Unicode_Table+dynamics =+ [(0x1d18c,"MUSICAL SYMBOL RINFORZANDO")+ ,(0x1d18d,"MUSICAL SYMBOL SUBITO")+ ,(0x1d18e,"MUSICAL SYMBOL Z")+ ,(0x1d18f,"MUSICAL SYMBOL PIANO")+ ,(0x1d190,"MUSICAL SYMBOL MEZZO")+ ,(0x1d191,"MUSICAL SYMBOL FORTE")+ ,(0x1d192,"MUSICAL SYMBOL CRESCENDO")+ ,(0x1d193,"MUSICAL SYMBOL DECRESCENDO")]++-- > putStrLn$ unicode_table_hs (unicode_table_block articulations_rng tbl)+articulations_rng :: Unicode_Range+articulations_rng = (0x1D17B,0x1D18B)++-- > putStrLn (map (toEnum . fst) articulations :: String)+articulations :: Unicode_Table+articulations =+ [(0x1d17b,"MUSICAL SYMBOL COMBINING ACCENT")+ ,(0x1d17c,"MUSICAL SYMBOL COMBINING STACCATO")+ ,(0x1d17d,"MUSICAL SYMBOL COMBINING TENUTO")+ ,(0x1d17e,"MUSICAL SYMBOL COMBINING STACCATISSIMO")+ ,(0x1d17f,"MUSICAL SYMBOL COMBINING MARCATO")+ ,(0x1d180,"MUSICAL SYMBOL COMBINING MARCATO-STACCATO")+ ,(0x1d181,"MUSICAL SYMBOL COMBINING ACCENT-STACCATO")+ ,(0x1d182,"MUSICAL SYMBOL COMBINING LOURE")+ ,(0x1d183,"MUSICAL SYMBOL ARPEGGIATO UP")+ ,(0x1d184,"MUSICAL SYMBOL ARPEGGIATO DOWN")+ ,(0x1d185,"MUSICAL SYMBOL COMBINING DOIT")+ ,(0x1d186,"MUSICAL SYMBOL COMBINING RIP")+ ,(0x1d187,"MUSICAL SYMBOL COMBINING FLIP")+ ,(0x1d188,"MUSICAL SYMBOL COMBINING SMEAR")+ ,(0x1d189,"MUSICAL SYMBOL COMBINING BEND")+ ,(0x1d18a,"MUSICAL SYMBOL COMBINING DOUBLE TONGUE")+ ,(0x1d18b,"MUSICAL SYMBOL COMBINING TRIPLE TONGUE")]++-- * Blocks++type Unicode_Block = (Unicode_Range,String)++-- > putStrLn$ unicode_table_hs (concatMap (flip unicode_table_block tbl . fst) unicode_blocks)+unicode_blocks :: [Unicode_Block]+unicode_blocks =+ [((0x1B00,0x1B7F),"Balinese")+ ,((0x2200,0x22FF),"Mathematical Operators")+ ,((0x25A0,0x25FF),"Geometric Shapes")+ ,((0x1D000,0x1D0FF),"Byzantine Musical Symbols")+ ,((0x1D100,0x1D1FF),"Musical Symbols")+ ,((0x1D200,0x1D24F),"Ancient Greek Musical Notation")]++-- * Table++-- | <http://unicode.org/Public/8.0.0/ucd/UnicodeData.txt>+--+-- > let fn = "/home/rohan/data/unicode.org/Public/8.0.0/ucd/UnicodeData.txt"+-- > tbl <- unicode_data_table_read fn+-- > length tbl == 29215+unicode_data_table_read :: FilePath -> IO Unicode_Table+unicode_data_table_read fn = do+ s <- T.read_file_utf8 fn+ let t = C.fromCSVTable (C.csvTable (C.parseDSV False ';' s))+ f x = (T.read_hex_err (x !! 0),x !! 1)+ return (map f t)++unicode_table_block :: (Int,Int) -> Unicode_Table -> Unicode_Table+unicode_table_block (l,r) = takeWhile ((<= r) . fst) . dropWhile ((< l) . fst)++unicode_point_hs :: Unicode_Point -> String+unicode_point_hs (n,s) = concat ["(0x",showHex n "",",\"",s,"\")"]++unicode_table_hs :: Unicode_Table -> String+unicode_table_hs = T.bracket ('[',']') . intercalate "," . map unicode_point_hs
+ Music/Theory/Wyschnegradsky.hs view
@@ -0,0 +1,331 @@+-- | <http://www.ivan-wyschnegradsky.fr/en/chromatic-drawings/>+module Music.Theory.Wyschnegradsky where++import Data.Char {- base -}+import Data.List {- list -}+import Data.List.Split {- split -}+import Data.Maybe {- base -}++import Music.Theory.List {- hmt -}+import Music.Theory.Pitch {- hmt -}+import Music.Theory.Pitch.Spelling.Table {- hmt -}++-- | In a modulo /m/ system, normalise step increments to be either -1+-- or 1. Non steps raise an error.+--+-- > map (normalise_step 6) [-5,-1,1,5] == [1,-1,1,-1]+normalise_step :: (Eq n,Num n) => n -> n -> n+normalise_step m n+ | n == 1 = 1+ | n == -1 = -1+ | n == m - 1 = -1+ | n == 1 - m = 1+ | otherwise = error "normalise_step"++-- | Wyschnegradsky writes the direction sign at the end of the number.+--+-- > map parse_num_sign ["2+","4-"] == [2,-4]+parse_num_sign :: (Num n, Read n) => String -> n+parse_num_sign s =+ case separate_last s of+ (n,'+') -> read n+ (n,'-') -> negate (read n)+ _ -> error "parse_num_sign"++-- | Expand a chromatic (step-wise) sequence, sign indicates direction.+--+-- > map vec_expand [2,-4] == [[1,1],[-1,-1,-1,-1]]+vec_expand :: Num n => Int -> [n]+vec_expand n = if n > 0 then replicate n 1 else replicate (abs n) (-1)++-- | Parse the vector notation used in some drawings, a comma+-- separated list of chromatic sequences.+--+-- > parse_vec Nothing 0 "4-,4+,4-,4+,4-,4+,4-,4+,4-"+-- > parse_vec Nothing 0 "2+,2-,2+,2-,2+,2-,2+,2-,2+,18+"+parse_vec :: Num n => Maybe Int -> n -> String -> [n]+parse_vec n m =+ let f = case n of+ Just i -> dx_d m . take i . cycle+ Nothing -> dx_d m+ in dropRight 1 . f . concatMap (vec_expand . parse_num_sign) . splitOn ","++-- | Modulo addition.+add_m :: Integral a => a -> a -> a -> a+add_m n p q = (p + q) `mod` n++-- | Parse hex colour string, as standard in HTML5.+--+-- > parse_hex_clr "#e14630" == (225,70,48)+parse_hex_clr :: (Read n,Num n) => String -> (n,n,n)+parse_hex_clr clr =+ let f p q = read ("0x" ++ [p,q])+ in case clr of+ ['#',p,q,r,s,t,u] -> (f p q,f r s,f t u)+ _ -> error "parse_hex"++-- | Type specialised.+parse_hex_clr_int :: String -> (Int,Int,Int)+parse_hex_clr_int = parse_hex_clr++-- | Normalise colour by dividing each component by /m/.+--+-- > clr_normalise 255 (parse_hex_clr "#ff0066") == (1,0,0.4)+clr_normalise :: (Real r,Fractional f) => f -> (r,r,r) -> (f,f,f)+clr_normalise m (r,g,b) = let f x = realToFrac x / m in (f r,f g,f b)++-- | Sequences are either in 'Radial' or 'Circumferential' order.+data Seq a = Radial [a] | Circumferential [a]++-- | Group sequence into normal (ie. 'Circumferential') order given+-- drawing dimensions.+seq_group :: Int -> Int -> Seq a -> [[a]]+seq_group c_div r_div s =+ case s of+ Circumferential c -> chunksOf c_div c+ Radial r -> transpose (chunksOf r_div r)++-- | Printer for pitch-class segments.+iw_pc_pp :: Integral n => String -> [[n]] -> IO ()+iw_pc_pp sep =+ let f = pitch_pp_opt (False,False) . octpc_to_pitch pc_spell_ks . (,) 4+ in putStrLn . intercalate sep . map (unwords . map f)++-- * U3++-- | Index to colour name abbreviation.+--+-- > map u3_ix_ch [0..5] == "ROYGBV"+u3_ix_ch :: Integral i => i -> Char+u3_ix_ch = genericIndex "ROYGBV" . (`mod` 6)++-- | Inverse of 'u3_ix_ch'.+--+-- > map u3_ch_ix "ROYGBV" == [0..5]+u3_ch_ix :: Char -> Int+u3_ch_ix = fromMaybe (error "u3_ch_ix") . flip elemIndex "ROYGBV"++-- | Drawing definition, as written by Wyschnegradsky.+--+-- > mapM_ (\(c,r) -> putStrLn (unlines ["C: " ++ c,"R: " ++ r])) u3_vec_text_iw+u3_vec_text_iw :: [(String, String)]+u3_vec_text_iw =+ [("4+,4-,4+,4-,2+"+ ,"4-,4+,4-,4+,4-,4+,4-,4+,4-")+ ,("9+,2+,2-,2+,2-,2+"+ ,"2+,2-,2+,2-,2+,2-,2+,2-,2+,18+")+ ,("12-,12+,12-"+ ,"18+,18-")+ ,("3+,3-,3+,3-,3+,3-"+ ,"18+,18-")+ ,("9+,9-"+ ,"3+,3-,3+,3-,3+,3-,3+,3-,3+,3-,3+,3-")+ ,("2+,2-,2+,2-,2+,2-"+ ,"6-,6+,6-,6+,6-,6+")+ ,("2+,2-,2+,2-,2+,2-"+ ,"6+,6-,6+,6-,6+,6-")+ ,("6+,6-"+ ,"2+,2-,2+,2-,2+,2-,2+,2-,2+,2-,2+,2-,2+,2-,2+,2-,2+,2-")]++-- | Re-written for local parser and to correct ambiguities and errors+-- (to align with actual drawing).+--+-- > let f = parse_vec Nothing 0 in map (\(p,q) -> (f p,f q)) u3_vec_text_rw+--+-- > let f (c,r) = putStrLn (unlines ["C: " ++ c,"R: " ++ r])+-- > in mapM_ f (interleave u3_vec_text_iw u3_vec_text_rw)+u3_vec_text_rw :: [(String, String)]+u3_vec_text_rw =+ [("4+,3-,5+,3-,3+"+ ,"4-,3+,5-,3+,5-,3+,5-,3+,5-") -- 1+ ,("9+,2+,1-,3+,1-,2+"+ ,"2+,1-,3+,1-,3+,1-,3+,1-,3+,1-,3+,1-,3+,1-,3+,1-,3+,2-") -- 2+ ,("12-,12+,12-"+ ,"18+,18-")+ ,("3+,2-,4+,2-,4+,3-"+ ,"18+,18-")+ ,("9+,9-"+ ,"3+,2-,4+,1-,1+,1-,3+,1-,1+,1-,3+,2-,4+,1-,1+,1-,3+,1-,1+,1-") -- 5+ ,("2+,1-,3+,1-,3+,2-"+ ,"6-,6+,6-,6+,6-,6+") -- 6+ ,("2+,1-,3+,1-,3+,2-"+ ,"6+,6-,6+,6-,6+,6-") -- 7+ ,("6+,6-"+ ,"2+,1-,3+,1-,3+,1-,3+,1-,3+,1-,3+,1-,3+,1-,3+,1-,3+,2-")] -- 8++-- | Parse of 'u3_vec_text_rw'.+--+-- > let {(c,r) = u3_vec_ix ; c' = map length c}+-- > in (length c,c',sum c',length r,map length r)+u3_vec_ix :: Num n => ([[n]],[[n]])+u3_vec_ix =+ let f (p,q) = [parse_vec Nothing 0 p,parse_vec Nothing 0 q]+ [c,r] = transpose (map f u3_vec_text_rw)+ in (c,r)++-- | Radial indices (ie. each /ray/ as an index sequence).+--+-- > putStrLn $ unlines $ map (map u3_ix_ch) u3_ix_radial+u3_ix_radial :: Integral n => [[n]]+u3_ix_radial =+ let (c,r) = u3_vec_ix+ r' = zipWith replicate (map length c) r+ in zipWith (\p q -> map (add_m 6 p) q) (concat c) (concat r')++-- | Colour names in index sequence.+u3_clr_nm :: [String]+u3_clr_nm = words "red orange yellow green blue violet"++-- | Colour values (hex strings) in index sequence.+u3_clr_hex :: [String]+u3_clr_hex = words "#e14630 #e06e30 #e2c48e #498b43 #2a5a64 #cb7b74"++-- | RGB form of 'u3_clr_hex'.+u3_clr_rgb :: Fractional n => [(n,n,n)]+u3_clr_rgb = map (clr_normalise 256 . parse_hex_clr_int) u3_clr_hex++-- | Notated radial color sequence, transcribed from drawing.+--+-- > map (\(n,c) -> let v = u3_ch_seq_to_vec c in (n,sum v,v)) u3_radial_ch+u3_radial_ch :: [(Int,[Char])]+u3_radial_ch =+ [(1,"RVBGY GBV BGYOR OYG YORVB VRO RVBGY GBVBGYO")+ ,(5,"ROYG YO YGBV BV BVRO RO ROYG YO YGBV BV BVR OR O")]++-- | Notated circumferenctial color sequence, transcribed from drawing.+--+-- > map (\(n,c) -> (n,u3_ch_seq_to_vec c)) u3_circ_ch+u3_circ_ch :: [(Int,[Char])]+u3_circ_ch =+ [(6,"ROYOYGBGBVRV")+ ,(7,"ROYOYGBGBVRV")+ ,(8,"ROYGBVRVBGYO")]++-- | Translate notated sequence to "re-written" vector notation.+u3_ch_seq_to_vec :: [Char] -> [Int]+u3_ch_seq_to_vec =+ map length .+ group .+ map (normalise_step 6) .+ d_dx .+ map u3_ch_ix .+ filter (not . isSpace)++-- * DC9++{- | Circumference pitch classes, C = 0.++> let c' = map length dc9_circ in (sum c',c') == (72,[5,6,7,2,3,4,4,3,2,7,7,4,4,3,2,2,3,4])++> iw_pc_pp " | " dc9_circ++-}+dc9_circ :: Num n => [[n]]+dc9_circ =+ [[6,5,4,3,2]+ ,[3,2,1,0,11,10]+ ,[11,10,9,8,7,6,5]+ ,[6,5]+ ,[6,5,4]+ ,[5,4,3,2]+ ,[3,2,1,0]+ ,[1,0,11]+ ,[0,11]+ ,[0,1,2,3,4,5,6]+ ,[5,6,7,8,9,10,9]+ ,[10,11,0,1]+ ,[0,1,2,3]+ ,[2,3,4]+ ,[3,4]+ ,[3,4]+ ,[3,4,5]+ ,[4,5,6,7]]++-- | Rayon pitch classes, C = 0.+--+-- > length dc9_rad == 18+-- > putStrLn $ unwords $ map f dc9_rad+dc9_rad :: Num n => [n]+dc9_rad = [0,10,8,6,4,2,0,10,8,6,4,2,0,10,8,6,4,2]++-- | Radial indices.+--+-- > map length dc9_ix == replicate 72 18+dc9_ix :: Integral n => [[n]]+dc9_ix = map (\n -> map (add_m 12 n) dc9_rad) (concat dc9_circ)++-- | Approximate colours, hex strings.+dc9_clr_hex :: [String]+dc9_clr_hex =+ let c = ["#e96d61","#e6572b"+ ,"#e07122","#e39e36"+ ,"#e8b623","#e5c928"+ ,"#c2ba3d","#a2a367"+ ,"#537a77","#203342"+ ,"#84525e","#bc6460"]+ n = interleave [6,4,2,0,10,8] [5,3,1,11,9,7] :: [Int]+ in map snd (sort (zip n c))++-- | RGB form of colours.+dc9_clr_rgb :: Fractional n => [(n,n,n)]+dc9_clr_rgb = map (clr_normalise 255 . parse_hex_clr_int) dc9_clr_hex++-- * U11++-- > 18 * 4 == 72+-- > let c' = map length u11_circ in (sum c',length c',c')+--+-- > iw_pc_pp "\n- " u11_circ+u11_circ :: Num n => [[n]]+u11_circ =+ [[7,8,9,10,11,0,1,2,3]+ ,[10,11,0,1,2,3,4,5,6]+ ,[0,1,2,3,4,5]+ ,[0,1,2]+ ,[10,11]+ ,[6,7]+ ,[2]+ ,[9]+ ,[4]+ ,[11]+ ,[6,7]+ ,[2]+ ,[9]+ ,[2]+ ,[11]+ ,[6,7]+ ,[2,3]+ ,[10,11,0]+ ,[7,8,9,10,11,0]+ ,[7,8,9,10,11,0,1,2,3]+ ,[10,11,0,1,2,3,4,5,6]]++-- > iw_pc_pp "|" [u11_gen_seq 7 18 [5]]+u11_gen_seq :: Integral i => i -> Int -> [i] -> [i]+u11_gen_seq z n = map (`mod` 12) . take n . dx_d z . cycle++u11_seq_rule :: Integral i => Maybe Int -> [i]+u11_seq_rule n = u11_gen_seq 0 18 (maybe [-1] (\x -> replicate x (-1) ++ [5]) n)++-- > ull_rad_text == "012588---------885210"+ull_rad_text :: [Char]+ull_rad_text =+ let x = "012588----"+ y = "-"+ in x ++ y ++ reverse x++-- > iw_pc_pp "\n- " u11_rad+u11_rad :: Integral n => [[n]]+u11_rad =+ let f c = if c == '-' then Nothing else Just (read [c])+ in map (u11_seq_rule . f) ull_rad_text++u11_clr_hex :: [String]+u11_clr_hex =+ let c = ["#dbb56a","#ffb05c","#ea7c3f","#f93829","#ee6054","#d18d9c"+ ,"#a94c79","#215272","#628b7d","#9dbc90","#ecdfaa","#fbeaa5"]+ n = reverse ([4..11] ++ [0..3]) :: [Int]+ in map snd (sort (zip n c))++u11_clr_rgb :: Fractional n => [(n,n,n)]+u11_clr_rgb = map (clr_normalise 256 . parse_hex_clr_int) u11_clr_hex
Music/Theory/Xenakis/S4.hs view
@@ -49,12 +49,12 @@ case sort x of [1,2,3,4] -> x [5,6,7,8] -> complement x- _ -> error "lower"+ _ -> error (show ("lower",x)) -- | Application of 'Label' /p/ on /q/. -- -- > l_on Q1 I == Q1--- > l_on D A == G+-- > l_on D Q12 == Q4 -- > [l_on L L,l_on E D,l_on D E] == [L2,C,B] l_on :: Label -> Label -> Label l_on p q =@@ -63,6 +63,48 @@ r = map (\i -> q' !! (i - 1)) p' in label_of r +{- | Generalisation of Fibonnaci process, /f/ is the binary operator+giving the next element, /p/ and /q/ are the initial elements.++See discussion in: Carlos Agon, Moreno Andreatta, Gérard Assayag, and+Stéphan Schaub. _Formal Aspects of Iannis Xenakis' "Symbolic Music": A+Computer-Aided Exploration of Compositional Processes_. Journal of New+Music Research, 33(2):145-159, 2004.++Note that the article has an error, printing Q4 for Q11 in the sequence below.++> import qualified Music.Theory.List as T++> let r = [D,Q12,Q4, E,Q8,Q2, E2,Q7,Q4, D2,Q3,Q11, L2,Q7,Q2, L,Q8,Q11]+> in (take 18 (fib_proc l_on D Q12) == r,T.duplicates r == [Q2,Q4,Q7,Q8,Q11])++Beginning E then G2 no Q nodes are visited.++> let r = [E,G2,L2,C,G,D,E,B,D2,L,G,C,L2,E2,D2,B]+> in (take 16 (fib_proc l_on E G2) == r,T.duplicates r == [B,C,D2,E,G,L2])++> import Music.Theory.List+> let [a,b] = take 2 (segments 18 18 (fib_proc l_on D Q12)) in a == b++The prime numbers that are not factors of 18 are {1,5,7,11,13,17}.+They form a closed group under modulo 18 multiplication.++> let {n = [5,7,11,13,17]+> ;r = [(5,7,17),(5,11,1),(5,13,11),(5,17,13)+> ,(7,11,5),(7,13,1),(7,17,11)+> ,(11,13,17),(11,17,7)+> ,(13,17,5)]}+> in [(p,q,(p * q) `mod` 18) | p <- n, q <- n, p < q] == r++The article also omits the 5 after 5,1 in the sequence below.++> let r = [11,13,17,5,13,11,17,7,11,5,1,5,5,7,17,11,7,5,17,13,5,11,1,11]+> in take 24 (fib_proc (\p q -> (p * q) `mod` 18) 11 13) == r++-}+fib_proc :: (a -> a -> a) -> a -> a -> [a]+fib_proc f p q = let r = f p q in p : fib_proc f q r+ -- | 'Seq' of 'Label', inverse of 'label_of'. -- -- > seq_of Q1 == [8,7,5,6,4,3,1,2]@@ -186,42 +228,56 @@ -- * Figures --- | Fig. VIII-6. Hexahedral (Octahedral) Group (p. 220)+-- | Label sequence of Fig. VIII-6. Hexahedral (Octahedral) Group (p. 220) ----- > length viii_6_l == 24--- > take 7 viii_6_l == [L2,L,A,Q1,Q7,Q3,Q9]-viii_6_l :: [Label]-viii_6_l =+-- > let r = [I,A,B,C,D,D2,E,E2,G,G2,L,L2,Q1,Q2,Q3,Q4,Q5,Q6,Q7,Q8,Q9,Q10,Q11,Q12]+-- > in viii_6_lseq == r+viii_6_lseq :: [Label]+viii_6_lseq = [L2,L,A,Q1,Q7,Q3,Q9 ,G2,G,C,Q8,Q5,Q10,Q2 ,E,E2,B,Q4,Q11,Q12,Q6 ,D,D2,I] +-- | Label sequence of Fig. VIII-7 (p.221)+--+-- > let r = [I,A,B,C,D,D2,E,E2,G,G2,L,L2,Q1,Q2,Q3,Q4,Q5,Q6,Q7,Q8,Q9,Q10,Q11,Q12]+-- > in viii_7_lseq == r+viii_7_lseq :: [Label]+viii_7_lseq =+ [I,A,B,C+ ,D,D2,E,E2+ ,G,G2,L,L2+ ,Q1,Q2,Q3,Q4+ ,Q5,Q6,Q7,Q8+ ,Q9,Q10,Q11,Q12]+ -- | Fig. VIII-7 (p.221) -- -- > map (take 4) (take 4 viii_7) == [[I,A,B,C] -- > ,[A,I,C,B] -- > ,[B,C,I,A] -- > ,[C,B,A,I]]+--+-- > import Music.Theory.Array.MD+--+-- > let t = md_matrix_opt show (\x -> "_" ++ x ++ "_") (head viii_7,head viii_7) viii_7+-- > putStrLn $ unlines $ md_table' t viii_7 :: [[Label]]-viii_7 =- let o = [I,A,B,C- ,D,D2,E,E2- ,G,G2,L,L2- ,Q1,Q2,Q3,Q4- ,Q5,Q6,Q7,Q8- ,Q9,Q10,Q11,Q12]- in map (\i -> map (`l_on` i) o) o+viii_7 = map (\i -> map (`l_on` i) viii_7_lseq) viii_7_lseq --- | Fig. VIII-6/b 'Labels' (p.221)+-- | Label sequence of Fig. VIII-6/b (p.221) -- -- > length viii_6b_l == length viii_6_l -- > take 8 viii_6b_l == [I,A,B,C,D2,D,E2,E]-viii_6b_l :: [Label]-viii_6b_l =- [I,A,B,C,D2,D,E2,E- ,G2,G,L2,L,Q7,Q2,Q3,Q11- ,Q8,Q6,Q1,Q5,Q9,Q10,Q4,Q12]+viii_6b_lseq :: [Label]+viii_6b_lseq =+ [I,A,B,C+ ,D2,D,E2,E+ ,G2,G,L2,L+ ,Q7,Q2,Q3,Q11+ ,Q8,Q6,Q1,Q5+ ,Q9,Q10,Q4,Q12] -- | Fig. VIII-6/b 'Half_Seq'. --@@ -258,7 +314,7 @@ -- | Variant of 'viii_6b' with 'Half_Seq'. viii_6b' :: [(Label,Half_Seq)]-viii_6b' = zip viii_6b_l viii_6b_p'+viii_6b' = zip viii_6b_lseq viii_6b_p' -- | Fig. VIII-6/b. --@@ -266,19 +322,19 @@ -- > ,(G2,[3,2,4,1,7,6,8,5]) -- > ,(Q8,[6,8,5,7,2,4,1,3])] viii_6b :: [(Label,Seq)]-viii_6b = zip viii_6b_l (map full_seq viii_6b_p')+viii_6b = zip viii_6b_lseq (map full_seq viii_6b_p') -- | The sequence of 'Rel' to give 'viii_6_l' from 'L2'. -- -- > apply_relations_l viii_6_relations L2 == viii_6_l -- > length (nub viii_6_relations) == 14 viii_6_relations :: [Rel]-viii_6_relations = relations (map half_seq_of viii_6_l)+viii_6_relations = relations (map half_seq_of viii_6_lseq) -- | The sequence of 'Rel' to give 'viii_6b_l' from 'I'. -- -- > apply_relations_l viii_6b_relations I == viii_6b_l -- > length (nub viii_6b_relations) == 10 viii_6b_relations :: [Rel]-viii_6b_relations = relations (map half_seq_of viii_6b_l)+viii_6b_relations = relations (map half_seq_of viii_6b_lseq)
Music/Theory/Xenakis/Sieve.hs view
@@ -14,6 +14,7 @@ | L (I,I) -- ^ Primitive 'Sieve' of /modulo/ and /index/ | Union Sieve Sieve -- ^ 'Union' of two 'Sieve's | Intersection Sieve Sieve -- ^ 'Intersection' of two 'Sieve's+ | Complement Sieve -- ^ 'Complement' of a 'Sieve' deriving (Eq,Show) -- | The 'Union' of a list of 'Sieve's, ie. 'foldl1' 'Union'.@@ -32,6 +33,20 @@ (∩) :: Sieve -> Sieve -> Sieve (∩) = Intersection +-- | Synonym for 'Complement'.+c :: Sieve -> Sieve+c = Complement++-- | Pretty-print sieve. Fully parenthesised.+sieve_pp :: Sieve -> String+sieve_pp s =+ case s of+ Empty -> "∅"+ L (p,q) -> concat [show p,".",show q]+ Union p q -> concat ["(",sieve_pp p," ∪ ",sieve_pp q,")"]+ Intersection p q -> concat ["(",sieve_pp p," ∩ ",sieve_pp q,")"]+ Complement p -> concat ["(∁ ",sieve_pp p,")"]+ -- | Variant of 'L', ie. 'curry' 'L'. -- -- > l 15 19 == L (15,19)@@ -49,6 +64,7 @@ -- | In a /normal/ 'Sieve' /m/ is '>' /i/. -- -- > normalise (L (15,19)) == L (15,4)+-- > normalise (L (11,13)) == L (11,2) normalise :: Sieve -> Sieve normalise s = case s of@@ -56,10 +72,12 @@ L (m,i) -> L (m,i `mod` m) Union s0 s1 -> Union (normalise s0) (normalise s1) Intersection s0 s1 -> Intersection (normalise s0) (normalise s1)+ Complement s' -> Complement (normalise s') -- | Predicate to test if a 'Sieve' is /normal/. -- -- > is_normal (L (15,4)) == True+-- > is_normal (L (11,13)) == False is_normal :: Sieve -> Bool is_normal s = s == normalise s @@ -74,7 +92,19 @@ L (m,i) -> n `mod` m == i `mod` m && n >= i Union s0 s1 -> element s0 n || element s1 n Intersection s0 s1 -> element s0 n && element s1 n+ Complement s' -> not (element s' n) +-- > take 9 (i_complement [1,3..]) == [0,2..16]+i_complement :: [I] -> [I]+i_complement =+ let f x s = case s of+ [] -> [x ..]+ e:s' -> case compare x e of+ LT -> x : f (x + 1) s+ EQ -> f (x + 1) s'+ GT -> error "i_complement"+ in f 0+ -- | Construct the sequence defined by a 'Sieve'. Note that building -- a sieve that contains an intersection clause that has no elements -- gives @_|_@.@@ -93,6 +123,7 @@ L (m,i) -> [i, i+m ..] Union s0 s1 -> u_f (merge (build s0) (build s1)) Intersection s0 s1 -> i_f (merge (build s0) (build s1))+ Complement s' -> i_complement (build s') {- | Variant of 'build' that gives the first /n/ places of the 'reduce' of 'Sieve'.@@ -124,6 +155,77 @@ > let r = [0,2,3,4,6,7,9,11,12,15,17,18,21,22,24,25,27,30,32] > in buildn 19 (5⋄2 ∪ 3⋄0 ∪ 7⋄4) == r +Agon et. al. p.155++> let {a = c (13⋄3 ∪ 13⋄5 ∪ 13⋄7 ∪ 13⋄9)+> ;b = 11⋄2+> ;c' = c (11⋄4 ∪ 11⋄8)+> ;d = 13⋄9+> ;e = 13⋄0 ∪ 13⋄1 ∪ 13⋄6+> ;f = (a ∩ b) ∪ (c' ∩ d) ∪ e}+> in buildn 13 f == [0,1,2,6,9,13,14,19,22,24,26,27,32]++> differentiate [0,1,2,6,9,13,14,19,22,24,26,27,32] == [1,1,4,3,4,1,5,3,2,2,1,5]++> import Music.Theory.Pitch++> let {n = [0,1,2,6,9,13,14,19,22,24,26,27,32]+> ;r = "C C𝄲 C♯ D♯ E𝄲 F𝄰 G A𝄲 B C C♯ C𝄰 E"}+> in unwords (map (pitch_class_pp . pc24et_to_pitch . (`mod` 24)) n) == r++Jonchaies++> let s = map (17⋄) [0,1,4,5,7,11,12,16]+> in differentiate (buildn 25 (union s))++Nekuïa++> let s = [24⋄0,14⋄2,22⋄3,31⋄4,28⋄7,29⋄9,19⋄10,25⋄13,24⋄14,26⋄17,23⋄21+> ,24⋄10,30⋄9,35⋄17,29⋄24,32⋄25,30⋄29,26⋄21,30⋄17,31⋄16]+> in differentiate (buildn 24 (union s))++Major scale:++> let s = (c(3⋄2) ∩ 4⋄0) ∪ (c(3⋄1) ∩ 4⋄1) ∪ (3⋄2 ∩ 4⋄2) ∪ (c(3⋄0) ∩ 4⋄3)+> in buildn 7 s == [0,2,4,5,7,9,11]++Nomos Alpha:++let {s = (c (13⋄3 ∪ 13⋄5 ∪ 13⋄7 ∪ 13⋄9) ∩ 11⋄2) ∪ (c (11⋄4 ∪ 11⋄8) ∩ 13⋄9) ∪ (13⋄0 ∪ 13⋄1 ∪ 13⋄6)+ ;r = [0,1,2,6,9,13,14,19,22,24,26,27,32,35,39,40,45,52,53,58,61,65,66,71,78,79,84,87,90,91,92,97]}+in buildn 32 s == r++/Psappha/ (Flint):++> let {s = union [(8⋄0∪8⋄1∪8⋄7)∩(5⋄1∪5⋄3)+> ,(8⋄0∪8⋄1∪8⋄2)∩5⋄0+> ,8⋄3∩(5⋄0∪5⋄1∪5⋄2∪5⋄3∪5⋄4)+> ,8⋄4∩(5⋄0∪5⋄1∪5⋄2∪5⋄3∪5⋄4)+> ,(8⋄5∪8⋄6)∩(5⋄2∪5⋄3∪5⋄4)+> ,8⋄1∩5⋄2+> ,8⋄6∩5⋄1]+> ;r = [0,1,3,4,6,8,10,11,12+> ,13,14,16,17,19,20,22,23,25+> ,27,28,29,31,33,35,36,37,38]}+> in buildn 27 s == r++À R. (Hommage à Maurice Ravel) (Squibbs, 1996)++> let {s = union [8⋄0∩(11⋄0∪11⋄4∪11⋄5∪11⋄6∪11⋄10)+> ,8⋄1∩(11⋄2∪11⋄3∪11⋄6∪11⋄7∪11⋄9)+> ,8⋄2∩(11⋄0∪11⋄1∪11⋄2∪11⋄3∪11⋄5∪11⋄10)+> ,8⋄3∩(11⋄1∪11⋄2∪11⋄3∪11⋄4∪11⋄10)+> ,8⋄4∩(11⋄0∪11⋄4∪11⋄8)+> ,8⋄5∩(11⋄0∪11⋄2∪11⋄3∪11⋄7∪11⋄9∪11⋄10)+> ,8⋄6∩(11⋄1∪11⋄3∪11⋄5∪11⋄7∪11⋄8∪11⋄9)+> ,8⋄7∩(11⋄1∪11⋄3∪11⋄6∪11⋄7∪11⋄8∪11⋄10)]+> ;r = [0,2,3,4,7,9,10,13,14,16+> ,17,21,23,25,29,30,32,34,35,38+> ,39,43,44,47,48,52,53,57,58,59+> ,62,63,66,67,69,72,73,77,78,82+> ,86,87]}+> in buildn 42 s == r+ -} buildn :: Int -> Sieve -> [I] buildn n = take n . build . reduce@@ -183,6 +285,8 @@ -- > let s = 3⋄2∩4⋄7∩6⋄11∩8⋄7 ∪ 6⋄9∩15⋄18 ∪ 13⋄5∩8⋄6∩4⋄2 ∪ 6⋄9∩15⋄19 -- > in reduce s == (24⋄23 ∪ 30⋄3 ∪ 104⋄70) --+-- > putStrLn $ sieve_pp (reduce s)+-- -- > let s = 3⋄2∩4⋄7∩6⋄11∩8⋄7 ∪ 6⋄9∩15⋄18 ∪ 13⋄5∩8⋄6∩4⋄2 ∪ 6⋄9∩15⋄19 -- > in reduce s == (24⋄23 ∪ 30⋄3 ∪ 104⋄70) reduce :: Sieve -> Sieve@@ -202,3 +306,4 @@ Intersection s1 Empty -> s1 Intersection (L p) (L q) -> maybe Empty L (reduce_intersection p q) Intersection s1 s2 -> f Intersection s1 s2+ Complement s' -> Complement (reduce s')
Music/Theory/Z.hs view
@@ -1,94 +1,147 @@--- | Generalised Z-/n/ functions.+-- | Z-/n/ functions with modulo function as parameter. module Music.Theory.Z where -{---From GHC 7.6 onwards there is the modular-arithmetic package, which subsumes this work.--{-# Language DataKinds #-}+import Data.Char {- base -}+import Data.List {- base -} -import Data.Modular {- modular-arithmetic -}-import GHC.TypeLits {- base -}+import qualified Music.Theory.List as T {- hmt -} -type Z n = Mod Integer n+-- | The modulo function for Z.+type Z t = (t -> t) --- > map negate [0::Z12 .. 11] == [0,11,10,9,8,7,6,5,4,3,2,1]--- > map (+ 5) [0::Z12 .. 11] == [5,6,7,8,9,10,11,0,1,2,3,4]-type Z12 = Mod Integer 12+-- | Is /n/ in (0,/m/-1).+is_z_n :: (Num a, Ord a) => a -> a -> Bool+is_z_n m n = n >= 0 && n < m --- > map invert [0::Z12 .. 11] == [0,11,10,9,8,7,6,5,4,3,2,1]-invert :: KnownNat n => Z n -> Z n-invert = negate+mod5 :: Integral i => Z i+mod5 n = n `mod` 5 --}+mod7 :: Integral i => Z i+mod7 n = n `mod` 7 -import Data.List {- base -}+mod12 :: Integral i => Z i+mod12 n = n `mod` 12 -lift_unary_Z :: Integral a => a -> (t -> a) -> t -> a-lift_unary_Z z f n = mod (f n) z+lift_unary_Z :: Z i -> (t -> i) -> t -> i+lift_unary_Z z f n = z (f n) -lift_binary_Z :: Integral a => a -> (s -> t -> a) -> s -> t -> a-lift_binary_Z z f n1 n2 = mod (n1 `f` n2) z+lift_binary_Z :: Z i -> (s -> t -> i) -> s -> t -> i+lift_binary_Z z f n1 n2 = z (n1 `f` n2) -- > import Music.Theory.Z -- > import qualified Music.Theory.Z12 as Z12--- > z_mod 12 (6::Z12.Z12) 12--- > z_add 12 (1::Z12.Z12) 5--- > (1::Z12.Z12) + 5--- > map (z_add 12 4) [1,5,6] == [5,9,10]-z_add :: Integral a => a -> a -> a -> a+-- > z_add id (11::Z12.Z12) 5 == 4+-- > (11::Z12.Z12) + 5 == 4+-- > map (z_add mod12 4) [1,5,6] == [5,9,10]+z_add :: Integral i => Z i -> i -> i -> i z_add z = lift_binary_Z z (+) -z_sub :: Integral a => a -> a -> a -> a+-- | The underlying type /i/ is presumed to be signed...+--+-- > z_sub mod12 0 8 == 4+--+-- > import Data.Word+-- > z_sub mod12 (0::Word8) 8 == 8+-- > ((0 - 8) :: Word8) == 248+-- > 248 `mod` 12 == 8+z_sub :: Integral i => Z i -> i -> i -> i z_sub z = lift_binary_Z z (-) -z_mul :: Integral a => a -> a -> a -> a+{- | Allowing unsigned /i/ is rather inefficient...+z_sub :: Integral i => Z i -> i -> i -> i+z_sub z p q =+ if p > q+ then z (p - q)+ else let m = z_modulus z+ in z (p + m - q)+-}++z_mul :: Integral i => Z i -> i -> i -> i z_mul z = lift_binary_Z z (*) -z_negate :: Integral a => a -> a -> a-z_negate z = lift_unary_Z z negate+-- > z_negate mod12 7 == 5+z_negate :: Integral i => Z i -> i -> i+z_negate z = z_sub z 0 -- error "Z numbers are not signed" -z_fromInteger :: Integral a => a -> Integer -> a-z_fromInteger z i = fromInteger i `mod` z+z_fromInteger :: Integral i => Z i -> Integer -> i+z_fromInteger z i = z (fromInteger i) -z_signum :: t -> t1 -> t2+z_signum :: t -> u -> v z_signum _ _ = error "Z numbers are not signed" -z_abs :: t -> t1 -> t2+z_abs :: t -> u -> v z_abs _ _ = error "Z numbers are not signed" --- > map (to_Z 12) [-9,-3,0] == [3,9,0]-to_Z :: Integral i => i -> i -> i+-- > map (to_Z mod12) [-9,-3,0] == [3,9,0]+to_Z :: Integral i => Z i -> i -> i to_Z z = z_fromInteger z . fromIntegral from_Z :: (Integral i,Num n) => i -> n from_Z = fromIntegral --- | Z not in set.+-- | Modulus of /z/. ----- > z_complement 5 [0,2,3] == [1,4]--- > z_complement 12 [0,2,4,5,7,9,11] == [1,3,6,8,10]-z_complement :: (Enum a, Eq a, Num a) => a -> [a] -> [a]-z_complement z = (\\) [0 .. z - 1]+-- > z_modulus mod12 == 12+z_modulus :: Integral i => Z i -> i+z_modulus z = maybe (error "z_modulus") (fromIntegral . (+ 1)) (findIndex ((== 0) . z) [1..]) -z_quot :: Integral i => i -> i -> i -> i+-- | Universe of 'Z'.+--+-- > z_univ mod12 == [0..11]+z_univ :: Integral i => Z i -> [i]+z_univ z = 0 : takeWhile ((> 0) . z) [1..]++-- | Z of 'z_univ' not in given set.+--+-- > z_complement mod5 [0,2,3] == [1,4]+-- > z_complement mod12 [0,2,4,5,7,9,11] == [1,3,6,8,10]+z_complement :: Integral i => Z i -> [i] -> [i]+z_complement z = (\\) (z_univ z)++z_quot :: Integral i => Z i -> i -> i -> i z_quot z p = to_Z z . quot p -z_rem :: Integral c => c -> c -> c -> c+z_rem :: Integral i => Z i -> i -> i -> i z_rem z p = to_Z z . rem p -z_div :: Integral c => c -> c -> c -> c-z_div z p = to_Z z . div p+div_err :: Integral i => String -> i -> i -> i+div_err s p q = if q == 0 then error ("div_err: zero" ++ s) else p `div` q --- > z_mod 12 6 12-z_mod :: Integral c => c -> c -> c -> c+z_div :: Integral i => Z i -> i -> i -> i+z_div z p = to_Z z . div_err "z_div" p++-- > z_mod mod12 6 12 == 6+z_mod :: Integral i => Z i -> i -> i -> i z_mod z p = to_Z z . mod p -z_quotRem :: Integral t => t -> t -> t -> (t, t)+z_quotRem :: Integral i => Z i -> i -> i -> (i,i) z_quotRem z p q = (z_quot z p q,z_quot z p q) -z_divMod :: Integral t => t -> t -> t -> (t, t)+z_divMod :: Integral i => Z i -> i -> i -> (i,i) z_divMod z p q = (z_div z p q,z_mod z p q) -z_toInteger :: Integral i => i -> i -> i+z_toInteger :: Integral i => Z i -> i -> i z_toInteger z = to_Z z++-- * Z16++mod16 :: Integral i => Z i+mod16 n = n `mod` 16++integral_to_digit :: Integral t => t -> Char+integral_to_digit = intToDigit . fromIntegral++is_z16 :: Integral t => t -> Bool+is_z16 = is_z_n 16++z16_to_char :: Integral t => t -> Char+z16_to_char = integral_to_digit++z16_set_pp :: Integral t => [t] -> String+z16_set_pp = T.bracket ('{','}') . map z16_to_char++z16_seq_pp :: Integral t => [t] -> String+z16_seq_pp = T.bracket ('<','>') . map z16_to_char++z16_vec_pp :: Integral t => [t] -> String+z16_vec_pp = T.bracket ('[',']') . map z16_to_char
+ Music/Theory/Z/Boros_1990.hs view
@@ -0,0 +1,296 @@+-- | James Boros. "Some Properties of the All-Trichord Hexachord".+-- _In Theory Only_, 11(6):19--41, 1990.+module Music.Theory.Z.Boros_1990 where++import Data.Char {- base -}+import Data.List {- base -}+import Data.Maybe {- base -}+import Numeric {- base -}++import qualified Data.Graph.Inductive.Graph as G {- fgl -}+import qualified Data.Graph.Inductive.Basic as G {- fgl -}+import qualified Data.Graph.Inductive.PatriciaTree as G {- fgl -}+import qualified Data.Graph.Inductive.Query.BFS as G {- fgl -}++import qualified Music.Theory.Array.MD as T+import qualified Music.Theory.Combinations as T+import qualified Music.Theory.Graph.Dot as T+import qualified Music.Theory.Graph.FGL as T+import qualified Music.Theory.List as T+import qualified Music.Theory.Set.List as T+import qualified Music.Theory.Tuple as T+import qualified Music.Theory.Z as T+import qualified Music.Theory.Z.Forte_1973 as T+import qualified Music.Theory.Z.TTO as T++-- * UTIL++singular :: String -> [t] -> t+singular err l =+ case l of+ [x] -> x+ _ -> error ("not singular: " ++ err)++set_eq :: Ord t => [t] -> [t] -> Bool+set_eq p q = T.set p == T.set q++elem_by :: (t -> t -> Bool) -> t -> [t] -> Bool+elem_by f e = any (f e)++-- * TTO++tto_tni_univ :: Integral i => [T.TTO i]+tto_tni_univ = filter (not . T.tto_M) (T.z_tto_univ T.mod12)++all_tn :: Integral i => [i] -> [[i]]+all_tn p = map (\n -> map (T.z_add T.mod12 n) p) [0..11]++all_tni :: Integral i => [i] -> [[i]]+all_tni p = map (\f -> T.z_tto_apply 5 T.mod12 f p) tto_tni_univ++uniq_tni :: Integral i => [i] -> [[i]]+uniq_tni = nub . all_tni++type PC = Int+type PCSET = [PC]+type SC = PCSET++pcset_trs :: Int -> PCSET -> PCSET+pcset_trs n p = sort (map (T.mod12 . (+ n)) p)++-- | Forte prime forms of the twelve trichordal set classes.+--+-- > length trichords == 12+trichords :: [PCSET]+trichords = filter ((== 3) . length) (T.sc_univ T.mod12)++-- | Is a pcset self-inversional, ie. is the inversion of /p/ a transposition of /p/.+--+-- > map (\p -> (p,self_inv p)) trichords+self_inv :: PCSET -> Bool+self_inv p = elem_by set_eq (map (T.z_negate T.mod12) p) (all_tn p)++-- | Pretty printer, comma separated.+--+-- > pcset_pp [0,3,7,10] == "0,3,7,10"+pcset_pp :: PCSET -> String+pcset_pp = intercalate "," . map show++-- | Pretty printer, hexadecimal, no separator.+--+-- > pcset_pp_hex [0,3,7,10] == "037A"+pcset_pp_hex :: PCSET -> String+pcset_pp_hex = map toUpper . concat . map (flip showHex "")++-- * ATH++-- | Forte prime form of the all-trichord hexachord.+--+-- > T.sc_name T.mod12 ath == "6-Z17"+-- > T.sc "6-Z17" == ath+ath :: PCSET+ath = [0,1,2,4,7,8]++-- | Is /p/ an instance of 'ath'.+is_ath :: PCSET -> Bool+is_ath p = T.forte_prime T.mod12 p == ath++-- | Table 1, p.20+--+-- > length ath_univ == 24+ath_univ :: [PCSET]+ath_univ = uniq_tni ath++-- | Calculate 'T.TTO' of pcset, which must be an instance of 'ath'.+--+-- > ath_tni [1,2,3,7,8,11] == T.TTO 3 False True+ath_tni :: PCSET -> T.TTO PC+ath_tni = singular "ath_tni" . filter (not . T.tto_M) . T.z_tto_rel 5 T.mod12 ath++-- | Give label for instance of 'ath', prime forms are written H and inversions h.+--+-- > ath_pp [1,2,3,7,8,11] == "h3"+ath_pp :: PCSET -> String+ath_pp p =+ let r = ath_tni p+ h = if T.tto_I r then 'h' else 'H'+ in h : show (T.tto_T r)++-- | The twenty three-element subsets of 'ath'.+--+-- > length ath_trichords == 20+ath_trichords :: [PCSET]+ath_trichords = T.combinations (3::Int) ath++-- | '\\' of 'ath' and /p/, ie. the pitch classes that are in 'ath' and not in /p/.+--+-- > ath_complement [0,1,2] == [4,7,8]+ath_complement :: PCSET -> PCSET+ath_complement p = ath \\ p++-- | /p/ is a pcset, /q/ a sc, calculate pcsets in /q/ that with /p/ form 'ath'.+--+-- > ath_completions [0,1,2] (T.sc "3-3") == [[6,7,10],[4,7,8]]+-- > ath_completions [6,7,10] (T.sc "3-5") == [[1,2,8]]+ath_completions :: PCSET -> SC -> [PCSET]+ath_completions p q =+ let f z = is_ath (p ++ z)+ in filter f (uniq_tni q)++realise_ath_seq :: [PCSET] -> [[PCSET]]+realise_ath_seq sq =+ case sq of+ p:q:sq' -> concatMap (\z -> map (p :) (realise_ath_seq (z : sq'))) (ath_completions p q)+ _ -> [sq]++-- return edges that connect z to nodes at gr in an ATH relation+ath_gr_extend :: T.GRAPH PCSET -> PCSET -> [T.EDGE PCSET]+ath_gr_extend gr c =+ let f x y = if is_ath (x ++ y) then Just (x,y) else Nothing+ g (p,q) = mapMaybe (f c) [p,q]+ in nub (map T.t2_sort (concatMap g gr))++gr_trs :: Int -> T.GRAPH PCSET -> T.GRAPH PCSET+gr_trs n = let f (p,q) = (pcset_trs n p,pcset_trs n q) in map f++-- * TABLES++-- > length table_3 == 20+table_3 :: [((PCSET,SC,T.SC_Name),(PCSET,SC,T.SC_Name))]+table_3 =+ let f p = let q = ath_complement p+ i x = (x,T.forte_prime T.mod12 x,T.sc_name T.mod12 x)+ in (i p,i q)+ in map f ath_trichords++-- > putStrLn $ unlines $ table_3_md+table_3_md :: [String]+table_3_md =+ let pp = pcset_pp_hex+ f ((p,q,r),(s,t,u)) = [pp p,pp q,r,pp s,pp t,u]+ hdr = ["P","P/SC","P/F","Q=H0-P","Q/SC","Q/F"]+ in T.md_table' (Just hdr,map f table_3)++-- > length table_4 == 10+table_4 :: [((PCSET,PCSET,T.SC_Name),(PCSET,PCSET,T.SC_Name))]+table_4 = nub (map T.t2_sort table_3)++-- > putStrLn $ unlines $ table_4_md+table_4_md :: [String]+table_4_md =+ let pp = pcset_pp_hex+ f ((p,q,r),(s,t,u)) = [pp p ++ "/" ++ pp s,pp q ++ "/" ++ pp t,r ++ "/" ++ u]+ hdr = ["Trichords","Prime Forms","Forte Numbers"]+ in T.md_table' (Just hdr,map f table_4)++table_5 :: [(PCSET,Int)]+table_5 = T.histogram (map (T.forte_prime T.mod12) ath_trichords)++-- > putStrLn $ unlines $ table_5_md+table_5_md :: [String]+table_5_md =+ let f (p,q) = [pcset_pp_hex p,show q]+ in T.md_table' (Just ["SC","#ATH"],map f table_5)++table_6 :: [(PCSET,Int,Int)]+table_6 =+ let f (p,n) = (p,n,length (filter (\q -> p `T.is_subset` q) ath_univ))+ in map f table_5++-- > putStrLn $ unlines $ table_6_md+table_6_md :: [String]+table_6_md =+ let f (p,q,r) = [pcset_pp_hex p,show q,show r]+ in T.md_table' (Just ["SC","#H0","#Hn"],map f table_6)++-- * FIGURES++fig_1 :: T.GRAPH PCSET+fig_1 = map (T.t2_map T.p3_snd) table_4++fig_1_gr :: G.Gr PCSET ()+fig_1_gr = T.g_from_edges fig_1++-- > putStrLn $ unlines $ map (unwords . map pcset_pp) fig_2+fig_2 :: [[PCSET]]+fig_2 =+ let g = G.undir fig_1_gr+ n = G.labNodes g+ n' = filter ((== 2) . G.deg g . fst) n+ c = T.combinations (2::Int) n'+ p = map (\[lhs,rhs] -> G.esp (fst lhs) (fst rhs) g) c+ p' = (filter (not . null) p)+ in map (mapMaybe (\x -> lookup x n)) p'++fig_3 :: [T.GRAPH PCSET]+fig_3 = map (concatMap (T.adj2 1) . realise_ath_seq) fig_2++fig_3_gr :: [G.Gr PCSET ()]+fig_3_gr = map T.g_from_edges fig_3++fig_4 :: [T.GRAPH PCSET]+fig_4 =+ let p = concatMap realise_ath_seq fig_2+ q = filter ([0,1,2] `elem`) p+ in map (T.adj2 1) q++fig_5 :: [T.GRAPH PCSET]+fig_5 =+ let c = [0,4,8]+ f gr = case ath_gr_extend gr c of+ [] -> Nothing+ r -> Just (gr ++ r)+ g0 = concat fig_4+ in mapMaybe (\n -> f (gr_trs n g0)) [0 .. 11]++-- * Drawing++uedge_set :: Ord v => [T.EDGE v] -> [T.EDGE v]+uedge_set = nub . map T.t2_sort++-- | Self-inversional pcsets are drawn in a double circle, other pcsets in a circle.+set_shape :: PCSET -> String+set_shape v = if self_inv v then "doublecircle" else "circle"++type GR = G.Gr PCSET ()++gr_pp' :: (PCSET -> String) -> T.GR_PP PCSET ()+gr_pp' f = (Just . set_shape,Just . f,const Nothing)++gr_pp :: T.GR_PP PCSET ()+gr_pp = gr_pp' pcset_pp++d_fig_1 :: [String]+d_fig_1 = T.g_to_udot [] gr_pp fig_1_gr++d_fig_3_g :: GR+d_fig_3_g = T.g_from_edges (uedge_set (concat fig_3))++d_fig_3 :: [String]+d_fig_3 = T.g_to_udot [] gr_pp d_fig_3_g++d_fig_3' :: [[String]]+d_fig_3' = map (T.g_to_udot [("node:shape","circle")] gr_pp) fig_3_gr++d_fig_4_g :: GR+d_fig_4_g = T.g_from_edges (uedge_set (concat fig_4))++d_fig_4 :: [String]+d_fig_4 = T.g_to_udot [] gr_pp d_fig_4_g++d_fig_5_g :: GR+d_fig_5_g = T.g_from_edges (uedge_set (concat fig_5))++d_fig_5 :: [String]+d_fig_5 = T.g_to_udot [("edge:len","1.5")] (gr_pp' pcset_pp_hex) d_fig_5_g++d_fig_5_e :: [T.EDGE_L PCSET PCSET]+d_fig_5_e = map (\(p,q) -> ((p,q),p++q)) (uedge_set (concat fig_5))++d_fig_5_g' :: G.Gr PCSET PCSET+d_fig_5_g' = T.g_from_edges_l d_fig_5_e++d_fig_5' :: [String]+d_fig_5' =+ let pp = (const (Just ""),const Nothing,Just . ath_pp)+ in T.g_to_udot [("node:shape","point"),("edge:len","1.25")] pp d_fig_5_g'
+ Music/Theory/Z/Clough_1979.hs view
@@ -0,0 +1,116 @@+-- | John Clough. "Aspects of Diatonic Sets".+-- _Journal of Music Theory_, 23(1):45--61, 1979.+module Music.Theory.Z.Clough_1979 where++import Data.List {- base -}++import qualified Music.Theory.List as T {- hmt -}++-- type Z7 = Int++transpose_to_zero :: Num n => [n] -> [n]+transpose_to_zero p =+ case p of+ [] -> []+ n:_ -> map (+ (negate n)) p++-- | Diatonic pitch class (Z7) set to /chord/.+--+-- > map dpcset_to_chord [[0,1],[0,2,4],[2,3,4,5,6]] == [[1,6],[2,2,3],[1,1,1,1,3]]+dpcset_to_chord :: Integral n => [n] -> [n]+dpcset_to_chord = T.d_dx . (++ [7]) . transpose_to_zero . nub . sort++-- | Inverse of 'dpcset_to_chord'.+--+-- > map chord_to_dpcset [[1,6],[2,2,3]] == [[0,1],[0,2,4]]+chord_to_dpcset :: Integral n => [n] -> [n]+chord_to_dpcset = T.dropRight 1 . T.dx_d 0++-- | Complement, ie. in relation to 'z7_univ'.+--+-- > map dpcset_complement [[0,1],[0,2,4]] == [[2,3,4,5,6],[1,3,5,6]]+dpcset_complement :: Integral n => [n] -> [n]+dpcset_complement p = filter (`notElem` p) z7_univ++-- | Interval class predicate (ie. 'is_z4').+is_ic :: Integral n => n -> Bool+is_ic n = n >= 0 && n < 4++-- | Interval to interval class.+--+-- > map i_to_ic [0..7] == [0,1,2,3,3,2,1,0]+i_to_ic :: Integral n => n -> n+i_to_ic n = if n > 3 then 7 - n else n++-- | Is /chord/, ie. is 'sum' @7@.+--+-- > is_chord [2,2,3]+is_chord :: Integral n => [n] -> Bool+is_chord = (== 7) . sum++-- | Interval vector.+--+-- > iv [2,2,3] == [0,2,1]+iv :: Integral n => [n] -> [n]+iv p =+ let h = T.generic_histogram p+ f n = T.lookup_def n 0 h+ in map f [1,2,3]++-- | Comparison function for 'inv'.+inf_cmp :: Ord a => [a] -> [a] -> Ordering+inf_cmp p q =+ if null p && null q+ then EQ+ else case compare (last p) (last q) of+ EQ -> inf_cmp (T.dropRight 1 p) (T.dropRight 1 q)+ r -> r++-- | Interval normal form.+--+-- > map inf [[2,2,3],[1,2,4],[2,1,4]] == [[2,2,3],[1,2,4],[2,1,4]]+inf :: Integral n => [n] -> [n]+inf = maximumBy inf_cmp . T.rotations++-- | Inverse of chord (retrograde).+--+-- > let p = [1,2,4] in (inf p,invert p,inf (invert p)) == ([1,2,4],[4,2,1],[2,1,4])+invert :: [n] -> [n]+invert = reverse++-- | Complement of /chord/.+--+-- > let r = [[1,1,1,1,3],[1,1,1,2,2],[1,1,2,1,2],[1,1,1,4],[2,1,1,3],[1,2,1,3],[1,2,2,2]]+-- > in map complement [[1,6],[2,5],[3,4],[1,1,5],[1,2,4],[1,3,3],[2,2,3]] == r+complement :: Integral n => [n] -> [n]+complement = inf . dpcset_to_chord . dpcset_complement . chord_to_dpcset++-- | Z7 pitch sequence to Z7 interval sequence, ie. 'mod7' of 'T.d_dx'.+--+-- > map iseq (permutations [0,1,2]) == [[1,1],[6,2],[6,6],[1,5],[5,1],[2,6]]+-- > map iseq (permutations [0,1,3]) == [[1,2],[6,3],[5,6],[2,4],[4,1],[3,5]]+-- > map iseq (permutations [0,2,3]) == [[2,1],[5,3],[6,5],[1,4],[4,2],[3,6]]+-- > map iseq (permutations [0,1,4]) == [[1,3],[6,4],[4,6],[3,3],[3,1],[4,4]]+-- > map iseq (permutations [0,2,4]) == [[2,2],[5,4],[5,5],[2,3],[3,2],[4,5]]+iseq :: Integral n => [n] -> [n]+iseq = map mod7 . T.d_dx++-- * Z++is_z_n :: Integral n => n -> n -> Bool+is_z_n m n = n >= 0 && n < m++is_z4 :: Integral n => n -> Bool+is_z4 = is_z_n 4++z_n_univ :: Integral n => n -> [n]+z_n_univ m = [0 .. m - 1]++z7_univ :: Integral n => [n]+z7_univ = z_n_univ 7++is_z7 :: Integral n => n -> Bool+is_z7 = is_z_n 7++mod7 :: Integral n => n -> n+mod7 n = n `mod` 7
+ Music/Theory/Z/Drape_1999.hs view
@@ -0,0 +1,36 @@+module Music.Theory.Z.Drape_1999 where++import Music.Theory.Z+import Music.Theory.Z.SRO+import Music.Theory.Z.TTO++{- | Relate sets (TnMI).++>>> $ pct rs 0123 641B+>>> T1M++> map tto_pp (rs 5 mod12 [0,1,2,3] [6,4,1,11]) == ["T1M","T4MI"]+-}+rs :: Integral t => t -> Z t -> [t] -> [t] -> [TTO t]+rs = z_tto_rel++{- | Relate segments.++>>> $ pct rsg 156 3BA+>>> T4I+>>> $ pct rsg 0123 05A3+>>> T0M+>>> $ pct rsg 0123 4B61+>>> RT1M+>>> $ pct rsg 0123 B614+>>> r3RT1M++> let sros = map sro_parse . words+> rsg 5 mod12 [1,5,6] [3,11,10] == sros "T4I r1RT4MI"+> rsg 5 mod12 [0,1,2,3] [0,5,10,3] == sros "T0M RT3MI"+> rsg 5 mod12 [0,1,2,3] [4,11,6,1] == sros "T4MI RT1M"+> rsg 5 mod12 [0,1,2,3] [11,6,1,4] == sros "r1T4MI r1RT1M"++-}+rsg :: Integral i => i -> Z i -> [i] -> [i] -> [SRO i]+rsg m z x y = filter (\o -> z_sro_apply m z o x == y) (z_sro_univ (length x) z)
Music/Theory/Z/Forte_1973.hs view
@@ -5,87 +5,95 @@ import Data.List {- base -} import Data.Maybe {- base -} -import Music.Theory.List-import qualified Music.Theory.Set.List as S-import Music.Theory.Z-import Music.Theory.Z.SRO+import qualified Music.Theory.List as T {- hmt -}+import qualified Music.Theory.Set.List as S {- hmt -} +import Music.Theory.Unicode {- hmt -}+import Music.Theory.Z {- hmt -}+import Music.Theory.Z.SRO {- hmt -}+ -- * Prime form -- | T-related rotations of /p/. ----- > t_rotations 12 [0,1,3] == [[0,1,3],[0,2,11],[0,9,10]]-t_rotations :: Integral a => a -> [a] -> [[a]]+-- > t_rotations mod12 [0,1,3] == [[0,1,3],[0,2,11],[0,9,10]]+t_rotations :: Integral i => Z i -> [i] -> [[i]] t_rotations z p =- let r = rotations (sort p)- in map (tn_to z 0) r+ let r = T.rotations (sort p)+ in map (z_sro_tn_to z 0) r -- | T\/I-related rotations of /p/. ----- > ti_rotations 12 [0,1,3] == [[0,1,3],[0,2,11],[0,9,10]--- > ,[0,9,11],[0,2,3],[0,1,10]]-ti_rotations :: Integral a => a -> [a] -> [[a]]+-- > ti_rotations mod12 [0,1,3] == [[0,1,3],[0,2,11],[0,9,10]+-- > ,[0,9,11],[0,2,3],[0,1,10]]+ti_rotations :: Integral i => Z i -> [i] -> [[i]] ti_rotations z p =- let q = invert z 0 p- r = rotations (sort p) ++ rotations (sort q)- in map (tn_to z 0) r+ let q = z_sro_invert z 0 p+ r = T.rotations (sort p) ++ T.rotations (sort q)+ in map (z_sro_tn_to z 0) r -- | Variant with default value for empty input list case.-minimumBy_or :: a -> (a -> a -> Ordering) -> [a] -> a+minimumBy_or :: t -> (t -> t -> Ordering) -> [t] -> t minimumBy_or p f q = if null q then p else minimumBy f q -- | Prime form rule requiring comparator, considering 't_rotations'.-t_cmp_prime :: Integral a => a -> ([a] -> [a] -> Ordering) -> [a] -> [a]+t_cmp_prime :: Integral i => Z i -> ([i] -> [i] -> Ordering) -> [i] -> [i] t_cmp_prime z f = minimumBy_or [] f . t_rotations z -- | Prime form rule requiring comparator, considering 'ti_rotations'.-ti_cmp_prime :: Integral a => a -> ([a] -> [a] -> Ordering) -> [a] -> [a]+ti_cmp_prime :: Integral i => Z i -> ([i] -> [i] -> Ordering) -> [i] -> [i] ti_cmp_prime z f = minimumBy_or [] f . ti_rotations z -- | Forte comparison function (rightmost first then leftmost outwards). -- -- > forte_cmp [0,1,3,6,8,9] [0,2,3,6,7,9] == LT forte_cmp :: (Ord t) => [t] -> [t] -> Ordering-forte_cmp [] [] = EQ forte_cmp p q =- let r = compare (last p) (last q)- in if r == EQ then compare p q else r+ case (p,q) of+ ([],[]) -> EQ+ ([],_) -> LT+ (_,[]) -> GT+ _ -> let r = compare (last p) (last q)+ in if r == EQ then compare p q else r -- | Forte prime form, ie. 'cmp_prime' of 'forte_cmp'. ----- > forte_prime 12 [0,1,3,6,8,9] == [0,1,3,6,8,9]--- > forte_prime 5 [0,1,4] == [0,1,2]+-- > forte_prime mod12 [0,1,3,6,8,9] == [0,1,3,6,8,9]+-- > forte_prime mod5 [0,1,4] == [0,1,2] ----- > S.set (map (forte_prime 5) (S.powerset [0..4]))-forte_prime :: Integral a => a -> [a] -> [a]+-- > S.set (map (forte_prime mod5) (S.powerset [0..4]))+-- > S.set (map (forte_prime mod7) (S.powerset [0..6]))+forte_prime :: Integral i => Z i -> [i] -> [i] forte_prime z = ti_cmp_prime z forte_cmp -- | Transpositional equivalence prime form, ie. 't_cmp_prime' of -- 'forte_cmp'. ----- > (forte_prime 12 [0,2,3],t_prime 12 [0,2,3]) == ([0,1,3],[0,2,3])-t_prime :: Integral a => a -> [a] -> [a]+-- > (forte_prime mod12 [0,2,3],t_prime mod12 [0,2,3]) == ([0,1,3],[0,2,3])+t_prime :: Integral i => Z i -> [i] -> [i] t_prime z = t_cmp_prime z forte_cmp -- * ICV Metric --- | Interval class of i interval /i/.+-- | Interval class of interval /i/. --+-- > map (ic 12) [0..11] == [0,1,2,3,4,5,6,5,4,3,2,1]+-- > map (ic 7) [0..6] == [0,1,2,3,3,2,1] -- > map (ic 5) [1,2,3,4] == [1,2,2,1] -- > map (ic 12) [5,6,7] == [5,6,5]--- > map (ic 12 . to_Z 12) [-13,-1,0,1,13] == [1,1,0,1,1]-ic :: Integral a => a -> a -> a-ic z i = if i <= (z `div` 2) then i else z_sub z z i+-- > map (ic 12 . to_Z mod12) [-13,-1,0,1,13] == [1,1,0,1,1]+ic :: Integral i => i -> i -> i+ic z i = if i <= (z `div` 2) then i else z - i -- | Forte notation for interval class vector. -- -- > icv 12 [0,1,2,4,7,8] == [3,2,2,3,3,2] icv :: (Integral i, Num n) => i -> [i] -> [n] icv z s =- let i = map (ic z . uncurry (z_sub z)) (S.pairs s)+ let i = map (ic z . flip mod z . uncurry (-)) (S.pairs s)+ f l = (head l,genericLength l) j = map f (group (sort i)) k = map (`lookup` j) [1 .. z `div` 2]- f l = (head l,genericLength l) in map (fromMaybe 0) k -- * BIP Metric@@ -98,4 +106,344 @@ -- -- > bip 12 [0,10,9,5,7,2,8,11,3,4,1,6] == [1,1,2,2,3,3,4,4,5,5,6] bip :: Integral a => a -> [a] -> [a]-bip z = sort . map (ic z . to_Z z) . d_dx+bip z = sort . map (ic z . flip mod z) . T.d_dx++-- * Name++{- | Generate SC universe, though not in order of the Forte table.++> let r = [[]+> ,[0]+> ,[0,1],[0,2],[0,3]+> ,[0,1,2],[0,1,3],[0,1,4],[0,2,4]+> ,[0,1,2,3],[0,1,2,4],[0,1,3,4],[0,1,3,5]+> ,[0,1,2,3,4],[0,1,2,3,5],[0,1,2,4,5]+> ,[0,1,2,3,4,5]+> ,[0,1,2,3,4,5,6]]+> in sc_univ mod7 == r++> sort (sc_univ mod12) == sort (map snd sc_table)++> zipWith (\p q -> (p == q,p,q)) (sc_univ mod12) (map snd sc_table)++-}+sc_univ :: Integral i => Z i -> [[i]]+sc_univ z =+ T.sort_by_two_stage length id $+ nub $+ map (forte_prime z) $+ S.powerset (z_univ z)++-- | Synonym for 'String'.+type SC_Name = String++-- | The set-class table (Forte prime forms).+--+-- > length sc_table == 224+sc_table :: Num n => [(SC_Name,[n])]+sc_table =+ [("0-1",[])+ ,("1-1",[0])+ ,("2-1",[0,1])+ ,("2-2",[0,2])+ ,("2-3",[0,3])+ ,("2-4",[0,4])+ ,("2-5",[0,5])+ ,("2-6",[0,6])+ ,("3-1",[0,1,2])+ ,("3-2",[0,1,3])+ ,("3-3",[0,1,4])+ ,("3-4",[0,1,5])+ ,("3-5",[0,1,6])+ ,("3-6",[0,2,4])+ ,("3-7",[0,2,5])+ ,("3-8",[0,2,6])+ ,("3-9",[0,2,7])+ ,("3-10",[0,3,6])+ ,("3-11",[0,3,7])+ ,("3-12",[0,4,8])+ ,("4-1",[0,1,2,3])+ ,("4-2",[0,1,2,4])+ ,("4-3",[0,1,3,4])+ ,("4-4",[0,1,2,5])+ ,("4-5",[0,1,2,6])+ ,("4-6",[0,1,2,7])+ ,("4-7",[0,1,4,5])+ ,("4-8",[0,1,5,6])+ ,("4-9",[0,1,6,7])+ ,("4-10",[0,2,3,5])+ ,("4-11",[0,1,3,5])+ ,("4-12",[0,2,3,6])+ ,("4-13",[0,1,3,6])+ ,("4-14",[0,2,3,7])+ ,("4-Z15",[0,1,4,6])+ ,("4-16",[0,1,5,7])+ ,("4-17",[0,3,4,7])+ ,("4-18",[0,1,4,7])+ ,("4-19",[0,1,4,8])+ ,("4-20",[0,1,5,8])+ ,("4-21",[0,2,4,6])+ ,("4-22",[0,2,4,7])+ ,("4-23",[0,2,5,7])+ ,("4-24",[0,2,4,8])+ ,("4-25",[0,2,6,8])+ ,("4-26",[0,3,5,8])+ ,("4-27",[0,2,5,8])+ ,("4-28",[0,3,6,9])+ ,("4-Z29",[0,1,3,7])+ ,("5-1",[0,1,2,3,4])+ ,("5-2",[0,1,2,3,5])+ ,("5-3",[0,1,2,4,5])+ ,("5-4",[0,1,2,3,6])+ ,("5-5",[0,1,2,3,7])+ ,("5-6",[0,1,2,5,6])+ ,("5-7",[0,1,2,6,7])+ ,("5-8",[0,2,3,4,6])+ ,("5-9",[0,1,2,4,6])+ ,("5-10",[0,1,3,4,6])+ ,("5-11",[0,2,3,4,7])+ ,("5-Z12",[0,1,3,5,6])+ ,("5-13",[0,1,2,4,8])+ ,("5-14",[0,1,2,5,7])+ ,("5-15",[0,1,2,6,8])+ ,("5-16",[0,1,3,4,7])+ ,("5-Z17",[0,1,3,4,8])+ ,("5-Z18",[0,1,4,5,7])+ ,("5-19",[0,1,3,6,7])+ ,("5-20",[0,1,3,7,8])+ ,("5-21",[0,1,4,5,8])+ ,("5-22",[0,1,4,7,8])+ ,("5-23",[0,2,3,5,7])+ ,("5-24",[0,1,3,5,7])+ ,("5-25",[0,2,3,5,8])+ ,("5-26",[0,2,4,5,8])+ ,("5-27",[0,1,3,5,8])+ ,("5-28",[0,2,3,6,8])+ ,("5-29",[0,1,3,6,8])+ ,("5-30",[0,1,4,6,8])+ ,("5-31",[0,1,3,6,9])+ ,("5-32",[0,1,4,6,9])+ ,("5-33",[0,2,4,6,8])+ ,("5-34",[0,2,4,6,9])+ ,("5-35",[0,2,4,7,9])+ ,("5-Z36",[0,1,2,4,7])+ ,("5-Z37",[0,3,4,5,8])+ ,("5-Z38",[0,1,2,5,8])+ ,("6-1",[0,1,2,3,4,5])+ ,("6-2",[0,1,2,3,4,6])+ ,("6-Z3",[0,1,2,3,5,6])+ ,("6-Z4",[0,1,2,4,5,6])+ ,("6-5",[0,1,2,3,6,7])+ ,("6-Z6",[0,1,2,5,6,7])+ ,("6-7",[0,1,2,6,7,8])+ ,("6-8",[0,2,3,4,5,7])+ ,("6-9",[0,1,2,3,5,7])+ ,("6-Z10",[0,1,3,4,5,7])+ ,("6-Z11",[0,1,2,4,5,7])+ ,("6-Z12",[0,1,2,4,6,7])+ ,("6-Z13",[0,1,3,4,6,7])+ ,("6-14",[0,1,3,4,5,8])+ ,("6-15",[0,1,2,4,5,8])+ ,("6-16",[0,1,4,5,6,8])+ ,("6-Z17",[0,1,2,4,7,8])+ ,("6-18",[0,1,2,5,7,8])+ ,("6-Z19",[0,1,3,4,7,8])+ ,("6-20",[0,1,4,5,8,9])+ ,("6-21",[0,2,3,4,6,8])+ ,("6-22",[0,1,2,4,6,8])+ ,("6-Z23",[0,2,3,5,6,8])+ ,("6-Z24",[0,1,3,4,6,8])+ ,("6-Z25",[0,1,3,5,6,8])+ ,("6-Z26",[0,1,3,5,7,8])+ ,("6-27",[0,1,3,4,6,9])+ ,("6-Z28",[0,1,3,5,6,9])+ ,("6-Z29",[0,1,3,6,8,9])+ ,("6-30",[0,1,3,6,7,9])+ ,("6-31",[0,1,3,5,8,9])+ ,("6-32",[0,2,4,5,7,9])+ ,("6-33",[0,2,3,5,7,9])+ ,("6-34",[0,1,3,5,7,9])+ ,("6-35",[0,2,4,6,8,10])+ ,("6-Z36",[0,1,2,3,4,7])+ ,("6-Z37",[0,1,2,3,4,8])+ ,("6-Z38",[0,1,2,3,7,8])+ ,("6-Z39",[0,2,3,4,5,8])+ ,("6-Z40",[0,1,2,3,5,8])+ ,("6-Z41",[0,1,2,3,6,8])+ ,("6-Z42",[0,1,2,3,6,9])+ ,("6-Z43",[0,1,2,5,6,8])+ ,("6-Z44",[0,1,2,5,6,9])+ ,("6-Z45",[0,2,3,4,6,9])+ ,("6-Z46",[0,1,2,4,6,9])+ ,("6-Z47",[0,1,2,4,7,9])+ ,("6-Z48",[0,1,2,5,7,9])+ ,("6-Z49",[0,1,3,4,7,9])+ ,("6-Z50",[0,1,4,6,7,9])+ ,("7-1",[0,1,2,3,4,5,6])+ ,("7-2",[0,1,2,3,4,5,7])+ ,("7-3",[0,1,2,3,4,5,8])+ ,("7-4",[0,1,2,3,4,6,7])+ ,("7-5",[0,1,2,3,5,6,7])+ ,("7-6",[0,1,2,3,4,7,8])+ ,("7-7",[0,1,2,3,6,7,8])+ ,("7-8",[0,2,3,4,5,6,8])+ ,("7-9",[0,1,2,3,4,6,8])+ ,("7-10",[0,1,2,3,4,6,9])+ ,("7-11",[0,1,3,4,5,6,8])+ ,("7-Z12",[0,1,2,3,4,7,9])+ ,("7-13",[0,1,2,4,5,6,8])+ ,("7-14",[0,1,2,3,5,7,8])+ ,("7-15",[0,1,2,4,6,7,8])+ ,("7-16",[0,1,2,3,5,6,9])+ ,("7-Z17",[0,1,2,4,5,6,9])+ ,("7-Z18",[0,1,2,3,5,8,9])+ ,("7-19",[0,1,2,3,6,7,9])+ ,("7-20",[0,1,2,4,7,8,9])+ ,("7-21",[0,1,2,4,5,8,9])+ ,("7-22",[0,1,2,5,6,8,9])+ ,("7-23",[0,2,3,4,5,7,9])+ ,("7-24",[0,1,2,3,5,7,9])+ ,("7-25",[0,2,3,4,6,7,9])+ ,("7-26",[0,1,3,4,5,7,9])+ ,("7-27",[0,1,2,4,5,7,9])+ ,("7-28",[0,1,3,5,6,7,9])+ ,("7-29",[0,1,2,4,6,7,9])+ ,("7-30",[0,1,2,4,6,8,9])+ ,("7-31",[0,1,3,4,6,7,9])+ ,("7-32",[0,1,3,4,6,8,9])+ ,("7-33",[0,1,2,4,6,8,10])+ ,("7-34",[0,1,3,4,6,8,10])+ ,("7-35",[0,1,3,5,6,8,10])+ ,("7-Z36",[0,1,2,3,5,6,8])+ ,("7-Z37",[0,1,3,4,5,7,8])+ ,("7-Z38",[0,1,2,4,5,7,8])+ ,("8-1",[0,1,2,3,4,5,6,7])+ ,("8-2",[0,1,2,3,4,5,6,8])+ ,("8-3",[0,1,2,3,4,5,6,9])+ ,("8-4",[0,1,2,3,4,5,7,8])+ ,("8-5",[0,1,2,3,4,6,7,8])+ ,("8-6",[0,1,2,3,5,6,7,8])+ ,("8-7",[0,1,2,3,4,5,8,9])+ ,("8-8",[0,1,2,3,4,7,8,9])+ ,("8-9",[0,1,2,3,6,7,8,9])+ ,("8-10",[0,2,3,4,5,6,7,9])+ ,("8-11",[0,1,2,3,4,5,7,9])+ ,("8-12",[0,1,3,4,5,6,7,9])+ ,("8-13",[0,1,2,3,4,6,7,9])+ ,("8-14",[0,1,2,4,5,6,7,9])+ ,("8-Z15",[0,1,2,3,4,6,8,9])+ ,("8-16",[0,1,2,3,5,7,8,9])+ ,("8-17",[0,1,3,4,5,6,8,9])+ ,("8-18",[0,1,2,3,5,6,8,9])+ ,("8-19",[0,1,2,4,5,6,8,9])+ ,("8-20",[0,1,2,4,5,7,8,9])+ ,("8-21",[0,1,2,3,4,6,8,10])+ ,("8-22",[0,1,2,3,5,6,8,10])+ ,("8-23",[0,1,2,3,5,7,8,10])+ ,("8-24",[0,1,2,4,5,6,8,10])+ ,("8-25",[0,1,2,4,6,7,8,10])+ ,("8-26",[0,1,2,4,5,7,9,10])+ ,("8-27",[0,1,2,4,5,7,8,10])+ ,("8-28",[0,1,3,4,6,7,9,10])+ ,("8-Z29",[0,1,2,3,5,6,7,9])+ ,("9-1",[0,1,2,3,4,5,6,7,8])+ ,("9-2",[0,1,2,3,4,5,6,7,9])+ ,("9-3",[0,1,2,3,4,5,6,8,9])+ ,("9-4",[0,1,2,3,4,5,7,8,9])+ ,("9-5",[0,1,2,3,4,6,7,8,9])+ ,("9-6",[0,1,2,3,4,5,6,8,10])+ ,("9-7",[0,1,2,3,4,5,7,8,10])+ ,("9-8",[0,1,2,3,4,6,7,8,10])+ ,("9-9",[0,1,2,3,5,6,7,8,10])+ ,("9-10",[0,1,2,3,4,6,7,9,10])+ ,("9-11",[0,1,2,3,5,6,7,9,10])+ ,("9-12",[0,1,2,4,5,6,8,9,10])+ ,("10-1",[0,1,2,3,4,5,6,7,8,9])+ ,("10-2",[0,1,2,3,4,5,6,7,8,10])+ ,("10-3",[0,1,2,3,4,5,6,7,9,10])+ ,("10-4",[0,1,2,3,4,5,6,8,9,10])+ ,("10-5",[0,1,2,3,4,5,7,8,9,10])+ ,("10-6",[0,1,2,3,4,6,7,8,9,10])+ ,("11-1",[0,1,2,3,4,5,6,7,8,9,10])+ ,("12-1",[0,1,2,3,4,5,6,7,8,9,10,11])]++-- | Unicode (non-breaking hyphen) variant.+sc_table_unicode :: Num n => [(SC_Name,[n])]+sc_table_unicode =+ let f = map (\c -> if c == '-' then non_breaking_hypen else c)+ in map (\(nm,pc) -> (f nm,pc)) sc_table++-- | Lookup name of prime form of set class. It is an error for the+-- input not to be a forte prime form.+--+-- > forte_prime_name [0,1,4,6] == ("4-Z15",[0,1,4,6])+forte_prime_name :: (Num n,Eq n) => [n] -> (SC_Name,[n])+forte_prime_name p = fromMaybe (error "forte_prime_name") (find (\(_,q) -> p == q) sc_table)++sc_tbl_lookup :: Integral i => Z i -> [(SC_Name,[i])] -> [i] -> Maybe (SC_Name,[i])+sc_tbl_lookup z tbl p = find (\(_,q) -> forte_prime z p == q) tbl++sc_tbl_lookup_err :: Integral i => Z i -> [(SC_Name,[i])] -> [i] -> (SC_Name,[i])+sc_tbl_lookup_err z tbl = fromMaybe (error "sc_tbl_lookup") . sc_tbl_lookup z tbl++sc_name' :: Integral i => Z i -> [(SC_Name,[i])] -> [i] -> SC_Name+sc_name' z tbl = fst . sc_tbl_lookup_err z tbl++-- | Lookup a set-class name. The input set is subject to+-- 'forte_prime' before lookup.+--+-- > sc_name mod12 [0,2,3,6,7] == "5-Z18"+-- > sc_name mod12 [0,1,4,6,7,8] == "6-Z17"+sc_name :: Integral i => Z i -> [i] -> SC_Name+sc_name z = sc_name' z sc_table++-- | Long name (ie. with enumeration of prime form).+--+-- > sc_name_long mod12 [0,1,4,6,7,8] == "6-Z17[012478]"+sc_name_long :: Integral i => Z i -> [i] -> SC_Name+sc_name_long z p =+ let (nm,p') = sc_tbl_lookup_err z sc_table p+ in nm ++ z16_vec_pp p'++-- | Unicode (non-breaking hyphen) variant.+sc_name_unicode :: Integral i => Z i -> [i] -> SC_Name+sc_name_unicode z = sc_name' z sc_table_unicode++-- | Lookup a set-class given a set-class name.+--+-- > sc "6-Z17" == [0,1,2,4,7,8]+sc :: Num n => SC_Name -> [n]+sc n = snd (fromMaybe (error "sc") (find (\(m,_) -> n == m) sc_table))++scs :: Num n => [[n]]+scs = map snd sc_table++-- | Cardinality /n/ subset of 'scs'.+--+-- > map (length . scs_n) [1..11] == [1,6,12,29,38,50,38,29,12,6,1]+scs_n :: (Integral i, Num n) => i -> [[n]]+scs_n n = filter ((== n) . genericLength) scs++-- | Vector indicating degree of intersection with inversion at each transposition.+--+-- > tics mod12 [0,2,4,5,7,9] == [3,2,5,0,5,2,3,4,1,6,1,4]+tics :: Integral i => Z i -> [i] -> [Int]+tics z p =+ let q = z_sro_t_related z (z_sro_invert z 0 p)+ in map (length . intersect p) q++-- * Z-relation++-- | Locate /Z/ relation of set class.+--+-- > fmap (sc_name mod12) (z_relation_of 12 (sc "7-Z12")) == Just "7-Z36"+z_relation_of :: Integral i => i -> [i] -> Maybe [i]+z_relation_of z x =+ let n = length x+ eq_i :: [Integer] -> [Integer] -> Bool+ eq_i = (==)+ f y = (x /= y) && (icv z x `eq_i` icv z y)+ in case filter f (scs_n n) of+ [] -> Nothing+ [r] -> Just r+ _ -> error "z_relation_of"
Music/Theory/Z/Read_1978.hs view
@@ -5,12 +5,14 @@ import Data.Bits {- base -} import Data.Char {- base -}-import Data.Function {- base -} import Data.List {- base -} import Data.Maybe {- base -} -import qualified Music.Theory.Z.SRO as T {- hmt -}+import qualified Music.Theory.List as T {- hmt -} +import qualified Music.Theory.Z as Z {- hmt -}+import qualified Music.Theory.Z.SRO as Z {- hmt -}+ -- | Coding. type Code = Int @@ -45,7 +47,7 @@ -- | Array to set. -- -- > array_to_set (map toEnum [1,1,0,0,1,0,0,0,1,1,1,0,0]) == [0,1,4,8,9,10]--- > T.encode [0,1,4,8,9,10] == 1811+-- > encode [0,1,4,8,9,10] == 1811 array_to_set :: Integral i => [Bool] -> [i] array_to_set = let f (i,e) = if e then Just i else Nothing@@ -57,8 +59,8 @@ -- | 'array_to_code' of 'set_to_array'. ----- > set_to_code 12 [0,2,3,5]--- > map (set_to_code 12) (T.ti_related 12 [0,2,3,5])+-- > set_to_code 12 [0,2,3,5] == 2880+-- > map (set_to_code 12) (T.z_ti_related (flip mod 12) [0,2,3,5]) set_to_code :: Integral i => i -> [i] -> Code set_to_code z = array_to_code . set_to_array z @@ -73,8 +75,9 @@ array_is_prime a = let c = array_to_code a p = array_to_set a- z = length a- u = maximum (map (set_to_code z) (T.ti_related z p))+ n = length a+ z = flip mod n+ u = maximum (map (set_to_code n) (Z.z_sro_ti_related z p)) in c == u -- | The augmentation rule adds @1@ in each empty slot at end of array.@@ -114,7 +117,7 @@ jn l = case l of (x,y):l' -> (x,concat (y : map snd l')) _ -> error ""- post_proc = map jn . groupBy ((==) `on` fst) . sortBy (compare `on` fst)+ post_proc = map jn . T.group_on fst . sortOn fst in post_proc ((0,[a0]) : f 0 a0) -- * Alternate (reverse) form.@@ -135,10 +138,10 @@ -- | Binary encoding prime form algorithm, equalivalent to Rahn. ----- > encode_prime 12 [0,1,3,6,8,9] == [0,2,3,6,7,9]+-- > encode_prime Z.mod12 [0,1,3,6,8,9] == [0,2,3,6,7,9] -- > Music.Theory.Z12.Rahn_1980.rahn_prime [0,1,3,6,8,9] == [0,2,3,6,7,9]-encode_prime :: Integral i => i -> [i] -> [i]+encode_prime :: Integral i => Z.Z i -> [i] -> [i] encode_prime z s =- let t = map (\n -> T.tn z n s) [0..11]- c = t ++ map (T.invert z 0) t- in decode z (minimum (map encode c))+ let t = map (\x -> Z.z_sro_tn z x s) (Z.z_univ z)+ c = t ++ map (Z.z_sro_invert z 0) t+ in decode (Z.z_modulus z) (minimum (map encode c))
Music/Theory/Z/SRO.hs view
@@ -2,82 +2,188 @@ module Music.Theory.Z.SRO where import Data.List {- base -}+import qualified Text.ParserCombinators.Parsec as P {- parsec -} +import qualified Music.Theory.List as T+import qualified Music.Theory.Parse as T+ import Music.Theory.Z +-- | Serial operator,of the form rRTMI.+data SRO t = SRO {sro_r :: Int+ ,sro_R :: Bool+ ,sro_T :: t+ ,sro_M :: Bool+ ,sro_I :: Bool}+ deriving (Eq,Show)++-- | Printer in 'rnRTnMI' form.+sro_pp :: Show t => SRO t -> String+sro_pp (SRO rN r tN m i) =+ concat [if rN /= 0 then 'r' : show rN else ""+ ,if r then "R" else ""+ ,'T' : show tN+ ,if m then "M" else ""+ ,if i then "I" else ""]++p_sro :: Integral t => P.GenParser Char () (SRO t)+p_sro = do+ let rot = P.option 0 (P.char 'r' >> T.parse_int)+ r <- rot+ r' <- T.is_char 'R'+ _ <- P.char 'T'+ t <- T.parse_int+ m <- T.is_char 'M'+ i <- T.is_char 'I'+ P.eof+ return (SRO r r' t m i)++-- | Parse a Morris format serial operator descriptor.+--+-- > sro_parse "r2RT3MI" == SRO 2 True 3 True True+sro_parse :: Integral i => String -> SRO i+sro_parse =+ either (\e -> error ("sro_parse failed\n" ++ show e)) id .+ P.parse p_sro ""++-- | The total set of serial operations.+--+-- > let u = z_sro_univ 3 mod12+-- > zip (map sro_pp u) (map (\o -> z_sro_apply 5 mod12 o [0,1,3]) u)+z_sro_univ :: Integral i => Int -> Z i -> [SRO i]+z_sro_univ n_rot z =+ [SRO r r' t m i |+ r <- [0 .. n_rot - 1],+ r' <- [False,True],+ t <- z_univ z,+ m <- [False,True],+ i <- [False,True]]++-- | The set of transposition 'SRO's.+z_sro_Tn :: Integral i => Z i -> [SRO i]+z_sro_Tn z = [SRO 0 False n False False | n <- z_univ z]++-- | The set of transposition and inversion 'SRO's.+z_sro_TnI :: Integral i => Z i -> [SRO i]+z_sro_TnI z =+ [SRO 0 False n False i |+ n <- z_univ z,+ i <- [False,True]]++-- | The set of retrograde and transposition and inversion 'SRO's.+z_sro_RTnI :: Integral i => Z i -> [SRO i]+z_sro_RTnI z =+ [SRO 0 r n False i |+ r <- [True,False],+ n <- z_univ z,+ i <- [False,True]]++-- | The set of transposition, @M5@ and inversion 'SRO's.+z_sro_TnMI :: Integral i => Z i -> [SRO i]+z_sro_TnMI z =+ [SRO 0 False n m i |+ n <- z_univ z,+ m <- [True,False],+ i <- [True,False]]++-- | The set of retrograde,transposition,@M5@ and inversion 'SRO's.+z_sro_RTnMI :: Integral i => Z i -> [SRO i]+z_sro_RTnMI z =+ [SRO 0 r n m i |+ r <- [True,False],+ n <- z_univ z,+ m <- [True,False],+ i <- [True,False]]++-- * Serial operations++-- | Apply SRO. M is ordinarily 5, but can be specified here.+--+-- > z_sro_apply 5 mod12 (SRO 1 True 1 True False) [0,1,2,3] == [11,6,1,4]+-- > z_sro_apply 5 mod12 (SRO 1 False 4 True True) [0,1,2,3] == [11,6,1,4]+z_sro_apply :: Integral i => i -> Z i -> SRO i -> [i] -> [i]+z_sro_apply mn z (SRO r r' t m i) x =+ let x1 = if i then z_sro_invert z 0 x else x+ x2 = if m then z_sro_mn z mn x1 else x1+ x3 = z_sro_tn z t x2+ x4 = if r' then reverse x3 else x3+ in T.rotate_left r x4+ -- | Transpose /p/ by /n/. ----- > tn 5 4 [0,1,4] == [4,0,3]--- > tn 12 4 [1,5,6] == [5,9,10]-tn :: (Integral i, Functor f) => i -> i -> f i -> f i-tn z n = fmap (z_add z n)+-- > z_sro_tn mod5 4 [0,1,4] == [4,0,3]+-- > z_sro_tn mod12 4 [1,5,6] == [5,9,10]+z_sro_tn :: (Integral i, Functor f) => Z i -> i -> f i -> f i+z_sro_tn z n = fmap (z_add z n) -- | Invert /p/ about /n/. ----- > invert 5 0 [0,1,4] == [0,4,1]--- > invert 12 6 [4,5,6] == [8,7,6]--- > invert 12 0 [0,1,3] == [0,11,9]-invert :: (Integral i, Functor f) => i -> i -> f i -> f i-invert z n = fmap (\p -> z_sub z n (z_sub z p n))+-- > z_sro_invert mod5 0 [0,1,4] == [0,4,1]+-- > z_sro_invert mod12 6 [4,5,6] == [8,7,6]+-- > z_sro_invert mod12 0 [0,1,3] == [0,11,9]+--+-- > import Data.Word {- base -}+-- > z_sro_invert mod12 (0::Word8) [1,4,8]+z_sro_invert :: (Integral i, Functor f) => Z i -> i -> f i -> f i+z_sro_invert z n = fmap (\p -> z_sub z n (z_sub z p n)) -- | Composition of 'invert' about @0@ and 'tn'. ----- > tni 5 1 [0,1,3] == [1,0,3]--- > tni 12 4 [1,5,6] == [3,11,10]--- > (invert 12 0 . tn 12 4) [1,5,6] == [7,3,2]-tni :: (Integral i, Functor f) => i -> i -> f i -> f i-tni z n = tn z n . invert z 0+-- > z_sro_tni mod5 1 [0,1,3] == [1,0,3]+-- > z_sro_tni mod12 4 [1,5,6] == [3,11,10]+-- > (z_sro_invert mod12 0 . z_sro_tn mod12 4) [1,5,6] == [7,3,2]+z_sro_tni :: (Integral i, Functor f) => Z i -> i -> f i -> f i+z_sro_tni z n = z_sro_tn z n . z_sro_invert z 0 -- | Modulo multiplication. ----- > mn 12 11 [0,1,4,9] == tni 12 0 [0,1,4,9]-mn :: (Integral i, Functor f) => i -> i -> f i -> f i-mn z n = fmap (z_mul z n)+-- > z_sro_mn mod12 11 [0,1,4,9] == z_tni mod12 0 [0,1,4,9]+z_sro_mn :: (Integral i, Functor f) => Z i -> i -> f i -> f i+z_sro_mn z n = fmap (z_mul z n) -- | T-related sequences of /p/. ----- > length (t_related 12 [0,3,6,9]) == 12-t_related :: (Integral i, Functor f) => i -> f i -> [f i]-t_related z p = fmap (\n -> tn z n p) [0..11]+-- > length (z_sro_t_related mod12 [0,3,6,9]) == 12+-- > z_sro_t_related mod5 [0,2] == [[0,2],[1,3],[2,4],[3,0],[4,1]]+z_sro_t_related :: (Integral i, Functor f) => Z i -> f i -> [f i]+z_sro_t_related z p = fmap (\n -> z_sro_tn z n p) (z_univ z) -- | T\/I-related sequences of /p/. ----- > length (ti_related 12 [0,1,3]) == 24--- > length (ti_related 12 [0,3,6,9]) == 24--- > ti_related 12 [0] == map return [0..11]-ti_related :: (Eq (f i), Integral i, Functor f) => i -> f i -> [f i]-ti_related z p = nub (t_related z p ++ t_related z (invert z 0 p))+-- > length (z_sro_ti_related mod12 [0,1,3]) == 24+-- > length (z_sro_ti_related mod12 [0,3,6,9]) == 24+-- > z_sro_ti_related mod12 [0] == map return [0..11]+z_sro_ti_related :: (Eq (f i), Integral i, Functor f) => Z i -> f i -> [f i]+z_sro_ti_related z p = nub (z_sro_t_related z p ++ z_sro_t_related z (z_sro_invert z 0 p)) -- | R\/T\/I-related sequences of /p/. ----- > length (rti_related 12 [0,1,3]) == 48--- > length (rti_related 12 [0,3,6,9]) == 24-rti_related :: Integral i => i -> [i] -> [[i]]-rti_related z p = let q = ti_related z p in nub (q ++ map reverse q)+-- > length (z_sro_rti_related mod12 [0,1,3]) == 48+-- > length (z_sro_rti_related mod12 [0,3,6,9]) == 24+z_sro_rti_related :: Integral i => Z i -> [i] -> [[i]]+z_sro_rti_related z p = let q = z_sro_ti_related z p in nub (q ++ map reverse q) -- * Sequence operations -- | Variant of 'tn', transpose /p/ so first element is /n/. ----- > tn_to 12 5 [0,1,3] == [5,6,8]--- > map (tn_to 12 0) [[0,1,3],[1,3,0],[3,0,1]]-tn_to :: Integral a => a -> a -> [a] -> [a]-tn_to z n p =+-- > z_sro_tn_to mod12 5 [0,1,3] == [5,6,8]+-- > map (z_sro_tn_to mod12 0) [[0,1,3],[1,3,0],[3,0,1]]+z_sro_tn_to :: Integral i => Z i -> i -> [i] -> [i]+z_sro_tn_to z n p = case p of [] -> []- x:xs -> n : tn z (z_sub z n x) xs+ x:xs -> n : z_sro_tn z (z_sub z n x) xs -- | Variant of 'invert', inverse about /n/th element. ----- > map (invert_ix 12 0) [[0,1,3],[3,4,6]] == [[0,11,9],[3,2,0]]--- > map (invert_ix 12 1) [[0,1,3],[3,4,6]] == [[2,1,11],[5,4,2]]-invert_ix :: Integral i => i -> Int -> [i] -> [i]-invert_ix z n p = invert z (p !! n) p+-- > map (z_sro_invert_ix mod12 0) [[0,1,3],[3,4,6]] == [[0,11,9],[3,2,0]]+-- > map (z_sro_invert_ix mod12 1) [[0,1,3],[3,4,6]] == [[2,1,11],[5,4,2]]+z_sro_invert_ix :: Integral i => Z i -> Int -> [i] -> [i]+z_sro_invert_ix z n p = z_sro_invert z (p !! n) p -- | The standard t-matrix of /p/. ----- > tmatrix 12 [0,1,3] == [[0,1,3]--- > ,[11,0,2]--- > ,[9,10,0]]-tmatrix :: Integral i => i -> [i] -> [[i]]-tmatrix z p = map (\n -> tn z n p) (tn_to z 0 (invert_ix z 0 p))+-- > z_tmatrix mod12 [0,1,3] == [[0,1,3],[11,0,2],[9,10,0]]+z_tmatrix :: Integral i => Z i -> [i] -> [[i]]+z_tmatrix z p = map (\n -> z_sro_tn z n p) (z_sro_tn_to z 0 (z_sro_invert_ix z 0 p))
+ Music/Theory/Z/TTO.hs view
@@ -0,0 +1,75 @@+module Music.Theory.Z.TTO where++import Data.List {- base -}+import Data.Maybe {- base -}+import qualified Text.ParserCombinators.Parsec as P {- parsec -}++import qualified Music.Theory.Parse as T+import qualified Music.Theory.Set.List as T+import Music.Theory.Z++-- | Twelve-tone operator, of the form TMI.+data TTO t = TTO {tto_T :: t,tto_M :: Bool,tto_I :: Bool}+ deriving (Eq,Show)++tto_identity :: Num t => TTO t+tto_identity = TTO 0 False False++-- | Pretty printer.+tto_pp :: Show t => TTO t -> String+tto_pp (TTO t m i) = concat ['T' : show t,if m then "M" else "",if i then "I" else ""]++p_tto :: Integral t => P.GenParser Char () (TTO t)+p_tto = do+ _ <- P.char 'T'+ t <- T.parse_int+ m <- T.is_char 'M'+ i <- T.is_char 'I'+ P.eof+ return (TTO t m i)++-- | Parser, transposition must be decimal.+--+-- > map (tto_pp . tto_parse) (words "T5 T3I T11M T9MI")+tto_parse :: Integral i => String -> TTO i+tto_parse = either (\e -> error ("tto_parse failed\n" ++ show e)) id . P.parse p_tto ""++-- | The set of all 'TTO', given 'Z' function.+--+-- > length (z_tto_univ mod12) == 48+-- > map tto_pp (z_tto_univ mod12)+z_tto_univ :: Integral t => Z t -> [TTO t]+z_tto_univ z = [TTO t m i | m <- [False,True], i <- [False,True], t <- z_univ z]++-- | M is ordinarily 5, but can be specified here.+--+-- > map (z_tto_f 5 mod12 (tto_parse "T1M")) [0,1,2,3] == [1,6,11,4]+z_tto_f :: Integral t => t -> Z t -> TTO t -> (t -> t)+z_tto_f mn z (TTO t m i) =+ let i_f = if i then z_negate z else id+ m_f = if m then z_mul z mn else id+ t_f = if t > 0 then z_add z t else id+ in t_f . m_f . i_f++-- | 'sort' of 'map' 'z_tto_f'.+--+-- > z_tto_apply 5 mod12 (tto_parse "T1M") [0,1,2,3] == [1,4,6,11]+z_tto_apply :: Integral t => t -> Z t -> TTO t -> [t] -> [t]+z_tto_apply mn z o = sort . map (z_tto_f mn z o)++tto_apply :: Integral t => t -> TTO t -> [t] -> [t]+tto_apply mn = z_tto_apply mn id++-- | Find 'TTO' that that map /x/ to /y/ given /m/ and /z/.+--+-- > map tto_pp (z_tto_rel 5 mod12 [0,1,2,3] [6,4,1,11]) == ["T1M","T4MI"]+z_tto_rel :: (Ord t,Integral t) => t -> Z t -> [t] -> [t] -> [TTO t]+z_tto_rel m z x y =+ let q = T.set y+ in mapMaybe (\o -> if z_tto_apply m z o x == q then Just o else Nothing) (z_tto_univ z)++-- | 'nub' of 'sort' of 'map' /z/.+--+-- > map (z_pcset mod12) [[0,6],[6,12],[12,18]] == replicate 3 [0,6]+z_pcset :: Ord t => Z t -> [t] -> [t]+z_pcset z = nub . sort . map z
Music/Theory/Z12.hs view
@@ -1,102 +1,111 @@-{-# Language GeneralizedNewtypeDeriving #-}-module Music.Theory.Z12 where+{-# Language DataKinds #-}+{- | Z12 -import Data.List {- base -}+Z12 are modulo 12 integers. --- | Z12 are modulo 12 integers.------ > map signum [-1,0::Z12,1] == [1,0,1]--- > map abs [-1,0::Z12,1] == [11,0,1]-newtype Z12 = Z12 Int deriving (Eq,Ord,Integral,Real)+> map signum [-1,0::Z12,1] == [1,0,1]+> map abs [-1,0::Z12,1] == [11,0,1] --- | Cyclic 'Enum' instance for Z12.------ > pred (0::Z12) == 11--- > succ (11::Z12) == 0--- > [9::Z12 .. 3] == [9,10,11,0,1,2,3]--- > [9::Z12,11 .. 3] == [9,11,1,3]-instance Enum Z12 where- pred = subtract 1- succ = (+) 1- toEnum = fromIntegral- fromEnum = fromIntegral- enumFromThenTo n m o =- let m' = m + (m - n)- in if m' == o then [n,m,o] else n : enumFromThenTo m m' o- enumFromTo n m =- let n' = succ n- in if n' == m then [n,m] else n : enumFromTo n' m+Aspects of the 'Enum' instance are cyclic. --- | 'Bounded' instance for Z12.------ > [minBound::Z12 .. maxBound] == [0::Z12 .. 11]-instance Bounded Z12 where- minBound = Z12 0- maxBound = Z12 11+> pred (0::Z12) == 11+> succ (11::Z12) == 0 --- | The Z12 modulo (ie. @12@) as a 'Z12' value. This is required--- when lifting generalised @Z@ functions to 'Z12'. It is /not/ the--- same as writing @12::Z12@.------ > z12_modulo == Z12 12--- > z12_modulo /= 12--- > (12::Z12) == 0--- > show z12_modulo == "(Z12 12)"-z12_modulo :: Z12-z12_modulo = Z12 12+'Bounded' works --- | Basis for Z12 show instance.------ > map show [-1,0::Z12,1,z12_modulo] == ["11","0","1","(Z12 12)"]-z12_showsPrec :: Int -> Z12 -> ShowS-z12_showsPrec p (Z12 i) =- let x = showsPrec p i- in if i < 0 || i > 11- then showString "(Z12 " . x . showString ")"- else x+> [minBound::Z12 .. maxBound] == [0::Z12 .. 11] -instance Show Z12 where showsPrec = z12_showsPrec+-}+module Music.Theory.Z12 where --- | Lift unary function over integers to Z12.+import Data.Char {- base -}+import Data.List {- base -}+import qualified Data.Modular as M {- modular-arithmetic -}+import qualified GHC.TypeLits as L {- base -}++import qualified Music.Theory.List as T {- hmt -}++-- | 'Mod' 'Int'.+type Z n = M.Mod Int n++-- | 'Z' 12. ----- > lift_unary_Z12 (negate) 7 == 5-lift_unary_Z12 :: (Int -> Int) -> Z12 -> Z12-lift_unary_Z12 f (Z12 a) = Z12 (f a `mod` 12)+-- > map negate [0::Z12 .. 0xB] == [0,0xB,0xA,9,8,7,6,5,4,3,2,1]+-- > map (+ 5) [0::Z12 .. 11] == [5,6,7,8,9,0xA,0xB,0,1,2,3,4]+type Z12 = M.Mod Int 12 --- | Lift unary function over integers to Z12.+-- | Cyclic form of 'enumFromThenTo'. ----- > map (lift_binary_Z12 (+) 4) [1,5,6] == [5,9,10]-lift_binary_Z12 :: (Int -> Int -> Int) -> Z12 -> Z12 -> Z12-lift_binary_Z12 f (Z12 a) (Z12 b) = Z12 (mod (a `f` b) 12)+-- > [9::Z12,11 .. 3] == []+-- > enumFromThenTo_cyc (9::Z12) 11 3 == [9,11,1,3]+enumFromThenTo_cyc :: L.KnownNat n => Z n -> Z n -> Z n -> [Z n]+enumFromThenTo_cyc n m o =+ let m' = m + (m - n)+ in case compare m' o of+ LT -> n : enumFromThenTo_cyc m m' o+ EQ -> [n,m,o]+ GT -> [n,m] --- | Raise an error if the internal 'Z12' value is negative.-check_negative :: (Int -> Int) -> Z12 -> Z12-check_negative f (Z12 n) =- if n < 0- then error "check_negative: negative Z12"- else Z12 (f n)+-- | Cyclic form of 'enumFromTo'.+--+-- > [9::Z12 .. 3] == []+-- > enumFromTo_cyc (9::Z12) 3 == [9,10,11,0,1,2,3]+enumFromTo_cyc :: L.KnownNat n => Z n -> Z n -> [Z n]+enumFromTo_cyc n m =+ let n' = succ n+ in if n' == m then [n,m] else n : enumFromTo_cyc n' m -instance Num Z12 where- (+) = lift_binary_Z12 (+)- (-) = lift_binary_Z12 (-)- (*) = lift_binary_Z12 (*)- negate = lift_unary_Z12 negate- fromInteger n = Z12 (fromInteger n `mod` 12)- signum = check_negative signum- abs = check_negative abs+{-+-} -- | Convert integral to 'Z12'. -- -- > map to_Z12 [-9,-3,0,13] == [3,9,0,1] to_Z12 :: Integral i => i -> Z12-to_Z12 = fromIntegral+to_Z12 = M.toMod . fromIntegral +int_to_Z12 :: Int -> Z12+int_to_Z12 = to_Z12+ -- | Convert 'Z12' to integral. from_Z12 :: Integral i => Z12 -> i-from_Z12 = fromIntegral+from_Z12 = fromIntegral . M.unMod +int_from_Z12 :: Z12 -> Int+int_from_Z12 = from_Z12+ -- | Z12 not in set. -- -- > complement [0,2,4,5,7,9,11] == [1,3,6,8,10] complement :: [Z12] -> [Z12] complement = (\\) [0 .. 11]++-- | Z12 to character (10 -> A, 11 -> B).+--+-- > map z12_to_char [0 .. 11] == "0123456789AB"+z12_to_char :: Z12 -> Char+z12_to_char = toUpper . intToDigit . M.unMod++-- | Z12 to character (10 -> A, 11 -> B).+--+-- > map char_to_z12 "0123456789AB" == [0..11]+char_to_z12 :: Char -> Z12+char_to_z12 = to_Z12 . digitToInt++-- | Unordered set notation (braces).+--+-- > z12_set_pp [0,1,3] == "{013}"+z12_set_pp :: [Z12] -> String+z12_set_pp = T.bracket ('{','}') . map z12_to_char++-- | Ordered sequence notation (angle brackets).+--+-- > z12_seq_pp [0,1,3] == "<013>"+z12_seq_pp :: [Z12] -> String+z12_seq_pp = T.bracket ('<','>') . map z12_to_char++-- | Ordered vector notation (square brackets).+--+-- > z12_vec_pp [0,1,3] == "[013]"+z12_vec_pp :: [Z12] -> String+z12_vec_pp = T.bracket ('[',']') . map z12_to_char
Music/Theory/Z12/Castren_1994.hs view
@@ -7,17 +7,18 @@ import Data.Ratio {- base -} import qualified Music.Theory.List as T-import Music.Theory.Z12 (Z12)-import qualified Music.Theory.Z12.Forte_1973 as T-import qualified Music.Theory.Z12.TTO as T+import Music.Theory.Z (mod12)+import qualified Music.Theory.Z.SRO as T+import qualified Music.Theory.Z.Forte_1973 as T +type Z12 = Int+ -- | Is /p/ symmetrical under inversion. ----- > import Music.Theory.Z12.Forte_1973--- > map inv_sym (scs_n 2) == [True,True,True,True,True,True]--- > map (fromEnum.inv_sym) (scs_n 3) == [1,0,0,0,0,1,0,0,1,1,0,1]+-- > map inv_sym (T.scs_n 2) == [True,True,True,True,True,True]+-- > map (fromEnum.inv_sym) (T.scs_n 3) == [1,0,0,0,0,1,0,0,1,1,0,1] inv_sym :: [Z12] -> Bool-inv_sym x = x `elem` map (\i -> sort (T.tn i (T.invert 0 x))) [0..11]+inv_sym x = x `elem` map (\i -> sort (T.z_sro_tn mod12 i (T.z_sro_invert mod12 0 x))) [0..11] -- | If /p/ is not 'inv_sym' then @(p,invert 0 p)@ else 'Nothing'. --@@ -27,7 +28,7 @@ sc_t_ti p = if inv_sym p then Nothing- else Just (p,T.t_prime (T.invert 0 p))+ else Just (p,T.t_prime mod12 (T.z_sro_invert mod12 0 p)) -- | Transpositional equivalence variant of Forte's 'sc_table'. The -- inversionally related classes are distinguished by labels @A@ and@@ -35,11 +36,11 @@ -- always the @A@ class. If neither @A@ nor @B@ appears in the name of -- a set-class, it is inversionally symmetrical. ----- > (length sc_table,length t_sc_table) == (224,352)+-- > (length T.sc_table,length t_sc_table) == (224,352) -- > lookup "5-Z18B" t_sc_table == Just [0,2,3,6,7] t_sc_table :: [(T.SC_Name,[Z12])] t_sc_table =- let f x = let nm = T.sc_name x+ let f x = let nm = T.sc_name mod12 x in case sc_t_ti x of Nothing -> [(nm,x)] Just (p,q) -> [(nm++"A",p),(nm++"B",q)]@@ -52,7 +53,7 @@ -- > t_sc_name [0,1,4,6,7,8] == "6-Z17B" t_sc_name :: [Z12] -> T.SC_Name t_sc_name p =- let n = find (\(_,q) -> T.t_prime p == q) t_sc_table+ let n = find (\(_,q) -> T.t_prime mod12 p == q) t_sc_table in fst (fromJust n) -- | Lookup a set-class given a set-class name.@@ -77,7 +78,7 @@ -- > t_subsets [0,1,2,3,4] [0,1,4] == [[0,1,4]] -- > t_subsets [0,2,3,6,7] [0,1,4] == [[2,3,6]] t_subsets :: [Z12] -> [Z12] -> [[Z12]]-t_subsets x a = filter (`T.is_subset` x) (T.t_related a)+t_subsets x a = filter (`T.is_subset` x) (map sort (T.z_sro_t_related mod12 a)) -- | T\/I-related /q/ that are subsets of /p/. --@@ -85,7 +86,7 @@ -- > ti_subsets [0,1,2,3,4] [0,1,4] == [[0,1,4],[0,3,4]] -- > ti_subsets [0,2,3,6,7] [0,1,4] == [[2,3,6],[3,6,7]] ti_subsets :: [Z12] -> [Z12] -> [[Z12]]-ti_subsets x a = filter (`T.is_subset` x) (T.ti_related a)+ti_subsets x a = filter (`T.is_subset` x) (nub (map sort (T.z_sro_ti_related mod12 a))) -- | Trivial run length encoder. --@@ -135,7 +136,7 @@ -- > dyad_class_percentage_vector [0,1,4,5,7] == [20,10,20,20,20,10] dyad_class_percentage_vector :: Integral i => [Z12] -> [i] dyad_class_percentage_vector p =- let p' = T.icv p+ let p' = T.icv 12 p in map (sum p' *) p' -- | /rel/ metric.
Music/Theory/Z12/Drape_1999.hs view
@@ -1,19 +1,26 @@ -- | Haskell implementations of @pct@ operations.--- See <http://slavepianos.org/rd/?t=pct>.+-- See <http://slavepianos.org/rd/t/pct>. module Music.Theory.Z12.Drape_1999 where import Data.Function {- base -} import Data.List {- base -} import Data.Maybe {- base -}+import Safe {- safe -} import qualified Music.Theory.List as T import qualified Music.Theory.Set.List as T-import Music.Theory.Z12-import qualified Music.Theory.Z12.Forte_1973 as T-import qualified Music.Theory.Z12.Morris_1987 as T-import qualified Music.Theory.Z12.TTO as TTO-import qualified Music.Theory.Z12.SRO as SRO+import qualified Music.Theory.Tuple as T +import qualified Music.Theory.Z as Z+import qualified Music.Theory.Z.SRO as Z+import qualified Music.Theory.Z.TTO as Z++import Music.Theory.Z12 (Z12)+import qualified Music.Theory.Z12 as Z12+import qualified Music.Theory.Z12.Forte_1973 as Z12+import qualified Music.Theory.Z12.TTO as Z12+import qualified Music.Theory.Z12.SRO as Z12+ -- | Cardinality filter -- -- > cf [0,3] (cg [1..4]) == [[1,2,3],[1,2,4],[1,3,4],[2,3,4],[]]@@ -24,6 +31,7 @@ -- values for slot. -- -- > cgg [[0,1],[5,7],[3]] == [[0,5,3],[0,7,3],[1,5,3],[1,7,3]]+-- > let n = "01" in cgg [n,n,n] == ["000","001","010","011","100","101","110","111"] cgg :: [[a]] -> [[a]] cgg l = case l of@@ -38,7 +46,7 @@ -- | Powerset filtered by cardinality. ----- >>> cg -r3 0159+-- >>> pct cg -r3 0159 -- 015 -- 019 -- 059@@ -48,22 +56,49 @@ cg_r :: (Integral n) => n -> [a] -> [[a]] cg_r n = cf [n] . cg --- | Cyclic interval segment.+{- | Chain pcsegs.++>>> echo 024579 | pct chn T0 3 | sort -u+579468 (RT8M)+579A02 (T5)++> chn_t0 3 [0,2,4,5,7,9] == [[5,7,9,10,0,2],[5,7,9,4,6,8]]++>>> echo 02457t | pct chn T0 2+7A0135 (RT5I)+7A81B9 (RT9MI)++> chn_t0 2 [0,2,4,5,7,10] == [[7,10,0,1,3,5],[7,10,8,1,11,9]]++-}+chn_t0 :: Int -> [Z12] -> [[Z12]]+chn_t0 n p =+ let f q = T.take_right n p == take n q+ in filter f (Z12.sro_rtmi_related p)++{- | Cyclic interval segment.++>>> echo 014295e38t76 | pct cisg+13A7864529B6++> ciseg [0,1,4,2,9,5,11,3,8,10,7,6] == [1,3,10,7,8,6,4,5,2,9,11,6]++-} ciseg :: [Z12] -> [Z12]-ciseg = T.int . cyc+ciseg = T.d_dx . cyc -- | Synonynm for 'complement'. ----- >>> cmpl 02468t+-- >>> pct cmpl 02468t -- 13579B -- -- > cmpl [0,2,4,6,8,10] == [1,3,5,7,9,11] cmpl :: [Z12] -> [Z12]-cmpl = complement+cmpl = Z12.complement -- | Form cycle. ----- >>> cyc 056+-- >>> echo 056 | pct cyc -- 0560 -- -- > cyc [0,5,6] == [0,5,6,0]@@ -86,7 +121,7 @@ -- | Diatonic implications. dim :: [Z12] -> [(Z12,[Z12])] dim p =- let g (i,q) = T.is_subset p (TTO.tn i q)+ let g (i,q) = T.is_subset p (Z12.tto_tn i q) f = filter g . zip [0..11] . repeat d = [0,2,4,5,7,9,11] m = [0,2,3,5,7,9,11]@@ -95,7 +130,7 @@ -- | Variant of 'dim' that is closer to the 'pct' form. ----- >>> dim 016+-- >>> pct dim 016 -- T1d -- T1m -- T0o@@ -110,7 +145,7 @@ -- | Diatonic interval set to interval set. ----- >>> dis 24+-- >>> pct dis 24 -- 1256 -- -- > dis [2,4] == [1,2,5,6]@@ -121,59 +156,106 @@ -- | Degree of intersection. ----- >>> echo 024579e | doi 6 | sort -u+-- >>> echo 024579e | pct doi 6 | sort -u -- 024579A -- 024679B -- -- > let p = [0,2,4,5,7,9,11] -- > in doi 6 p p == [[0,2,4,5,7,9,10],[0,2,4,6,7,9,11]] ----- >>> echo 01234 | doi 2 7-35 | sort -u+-- >>> echo 01234 | pct doi 2 7-35 | sort -u -- 13568AB -- -- > doi 2 (T.sc "7-35") [0,1,2,3,4] == [[1,3,5,6,8,10,11]] doi :: Int -> [Z12] -> [Z12] -> [[Z12]] doi n p q =- let f j = [TTO.tn j p,TTO.tni j p]+ let f j = [Z12.tto_tn j p,Z12.tto_tni j p] xs = concatMap f [0..11] in T.set (filter (\x -> length (x `intersect` q) == n) xs) -- | Forte name. fn :: [Z12] -> String-fn = T.sc_name+fn = Z12.sc_name --- | p `has_ess` q is true iff p can embed q in sequence.-has_ess :: [Z12] -> [Z12] -> Bool-has_ess _ [] = True-has_ess [] _ = False-has_ess (p:ps) (q:qs) = if p == q- then has_ess ps qs- else has_ess ps (q:qs)+-- | Z12 cycles.+frg_cyc :: T.T6 [[Z12]]+frg_cyc =+ let c1 = [[0..11]]+ c2 = map (\n -> map (+ n) [0,2..10]) [0..1]+ c3 = map (\n -> map (+ n) [0,3..9]) [0..2]+ c4 = map (\n -> map (+ n) [0,4..8]) [0..3]+ c5 = map (map (* 5)) c1+ c6 = map (\n -> map (+ n) [0,6]) [0..5]+ in (c1,c2,c3,c4,c5,c6) +-- | Fragmentation of cycles.+frg :: [Z12] -> T.T6 [String]+frg p =+ let f = map (\n -> if n `elem` p then Z12.z12_to_char n else '-')+ in T.t6_map (map f) frg_cyc++ic_cycle_vector :: [Z12] -> T.T6 [Int]+ic_cycle_vector p =+ let f str = let str' = if length str > 2 then T.close str else str+ in length (filter (\(x,y) -> x /= '-' && y /= '-') (T.adj2 1 str'))+ in T.t6_map (map f) (frg p)++-- | Pretty printer for 'ic_cycle_vector'.+--+-- > let r = "IC cycle vector: <1> <22> <111> <1100> <5> <000000>"+-- > in ic_cycle_vector_pp (ic_cycle_vector [0,2,4,5,7,9]) == r+ic_cycle_vector_pp :: T.T6 [Int] -> String+ic_cycle_vector_pp = ("IC cycle vector: " ++) . unwords . T.t6_to_list . T.t6_map Z.z16_seq_pp++frg_hdr :: [String]+frg_hdr = map (\n -> "Fragmentation of " ++ show n ++ "-cycle(s)") [1::Int .. 6]++{-| Fragmentation of cycles.++>>> pct frg 024579+Fragmentation of 1-cycle(s): [0-2-45-7-9--]+Fragmentation of 2-cycle(s): [024---] [--579-]+Fragmentation of 3-cycle(s): [0--9] [-47-] [25--]+Fragmentation of 4-cycle(s): [04-] [-59] [2--] [-7-]+Fragmentation of 5-cycle(s): [05------4927]+Fragmentation of 6-cycle(s): [0-] [-7] [2-] [-9] [4-] [5-]+IC cycle vector: <1> <22> <111> <1100> <5> <000000>++> putStrLn $ frg_pp [0,2,4,5,7,9]+-}+frg_pp :: [Z12] -> String+frg_pp =+ let f = unwords . map (\p -> T.bracket ('[',']') p)+ g x y = x ++ ": " ++ y+ in unlines . zipWith g frg_hdr . T.t6_to_list . T.t6_map f . frg+ -- | Embedded segment search. ----- >>> echo 23a | ess 0164325+-- >>> echo 23A | pct ess 0164325 -- 2B013A9 -- 923507A ----- > ess [2,3,10] [0,1,6,4,3,2,5] == [[9,2,3,5,0,7,10],[2,11,0,1,3,10,9]]+-- > ess [0,1,6,4,3,2,5] [2,3,10] == [[9,2,3,5,0,7,10],[2,11,0,1,3,10,9]] ess :: [Z12] -> [Z12] -> [[Z12]]-ess p = filter (`has_ess` p) . SRO.rtmi_related+ess p q = filter (`T.is_embedding` q) (Z12.sro_rtmi_related p) -- | Can the set-class q (under prime form algorithm pf) be -- drawn from the pcset p. has_sc_pf :: (Integral a) => ([a] -> [a]) -> [a] -> [a] -> Bool has_sc_pf pf p q = let n = length q- in q `elem` map pf (cf [n] (cg p))+ in pf q `elem` map pf (cf [n] (cg p)) -- | Can the set-class q be drawn from the pcset p.+--+-- > let d = [0,2,4,5,7,9,11] in has_sc d (complement d) == True+-- > has_sc [] [] == True has_sc :: [Z12] -> [Z12] -> Bool-has_sc = has_sc_pf T.forte_prime+has_sc = has_sc_pf Z12.forte_prime -- | Interval cycle filter. ----- >>> echo 22341 | icf+-- >>> echo 22341 | pct icf -- 22341 -- -- > icf [[2,2,3,4,1]] == [[2,2,3,4,1]]@@ -182,7 +264,7 @@ -- | Interval class set to interval sets. ----- >>> ici -c 123+-- >>> pct ici -c 123 -- 123 -- 129 -- 1A3@@ -204,51 +286,57 @@ -- | Interval-class segment. ----- >>> icseg 013265e497t8+-- >>> pct icseg 013265e497t8 -- 12141655232 -- -- > icseg [0,1,3,2,6,5,11,4,9,7,10,8] == [1,2,1,4,1,6,5,5,2,3,2] icseg :: [Z12] -> [Z12]-icseg = map T.ic . iseg+icseg = map Z12.ic . iseg -- | Interval segment (INT). iseg :: [Z12] -> [Z12]-iseg = T.int+iseg = T.d_dx -- | Imbrications.-imb :: (Integral n) => [n] -> [a] -> [[a]]+--+-- > let r = [[[0,2,4],[2,4,5],[4,5,7],[5,7,9]]+-- > ,[[0,2,4,5],[2,4,5,7],[4,5,7,9]]]+-- > in imb [3,4] [0,2,4,5,7,9] == r+imb :: (Integral n) => [n] -> [a] -> [[[a]]] imb cs p = let g n = (== n) . genericLength f ps n = filter (g n) (map (genericTake n) ps)- in concatMap (f (tails p)) cs+ in map (f (tails p)) cs --- | 'issb' gives the set-classes that can append to 'p' to give 'q'.------ >>> issb 3-7 6-32--- 3-7--- 3-2--- 3-11------ > issb (T.sc "3-7") (T.sc "6-32") == ["3-2","3-7","3-11"]+{- | 'issb' gives the set-classes that can append to 'p' to give 'q'.++>>> pct issb 3-7 6-32+3-7+3-2+3-11++> issb (T.sc "3-7") (T.sc "6-32") == ["3-2","3-7","3-11"]++-} issb :: [Z12] -> [Z12] -> [String] issb p q = let k = length q - length p- f = any id . map (\x -> T.forte_prime (p ++ x) == q) . TTO.ti_related- in map T.sc_name (filter f (cf [k] T.scs))+ f = any id . map (\x -> Z12.forte_prime (p ++ x) == q) . Z12.tto_ti_related+ in map Z12.sc_name (filter f (cf [k] Z12.scs)) -- | Matrix search. ----- >>> mxs 024579 642 | sort -u+-- >>> pct mxs 024579 642 | sort -u -- 6421B9 -- B97642 -- -- > T.set (mxs [0,2,4,5,7,9] [6,4,2]) == [[6,4,2,1,11,9],[11,9,7,6,4,2]] mxs :: [Z12] -> [Z12] -> [[Z12]]-mxs p q = filter (q `isInfixOf`) (SRO.rti_related p)+mxs p q = filter (q `isInfixOf`) (Z12.sro_rti_related p) -- | Normalize. ----- >>> nrm 0123456543210+-- >>> pct nrm 0123456543210 -- 0123456 -- -- > nrm [0,1,2,3,4,5,6,5,4,3,2,1,0] == [0,1,2,3,4,5,6]@@ -259,84 +347,242 @@ nrm_r :: (Ord a) => [a] -> [a] nrm_r = sort --- | Pitch-class invariances (called @pi@ at @pct@).------ >>> pi 0236 12--- 0236--- 6320--- 532B--- B235------ > pci [0,2,3,6] [1,2] == [[0,2,3,6],[5,3,2,11],[6,3,2,0],[11,2,3,5]]-pci :: [Z12] -> [Z12] -> [[Z12]]-pci p i =- let f q = T.set (map (q `genericIndex`) i)- in filter (\q -> f q == f p) (SRO.rti_related p)+{- | Pitch-class invariances (called @pi@ at @pct@). --- | Relate sets.+>>> pct pi 0236 12+pcseg 0236+pcseg 6320+pcseg 532B+pcseg B235++> pci [1,2] [0,2,3,6] == [[0,2,3,6],[5,3,2,11],[6,3,2,0],[11,2,3,5]]++-}+pci :: [Int] -> [Z12] -> [[Z12]]+pci i p =+ let f q = T.set (map (q !!) i)+ in filter (\q -> f q == f p) (Z12.sro_rti_related p)++-- | Relate sets (TnMI). ----- >>> rs 0123 641e+-- >>> pct rs 0123 641e -- T1M ----- > import Music.Theory.Z12.Morris_1987.Parse--- > rs [0,1,2,3] [6,4,1,11] == [(rnrtnmi "T1M",[1,6,11,4])--- > ,(rnrtnmi "T4MI",[4,11,6,1])]-rs :: [Z12] -> [Z12] -> [(T.SRO, [Z12])]+-- > rs [0,1,2,3] [6,4,1,11] == [(Z.tto_parse "T1M",[1,6,11,4])+-- > ,(Z.tto_parse "T4MI",[4,11,6,1])]+rs :: [Z12] -> [Z12] -> [(Z.TTO Z12, [Z12])] rs x y =- let xs = map (\o -> (o, o `T.sro` x)) T.sro_TnMI+ let xs = map (\o -> (o,Z.z_tto_apply 5 id o x)) (Z.z_tto_univ id) q = T.set y in filter (\(_,p) -> T.set p == q) xs --- | Relate segments.------ >>> rsg 156 3BA--- T4I------ > rsg [1,5,6] [3,11,10] == [rnrtnmi "T4I",rnrtnmi "r1RT4MI"]------ >>> rsg 0123 05t3--- T0M------ > rsg [0,1,2,3] [0,5,10,3] == [rnrtnmi "T0M",rnrtnmi "RT3MI"]------ >>> rsg 0123 4e61--- RT1M------ > rsg [0,1,2,3] [4,11,6,1] == [rnrtnmi "T4MI",rnrtnmi "RT1M"]------ >>> echo e614 | rsg 0123--- r3RT1M------ > rsg [0,1,2,3] [11,6,1,4] == [rnrtnmi "r1T4MI",rnrtnmi "r1RT1M"]----rsg :: [Z12] -> [Z12] -> [T.SRO]-rsg x y = map fst (filter (\(_,x') -> x' == y) (T.sros x))+rs1 :: [Z12] -> [Z12] -> Maybe (Z.TTO Z12)+rs1 p = fmap fst . headMay . rs p +{- | Relate segments.++>>> pct rsg 156 3BA+T4I++> rsg [1,5,6] [3,11,10] == [Z.sro_parse "T4I",Z.sro_parse "r1RT4MI"]++>>> pct rsg 0123 05t3+T0M++> rsg [0,1,2,3] [0,5,10,3] == [Z.sro_parse "T0M",Z.sro_parse "RT3MI"]++>>> pct rsg 0123 4e61+RT1M++> rsg [0,1,2,3] [4,11,6,1] == [Z.sro_parse "T4MI",Z.sro_parse "RT1M"]++>>> echo e614 | pct rsg 0123+r3RT1M++> rsg [0,1,2,3] [11,6,1,4] == [Z.sro_parse "r1T4MI",Z.sro_parse "r1RT1M"]++-}+rsg :: [Z12] -> [Z12] -> [Z.SRO Z12]+rsg x y = filter (\o -> sro o x == y) (Z.z_sro_univ (length x) id)+ -- | Subsets. sb :: [[Z12]] -> [[Z12]] sb xs = let f p = all id (map (`has_sc` p) xs)- in filter f T.scs+ in filter f Z12.scs --- | Super set-class.------ >>> spsc 4-11 4-12--- 5-26[02458]------ > spsc [T.sc "4-11",T.sc "4-12"] == ["5-26"]------ >>> spsc 3-11 3-8--- 4-27[0258]--- 4-Z29[0137]------ > spsc [T.sc "3-11",T.sc "3-8"] == ["4-27","4-Z29"]------ >>> spsc `fl 3`--- 6-Z17[012478]+{- | scc = set class completion++>>> pct scc 6-32 168+35A+49B+3AB+34B++> scc (Z12.sc "6-32") [1,6,8] == [[3,5,10],[4,9,11],[3,10,11],[3,4,11]]++-}+scc :: [Z12] -> [Z12] -> [[Z12]]+scc r p = map (\\ p) (filter (T.is_subset p) (Z12.tto_ti_related r))++si_hdr :: [String]+si_hdr =+ ["pitch-class-set"+ ,"set-class"+ ,"interval-class-vector"+ ,"tics"+ ,"complement"+ ,"multiplication-by-five-transform"]++type SI = ([Z12],Z.TTO Z12,[Z12])++-- > si_raw [0,5,3,11]+si_raw :: [Z12] -> (SI,[Z12],[Int],SI,SI)+si_raw p =+ let n = length p+ p_icv = Z12.to_Z12 n : Z12.icv p+ gen_si x = let x_f = Z12.forte_prime x+ Just x_o = rs1 x_f x+ in (nub (sort x),x_o,x_f)+ in (gen_si p,p_icv,tics p,gen_si (Z12.complement p),gen_si (map (* 5) p))++si_raw_pp :: [Z12] -> [String]+si_raw_pp p =+ let pf_pp concise (x_o,x_f) =+ concat [Z.tto_pp x_o," ",Z12.sc_name x_f+ ,if concise then "" else Z12.z12_vec_pp x_f]+ si_pp (x,x_o,x_f) = concat [Z12.z12_set_pp x," (",pf_pp True (x_o,x_f),")"]+ ((p',p_o,p_f),p_icv,p_tics,c,m) = si_raw p+ in [Z12.z12_set_pp p'+ ,pf_pp False (p_o,p_f)+ ,Z12.z12_vec_pp p_icv+ ,Z.z16_vec_pp p_tics+ ,si_pp c+ ,si_pp m]++-- | Set information. ----- > spsc (cf [3] T.scs) == ["6-Z17"]-spsc :: [[Z12]] -> [String]+-- > putStr $ unlines $ si [0,5,3,11]+si :: [Z12] -> [String]+si p = zipWith (\k v -> concat [k,": ",v]) si_hdr (si_raw_pp p)++{- | Super set-class.++>>> pct spsc 4-11 4-12+5-26[02458]++> spsc [Z12.sc "4-11",Z12.sc "4-12"] == [[0,2,4,5,8]]++>>> pct spsc 3-11 3-8+4-27[0258]+4-Z29[0137]++> spsc [Z12.sc "3-11",Z12.sc "3-8"] == [[0,2,5,8],[0,1,3,7]]++>>> pct spsc `pct fl 3`+6-Z17[012478]++> spsc (cf [3] Z12.scs) == [[0,1,2,4,7,8]]++-}+spsc :: [[Z12]] -> [[Z12]] spsc xs = let f y = all (y `has_sc`) xs g = (==) `on` length- in (map T.sc_name . head . groupBy g . filter f) T.scs+ in (head . groupBy g . filter f) Z12.scs++{- | sra = stravinsky rotational array++>>> echo 019BA7 | pct sra+019BA7+08A96B+021A34+0B812A+0923B1+056243++> let r = [[0,1,9,11,10,7],[0,8,10,9,6,11],[0,2,1,10,3,4]+> ,[0,11,8,1,2,10],[0,9,2,3,11,1],[0,5,6,2,4,3]]+> in sra [0,1,9,11,10,7] == r++-}+sra :: [Z12] -> [[Z12]]+sra = map (Z12.sro_tn_to 0) . T.rotations++{- | Serial operation.++>>> echo 156 | pct sro T4+59A++> sro (Z.sro_parse "T4") [1,5,6] == [5,9,10]++>>> echo 024579 | pct sro RT4I+79B024++> sro (Z.SRO 0 True 4 False True) [0,2,4,5,7,9] == [7,9,11,0,2,4]++>>> echo 156 | pct sro T4I+3BA++> sro (Z.sro_parse "T4I") [1,5,6] == [3,11,10]+> sro (Z.SRO 0 False 4 False True) [1,5,6] == [3,11,10]++>>> echo 156 | pct sro T4 | pct sro T0I+732++> (sro (Z.sro_parse "T0I") . sro (Z.sro_parse "T4")) [1,5,6] == [7,3,2]++>>> echo 024579 | pct sro RT4I+79B024++> sro (Z.sro_parse "RT4I") [0,2,4,5,7,9] == [7,9,11,0,2,4]++-}+sro :: Z.SRO Z12 -> [Z12] -> [Z12]+sro o = Z.z_sro_apply 5 id o++-- | Vector indicating degree of intersection with inversion at each transposition.+--+-- > tics [0,2,4,5,7,9] == [3,2,5,0,5,2,3,4,1,6,1,4]+-- > map tics Z12.scs+tics :: [Z12] -> [Int]+tics p =+ let q = Z12.tto_t_related (Z12.tto_invert 0 p)+ in map (length . intersect p) q++{- | tmatrix++>>> pct tmatrix 1258++1258+0147+9A14+67A1++> tmatrix [1,2,5,8] == [[1,2,5,8],[0,1,4,7],[9,10,1,4],[6,7,10,1]]++-}+tmatrix :: [Z12] -> [[Z12]]+tmatrix p =+ let i = map negate (T.d_dx p)+ in map (\n -> map (+ n) p) (T.dx_d 0 i)+++{- | trs = transformations search. Search all RTnMI of /p/ for /q/.++>>> echo 642 | pct trs 024579 | sort -u+531642+6421B9+642753+B97642++> let r = [[5,3,1,6,4,2],[6,4,2,1,11,9],[6,4,2,7,5,3],[11,9,7,6,4,2]]+> in sort (trs [0,2,4,5,7,9] [6,4,2]) == r++-}+trs :: [Z12] -> [Z12] -> [[Z12]]+trs p q = filter (q `isInfixOf`) (Z12.sro_rtmi_related p)++-- > trs_m [0,2,4,5,7,9] [6,4,2] == [[6,4,2,1,11,9],[11,9,7,6,4,2]]+trs_m :: [Z12] -> [Z12] -> [[Z12]]+trs_m p q = filter (q `isInfixOf`) (Z12.sro_rti_related p)
Music/Theory/Z12/Forte_1973.hs view
@@ -2,9 +2,6 @@ -- Press, New Haven, 1973. module Music.Theory.Z12.Forte_1973 where -import Data.List {- base -}-import Data.Maybe {- base -}- import qualified Music.Theory.Z.Forte_1973 as Z import Music.Theory.Z12 @@ -14,262 +11,38 @@ -- -- > t_rotations [0,1,3] == [[0,1,3],[0,2,11],[0,9,10]] t_rotations :: [Z12] -> [[Z12]]-t_rotations = Z.t_rotations z12_modulo+t_rotations = Z.t_rotations id -- | T\/I-related rotations of /p/. -- -- > ti_rotations [0,1,3] == [[0,1,3],[0,2,11],[0,9,10] -- > ,[0,9,11],[0,2,3],[0,1,10]] ti_rotations :: [Z12] -> [[Z12]]-ti_rotations = Z.ti_rotations z12_modulo+ti_rotations = Z.ti_rotations id -- | Forte prime form, ie. 'cmp_prime' of 'forte_cmp'. -- -- > forte_prime [0,1,3,6,8,9] == [0,1,3,6,8,9]+-- > forte_prime [0,2,3,6,7] == [0,1,4,5,7] forte_prime :: [Z12] -> [Z12]-forte_prime = Z.forte_prime z12_modulo+forte_prime = Z.forte_prime id -- | Transpositional equivalence prime form, ie. 't_cmp_prime' of -- 'forte_cmp'. -- -- > (forte_prime [0,2,3],t_prime [0,2,3]) == ([0,1,3],[0,2,3]) t_prime :: [Z12] -> [Z12]-t_prime = Z.t_prime z12_modulo+t_prime = Z.t_prime id -- * Set Class Table --- | Synonym for 'String'.-type SC_Name = String+type SC_Name = Z.SC_Name -- | The set-class table (Forte prime forms). -- -- > length sc_table == 224 sc_table :: [(SC_Name,[Z12])]-sc_table =- [("0-1",[])- ,("1-1",[0])- ,("2-1",[0,1])- ,("2-2",[0,2])- ,("2-3",[0,3])- ,("2-4",[0,4])- ,("2-5",[0,5])- ,("2-6",[0,6])- ,("3-1",[0,1,2])- ,("3-2",[0,1,3])- ,("3-3",[0,1,4])- ,("3-4",[0,1,5])- ,("3-5",[0,1,6])- ,("3-6",[0,2,4])- ,("3-7",[0,2,5])- ,("3-8",[0,2,6])- ,("3-9",[0,2,7])- ,("3-10",[0,3,6])- ,("3-11",[0,3,7])- ,("3-12",[0,4,8])- ,("4-1",[0,1,2,3])- ,("4-2",[0,1,2,4])- ,("4-3",[0,1,3,4])- ,("4-4",[0,1,2,5])- ,("4-5",[0,1,2,6])- ,("4-6",[0,1,2,7])- ,("4-7",[0,1,4,5])- ,("4-8",[0,1,5,6])- ,("4-9",[0,1,6,7])- ,("4-10",[0,2,3,5])- ,("4-11",[0,1,3,5])- ,("4-12",[0,2,3,6])- ,("4-13",[0,1,3,6])- ,("4-14",[0,2,3,7])- ,("4-Z15",[0,1,4,6])- ,("4-16",[0,1,5,7])- ,("4-17",[0,3,4,7])- ,("4-18",[0,1,4,7])- ,("4-19",[0,1,4,8])- ,("4-20",[0,1,5,8])- ,("4-21",[0,2,4,6])- ,("4-22",[0,2,4,7])- ,("4-23",[0,2,5,7])- ,("4-24",[0,2,4,8])- ,("4-25",[0,2,6,8])- ,("4-26",[0,3,5,8])- ,("4-27",[0,2,5,8])- ,("4-28",[0,3,6,9])- ,("4-Z29",[0,1,3,7])- ,("5-1",[0,1,2,3,4])- ,("5-2",[0,1,2,3,5])- ,("5-3",[0,1,2,4,5])- ,("5-4",[0,1,2,3,6])- ,("5-5",[0,1,2,3,7])- ,("5-6",[0,1,2,5,6])- ,("5-7",[0,1,2,6,7])- ,("5-8",[0,2,3,4,6])- ,("5-9",[0,1,2,4,6])- ,("5-10",[0,1,3,4,6])- ,("5-11",[0,2,3,4,7])- ,("5-Z12",[0,1,3,5,6])- ,("5-13",[0,1,2,4,8])- ,("5-14",[0,1,2,5,7])- ,("5-15",[0,1,2,6,8])- ,("5-16",[0,1,3,4,7])- ,("5-Z17",[0,1,3,4,8])- ,("5-Z18",[0,1,4,5,7])- ,("5-19",[0,1,3,6,7])- ,("5-20",[0,1,3,7,8])- ,("5-21",[0,1,4,5,8])- ,("5-22",[0,1,4,7,8])- ,("5-23",[0,2,3,5,7])- ,("5-24",[0,1,3,5,7])- ,("5-25",[0,2,3,5,8])- ,("5-26",[0,2,4,5,8])- ,("5-27",[0,1,3,5,8])- ,("5-28",[0,2,3,6,8])- ,("5-29",[0,1,3,6,8])- ,("5-30",[0,1,4,6,8])- ,("5-31",[0,1,3,6,9])- ,("5-32",[0,1,4,6,9])- ,("5-33",[0,2,4,6,8])- ,("5-34",[0,2,4,6,9])- ,("5-35",[0,2,4,7,9])- ,("5-Z36",[0,1,2,4,7])- ,("5-Z37",[0,3,4,5,8])- ,("5-Z38",[0,1,2,5,8])- ,("6-1",[0,1,2,3,4,5])- ,("6-2",[0,1,2,3,4,6])- ,("6-Z3",[0,1,2,3,5,6])- ,("6-Z4",[0,1,2,4,5,6])- ,("6-5",[0,1,2,3,6,7])- ,("6-Z6",[0,1,2,5,6,7])- ,("6-7",[0,1,2,6,7,8])- ,("6-8",[0,2,3,4,5,7])- ,("6-9",[0,1,2,3,5,7])- ,("6-Z10",[0,1,3,4,5,7])- ,("6-Z11",[0,1,2,4,5,7])- ,("6-Z12",[0,1,2,4,6,7])- ,("6-Z13",[0,1,3,4,6,7])- ,("6-14",[0,1,3,4,5,8])- ,("6-15",[0,1,2,4,5,8])- ,("6-16",[0,1,4,5,6,8])- ,("6-Z17",[0,1,2,4,7,8])- ,("6-18",[0,1,2,5,7,8])- ,("6-Z19",[0,1,3,4,7,8])- ,("6-20",[0,1,4,5,8,9])- ,("6-21",[0,2,3,4,6,8])- ,("6-22",[0,1,2,4,6,8])- ,("6-Z23",[0,2,3,5,6,8])- ,("6-Z24",[0,1,3,4,6,8])- ,("6-Z25",[0,1,3,5,6,8])- ,("6-Z26",[0,1,3,5,7,8])- ,("6-27",[0,1,3,4,6,9])- ,("6-Z28",[0,1,3,5,6,9])- ,("6-Z29",[0,1,3,6,8,9])- ,("6-30",[0,1,3,6,7,9])- ,("6-31",[0,1,3,5,8,9])- ,("6-32",[0,2,4,5,7,9])- ,("6-33",[0,2,3,5,7,9])- ,("6-34",[0,1,3,5,7,9])- ,("6-35",[0,2,4,6,8,10])- ,("6-Z36",[0,1,2,3,4,7])- ,("6-Z37",[0,1,2,3,4,8])- ,("6-Z38",[0,1,2,3,7,8])- ,("6-Z39",[0,2,3,4,5,8])- ,("6-Z40",[0,1,2,3,5,8])- ,("6-Z41",[0,1,2,3,6,8])- ,("6-Z42",[0,1,2,3,6,9])- ,("6-Z43",[0,1,2,5,6,8])- ,("6-Z44",[0,1,2,5,6,9])- ,("6-Z45",[0,2,3,4,6,9])- ,("6-Z46",[0,1,2,4,6,9])- ,("6-Z47",[0,1,2,4,7,9])- ,("6-Z48",[0,1,2,5,7,9])- ,("6-Z49",[0,1,3,4,7,9])- ,("6-Z50",[0,1,4,6,7,9])- ,("7-1",[0,1,2,3,4,5,6])- ,("7-2",[0,1,2,3,4,5,7])- ,("7-3",[0,1,2,3,4,5,8])- ,("7-4",[0,1,2,3,4,6,7])- ,("7-5",[0,1,2,3,5,6,7])- ,("7-6",[0,1,2,3,4,7,8])- ,("7-7",[0,1,2,3,6,7,8])- ,("7-8",[0,2,3,4,5,6,8])- ,("7-9",[0,1,2,3,4,6,8])- ,("7-10",[0,1,2,3,4,6,9])- ,("7-11",[0,1,3,4,5,6,8])- ,("7-Z12",[0,1,2,3,4,7,9])- ,("7-13",[0,1,2,4,5,6,8])- ,("7-14",[0,1,2,3,5,7,8])- ,("7-15",[0,1,2,4,6,7,8])- ,("7-16",[0,1,2,3,5,6,9])- ,("7-Z17",[0,1,2,4,5,6,9])- ,("7-Z18",[0,1,2,3,5,8,9])- ,("7-19",[0,1,2,3,6,7,9])- ,("7-20",[0,1,2,4,7,8,9])- ,("7-21",[0,1,2,4,5,8,9])- ,("7-22",[0,1,2,5,6,8,9])- ,("7-23",[0,2,3,4,5,7,9])- ,("7-24",[0,1,2,3,5,7,9])- ,("7-25",[0,2,3,4,6,7,9])- ,("7-26",[0,1,3,4,5,7,9])- ,("7-27",[0,1,2,4,5,7,9])- ,("7-28",[0,1,3,5,6,7,9])- ,("7-29",[0,1,2,4,6,7,9])- ,("7-30",[0,1,2,4,6,8,9])- ,("7-31",[0,1,3,4,6,7,9])- ,("7-32",[0,1,3,4,6,8,9])- ,("7-33",[0,1,2,4,6,8,10])- ,("7-34",[0,1,3,4,6,8,10])- ,("7-35",[0,1,3,5,6,8,10])- ,("7-Z36",[0,1,2,3,5,6,8])- ,("7-Z37",[0,1,3,4,5,7,8])- ,("7-Z38",[0,1,2,4,5,7,8])- ,("8-1",[0,1,2,3,4,5,6,7])- ,("8-2",[0,1,2,3,4,5,6,8])- ,("8-3",[0,1,2,3,4,5,6,9])- ,("8-4",[0,1,2,3,4,5,7,8])- ,("8-5",[0,1,2,3,4,6,7,8])- ,("8-6",[0,1,2,3,5,6,7,8])- ,("8-7",[0,1,2,3,4,5,8,9])- ,("8-8",[0,1,2,3,4,7,8,9])- ,("8-9",[0,1,2,3,6,7,8,9])- ,("8-10",[0,2,3,4,5,6,7,9])- ,("8-11",[0,1,2,3,4,5,7,9])- ,("8-12",[0,1,3,4,5,6,7,9])- ,("8-13",[0,1,2,3,4,6,7,9])- ,("8-14",[0,1,2,4,5,6,7,9])- ,("8-Z15",[0,1,2,3,4,6,8,9])- ,("8-16",[0,1,2,3,5,7,8,9])- ,("8-17",[0,1,3,4,5,6,8,9])- ,("8-18",[0,1,2,3,5,6,8,9])- ,("8-19",[0,1,2,4,5,6,8,9])- ,("8-20",[0,1,2,4,5,7,8,9])- ,("8-21",[0,1,2,3,4,6,8,10])- ,("8-22",[0,1,2,3,5,6,8,10])- ,("8-23",[0,1,2,3,5,7,8,10])- ,("8-24",[0,1,2,4,5,6,8,10])- ,("8-25",[0,1,2,4,6,7,8,10])- ,("8-26",[0,1,2,4,5,7,9,10])- ,("8-27",[0,1,2,4,5,7,8,10])- ,("8-28",[0,1,3,4,6,7,9,10])- ,("8-Z29",[0,1,2,3,5,6,7,9])- ,("9-1",[0,1,2,3,4,5,6,7,8])- ,("9-2",[0,1,2,3,4,5,6,7,9])- ,("9-3",[0,1,2,3,4,5,6,8,9])- ,("9-4",[0,1,2,3,4,5,7,8,9])- ,("9-5",[0,1,2,3,4,6,7,8,9])- ,("9-6",[0,1,2,3,4,5,6,8,10])- ,("9-7",[0,1,2,3,4,5,7,8,10])- ,("9-8",[0,1,2,3,4,6,7,8,10])- ,("9-9",[0,1,2,3,5,6,7,8,10])- ,("9-10",[0,1,2,3,4,6,7,9,10])- ,("9-11",[0,1,2,3,5,6,7,9,10])- ,("9-12",[0,1,2,4,5,6,8,9,10])- ,("10-1",[0,1,2,3,4,5,6,7,8,9])- ,("10-2",[0,1,2,3,4,5,6,7,8,10])- ,("10-3",[0,1,2,3,4,5,6,7,9,10])- ,("10-4",[0,1,2,3,4,5,6,8,9,10])- ,("10-5",[0,1,2,3,4,5,7,8,9,10])- ,("10-6",[0,1,2,3,4,6,7,8,9,10])- ,("11-1",[0,1,2,3,4,5,6,7,8,9,10])- ,("12-1",[0,1,2,3,4,5,6,7,8,9,10,11])]+sc_table = Z.sc_table -- | Lookup a set-class name. The input set is subject to -- 'forte_prime' before lookup.@@ -277,15 +50,17 @@ -- > sc_name [0,2,3,6,7] == "5-Z18" -- > sc_name [0,1,4,6,7,8] == "6-Z17" sc_name :: [Z12] -> SC_Name-sc_name p =- let n = find (\(_,q) -> forte_prime p == q) sc_table- in fst (fromMaybe (error "sc_name") n)+sc_name = Z.sc_name id +-- > sc_name_long [0,1,4,6,7,8] == "6-Z17[012478]"+sc_name_long :: [Z12] -> SC_Name+sc_name_long = Z.sc_name_long id+ -- | Lookup a set-class given a set-class name. -- -- > sc "6-Z17" == [0,1,2,4,7,8] sc :: SC_Name -> [Z12]-sc n = snd (fromMaybe (error "sc") (find (\(m,_) -> n == m) sc_table))+sc = Z.sc {- | List of set classes (the set class universe). @@ -517,26 +292,26 @@ -} scs :: [[Z12]]-scs = map snd sc_table+scs = Z.scs -- | Cardinality /n/ subset of 'scs'. -- -- > map (length . scs_n) [1..11] == [1,6,12,29,38,50,38,29,12,6,1] scs_n :: Integral i => i -> [[Z12]]-scs_n n = filter ((== n) . genericLength) scs+scs_n = Z.scs_n -- * BIP Metric -- | Basic interval pattern, see Allen Forte \"The Basic Interval Patterns\" -- /JMT/ 17/2 (1973):234-272 ----- >>> bip 0t95728e3416+-- >>> pct bip 0t95728e3416 -- 11223344556 -- -- > bip [0,10,9,5,7,2,8,11,3,4,1,6] == [1,1,2,2,3,3,4,4,5,5,6] -- > bip (pco "0t95728e3416") == [1,1,2,2,3,3,4,4,5,5,6] bip :: [Z12] -> [Z12]-bip = Z.bip z12_modulo+bip = map int_to_Z12 . Z.bip 12 . map int_from_Z12 -- * ICV Metric @@ -545,10 +320,22 @@ -- > map ic [5,6,7] == [5,6,5] -- > map ic [-13,-1,0,1,13] == [1,1,0,1,1] ic :: Z12 -> Z12-ic = Z.ic z12_modulo+ic = int_to_Z12 . Z.ic 12 . int_from_Z12 -- | Forte notation for interval class vector. -- -- > icv [0,1,2,4,7,8] == [3,2,2,3,3,2] icv :: Integral i => [Z12] -> [i]-icv = Z.icv z12_modulo+icv = map fromInteger . Z.icv 12 . map int_from_Z12++-- | Type specialise...+icv' :: [Z12] -> [Int]+icv' = icv++-- * Z-relation++-- | Locate /Z/ relation of set class.+--+-- > fmap sc_name (z_relation_of (sc "7-Z12")) == Just "7-Z36"+z_relation_of :: [Z12] -> Maybe [Z12]+z_relation_of = fmap (map int_to_Z12) . Z.z_relation_of 12 . map int_from_Z12
Music/Theory/Z12/Lewin_1980.hs view
@@ -3,8 +3,9 @@ module Music.Theory.Z12.Lewin_1980 where import Data.List-import Music.Theory.Z12 import qualified Music.Theory.Z12.Castren_1994 as C++type Z12 = Int -- | REL function with given /ncv/ function (see 't_rel' and 'ti_rel'). rel :: Floating n => (Int -> [a] -> [n]) -> [a] -> [a] -> n
Music/Theory/Z12/Morris_1974.hs view
@@ -2,35 +2,35 @@ -- /Journal of Music Theory/, 18:364-389, 1974. module Music.Theory.Z12.Morris_1974 where -import Control.Monad.Logic {- logict -}+import qualified Control.Monad.Logic as L {- logict -} --- | 'msum' '.' 'map' 'return'.+-- | 'L.msum' '.' 'map' 'return'. ----- > observeAll (fromList [1..7]) == [1..7]-fromList :: MonadPlus m => [a] -> m a-fromList = msum . map return+-- > L.observeAll (fromList [1..7]) == [1..7]+fromList :: L.MonadPlus m => [a] -> m a+fromList = L.msum . map return --- | 'MonadPlus' all-interval series.+-- | 'L.MonadLogic' all-interval series. ----- > [0,1,3,2,9,5,10,4,7,11,8,6] `elem` observeAll (all_interval_m 12)--- > length (observeAll (all_interval_m 12)) == 3856--- > map (length . observeAll . all_interval_m) [4,6,8,10] == [2,4,24,288]-all_interval_m :: MonadPlus m => Int -> m [Int]+-- > map (length . L.observeAll . all_interval_m) [4,6,8,10] == [2,4,24,288]+-- > [0,1,3,2,9,5,10,4,7,11,8,6] `elem` L.observeAll (all_interval_m 12)+-- > length (L.observeAll (all_interval_m 12)) == 3856+all_interval_m :: L.MonadLogic m => Int -> m [Int] all_interval_m n =- let rec p q =- if length p == n+ let recur k p q = -- k = length p+ if k == n then return (reverse p) else do i <- fromList [1 .. n - 1]- guard (i `notElem` p)+ L.guard (i `notElem` p) let j:_ = p m = abs ((i - j) `mod` n)- guard (m `notElem` q)- rec (i:p) (m:q)- in rec [0] []+ L.guard (m `notElem` q)+ recur (k + 1) (i : p) (m : q)+ in recur 1 [0] [] --- | 'observeAll' of 'all_interval_m'.+-- | 'L.observeAll' of 'all_interval_m'. -- -- > let r = [[0,1,5,2,4,3],[0,2,1,4,5,3],[0,4,5,2,1,3],[0,5,1,4,2,3]] -- > in all_interval 6 == r all_interval :: Int -> [[Int]]-all_interval = observeAll . all_interval_m+all_interval = L.observeAll . all_interval_m
Music/Theory/Z12/Morris_1987.hs view
@@ -2,98 +2,11 @@ -- Compositional Design/. Yale University Press, New Haven, 1987. module Music.Theory.Z12.Morris_1987 where -import Data.List import Music.Theory.List import Music.Theory.Z12-import Music.Theory.Z12.SRO -- | @INT@ operator. -- -- > int [0,1,3,6,10] == [1,2,3,4] int :: [Z12] -> [Z12] int = d_dx---- * Serial operations---- | Serial Operator,of the form rRTMI.-data SRO = SRO Z12 Bool Z12 Bool Bool- deriving (Eq,Show)---- | Serial operation.------ >>> sro T4 156--- 59A------ > sro (rnrtnmi "T4") (pco "156") == [5,9,10]------ >>> echo 024579 | sro RT4I--- 79B024------ > sro (SRO 0 True 4 False True) [0,2,4,5,7,9] == [7,9,11,0,2,4]------ >>> sro T4I 156--- 3BA------ > sro (rnrtnmi "T4I") (pco "156") == [3,11,10]--- > sro (SRO 0 False 4 False True) [1,5,6] == [3,11,10]------ >>> echo 156 | sro T4 | sro T0I--- 732------ > (sro (rnrtnmi "T0I") . sro (rnrtnmi "T4")) (pco "156") == [7,3,2]------ >>> echo 024579 | sro RT4I--- 79B024------ > sro (rnrtnmi "RT4I") (pco "024579") == [7,9,11,0,2,4]------ > sro (SRO 1 True 1 True False) [0,1,2,3] == [11,6,1,4]--- > sro (SRO 1 False 4 True True) [0,1,2,3] == [11,6,1,4]-sro :: SRO -> [Z12] -> [Z12]-sro (SRO r r' t m i) x =- let x1 = if i then invert 0 x else x- x2 = if m then m5 x1 else x1- x3 = tn t x2- x4 = if r' then reverse x3 else x3- in genericRotate_left r x4---- | The total set of serial operations.-sros :: [Z12] -> [(SRO,[Z12])]-sros x = [let o = (SRO r r' t m i) in (o,sro o x) |- r <- [0 .. genericLength x - 1],- r' <- [False,True],- t <- [0 .. 11],- m <- [False,True],- i <- [False,True]]---- | The set of transposition 'SRO's.-sro_Tn ::[SRO]-sro_Tn = [SRO 0 False n False False | n <- [0..11]]---- | The set of transposition and inversion 'SRO's.-sro_TnI ::[SRO]-sro_TnI = [SRO 0 False n False i |- n <- [0..11],- i <- [False,True]]---- | The set of retrograde and transposition and inversion 'SRO's.-sro_RTnI ::[SRO]-sro_RTnI = [SRO 0 r n False i |- r <- [True,False],- n <- [0..11],- i <- [False,True]]---- | The set of transposition,@M5@ and inversion 'SRO's.-sro_TnMI ::[SRO]-sro_TnMI = [SRO 0 False n m i |- n <- [0..11],- m <- [True,False],- i <- [True,False]]---- | The set of retrograde,transposition,@M5@ and inversion 'SRO's.-sro_RTnMI ::[SRO]-sro_RTnMI = [SRO 0 r n m i |- r <- [True,False],- n <- [0..11],- m <- [True,False],- i <- [True,False]]
Music/Theory/Z12/Morris_1987/Parse.hs view
@@ -1,45 +1,9 @@ -- | Parsers for pitch class sets and sequences, and for 'SRO's.-module Music.Theory.Z12.Morris_1987.Parse (rnrtnmi,pco) where+module Music.Theory.Z12.Morris_1987.Parse where -import Control.Monad {- base -} import Data.Char {- base -}-import Text.ParserCombinators.Parsec {- parsec -} import Music.Theory.Z12-import Music.Theory.Z12.Morris_1987---- | A 'Char' parser.-type P a = GenParser Char () a---- | Boolean 'P' for given 'Char'.-is_char :: Char -> P Bool-is_char c =- let f '_' = False- f _ = True- in liftM f (option '_' (char c))---- | Parse 'Int'.-get_int :: P Z12-get_int = liftM (fromInteger . read) (many1 digit)---- | Parse a Morris format serial operator descriptor.------ > rnrtnmi "r2RT3MI" == SRO 2 True 3 True True-rnrtnmi :: String -> SRO-rnrtnmi s =- let p = do r <- rot- r' <- is_char 'R'- _ <- char 'T'- t <- get_int- m <- is_char 'M'- i <- is_char 'I'- eof- return (SRO r r' t m i)- rot = option 0 (char 'r' >> get_int)- in either- (\e -> error ("rnRTnMI parse failed\n" ++ show e))- id- (parse p "" s) -- | Parse a /pitch class object/ string. Each 'Char' is either a -- number, a space which is ignored, or a letter name for the numbers
Music/Theory/Z12/Rahn_1980.hs view
@@ -22,4 +22,4 @@ -- > ,[0,1,2,4,5,7,9,10]] -- > in all (\p -> forte_prime p /= rahn_prime p) s == True rahn_prime :: [Z12] -> [Z12]-rahn_prime = Z.ti_cmp_prime z12_modulo rahn_cmp+rahn_prime = Z.ti_cmp_prime id rahn_cmp
Music/Theory/Z12/Read_1978.hs view
@@ -25,4 +25,4 @@ -- > encode_prime [0,1,3,6,8,9] == [0,2,3,6,7,9] -- > Music.Theory.Z12.Rahn_1980.rahn_prime [0,1,3,6,8,9] == [0,2,3,6,7,9] encode_prime :: [Z12] -> [Z12]-encode_prime = Z.encode_prime z12_modulo+encode_prime = Z.encode_prime id
Music/Theory/Z12/SRO.hs view
@@ -1,91 +1,92 @@ -- | Serial (ordered) pitch-class operations on 'Z12'. module Music.Theory.Z12.SRO where -import Data.List+import Data.List {- base -}+ import qualified Music.Theory.List as T import qualified Music.Theory.Z.SRO as Z-import Music.Theory.Z12+import Music.Theory.Z12 -- | Transpose /p/ by /n/. ----- > tn 4 [1,5,6] == [5,9,10]-tn :: Z12 -> [Z12] -> [Z12]-tn = Z.tn z12_modulo+-- > sro_tn 4 [1,5,6] == [5,9,10]+sro_tn :: Z12 -> [Z12] -> [Z12]+sro_tn = Z.z_sro_tn id -- | Invert /p/ about /n/. ----- > invert 6 [4,5,6] == [8,7,6]--- > invert 0 [0,1,3] == [0,11,9]-invert :: Z12 -> [Z12] -> [Z12]-invert = Z.invert z12_modulo+-- > sro_invert 6 [4,5,6] == [8,7,6]+-- > sro_invert 0 [0,1,3] == [0,11,9]+sro_invert :: Z12 -> [Z12] -> [Z12]+sro_invert = Z.z_sro_invert id -- | Composition of 'invert' about @0@ and 'tn'. -- -- > tni 4 [1,5,6] == [3,11,10]--- > (invert 0 . tn 4) [1,5,6] == [7,3,2]-tni :: Z12 -> [Z12] -> [Z12]-tni = Z.tni z12_modulo+-- > (sro_invert 0 . sro_tn 4) [1,5,6] == [7,3,2]+sro_tni :: Z12 -> [Z12] -> [Z12]+sro_tni = Z.z_sro_tni id -- | Modulo 12 multiplication ----- > mn 11 [0,1,4,9] == tni 0 [0,1,4,9]-mn :: Z12 -> [Z12] -> [Z12]-mn = Z.mn z12_modulo+-- > sro_mn 11 [0,1,4,9] == sro_tni 0 [0,1,4,9]+sro_mn :: Z12 -> [Z12] -> [Z12]+sro_mn = Z.z_sro_mn id -- | M5, ie. 'mn' @5@. ----- > m5 [0,1,3] == [0,5,3]-m5 :: [Z12] -> [Z12]-m5 = mn 5+-- > sro_m5 [0,1,3] == [0,5,3]+sro_m5 :: [Z12] -> [Z12]+sro_m5 = sro_mn 5 -- | T-related sequences of /p/. ----- > length (t_related [0,3,6,9]) == 12-t_related :: [Z12] -> [[Z12]]-t_related = Z.t_related z12_modulo+-- > length (sro_t_related [0,3,6,9]) == 12+sro_t_related :: [Z12] -> [[Z12]]+sro_t_related = Z.z_sro_t_related id -- | T\/I-related sequences of /p/. -- -- > length (ti_related [0,1,3]) == 24 -- > length (ti_related [0,3,6,9]) == 24 -- > ti_related [0] == map return [0..11]-ti_related :: [Z12] -> [[Z12]]-ti_related = Z.ti_related z12_modulo+sro_ti_related :: [Z12] -> [[Z12]]+sro_ti_related = Z.z_sro_ti_related id -- | R\/T\/I-related sequences of /p/. -- -- > length (rti_related [0,1,3]) == 48 -- > length (rti_related [0,3,6,9]) == 24-rti_related :: [Z12] -> [[Z12]]-rti_related = Z.rti_related z12_modulo+sro_rti_related :: [Z12] -> [[Z12]]+sro_rti_related = Z.z_sro_rti_related id --- | T\/M\/I-related sequences of /p/.-tmi_related :: [Z12] -> [[Z12]]-tmi_related p = let q = ti_related p in nub (q ++ map m5 q)+-- | T\/M\/I-related sequences of /p/, duplicates removed.+sro_tmi_related :: [Z12] -> [[Z12]]+sro_tmi_related p = let q = sro_ti_related p in nub (q ++ map sro_m5 q) --- | R\/T\/M\/I-related sequences of /p/.-rtmi_related :: [Z12] -> [[Z12]]-rtmi_related p = let q = tmi_related p in nub (q ++ map reverse q)+-- | R\/T\/M\/I-related sequences of /p/, duplicates removed.+sro_rtmi_related :: [Z12] -> [[Z12]]+sro_rtmi_related p = let q = sro_tmi_related p in nub (q ++ map reverse q) --- | r\/R\/T\/M\/I-related sequences of /p/.-rrtmi_related :: [Z12] -> [[Z12]]-rrtmi_related p = nub (concatMap rtmi_related (T.rotations p))+-- | r\/R\/T\/M\/I-related sequences of /p/, duplicates removed.+sro_rrtmi_related :: [Z12] -> [[Z12]]+sro_rrtmi_related p = nub (concatMap sro_rtmi_related (T.rotations p)) -- * Sequence operations -- | Variant of 'tn', transpose /p/ so first element is /n/. ----- > tn_to 5 [0,1,3] == [5,6,8]--- > map (tn_to 0) [[0,1,3],[1,3,0],[3,0,1]] == [[0,1,3],[0,2,11],[0,9,10]]-tn_to :: Z12 -> [Z12] -> [Z12]-tn_to = Z.tn_to z12_modulo+-- > sro_tn_to 5 [0,1,3] == [5,6,8]+-- > map (sro_tn_to 0) [[0,1,3],[1,3,0],[3,0,1]] == [[0,1,3],[0,2,11],[0,9,10]]+sro_tn_to :: Z12 -> [Z12] -> [Z12]+sro_tn_to = Z.z_sro_tn_to id -- | Variant of 'invert', inverse about /n/th element. ----- > map (invert_ix 0) [[0,1,3],[3,4,6]] == [[0,11,9],[3,2,0]]--- > map (invert_ix 1) [[0,1,3],[3,4,6]] == [[2,1,11],[5,4,2]]-invert_ix :: Int -> [Z12] -> [Z12]-invert_ix = Z.invert_ix z12_modulo+-- > map (sro_invert_ix 0) [[0,1,3],[3,4,6]] == [[0,11,9],[3,2,0]]+-- > map (sro_invert_ix 1) [[0,1,3],[3,4,6]] == [[2,1,11],[5,4,2]]+sro_invert_ix :: Int -> [Z12] -> [Z12]+sro_invert_ix = Z.z_sro_invert_ix id -- | The standard t-matrix of /p/. --@@ -93,4 +94,4 @@ -- > ,[11,0,2] -- > ,[9,10,0]] tmatrix :: [Z12] -> [[Z12]]-tmatrix = Z.tmatrix z12_modulo+tmatrix = Z.z_tmatrix id
Music/Theory/Z12/TTO.hs view
@@ -1,7 +1,8 @@ -- | Pitch-class set (unordered) operations on 'Z12'. module Music.Theory.Z12.TTO where -import Data.List+import Data.List {- base -}+ import Music.Theory.Z12 -- | Map to pitch-class and reduce to set.@@ -12,47 +13,47 @@ -- | Transpose by n. ----- > tn 4 [1,5,6] == [5,9,10]--- > tn 4 [0,4,8] == [0,4,8]-tn :: Z12 -> [Z12] -> [Z12]-tn n = sort . map (+ n)+-- > tto_tn 4 [1,5,6] == [5,9,10]+-- > tto_tn 4 [0,4,8] == [0,4,8]+tto_tn :: Z12 -> [Z12] -> [Z12]+tto_tn n = sort . map (+ n) -- | Invert about n. ----- > invert 6 [4,5,6] == [6,7,8]--- > invert 0 [0,1,3] == [0,9,11]-invert :: Z12 -> [Z12] -> [Z12]-invert n = sort . map (\p -> n - (p - n))+-- > tto_invert 6 [4,5,6] == [6,7,8]+-- > tto_invert 0 [0,1,3] == [0,9,11]+tto_invert :: Z12 -> [Z12] -> [Z12]+tto_invert n = sort . map (\p -> n - (p - n)) -- | Composition of 'invert' about @0@ and 'tn'. ----- > tni 4 [1,5,6] == [3,10,11]--- > (invert 0 . tn 4) [1,5,6] == [2,3,7]-tni :: Z12 -> [Z12] -> [Z12]-tni n = tn n . invert 0+-- > tto_tni 4 [1,5,6] == [3,10,11]+-- > (tto_invert 0 . tto_tn 4) [1,5,6] == [2,3,7]+tto_tni :: Z12 -> [Z12] -> [Z12]+tto_tni n = tto_tn n . tto_invert 0 -- | Modulo 12 multiplication ----- > mn 11 [0,1,4,9] == invert 0 [0,1,4,9]-mn :: Z12 -> [Z12] -> [Z12]-mn n = sort . map (* n)+-- > tto_mn 11 [0,1,4,9] == tto_invert 0 [0,1,4,9]+tto_mn :: Z12 -> [Z12] -> [Z12]+tto_mn n = sort . map (* n) -- | M5, ie. 'mn' @5@. ----- > m5 [0,1,3] == [0,3,5]-m5 :: [Z12] -> [Z12]-m5 = mn 5+-- > tto_m5 [0,1,3] == [0,3,5]+tto_m5 :: [Z12] -> [Z12]+tto_m5 = tto_mn 5 -- | T-related sets of /p/. ----- > length (t_related [0,1,3]) == 12--- > t_related [0,3,6,9] == [[0,3,6,9],[1,4,7,10],[2,5,8,11]]-t_related :: [Z12] -> [[Z12]]-t_related p = nub (map (`tn` p) [0..11])+-- > length (tto_t_related [0,1,3]) == 12+-- > tto_t_related [0,3,6,9] == [[0,3,6,9],[1,4,7,10],[2,5,8,11]]+tto_t_related :: [Z12] -> [[Z12]]+tto_t_related p = nub (map (`tto_tn` p) [0..11]) -- | T\/I-related set of /p/. ----- > length (ti_related [0,1,3]) == 24--- > ti_related [0,3,6,9] == [[0,3,6,9],[1,4,7,10],[2,5,8,11]]-ti_related :: [Z12] -> [[Z12]]-ti_related p = nub (t_related p ++ t_related (invert 0 p))+-- > length (tto_ti_related [0,1,3]) == 24+-- > tto_ti_related [0,3,6,9] == [[0,3,6,9],[1,4,7,10],[2,5,8,11]]+tto_ti_related :: [Z12] -> [[Z12]]+tto_ti_related p = nub (tto_t_related p ++ tto_t_related (tto_invert 0 p))
README view
@@ -6,10 +6,16 @@ - [hmt-diagrams][hmt-diagrams] +## cli++[db](?t=hmt&e=md/db.md),+[pct](?t=hmt&e=md/pct.md),+[scala](?t=hmt&e=md/scala.md)+ [hs]: http://haskell.org/ [hmt-diagrams]: http://rd.slavepianos.org/?t=hmt-diagrams -© [rohan drape][rd], 2006-2014, [gpl][gpl].+© [rohan drape][rd], 2006-2017, [gpl][gpl]. [rd]: http://rd.slavepianos.org/ [gpl]: http://gnu.org/copyleft/
+ data/csv/mnd/1080-C01.csv view
@@ -0,0 +1,1801 @@+time,on/off,note,velocity,channel,param+0.0000,on,62,100,1,+1.0000,off,62,0,1,+1.0000,on,69,100,1,+2.0000,off,69,0,1,+2.0000,on,65,100,1,+3.0000,off,65,0,1,+3.0000,on,62,100,1,+4.0000,off,62,0,1,+4.0000,on,61,100,1,+5.0000,off,61,0,1,+5.0000,on,62,100,1,+5.5000,off,62,0,1,+5.5000,on,64,100,1,+6.0000,off,64,0,1,+6.0000,on,65,100,1,+7.2500,off,65,0,1,+7.2500,on,67,100,1,+7.5000,off,67,0,1,+7.5000,on,65,100,1,+7.7500,off,65,0,1,+7.7500,on,64,100,1,+8.0000,off,64,0,1,+8.0000,on,69,100,0,+8.0000,on,62,100,1,+8.5000,off,62,0,1,+8.5000,on,64,100,1,+9.0000,off,69,0,0,+9.0000,off,64,0,1,+9.0000,on,74,100,0,+9.0000,on,65,100,1,+9.5000,off,65,0,1,+9.5000,on,67,100,1,+10.0000,off,74,0,0,+10.0000,off,67,0,1,+10.0000,on,72,100,0,+10.0000,on,69,100,1,+10.5000,off,69,0,1,+10.5000,on,57,100,1,+10.7500,off,57,0,1,+10.7500,on,59,100,1,+11.0000,off,72,0,0,+11.0000,off,59,0,1,+11.0000,on,69,100,0,+11.0000,on,60,100,1,+11.2500,off,60,0,1,+11.2500,on,57,100,1,+11.5000,off,57,0,1,+11.5000,on,65,100,1,+12.0000,off,69,0,0,+12.0000,on,68,100,0,+12.2500,off,65,0,1,+12.2500,on,59,100,1,+12.5000,off,59,0,1,+12.5000,on,64,100,1,+13.0000,off,68,0,0,+13.0000,on,69,100,0,+13.2500,off,64,0,1,+13.2500,on,65,100,1,+13.5000,off,69,0,0,+13.5000,off,65,0,1,+13.5000,on,71,100,0,+13.5000,on,64,100,1,+13.7500,off,64,0,1,+13.7500,on,62,100,1,+14.0000,off,71,0,0,+14.0000,off,62,0,1,+14.0000,on,72,100,0,+14.0000,on,64,100,1,+14.5000,off,64,0,1,+14.5000,on,66,100,1,+15.0000,off,66,0,1,+15.0000,on,67,100,1,+15.2500,off,72,0,0,+15.2500,on,74,100,0,+15.5000,off,74,0,0,+15.5000,on,72,100,0,+15.7500,off,72,0,0,+15.7500,on,70,100,0,+16.0000,off,70,0,0,+16.0000,on,69,100,0,+16.0000,on,50,100,3,+16.2500,off,69,0,0,+16.2500,on,62,100,0,+16.5000,off,67,0,1,+16.5000,off,62,0,0,+16.5000,on,74,100,0,+16.5000,on,65,100,1,+17.0000,off,50,0,3,+17.0000,off,65,0,1,+17.0000,on,64,100,1,+17.0000,on,57,100,3,+17.5000,off,74,0,0,+17.5000,on,73,100,0,+18.0000,off,64,0,1,+18.0000,off,57,0,3,+18.0000,off,73,0,0,+18.0000,on,74,100,0,+18.0000,on,62,100,1,+18.0000,on,53,100,3,+18.2500,off,74,0,0,+18.2500,on,69,100,0,+18.5000,off,69,0,0,+18.5000,on,72,100,0,+18.7500,off,62,0,1,+18.7500,on,64,100,1,+19.0000,off,53,0,3,+19.0000,off,64,0,1,+19.0000,on,65,100,1,+19.0000,on,50,100,3,+19.2500,off,72,0,0,+19.2500,on,69,100,0,+19.5000,off,69,0,0,+19.5000,on,70,100,0,+19.7500,off,65,0,1,+19.7500,on,62,100,1,+20.0000,off,50,0,3,+20.0000,off,62,0,1,+20.0000,on,67,100,1,+20.0000,on,49,100,3,+20.2500,off,70,0,0,+20.2500,on,64,100,0,+20.5000,off,64,0,0,+20.5000,on,69,100,0,+20.7500,off,67,0,1,+20.7500,on,67,100,1,+21.0000,off,49,0,3,+21.0000,off,67,0,1,+21.0000,on,65,100,1,+21.0000,on,50,100,3,+21.2500,off,65,0,1,+21.2500,on,64,100,1,+21.5000,off,50,0,3,+21.5000,off,64,0,1,+21.5000,on,62,100,1,+21.5000,on,52,100,3,+21.7500,off,62,0,1,+21.7500,on,61,100,1,+22.0000,off,69,0,0,+22.0000,off,52,0,3,+22.0000,off,61,0,1,+22.0000,on,69,100,0,+22.0000,on,62,100,1,+22.0000,on,53,100,3,+22.2500,off,69,0,0,+22.2500,on,72,100,0,+22.5000,off,62,0,1,+22.5000,on,67,100,1,+22.7500,off,72,0,0,+22.7500,on,71,100,0,+23.0000,off,71,0,0,+23.0000,on,72,100,0,+23.2500,off,53,0,3,+23.2500,on,55,100,3,+23.5000,off,67,0,1,+23.5000,off,55,0,3,+23.5000,on,60,100,1,+23.5000,on,53,100,3,+23.7500,off,53,0,3,+23.7500,on,52,100,3,+24.0000,off,60,0,1,+24.0000,off,52,0,3,+24.0000,on,65,100,1,+24.0000,on,57,100,2,+24.0000,on,50,100,3,+24.2500,off,72,0,0,+24.2500,on,62,100,0,+24.5000,off,62,0,0,+24.5000,on,72,100,0,+24.7500,off,65,0,1,+24.7500,on,64,100,1,+25.0000,off,57,0,2,+25.0000,off,50,0,3,+25.0000,off,64,0,1,+25.0000,on,65,100,1,+25.0000,on,62,100,2,+25.2500,off,72,0,0,+25.2500,on,69,100,0,+25.5000,off,69,0,0,+25.5000,on,71,100,0,+25.7500,off,65,0,1,+25.7500,on,56,100,1,+26.0000,off,62,0,2,+26.0000,off,56,0,1,+26.0000,on,64,100,1,+26.0000,on,60,100,2,+26.5000,off,71,0,0,+26.5000,on,69,100,0,+26.5000,on,45,100,3,+26.7500,off,69,0,0,+26.7500,off,45,0,3,+26.7500,on,68,100,0,+26.7500,on,47,100,3,+27.0000,off,60,0,2,+27.0000,off,68,0,0,+27.0000,off,47,0,3,+27.0000,on,69,100,0,+27.0000,on,57,100,2,+27.0000,on,48,100,3,+27.2500,off,48,0,3,+27.2500,on,45,100,3,+27.5000,off,64,0,1,+27.5000,off,45,0,3,+27.5000,on,62,100,1,+27.5000,on,53,100,3,+27.7500,off,62,0,1,+27.7500,on,60,100,1,+28.0000,off,69,0,0,+28.0000,off,57,0,2,+28.0000,off,60,0,1,+28.0000,on,71,100,0,+28.0000,on,62,100,1,+28.0000,on,56,100,2,+28.2500,off,53,0,3,+28.2500,off,62,0,1,+28.2500,on,65,100,1,+28.2500,on,47,100,3,+28.5000,off,65,0,1,+28.5000,off,47,0,3,+28.5000,on,64,100,1,+28.5000,on,52,100,3,+28.7500,off,64,0,1,+28.7500,on,62,100,1,+29.0000,off,71,0,0,+29.0000,off,56,0,2,+29.0000,off,62,0,1,+29.0000,on,72,100,0,+29.0000,on,60,100,1,+29.0000,on,57,100,2,+29.2500,off,52,0,3,+29.2500,on,53,100,3,+29.5000,off,72,0,0,+29.5000,off,60,0,1,+29.5000,off,57,0,2,+29.5000,off,53,0,3,+29.5000,on,74,100,0,+29.5000,on,59,100,2,+29.5000,on,52,100,3,+29.7500,off,52,0,3,+29.7500,on,50,100,3,+30.0000,off,74,0,0,+30.0000,off,59,0,2,+30.0000,off,50,0,3,+30.0000,on,67,100,0,+30.0000,on,60,100,2,+30.0000,on,52,100,3,+30.2500,off,67,0,0,+30.2500,off,52,0,3,+30.2500,on,70,100,0,+30.2500,on,55,100,3,+30.5000,off,70,0,0,+30.5000,off,55,0,3,+30.5000,on,69,100,0,+30.5000,on,54,100,3,+30.7500,off,54,0,3,+30.7500,on,57,100,3,+31.0000,off,57,0,3,+31.0000,on,55,100,3,+31.2500,off,60,0,2,+31.2500,off,69,0,0,+31.2500,on,70,100,0,+31.2500,on,62,100,2,+31.5000,off,70,0,0,+31.5000,off,62,0,2,+31.5000,on,69,100,0,+31.5000,on,60,100,2,+31.7500,off,69,0,0,+31.7500,off,60,0,2,+31.7500,on,67,100,0,+31.7500,on,58,100,2,+32.0000,off,55,0,3,+32.0000,off,58,0,2,+32.0000,on,57,100,2,+32.0000,on,50,100,3,+32.2500,off,67,0,0,+32.2500,on,64,100,0,+32.5000,off,64,0,0,+32.5000,on,65,100,0,+32.7500,off,65,0,0,+32.7500,on,62,100,0,+33.0000,off,62,0,0,+33.0000,on,70,100,0,+33.2500,off,57,0,2,+33.2500,on,53,100,2,+33.5000,off,50,0,3,+33.5000,off,53,0,2,+33.5000,on,55,100,2,+33.5000,on,52,100,3,+33.7500,off,52,0,3,+33.7500,on,50,100,3,+34.0000,off,55,0,2,+34.0000,off,50,0,3,+34.0000,on,60,100,2,+34.0000,on,52,100,3,+34.2500,off,70,0,0,+34.2500,on,67,100,0,+34.5000,off,52,0,3,+34.5000,off,67,0,0,+34.5000,on,69,100,0,+34.5000,on,53,100,3,+34.7500,off,53,0,3,+34.7500,on,52,100,3,+35.0000,off,69,0,0,+35.0000,off,52,0,3,+35.0000,on,74,100,0,+35.0000,on,54,100,3,+35.2500,off,60,0,2,+35.2500,on,57,100,2,+35.5000,off,54,0,3,+35.5000,off,57,0,2,+35.5000,on,59,100,2,+35.5000,on,55,100,3,+35.7500,off,55,0,3,+35.7500,on,54,100,3,+36.0000,off,59,0,2,+36.0000,off,54,0,3,+36.0000,on,64,100,2,+36.0000,on,56,100,3,+36.2500,off,74,0,0,+36.2500,on,71,100,0,+36.5000,off,56,0,3,+36.5000,off,71,0,0,+36.5000,on,72,100,0,+36.5000,on,57,100,3,+36.7500,off,57,0,3,+36.7500,on,56,100,3,+37.0000,off,72,0,0,+37.0000,off,56,0,3,+37.0000,on,77,100,0,+37.0000,on,57,100,3,+37.2500,off,64,0,2,+37.2500,on,61,100,2,+37.5000,off,57,0,3,+37.5000,off,61,0,2,+37.5000,on,62,100,2,+37.5000,on,58,100,3,+37.7500,off,58,0,3,+37.7500,on,57,100,3,+38.0000,off,62,0,2,+38.0000,off,57,0,3,+38.0000,on,67,100,2,+38.0000,on,59,100,3,+38.2500,off,77,0,0,+38.2500,on,74,100,0,+38.5000,off,59,0,3,+38.5000,off,74,0,0,+38.5000,on,76,100,0,+38.5000,on,60,100,3,+38.7500,off,60,0,3,+38.7500,on,59,100,3,+39.0000,off,76,0,0,+39.0000,off,59,0,3,+39.0000,on,69,100,0,+39.0000,on,61,100,3,+39.2500,off,67,0,2,+39.2500,on,64,100,2,+39.5000,off,69,0,0,+39.5000,off,61,0,3,+39.5000,off,64,0,2,+39.5000,on,74,100,0,+39.5000,on,65,100,2,+39.5000,on,62,100,3,+39.7500,off,62,0,3,+39.7500,on,56,100,3,+40.0000,off,65,0,2,+40.0000,off,56,0,3,+40.0000,on,64,100,2,+40.0000,on,57,100,3,+40.2500,off,74,0,0,+40.2500,on,71,100,0,+40.5000,off,71,0,0,+40.5000,on,72,100,0,+40.7500,off,64,0,2,+40.7500,on,69,100,2,+41.0000,off,72,0,0,+41.0000,off,69,0,2,+41.0000,on,65,100,0,+41.0000,on,62,100,2,+41.2500,off,57,0,3,+41.2500,on,53,100,3,+41.5000,off,65,0,0,+41.5000,off,53,0,3,+41.5000,on,70,100,0,+41.5000,on,55,100,3,+41.7500,off,62,0,2,+41.7500,on,64,100,2,+42.0000,off,70,0,0,+42.0000,off,64,0,2,+42.0000,on,69,100,0,+42.0000,on,61,100,2,+42.2500,off,55,0,3,+42.2500,on,52,100,3,+42.5000,off,61,0,2,+42.5000,off,52,0,3,+42.5000,on,62,100,2,+42.5000,on,53,100,3,+42.7500,off,62,0,2,+42.7500,on,57,100,2,+43.0000,off,69,0,0,+43.0000,off,57,0,2,+43.0000,on,62,100,0,+43.0000,on,59,100,2,+43.2500,off,53,0,3,+43.2500,on,50,100,3,+43.5000,off,62,0,0,+43.5000,off,50,0,3,+43.5000,on,67,100,0,+43.5000,on,52,100,3,+43.7500,off,59,0,2,+43.7500,on,61,100,2,+44.0000,off,52,0,3,+44.0000,off,61,0,2,+44.0000,on,62,100,1,+44.0000,on,62,100,2,+44.0000,on,50,100,3,+44.2500,off,67,0,0,+44.2500,on,64,100,0,+44.5000,off,62,0,2,+44.5000,off,64,0,0,+44.5000,on,65,100,0,+44.5000,on,57,100,2,+44.7500,off,65,0,0,+44.7500,on,74,100,0,+45.0000,off,62,0,1,+45.0000,off,74,0,0,+45.0000,on,64,100,0,+45.0000,on,69,100,1,+45.2500,off,50,0,3,+45.2500,on,47,100,3,+45.5000,off,47,0,3,+45.5000,on,49,100,3,+46.0000,off,69,0,1,+46.0000,off,49,0,3,+46.0000,on,65,100,1,+46.0000,on,50,100,3,+46.2500,off,64,0,0,+46.2500,on,62,100,0,+46.5000,off,62,0,0,+46.5000,on,69,100,0,+46.7500,off,50,0,3,+46.7500,on,48,100,3,+47.0000,off,57,0,2,+47.0000,off,65,0,1,+47.0000,off,48,0,3,+47.0000,on,62,100,1,+47.0000,on,58,100,2,+47.0000,on,46,100,3,+47.5000,off,69,0,0,+47.5000,on,67,100,0,+48.0000,off,62,0,1,+48.0000,off,58,0,2,+48.0000,off,46,0,3,+48.0000,off,67,0,0,+48.0000,on,69,100,0,+48.0000,on,61,100,1,+48.0000,on,45,100,3,+48.2500,on,52,100,2,+48.5000,off,52,0,2,+48.5000,on,57,100,2,+48.7500,off,45,0,3,+48.7500,on,43,100,3,+49.0000,off,69,0,0,+49.0000,off,61,0,1,+49.0000,off,43,0,3,+49.0000,on,62,100,1,+49.0000,on,41,100,3,+49.2500,off,57,0,2,+49.2500,off,41,0,3,+49.2500,on,58,100,2,+49.2500,on,43,100,3,+49.5000,off,62,0,1,+49.5000,off,58,0,2,+49.5000,off,43,0,3,+49.5000,on,64,100,1,+49.5000,on,57,100,2,+49.5000,on,41,100,3,+49.7500,off,57,0,2,+49.7500,off,41,0,3,+49.7500,on,55,100,2,+49.7500,on,40,100,3,+50.0000,off,64,0,1,+50.0000,off,55,0,2,+50.0000,off,40,0,3,+50.0000,on,65,100,1,+50.0000,on,57,100,2,+50.0000,on,38,100,3,+50.2500,off,38,0,3,+50.2500,on,41,100,3,+50.5000,off,57,0,2,+50.5000,off,41,0,3,+50.5000,on,59,100,2,+50.5000,on,40,100,3,+50.7500,off,40,0,3,+50.7500,on,38,100,3,+51.0000,off,59,0,2,+51.0000,off,38,0,3,+51.0000,on,60,100,2,+51.0000,on,45,100,3,+51.2500,off,65,0,1,+51.2500,on,67,100,1,+51.5000,off,67,0,1,+51.5000,on,65,100,1,+51.7500,off,45,0,3,+51.7500,off,65,0,1,+51.7500,on,64,100,1,+51.7500,on,41,100,3,+52.0000,off,64,0,1,+52.0000,off,41,0,3,+52.0000,on,62,100,1,+52.0000,on,46,100,3,+52.2500,off,60,0,2,+52.2500,on,57,100,2,+52.5000,off,62,0,1,+52.5000,off,57,0,2,+52.5000,on,67,100,1,+52.5000,on,58,100,2,+52.7500,off,46,0,3,+52.7500,on,43,100,3,+53.0000,off,58,0,2,+53.0000,off,43,0,3,+53.0000,on,57,100,2,+53.0000,on,50,100,3,+53.2500,off,67,0,1,+53.2500,on,64,100,1,+53.5000,off,57,0,2,+53.5000,off,64,0,1,+53.5000,on,65,100,1,+53.5000,on,62,100,2,+53.7500,off,50,0,3,+53.7500,on,53,100,3,+54.0000,off,65,0,1,+54.0000,off,53,0,3,+54.0000,on,64,100,1,+54.0000,on,57,100,3,+54.2500,off,62,0,2,+54.2500,on,59,100,2,+54.5000,off,64,0,1,+54.5000,off,59,0,2,+54.5000,on,69,100,1,+54.5000,on,60,100,2,+54.7500,off,57,0,3,+54.7500,on,45,100,3,+55.0000,off,60,0,2,+55.0000,off,45,0,3,+55.0000,on,59,100,2,+55.0000,on,40,100,3,+55.2500,off,69,0,1,+55.2500,on,66,100,1,+55.5000,off,59,0,2,+55.5000,off,66,0,1,+55.5000,on,67,100,1,+55.5000,on,64,100,2,+56.0000,off,40,0,3,+56.0000,off,67,0,1,+56.0000,on,69,100,0,+56.0000,on,66,100,1,+56.2500,off,64,0,2,+56.2500,on,57,100,2,+56.5000,off,57,0,2,+56.5000,on,62,100,2,+56.7500,off,66,0,1,+56.7500,on,74,100,1,+57.0000,off,69,0,0,+57.0000,off,74,0,1,+57.0000,on,76,100,0,+57.0000,on,68,100,1,+57.0000,on,52,100,3,+57.2500,off,62,0,2,+57.2500,on,62,100,2,+57.5000,off,62,0,2,+57.5000,on,60,100,2,+57.7500,off,60,0,2,+57.7500,on,59,100,2,+58.0000,off,76,0,0,+58.0000,off,68,0,1,+58.0000,off,52,0,3,+58.0000,off,59,0,2,+58.0000,on,72,100,0,+58.0000,on,69,100,1,+58.0000,on,60,100,2,+58.0000,on,57,100,3,+58.2500,off,60,0,2,+58.2500,on,62,100,2,+58.5000,off,69,0,1,+58.5000,off,62,0,2,+58.5000,on,64,100,2,+58.7500,on,57,100,1,+59.0000,off,72,0,0,+59.0000,off,57,0,3,+59.0000,off,57,0,1,+59.0000,on,69,100,0,+59.0000,on,60,100,1,+59.0000,on,53,100,3,+59.2500,off,64,0,2,+59.2500,on,64,100,2,+59.5000,off,60,0,1,+59.5000,off,64,0,2,+59.5000,on,57,100,1,+59.5000,on,62,100,2,+59.7500,off,62,0,2,+59.7500,on,60,100,2,+60.0000,off,69,0,0,+60.0000,off,57,0,1,+60.0000,off,60,0,2,+60.0000,on,68,100,0,+60.0000,on,62,100,1,+60.0000,on,59,100,2,+60.2500,off,53,0,3,+60.2500,on,53,100,3,+60.5000,off,62,0,1,+60.5000,off,53,0,3,+60.5000,on,65,100,1,+60.5000,on,52,100,3,+60.7500,off,52,0,3,+60.7500,on,50,100,3,+61.0000,off,68,0,0,+61.0000,off,59,0,2,+61.0000,off,65,0,1,+61.0000,off,50,0,3,+61.0000,on,69,100,0,+61.0000,on,64,100,1,+61.0000,on,60,100,2,+61.0000,on,48,100,3,+61.2500,off,48,0,3,+61.2500,on,50,100,3,+61.5000,off,69,0,0,+61.5000,off,64,0,1,+61.5000,off,60,0,2,+61.5000,off,50,0,3,+61.5000,on,71,100,0,+61.5000,on,62,100,1,+61.5000,on,56,100,2,+61.5000,on,48,100,3,+61.7500,off,48,0,3,+61.7500,on,47,100,3,+62.0000,off,71,0,0,+62.0000,off,62,0,1,+62.0000,off,56,0,2,+62.0000,off,47,0,3,+62.0000,on,72,100,0,+62.0000,on,60,100,1,+62.0000,on,57,100,2,+62.0000,on,45,100,3,+62.2500,off,57,0,2,+62.2500,on,55,100,2,+62.5000,off,60,0,1,+62.5000,off,55,0,2,+62.5000,on,69,100,1,+62.5000,on,54,100,2,+62.7500,off,54,0,2,+62.7500,on,52,100,2,+63.0000,off,45,0,3,+63.0000,off,52,0,2,+63.0000,on,54,100,2,+63.0000,on,50,100,3,+63.2500,off,72,0,0,+63.2500,on,74,100,0,+63.5000,off,69,0,1,+63.5000,off,54,0,2,+63.5000,off,74,0,0,+63.5000,on,72,100,0,+63.5000,on,62,100,1,+63.5000,on,55,100,2,+63.7500,off,72,0,0,+63.7500,on,70,100,0,+64.0000,off,50,0,3,+64.0000,off,62,0,1,+64.0000,off,70,0,0,+64.0000,on,69,100,0,+64.0000,on,64,100,1,+64.0000,on,49,100,3,+64.2500,off,55,0,2,+64.2500,on,55,100,2,+64.5000,off,69,0,0,+64.5000,off,64,0,1,+64.5000,off,55,0,2,+64.5000,on,69,100,1,+64.5000,on,53,100,2,+64.7500,off,53,0,2,+64.7500,on,52,100,2,+65.0000,off,49,0,3,+65.0000,off,52,0,2,+65.0000,on,53,100,2,+65.0000,on,45,100,3,+65.2500,off,69,0,1,+65.2500,off,53,0,2,+65.2500,on,67,100,1,+65.2500,on,52,100,2,+65.5000,off,67,0,1,+65.5000,off,52,0,2,+65.5000,on,69,100,0,+65.5000,on,65,100,1,+65.5000,on,50,100,2,+65.7500,off,65,0,1,+65.7500,off,50,0,2,+65.7500,on,64,100,1,+65.7500,on,49,100,2,+66.0000,off,45,0,3,+66.0000,off,64,0,1,+66.0000,off,49,0,2,+66.0000,on,62,100,1,+66.0000,on,50,100,2,+66.0000,on,42,100,3,+66.2500,off,69,0,0,+66.2500,on,72,100,0,+66.5000,off,50,0,2,+66.5000,off,72,0,0,+66.5000,on,70,100,0,+66.7500,off,70,0,0,+66.7500,on,69,100,0,+67.0000,off,42,0,3,+67.0000,off,69,0,0,+67.0000,on,70,100,0,+67.0000,on,43,100,3,+67.2500,off,70,0,0,+67.2500,on,69,100,0,+67.5000,off,43,0,3,+67.5000,off,69,0,0,+67.5000,on,67,100,0,+67.5000,on,45,100,3,+67.7500,off,67,0,0,+67.7500,on,66,100,0,+68.0000,off,45,0,3,+68.0000,off,66,0,0,+68.0000,on,67,100,0,+68.0000,on,46,100,3,+68.2500,off,62,0,1,+68.2500,on,62,100,1,+68.5000,off,62,0,1,+68.5000,on,67,100,1,+68.7500,off,67,0,0,+68.7500,on,70,100,0,+69.0000,off,70,0,0,+69.0000,on,64,100,0,+69.2500,off,46,0,3,+69.2500,off,67,0,1,+69.2500,on,67,100,1,+69.2500,on,48,100,3,+69.5000,off,67,0,1,+69.5000,off,48,0,3,+69.5000,on,60,100,1,+69.5000,on,46,100,3,+69.7500,off,64,0,0,+69.7500,off,46,0,3,+69.7500,on,66,100,0,+69.7500,on,45,100,3,+70.0000,off,66,0,0,+70.0000,off,45,0,3,+70.0000,on,67,100,0,+70.0000,on,43,100,3,+70.2500,off,60,0,1,+70.2500,on,57,100,1,+70.5000,off,57,0,1,+70.5000,on,58,100,1,+70.7500,off,67,0,0,+70.7500,on,64,100,0,+71.0000,off,58,0,1,+71.0000,off,64,0,0,+71.0000,on,61,100,0,+71.0000,on,57,100,1,+71.2500,off,43,0,3,+71.2500,on,40,100,3,+71.5000,off,40,0,3,+71.5000,on,41,100,3,+71.7500,off,61,0,0,+71.7500,on,69,100,0,+72.0000,off,41,0,3,+72.0000,off,69,0,0,+72.0000,on,62,100,0,+72.0000,on,46,100,3,+72.2500,off,57,0,1,+72.2500,on,53,100,1,+72.5000,off,53,0,1,+72.5000,on,55,100,1,+72.7500,off,62,0,0,+72.7500,on,65,100,0,+73.0000,off,55,0,1,+73.0000,off,65,0,0,+73.0000,on,64,100,0,+73.0000,on,60,100,1,+73.2500,off,46,0,3,+73.2500,on,43,100,3,+73.5000,off,43,0,3,+73.5000,on,45,100,3,+73.7500,off,64,0,0,+73.7500,on,72,100,0,+74.0000,off,45,0,3,+74.0000,off,72,0,0,+74.0000,on,65,100,0,+74.0000,on,50,100,3,+74.2500,off,60,0,1,+74.2500,on,57,100,1,+74.5000,off,57,0,1,+74.5000,on,59,100,1,+74.7500,off,65,0,0,+74.7500,on,69,100,0,+75.0000,off,59,0,1,+75.0000,off,69,0,0,+75.0000,on,67,100,0,+75.0000,on,64,100,1,+75.2500,off,50,0,3,+75.2500,on,47,100,3,+75.5000,off,47,0,3,+75.5000,on,48,100,3,+75.7500,off,67,0,0,+75.7500,on,76,100,0,+76.0000,off,48,0,3,+76.0000,off,76,0,0,+76.0000,on,69,100,0,+76.0000,on,53,100,3,+76.2500,off,64,0,1,+76.2500,on,61,100,1,+76.5000,off,61,0,1,+76.5000,on,62,100,1,+76.7500,off,69,0,0,+76.7500,on,72,100,0,+77.0000,off,62,0,1,+77.0000,off,72,0,0,+77.0000,on,71,100,0,+77.0000,on,67,100,1,+77.2500,off,53,0,3,+77.2500,on,50,100,3,+77.5000,off,50,0,3,+77.5000,on,52,100,3,+77.7500,off,71,0,0,+77.7500,on,79,100,0,+78.0000,off,52,0,3,+78.0000,off,79,0,0,+78.0000,on,73,100,0,+78.0000,on,52,100,2,+78.0000,on,45,100,3,+78.2500,off,67,0,1,+78.2500,on,69,100,1,+78.5000,off,69,0,1,+78.5000,on,70,100,1,+78.7500,off,45,0,3,+78.7500,on,55,100,3,+79.0000,off,73,0,0,+79.0000,off,52,0,2,+79.0000,off,70,0,1,+79.0000,off,55,0,3,+79.0000,on,74,100,0,+79.0000,on,69,100,1,+79.0000,on,57,100,2,+79.0000,on,53,100,3,+79.2500,off,53,0,3,+79.2500,on,52,100,3,+79.5000,off,74,0,0,+79.5000,off,52,0,3,+79.5000,on,76,100,0,+79.5000,on,50,100,3,+79.7500,off,50,0,3,+79.7500,on,49,100,3,+80.0000,off,57,0,2,+80.0000,off,49,0,3,+80.0000,on,53,100,2,+80.0000,on,50,100,3,+80.2500,off,76,0,0,+80.2500,on,73,100,0,+80.5000,off,73,0,0,+80.5000,on,74,100,0,+80.7500,off,50,0,3,+80.7500,on,41,100,3,+81.0000,off,53,0,2,+81.0000,off,41,0,3,+81.0000,on,50,100,2,+81.0000,on,46,100,3,+81.2500,off,69,0,1,+81.2500,on,65,100,1,+81.5000,off,65,0,1,+81.5000,on,67,100,1,+81.7500,off,74,0,0,+81.7500,on,76,100,0,+82.0000,off,50,0,2,+82.0000,off,46,0,3,+82.0000,off,67,0,1,+82.0000,off,76,0,0,+82.0000,on,77,100,0,+82.0000,on,69,100,1,+82.0000,on,49,100,2,+82.0000,on,45,100,3,+82.2500,off,77,0,0,+82.2500,on,76,100,0,+82.5000,off,76,0,0,+82.5000,on,79,100,0,+82.7500,off,69,0,1,+82.7500,on,70,100,1,+83.0000,off,49,0,2,+83.0000,off,70,0,1,+83.0000,on,69,100,1,+83.0000,on,50,100,2,+83.2500,off,79,0,0,+83.2500,on,77,100,0,+83.5000,off,69,0,1,+83.5000,off,50,0,2,+83.5000,off,77,0,0,+83.5000,on,76,100,0,+83.5000,on,67,100,1,+83.5000,on,52,100,2,+83.7500,off,76,0,0,+83.7500,on,74,100,0,+84.0000,off,52,0,2,+84.0000,off,74,0,0,+84.0000,on,73,100,0,+84.0000,on,53,100,2,+84.2500,off,73,0,0,+84.2500,on,69,100,0,+84.5000,off,67,0,1,+84.5000,off,69,0,0,+84.5000,on,74,100,0,+84.5000,on,65,100,1,+84.7500,off,45,0,3,+84.7500,off,65,0,1,+84.7500,on,62,100,1,+84.7500,on,46,100,3,+85.0000,off,62,0,1,+85.0000,off,46,0,3,+85.0000,on,69,100,1,+85.0000,on,45,100,3,+85.2500,off,53,0,2,+85.2500,off,74,0,0,+85.2500,off,45,0,3,+85.2500,on,71,100,0,+85.2500,on,55,100,2,+85.2500,on,43,100,3,+85.5000,off,71,0,0,+85.5000,off,55,0,2,+85.5000,off,43,0,3,+85.5000,on,72,100,0,+85.5000,on,53,100,2,+85.5000,on,45,100,3,+85.7500,off,69,0,1,+85.7500,off,53,0,2,+85.7500,on,67,100,1,+85.7500,on,52,100,2,+86.0000,off,72,0,0,+86.0000,off,45,0,3,+86.0000,off,67,0,1,+86.0000,off,52,0,2,+86.0000,on,72,100,0,+86.0000,on,66,100,1,+86.0000,on,50,100,2,+86.0000,on,46,100,3,+86.2500,off,66,0,1,+86.2500,on,62,100,1,+86.5000,off,72,0,0,+86.5000,off,62,0,1,+86.5000,on,70,100,0,+86.5000,on,67,100,1,+86.7500,off,46,0,3,+86.7500,on,43,100,3,+87.0000,off,70,0,0,+87.0000,off,43,0,3,+87.0000,on,69,100,0,+87.0000,on,50,100,3,+87.2500,off,67,0,1,+87.2500,on,64,100,1,+87.5000,off,50,0,2,+87.5000,off,69,0,0,+87.5000,off,64,0,1,+87.5000,on,65,100,1,+87.5000,on,57,100,2,+87.7500,off,57,0,2,+87.7500,on,53,100,2,+88.0000,off,53,0,2,+88.0000,on,58,100,2,+88.2500,off,65,0,1,+88.2500,on,62,100,1,+88.5000,off,50,0,3,+88.5000,off,62,0,1,+88.5000,on,67,100,1,+88.5000,on,52,100,3,+88.7500,off,58,0,2,+88.7500,on,55,100,2,+89.0000,off,55,0,2,+89.0000,on,60,100,2,+89.2500,off,67,0,1,+89.2500,on,64,100,1,+89.5000,off,52,0,3,+89.5000,off,64,0,1,+89.5000,on,69,100,1,+89.5000,on,53,100,3,+89.7500,off,60,0,2,+89.7500,on,57,100,2,+90.0000,off,57,0,2,+90.0000,on,62,100,2,+90.2500,off,69,0,1,+90.2500,on,65,100,1,+90.5000,off,62,0,2,+90.5000,off,65,0,1,+90.5000,on,70,100,1,+90.5000,on,55,100,2,+90.7500,off,53,0,3,+90.7500,on,50,100,3,+91.0000,off,55,0,2,+91.0000,off,50,0,3,+91.0000,on,60,100,2,+91.0000,on,52,100,3,+91.2500,off,70,0,1,+91.2500,on,67,100,1,+91.5000,off,60,0,2,+91.5000,off,67,0,1,+91.5000,on,69,100,1,+91.5000,on,53,100,2,+91.7500,off,52,0,3,+91.7500,on,49,100,3,+92.0000,off,53,0,2,+92.0000,off,49,0,3,+92.0000,on,58,100,2,+92.0000,on,50,100,3,+92.2500,off,69,0,1,+92.2500,on,65,100,1,+92.5000,off,58,0,2,+92.5000,off,65,0,1,+92.5000,on,67,100,1,+92.5000,on,52,100,2,+92.7500,off,50,0,3,+92.7500,on,47,100,3,+93.0000,off,52,0,2,+93.0000,off,47,0,3,+93.0000,on,57,100,2,+93.0000,on,49,100,3,+93.2500,off,49,0,3,+93.2500,on,45,100,3,+93.5000,off,67,0,1,+93.5000,off,45,0,3,+93.5000,on,65,100,1,+93.5000,on,50,100,3,+93.7500,off,65,0,1,+93.7500,on,62,100,1,+94.0000,off,57,0,2,+94.0000,off,62,0,1,+94.0000,on,69,100,1,+94.0000,on,52,100,2,+94.2500,off,50,0,3,+94.2500,on,48,100,3,+94.5000,off,52,0,2,+94.5000,off,48,0,3,+94.5000,on,57,100,2,+94.5000,on,47,100,3,+94.7500,off,47,0,3,+94.7500,on,45,100,3,+95.0000,off,69,0,1,+95.0000,off,45,0,3,+95.0000,on,74,100,1,+95.0000,on,47,100,3,+95.2500,off,57,0,2,+95.2500,on,56,100,2,+95.5000,off,56,0,2,+95.5000,on,54,100,2,+95.7500,off,54,0,2,+95.7500,on,56,100,2,+96.0000,off,47,0,3,+96.0000,off,56,0,2,+96.0000,on,76,100,0,+96.0000,on,57,100,2,+96.0000,on,45,100,3,+96.2500,off,74,0,1,+96.2500,on,73,100,1,+96.5000,off,45,0,3,+96.5000,off,73,0,1,+96.5000,on,71,100,1,+96.7500,off,57,0,2,+96.7500,off,71,0,1,+96.7500,on,73,100,1,+96.7500,on,55,100,2,+97.0000,off,76,0,0,+97.0000,off,73,0,1,+97.0000,off,55,0,2,+97.0000,on,81,100,0,+97.0000,on,74,100,1,+97.0000,on,53,100,2,+97.2500,off,74,0,1,+97.2500,off,53,0,2,+97.2500,on,69,100,1,+97.2500,on,52,100,2,+97.5000,off,69,0,1,+97.5000,off,52,0,2,+97.5000,on,76,100,1,+97.5000,on,50,100,2,+97.7500,off,50,0,2,+97.7500,on,49,100,2,+98.0000,off,81,0,0,+98.0000,off,49,0,2,+98.0000,on,77,100,0,+98.0000,on,50,100,2,+98.2500,off,76,0,1,+98.2500,on,69,100,1,+98.5000,off,50,0,2,+98.5000,off,69,0,1,+98.5000,on,74,100,1,+98.5000,on,53,100,2,+98.7500,off,53,0,2,+98.7500,on,50,100,2,+99.0000,off,77,0,0,+99.0000,off,74,0,1,+99.0000,off,50,0,2,+99.0000,on,74,100,0,+99.0000,on,58,100,2,+99.2500,on,65,100,1,+99.5000,off,58,0,2,+99.5000,off,65,0,1,+99.5000,on,70,100,1,+99.5000,on,55,100,2,+99.7500,off,55,0,2,+99.7500,on,52,100,2,+100.0000,off,74,0,0,+100.0000,off,52,0,2,+100.0000,on,73,100,0,+100.0000,on,57,100,2,+100.2500,off,70,0,1,+100.2500,on,64,100,1,+100.5000,off,64,0,1,+100.5000,on,69,100,1,+100.7500,off,57,0,2,+100.7500,on,65,100,2,+101.0000,off,73,0,0,+101.0000,off,65,0,2,+101.0000,on,74,100,0,+101.0000,on,59,100,2,+101.2500,off,69,0,1,+101.2500,on,67,100,1,+101.5000,off,74,0,0,+101.5000,off,59,0,2,+101.5000,off,67,0,1,+101.5000,on,76,100,0,+101.5000,on,65,100,1,+101.5000,on,61,100,2,+101.7500,off,65,0,1,+101.7500,on,64,100,1,+102.0000,off,76,0,0,+102.0000,off,61,0,2,+102.0000,off,64,0,1,+102.0000,on,77,100,0,+102.0000,on,62,100,1,+102.0000,on,62,100,2,+102.2500,off,62,0,1,+102.2500,on,69,100,1,+102.5000,off,62,0,2,+102.5000,off,69,0,1,+102.5000,on,74,100,1,+102.5000,on,59,100,2,+102.7500,off,74,0,1,+102.7500,off,59,0,2,+102.7500,on,71,100,1,+102.7500,on,55,100,2,+103.0000,off,71,0,1,+103.0000,off,55,0,2,+103.0000,on,67,100,1,+103.0000,on,60,100,2,+103.2500,off,77,0,0,+103.2500,off,67,0,1,+103.2500,on,79,100,0,+103.2500,on,64,100,1,+103.5000,off,60,0,2,+103.5000,off,79,0,0,+103.5000,off,64,0,1,+103.5000,on,77,100,0,+103.5000,on,72,100,1,+103.5000,on,57,100,2,+103.7500,off,77,0,0,+103.7500,off,57,0,2,+103.7500,on,76,100,0,+103.7500,on,53,100,2,+104.0000,off,76,0,0,+104.0000,off,53,0,2,+104.0000,on,74,100,0,+104.0000,on,58,100,2,+104.2500,off,58,0,2,+104.2500,on,62,100,2,+104.5000,off,72,0,1,+104.5000,off,62,0,2,+104.5000,on,70,100,1,+104.5000,on,67,100,2,+104.7500,off,74,0,0,+104.7500,on,76,100,0,+105.0000,off,70,0,1,+105.0000,off,76,0,0,+105.0000,on,73,100,0,+105.0000,on,69,100,1,+105.2500,off,67,0,2,+105.2500,on,64,100,2,+105.5000,off,73,0,0,+105.5000,off,64,0,2,+105.5000,on,74,100,0,+105.5000,on,65,100,2,+105.7500,off,74,0,0,+105.7500,on,77,100,0,+106.0000,off,69,0,1,+106.0000,off,77,0,0,+106.0000,on,70,100,0,+106.0000,on,67,100,1,+106.2500,off,65,0,2,+106.2500,on,65,100,2,+106.5000,off,65,0,2,+106.5000,on,64,100,2,+106.7500,off,67,0,1,+106.7500,off,64,0,2,+106.7500,on,65,100,1,+106.7500,on,62,100,2,+107.0000,off,65,0,1,+107.0000,off,62,0,2,+107.0000,on,64,100,1,+107.0000,on,61,100,2,+107.2500,off,70,0,0,+107.2500,on,70,100,0,+107.5000,off,70,0,0,+107.5000,on,69,100,0,+107.7500,off,69,0,0,+107.7500,on,67,100,0,+108.0000,off,61,0,2,+108.0000,off,67,0,0,+108.0000,on,65,100,0,+108.0000,on,62,100,2,+108.2500,off,62,0,2,+108.2500,on,60,100,2,+108.5000,off,64,0,1,+108.5000,off,60,0,2,+108.5000,on,62,100,1,+108.5000,on,58,100,2,+108.7500,off,62,0,1,+108.7500,off,58,0,2,+108.7500,on,61,100,1,+108.7500,on,57,100,2,+109.0000,off,65,0,0,+109.0000,off,61,0,1,+109.0000,off,57,0,2,+109.0000,on,70,100,0,+109.0000,on,62,100,1,+109.0000,on,55,100,2,+109.2500,off,55,0,2,+109.2500,on,57,100,2,+109.5000,off,62,0,1,+109.5000,off,57,0,2,+109.5000,on,67,100,1,+109.5000,on,58,100,2,+109.7500,off,58,0,2,+109.7500,on,60,100,2,+110.0000,off,70,0,0,+110.0000,off,60,0,2,+110.0000,on,69,100,0,+110.0000,on,62,100,2,+110.0000,on,50,100,3,+110.2500,off,62,0,2,+110.2500,on,57,100,2,+110.5000,off,57,0,2,+110.5000,on,62,100,2,+110.7500,off,67,0,1,+110.7500,on,65,100,1,+111.0000,off,50,0,3,+111.0000,off,65,0,1,+111.0000,on,64,100,1,+111.0000,on,57,100,3,+111.2500,off,62,0,2,+111.2500,on,59,100,2,+111.5000,off,69,0,0,+111.5000,off,59,0,2,+111.5000,on,76,100,0,+111.5000,on,61,100,2,+111.7500,off,64,0,1,+111.7500,on,64,100,1,+112.0000,off,57,0,3,+112.0000,off,64,0,1,+112.0000,on,69,100,1,+112.0000,on,53,100,3,+112.2500,off,76,0,0,+112.2500,off,61,0,2,+112.2500,on,73,100,0,+112.2500,on,64,100,2,+112.5000,off,73,0,0,+112.5000,off,64,0,2,+112.5000,on,74,100,0,+112.5000,on,57,100,2,+112.7500,off,74,0,0,+112.7500,off,57,0,2,+112.7500,on,76,100,0,+112.7500,on,61,100,2,+113.0000,off,53,0,3,+113.0000,off,76,0,0,+113.0000,off,61,0,2,+113.0000,on,77,100,0,+113.0000,on,62,100,2,+113.0000,on,50,100,3,+113.2500,off,77,0,0,+113.2500,on,74,100,0,+113.5000,off,69,0,1,+113.5000,off,62,0,2,+113.5000,off,74,0,0,+113.5000,on,79,100,0,+113.5000,on,67,100,1,+113.5000,on,58,100,2,+113.7500,off,67,0,1,+113.7500,off,58,0,2,+113.7500,on,70,100,1,+113.7500,on,55,100,2,+114.0000,off,50,0,3,+114.0000,off,70,0,1,+114.0000,off,55,0,2,+114.0000,on,69,100,1,+114.0000,on,52,100,2,+114.0000,on,49,100,3,+114.2500,off,79,0,0,+114.2500,on,76,100,0,+114.5000,off,76,0,0,+114.5000,on,81,100,0,+114.7500,off,81,0,0,+114.7500,on,79,100,0,+115.0000,off,52,0,2,+115.0000,off,49,0,3,+115.0000,off,79,0,0,+115.0000,on,77,100,0,+115.0000,on,53,100,2,+115.0000,on,50,100,3,+115.2500,off,69,0,1,+115.2500,off,77,0,0,+115.2500,on,76,100,0,+115.2500,on,67,100,1,+115.5000,off,53,0,2,+115.5000,off,50,0,3,+115.5000,off,76,0,0,+115.5000,off,67,0,1,+115.5000,on,74,100,0,+115.5000,on,65,100,1,+115.5000,on,55,100,2,+115.5000,on,52,100,3,+115.7500,off,74,0,0,+115.7500,off,65,0,1,+115.7500,on,73,100,0,+115.7500,on,64,100,1,+116.0000,off,55,0,2,+116.0000,off,52,0,3,+116.0000,off,73,0,0,+116.0000,off,64,0,1,+116.0000,on,74,100,0,+116.0000,on,62,100,1,+116.0000,on,57,100,2,+116.0000,on,53,100,3,+116.2500,off,74,0,0,+116.2500,on,72,100,0,+116.5000,off,72,0,0,+116.5000,on,70,100,0,+116.7500,off,70,0,0,+116.7500,on,69,100,0,+117.0000,off,57,0,2,+117.0000,off,69,0,0,+117.0000,on,67,100,0,+117.0000,on,59,100,2,+117.2500,off,53,0,3,+117.2500,on,55,100,3,+117.5000,off,62,0,1,+117.5000,off,59,0,2,+117.5000,off,55,0,3,+117.5000,on,64,100,1,+117.5000,on,61,100,2,+117.5000,on,53,100,3,+117.7500,off,53,0,3,+117.7500,on,52,100,3,+118.0000,off,64,0,1,+118.0000,off,61,0,2,+118.0000,off,52,0,3,+118.0000,on,57,100,1,+118.0000,on,62,100,2,+118.0000,on,50,100,3,+118.2500,off,67,0,0,+118.2500,on,64,100,0,+118.5000,off,57,0,1,+118.5000,off,62,0,2,+118.5000,off,64,0,0,+118.5000,on,65,100,0,+118.7500,off,65,0,0,+118.7500,on,62,100,0,+119.0000,off,62,0,0,+119.0000,on,69,100,0,+119.2500,off,50,0,3,+119.2500,on,51,100,3,+119.5000,off,51,0,3,+119.5000,on,63,100,1,+119.5000,on,54,100,2,+119.5000,on,50,100,3,+119.7500,off,50,0,3,+119.7500,on,48,100,3,+120.0000,off,63,0,1,+120.0000,off,54,0,2,+120.0000,off,48,0,3,+120.0000,on,62,100,1,+120.0000,on,55,100,2,+120.0000,on,46,100,3,+120.2500,off,69,0,0,+120.2500,off,55,0,2,+120.2500,on,66,100,0,+120.2500,on,57,100,2,+120.5000,off,66,0,0,+120.5000,off,57,0,2,+120.5000,on,67,100,0,+120.5000,on,58,100,2,+120.7500,off,67,0,0,+120.7500,on,70,100,0,+121.0000,off,62,0,1,+121.0000,off,58,0,2,+121.0000,off,70,0,0,+121.0000,on,72,100,0,+121.2500,off,46,0,3,+121.2500,on,48,100,3,+121.5000,off,48,0,3,+121.5000,on,66,100,1,+121.5000,on,60,100,2,+121.5000,on,46,100,3,+121.7500,off,46,0,3,+121.7500,on,45,100,3,+122.0000,off,66,0,1,+122.0000,off,60,0,2,+122.0000,off,45,0,3,+122.0000,on,67,100,1,+122.0000,on,62,100,2,+122.0000,on,43,100,3,+122.2500,off,72,0,0,+122.2500,off,67,0,1,+122.2500,on,69,100,0,+122.2500,on,66,100,1,+122.5000,off,69,0,0,+122.5000,off,66,0,1,+122.5000,on,70,100,0,+122.5000,on,67,100,1,+122.7500,off,70,0,0,+122.7500,on,74,100,0,+123.0000,off,62,0,2,+123.0000,off,67,0,1,+123.0000,off,74,0,0,+123.0000,on,75,100,0,+123.2500,on,55,100,2,+123.5000,off,43,0,3,+123.5000,off,75,0,0,+123.5000,on,74,100,0,+123.5000,on,70,100,1,+123.5000,on,43,100,3,+123.7500,off,55,0,2,+123.7500,on,53,100,2,+124.0000,off,74,0,0,+124.0000,off,53,0,2,+124.0000,on,73,100,0,+124.0000,on,52,100,2,+124.2500,off,70,0,1,+124.2500,on,69,100,1,+124.5000,off,73,0,0,+124.5000,off,69,0,1,+124.5000,on,81,100,0,+124.5000,on,77,100,1,+124.7500,off,77,0,1,+124.7500,on,74,100,1,+125.0000,off,52,0,2,+125.0000,off,74,0,1,+125.0000,on,71,100,1,+125.2500,off,81,0,0,+125.2500,on,74,100,0,+125.5000,off,71,0,1,+125.5000,off,74,0,0,+125.5000,on,79,100,0,+125.5000,on,76,100,1,+125.7500,off,76,0,1,+125.7500,on,73,100,1,+126.0000,off,73,0,1,+126.0000,on,69,100,1,+126.2500,off,79,0,0,+126.2500,on,73,100,0,+126.5000,off,69,0,1,+126.5000,off,73,0,0,+126.5000,on,77,100,0,+126.5000,on,74,100,1,+126.5000,on,53,100,2,+126.7500,off,74,0,1,+126.7500,off,53,0,2,+126.7500,on,69,100,1,+126.7500,on,50,100,2,+127.0000,off,69,0,1,+127.0000,off,50,0,2,+127.0000,on,70,100,1,+127.0000,on,55,100,2,+127.2500,off,77,0,0,+127.2500,on,74,100,0,+127.5000,off,74,0,0,+127.5000,on,76,100,0,+127.7500,off,70,0,1,+127.7500,off,55,0,2,+127.7500,on,67,100,1,+127.7500,on,49,100,2,+128.0000,off,67,0,1,+128.0000,off,49,0,2,+128.0000,on,69,100,1,+128.0000,on,53,100,2,+128.2500,off,76,0,0,+128.2500,on,73,100,0,+128.5000,off,73,0,0,+128.5000,on,74,100,0,+128.7500,off,69,0,1,+128.7500,off,53,0,2,+128.7500,on,65,100,1,+128.7500,on,50,100,2,+129.0000,off,65,0,1,+129.0000,off,50,0,2,+129.0000,on,64,100,1,+129.0000,on,57,100,2,+129.2500,off,74,0,0,+129.2500,on,71,100,0,+129.5000,off,43,0,3,+129.5000,off,71,0,0,+129.5000,on,72,100,0,+129.5000,on,45,100,3,+129.7500,off,64,0,1,+129.7500,on,67,100,1,+130.0000,off,57,0,2,+130.0000,off,45,0,3,+130.0000,off,67,0,1,+130.0000,on,66,100,1,+130.0000,on,50,100,2,+130.0000,on,46,100,3,+130.2500,off,66,0,1,+130.2500,on,62,100,1,+130.5000,off,72,0,0,+130.5000,off,50,0,2,+130.5000,off,62,0,1,+130.5000,on,70,100,0,+130.5000,on,67,100,1,+130.5000,on,62,100,2,+130.7500,off,46,0,3,+130.7500,on,43,100,3,+131.0000,off,70,0,0,+131.0000,off,43,0,3,+131.0000,on,69,100,0,+131.0000,on,50,100,3,+131.2500,off,67,0,1,+131.2500,on,64,100,1,+131.5000,off,62,0,2,+131.5000,off,64,0,1,+131.5000,on,65,100,1,+131.5000,on,57,100,2,+131.7500,off,69,0,0,+131.7500,off,57,0,2,+131.7500,on,69,100,0,+131.7500,on,53,100,2,+132.0000,off,69,0,0,+132.0000,off,53,0,2,+132.0000,on,74,100,0,+132.0000,on,58,100,2,+132.2500,off,50,0,3,+132.2500,off,65,0,1,+132.2500,off,74,0,0,+132.2500,on,77,100,0,+132.2500,on,74,100,1,+132.2500,on,46,100,3,+132.5000,off,77,0,0,+132.5000,off,74,0,1,+132.5000,off,46,0,3,+132.5000,on,76,100,0,+132.5000,on,72,100,1,+132.5000,on,48,100,3,+132.7500,off,76,0,0,+132.7500,on,79,100,0,+133.0000,off,48,0,3,+133.0000,off,79,0,0,+133.0000,on,77,100,0,+133.0000,on,53,100,3,+133.2500,off,58,0,2,+133.2500,off,77,0,0,+133.2500,on,76,100,0,+133.2500,on,56,100,2,+133.5000,off,76,0,0,+133.5000,off,56,0,2,+133.5000,on,74,100,0,+133.5000,on,57,100,2,+133.7500,off,72,0,1,+133.7500,on,72,100,1,+134.0000,off,57,0,2,+134.0000,off,72,0,1,+134.0000,on,70,100,1,+134.0000,on,62,100,2,+134.2500,off,53,0,3,+134.2500,off,74,0,0,+134.2500,off,70,0,1,+134.2500,on,77,100,0,+134.2500,on,69,100,1,+134.2500,on,50,100,3,+134.5000,off,69,0,1,+134.5000,off,50,0,3,+134.5000,on,68,100,1,+134.5000,on,52,100,3,+134.7500,off,77,0,0,+134.7500,on,76,100,0,+135.0000,off,68,0,1,+135.0000,off,52,0,3,+135.0000,off,76,0,0,+135.0000,on,77,100,0,+135.0000,on,69,100,1,+135.0000,on,57,100,3,+135.2500,off,62,0,2,+135.2500,off,77,0,0,+135.2500,on,74,100,0,+135.2500,on,59,100,2,+135.5000,off,74,0,0,+135.5000,off,59,0,2,+135.5000,on,76,100,0,+135.5000,on,60,100,2,+135.7500,off,69,0,1,+135.7500,on,64,100,1,+136.0000,off,60,0,2,+136.0000,off,64,0,1,+136.0000,on,69,100,1,+136.0000,on,65,100,2,+136.2500,off,57,0,3,+136.2500,off,76,0,0,+136.2500,on,74,100,0,+136.2500,on,53,100,3,+136.5000,off,69,0,1,+136.5000,off,74,0,0,+136.5000,off,53,0,3,+136.5000,on,72,100,0,+136.5000,on,67,100,1,+136.5000,on,55,100,3,+136.7500,off,72,0,0,+136.7500,on,71,100,0,+137.0000,off,55,0,3,+137.0000,off,71,0,0,+137.0000,on,72,100,0,+137.0000,on,60,100,3,+137.2500,off,65,0,2,+137.2500,on,62,100,2,+137.5000,off,62,0,2,+137.5000,on,63,100,2,+137.7500,off,67,0,1,+137.7500,off,72,0,0,+137.7500,on,81,100,0,+137.7500,on,72,100,1,+138.0000,off,63,0,2,+138.0000,off,81,0,0,+138.0000,off,72,0,1,+138.0000,on,79,100,0,+138.0000,on,69,100,1,+138.0000,on,62,100,2,+138.2500,off,60,0,3,+138.2500,off,79,0,0,+138.2500,on,78,100,0,+138.2500,on,57,100,3,+138.5000,off,69,0,1,+138.5000,off,78,0,0,+138.5000,off,57,0,3,+138.5000,on,79,100,0,+138.5000,on,67,100,1,+138.5000,on,58,100,3,+138.7500,off,79,0,0,+138.7500,on,82,100,0,+139.0000,off,62,0,2,+139.0000,off,82,0,0,+139.0000,on,73,100,0,+139.0000,on,64,100,2,+139.5000,off,67,0,1,+139.5000,off,58,0,3,+139.5000,off,73,0,0,+139.5000,off,64,0,2,+141.0000,on,74,100,0,+141.0000,on,69,100,1,+141.0000,on,65,100,2,+141.0000,on,57,100,3,+141.5000,off,74,0,0,+141.5000,off,69,0,1,+141.5000,off,65,0,2,+141.5000,off,57,0,3,+143.0000,on,74,100,0,+143.0000,on,71,100,1,+143.0000,on,65,100,2,+143.0000,on,56,100,3,+144.0000,off,71,0,1,+144.0000,off,56,0,3,+144.0000,on,69,100,1,+144.0000,on,57,100,3,+144.5000,off,65,0,2,+144.5000,on,64,100,2,+144.7500,off,64,0,2,+144.7500,on,62,100,2,+145.0000,off,62,0,2,+145.0000,on,64,100,2,+145.2500,off,74,0,0,+145.2500,on,71,100,0,+145.5000,off,57,0,3,+145.5000,off,64,0,2,+145.5000,off,71,0,0,+145.5000,on,73,100,0,+145.5000,on,45,100,3,+145.7500,off,69,0,1,+145.7500,on,67,100,1,+146.0000,off,73,0,0,+146.0000,off,45,0,3,+146.0000,off,67,0,1,+146.0000,on,74,100,0,+146.0000,on,66,100,1,+146.0000,on,57,100,2,+146.0000,on,50,100,3,+146.2500,off,66,0,1,+146.2500,on,67,100,1,+146.5000,off,67,0,1,+146.5000,on,69,100,1,+146.7500,off,74,0,0,+146.7500,on,72,100,0,+147.0000,off,57,0,2,+147.0000,off,72,0,0,+147.0000,on,70,100,0,+147.0000,on,62,100,2,+147.2500,off,69,0,1,+147.2500,on,67,100,1,+147.5000,off,67,0,1,+147.5000,on,72,100,1,+147.7500,off,70,0,0,+147.7500,on,69,100,0,+148.0000,off,62,0,2,+148.0000,off,69,0,0,+148.0000,on,62,100,0,+148.0000,on,58,100,2,+148.2500,off,72,0,1,+148.2500,on,66,100,1,+148.5000,off,66,0,1,+148.5000,on,67,100,1,+148.7500,off,67,0,1,+148.7500,on,70,100,1,+149.0000,off,62,0,0,+149.0000,off,58,0,2,+149.0000,off,70,0,1,+149.0000,on,63,100,1,+149.0000,on,55,100,2,+149.2500,on,67,100,0,+149.5000,off,67,0,0,+149.5000,on,69,100,0,+149.7500,off,69,0,0,+149.7500,on,72,100,0,+150.0000,off,63,0,1,+150.0000,off,55,0,2,+150.0000,on,62,100,1,+150.0000,on,54,100,2,+150.2500,off,72,0,0,+150.2500,on,70,100,0,+150.5000,off,62,0,1,+150.5000,off,70,0,0,+150.5000,on,72,100,0,+150.5000,on,57,100,1,+150.7500,off,72,0,0,+150.7500,on,75,100,0,+151.0000,off,54,0,2,+151.0000,off,57,0,1,+151.0000,on,58,100,1,+151.0000,on,55,100,2,+151.2500,off,75,0,0,+151.2500,on,74,100,0,+151.5000,off,58,0,1,+151.5000,off,55,0,2,+151.5000,off,74,0,0,+151.5000,on,78,100,0,+151.5000,on,60,100,1,+151.5000,on,57,100,2,+151.7500,off,78,0,0,+151.7500,on,81,100,0,+152.0000,off,60,0,1,+152.0000,off,57,0,2,+152.0000,on,62,100,1,+152.0000,on,58,100,2,+152.2500,off,81,0,0,+152.2500,on,79,100,0,+152.3750,off,79,0,0,+152.3750,on,81,100,0,+152.5000,off,62,0,1,+152.5000,off,81,0,0,+152.5000,on,82,100,0,+152.5000,on,55,100,1,+152.7500,off,82,0,0,+152.7500,on,73,100,0,+153.0000,off,73,0,0,+153.0000,on,74,100,0,+153.2500,off,58,0,2,+153.2500,off,55,0,1,+153.2500,on,70,100,1,+153.2500,on,62,100,2,+153.5000,off,70,0,1,+153.5000,off,62,0,2,+153.5000,on,69,100,1,+153.5000,on,60,100,2,+153.7500,off,69,0,1,+153.7500,off,60,0,2,+153.7500,on,67,100,1,+153.7500,on,58,100,2,+154.0000,off,58,0,2,+154.0000,on,57,100,2,+154.2500,off,67,0,1,+154.2500,on,66,100,1,+154.5000,off,57,0,2,+154.5000,off,66,0,1,+154.5000,on,64,100,1,+154.5000,on,57,100,2,+154.7500,off,64,0,1,+154.7500,on,67,100,1,+155.0000,off,67,0,1,+155.0000,on,66,100,1,+156.0000,off,50,0,3,+156.0000,off,74,0,0,+156.0000,off,57,0,2,+156.0000,off,66,0,1,
+ data/dot/euler-j5-a.dot view
@@ -0,0 +1,30 @@+graph g {+graph [layout="dot",rankdir="TB",nodesep=0.5];+edge [fontsize="8",fontname="century schoolbook"];+node [shape="plaintext",fontsize="10",fontname="century schoolbook"];+R_5_3 [label="A♮\n5:3"];+R_5_4 [label="E♮\n5:4"];+R_15_8 [label="B♮\n15:8"];+R_16_9 [label="B♭\n16:9"];+R_4_3 [label="F♮\n4:3"];+R_1_1 [label="C♮\n1:1"];+R_3_2 [label="G♮\n3:2"];+R_9_8 [label="D♮\n9:8"];+R_64_45 [label="F♯\n64:45"];+R_16_15 [label="C♯\n16:15"];+R_8_5 [label="A♭\n8:5"];+R_6_5 [label="E♭\n6:5"];+R_5_3 -- R_5_4 -- R_15_8;+R_16_9 -- R_4_3 -- R_1_1 -- R_3_2 -- R_9_8;+R_64_45 -- R_16_15 -- R_8_5 -- R_6_5;+R_4_3 -- R_5_3 [label=" (8:5)"];+R_1_1 -- R_5_4 [label=" (8:5)"];+R_3_2 -- R_15_8 [label=" (8:5)"];+R_64_45 -- R_16_9 [label=" (8:5)"];+R_16_15 -- R_4_3 [label=" (8:5)"];+R_8_5 -- R_1_1 [label=" (8:5)"];+R_6_5 -- R_3_2 [label=" (8:5)"];+{rank=min; R_5_3 R_5_4 R_15_8}+{rank=same; R_16_9 R_4_3 R_1_1 R_3_2 R_9_8}+{rank=max; R_64_45 R_16_15 R_8_5 R_6_5}+}
+ data/dot/euler-j5-b.dot view
@@ -0,0 +1,30 @@+graph g {+graph [layout="dot",rankdir="TB",nodesep=0.5];+edge [fontsize="8",fontname="century schoolbook"];+node [shape="plaintext",fontsize="10",fontname="century schoolbook"];+R_5_3 [label="A♮\n5:3"];+R_5_4 [label="E♮\n5:4"];+R_15_8 [label="B♮\n15:8"];+R_45_32 [label="F♯\n45:32"];+R_16_9 [label="B♭\n16:9"];+R_4_3 [label="F♮\n4:3"];+R_1_1 [label="C♮\n1:1"];+R_3_2 [label="G♮\n3:2"];+R_9_8 [label="D♮\n9:8"];+R_16_15 [label="C♯\n16:15"];+R_8_5 [label="A♭\n8:5"];+R_6_5 [label="E♭\n6:5"];+R_5_3 -- R_5_4 -- R_15_8 -- R_45_32;+R_16_9 -- R_4_3 -- R_1_1 -- R_3_2 -- R_9_8;+R_16_15 -- R_8_5 -- R_6_5;+R_4_3 -- R_5_3 [label=" (8:5)"];+R_1_1 -- R_5_4 [label=" (8:5)"];+R_3_2 -- R_15_8 [label=" (8:5)"];+R_9_8 -- R_45_32 [label=" (8:5)"];+R_16_15 -- R_4_3 [label=" (8:5)"];+R_8_5 -- R_1_1 [label=" (8:5)"];+R_6_5 -- R_3_2 [label=" (8:5)"];+{rank=min; R_5_3 R_5_4 R_15_8 R_45_32}+{rank=same; R_16_9 R_4_3 R_1_1 R_3_2 R_9_8}+{rank=max; R_16_15 R_8_5 R_6_5}+}
+ data/dot/euler-j7.dot view
@@ -0,0 +1,29 @@+graph g {+graph [layout="dot",rankdir="TB",nodesep=0.5];+edge [fontsize="8",fontname="century schoolbook"];+node [shape="plaintext",fontsize="10",fontname="century schoolbook"];+R_5_4 [label="E♮\n5:4"];+R_15_8 [label="B♮\n15:8"];+R_45_32 [label="F♯\n45:32"];+R_135_128 [label="C♯\n135:128"];+R_4_3 [label="F♮\n4:3"];+R_1_1 [label="C♮\n1:1"];+R_3_2 [label="G♮\n3:2"];+R_9_8 [label="D♮\n9:8"];+R_27_16 [label="A♮\n27:16"];+R_14_9 [label="A♭\n14:9"];+R_7_6 [label="E♭\n7:6"];+R_7_4 [label="B♭\n7:4"];+R_5_4 -- R_15_8 -- R_45_32 -- R_135_128;+R_4_3 -- R_1_1 -- R_3_2 -- R_9_8 -- R_27_16;+R_14_9 -- R_7_6 -- R_7_4;+R_1_1 -- R_5_4 [label=" (8:5)"];+R_3_2 -- R_15_8 [label=" (8:5)"];+R_9_8 -- R_45_32 [label=" (8:5)"];+R_27_16 -- R_135_128 [label=" (8:5)"];+R_7_6 -- R_4_3 [label=" (7:4)"];+R_7_4 -- R_1_1 [label=" (7:4)"];+{rank=min; R_5_4 R_15_8 R_45_32 R_135_128}+{rank=same; R_4_3 R_1_1 R_3_2 R_9_8 R_27_16}+{rank=max; R_14_9 R_7_6 R_7_4}+}
+ data/dot/euler-wtp.dot view
@@ -0,0 +1,30 @@+graph g {+graph [layout="dot",rankdir="TB",nodesep=0.5];+edge [fontsize="8",fontname="century schoolbook"];+node [shape="plaintext",fontsize="10",fontname="century schoolbook"];+R_49_32 [label="B♭=738\n49:32"];+R_147_128 [label="F♮=240\n147:128"];+R_441_256 [label="C♮=942\n441:256"];+R_1323_1024 [label="G♮=444\n1323:1024"];+R_7_4 [label="C♯=969\n7:4"];+R_21_16 [label="A♭=471\n21:16"];+R_63_32 [label="E♭=1173\n63:32"];+R_189_128 [label="B♭=675\n189:128"];+R_567_512 [label="F♮=177\n567:512"];+R_1_1 [label="E♭=0\n1:1"];+R_3_2 [label="B♭=702\n3:2"];+R_9_8 [label="F♮=204\n9:8"];+R_49_32 -- R_147_128 -- R_441_256 -- R_1323_1024;+R_7_4 -- R_21_16 -- R_63_32 -- R_189_128 -- R_567_512;+R_1_1 -- R_3_2 -- R_9_8;+R_7_4 -- R_49_32 [label=" (8:7)"];+R_21_16 -- R_147_128 [label=" (8:7)"];+R_63_32 -- R_441_256 [label=" (8:7)"];+R_189_128 -- R_1323_1024 [label=" (8:7)"];+R_1_1 -- R_7_4 [label=" (8:7)"];+R_3_2 -- R_21_16 [label=" (8:7)"];+R_9_8 -- R_63_32 [label=" (8:7)"];+{rank=min; R_49_32 R_147_128 R_441_256 R_1323_1024}+{rank=same; R_7_4 R_21_16 R_63_32 R_189_128 R_567_512}+{rank=max; R_1_1 R_3_2 R_9_8}+}
+ data/dot/tj_oh_p012.dot view
@@ -0,0 +1,30 @@+graph g {+graph [layout="dot",rankdir="TB",nodesep=0.5];+edge [fontsize="8",fontname="century schoolbook"];+node [shape="plaintext",fontsize="10",fontname="century schoolbook"];+R_5_3 [label="A♮=884\n5:3"];+R_5_4 [label="E♮=386\n5:4"];+R_15_8 [label="B♮=1088\n15:8"];+R_45_32 [label="F♯=590\n45:32"];+R_16_9 [label="B♭=996\n16:9"];+R_4_3 [label="F♮=498\n4:3"];+R_1_1 [label="C♮=0\n1:1"];+R_3_2 [label="G♮=702\n3:2"];+R_9_8 [label="D♮=204\n9:8"];+R_16_15 [label="C♯=112\n16:15"];+R_8_5 [label="A♭=814\n8:5"];+R_6_5 [label="E♭=316\n6:5"];+R_5_3 -- R_5_4 -- R_15_8 -- R_45_32;+R_16_9 -- R_4_3 -- R_1_1 -- R_3_2 -- R_9_8;+R_16_15 -- R_8_5 -- R_6_5;+R_4_3 -- R_5_3 [label=" (8:5)"];+R_1_1 -- R_5_4 [label=" (8:5)"];+R_3_2 -- R_15_8 [label=" (8:5)"];+R_9_8 -- R_45_32 [label=" (8:5)"];+R_16_15 -- R_4_3 [label=" (8:5)"];+R_8_5 -- R_1_1 [label=" (8:5)"];+R_6_5 -- R_3_2 [label=" (8:5)"];+{rank=min; R_5_3 R_5_4 R_15_8 R_45_32}+{rank=same; R_16_9 R_4_3 R_1_1 R_3_2 R_9_8}+{rank=max; R_16_15 R_8_5 R_6_5}+}
+ data/dot/tj_oh_p014.dot view
@@ -0,0 +1,58 @@+graph+ g {+graph [start=168732,layout=neato,epsilon=0.000001];+node [shape=plaintext,fontsize=10,fontname="century schoolbook"];+0 [label="C♮"];+1 [label="c♮"];+2 [label="C♯"];+3 [label="c♯"];+4 [label="D♮"];+5 [label="d♮"];+6 [label="E♭"];+7 [label="e♭"];+8 [label="E♮"];+9 [label="e♮"];+10 [label="F♮"];+11 [label="f♮"];+12 [label="F♯"];+13 [label="f♯"];+14 [label="G♮"];+15 [label="g♮"];+16 [label="A♭"];+17 [label="a♭"];+18 [label="A♮"];+19 [label="a♮"];+20 [label="B♮"];+21 [label="b♮"];+22 [label="b♭"];+23 [label="B♭"];+0 -- 1;+0 -- 9;+0 -- 19;+2 -- 3;+2 -- 11;+2 -- 22;+4 -- 5;+4 -- 21;+6 -- 1;+6 -- 7;+6 -- 15;+8 -- 3;+8 -- 9;+8 -- 17;+10 -- 11;+12 -- 13;+12 -- 22;+14 -- 9;+14 -- 15;+14 -- 21;+16 -- 11;+16 -- 17;+18 -- 3;+18 -- 13;+18 -- 19;+20 -- 17;+20 -- 21;+23 -- 5;+23 -- 15;+}
+ data/dot/tj_oh_p031.dot view
@@ -0,0 +1,53 @@+graph+ g {+graph [layout=neato,epsilon=0.000001];+node [shape=plaintext,fontsize=10,fontname="century schoolbook"];+0 [label="0,2,4,7"];+1 [label="0,2,7,10"];+2 [label="0,2,4,9"];+3 [label="1,3,5,8"];+4 [label="1,3,8,11"];+5 [label="1,3,5,10"];+6 [label="2,4,6,9"];+7 [label="2,4,6,11"];+8 [label="0,5,7,9"];+9 [label="2,5,7,9"];+10 [label="1,6,8,10"];+11 [label="3,6,8,10"];+12 [label="2,7,9,11"];+13 [label="4,7,9,11"];+14 [label="0,3,8,10"];+15 [label="0,5,8,10"];+16 [label="1,4,9,11"];+17 [label="1,6,9,11"];+18 [label="0,2,5,10"];+19 [label="1,3,6,11"];+20 [label="3,5,7,10"];+21 [label="4,6,8,11"];+22 [label="0,3,5,7"];+23 [label="1,4,6,8"];+0 -- 1;+0 -- 2;+2 -- 6;+3 -- 4;+3 -- 5;+5 -- 20;+6 -- 7;+7 -- 21;+8 -- 9;+9 -- 12;+10 -- 11;+12 -- 13;+14 -- 11;+14 -- 15;+16 -- 13;+16 -- 17;+18 -- 1;+18 -- 15;+19 -- 4;+19 -- 17;+22 -- 8;+22 -- 20;+23 -- 10;+23 -- 21;+}
+ data/dot/tj_oh_p125.dot view
@@ -0,0 +1,72 @@+graph+ g {+graph [layout=neato,epsilon=0.000001];+node [shape=plaintext,fontsize=10,fontname="century schoolbook"];+0 [label="0,4,11"];+1 [label="0,5,11"];+2 [label="1,4,11"];+3 [label="0,5,10"];+4 [label="0,6,10"];+5 [label="1,5,10"];+6 [label="0,6,9"];+7 [label="0,7,9"];+8 [label="1,6,9"];+9 [label="0,7,8"];+10 [label="1,7,8"];+11 [label="1,3,11"];+12 [label="2,3,11"];+13 [label="1,4,10"];+14 [label="2,4,10"];+15 [label="1,5,9"];+16 [label="2,5,9"];+17 [label="1,6,8"];+18 [label="2,6,8"];+19 [label="2,3,10"];+20 [label="2,4,9"];+21 [label="3,4,9"];+22 [label="2,5,8"];+23 [label="3,5,8"];+24 [label="2,6,7"];+25 [label="3,6,7"];+26 [label="3,4,8"];+27 [label="3,5,7"];+28 [label="4,5,7"];+29 [label="4,5,6"];+0 -- 1;+0 -- 2;+3 -- 1;+3 -- 4;+3 -- 5;+6 -- 4;+6 -- 7;+6 -- 8;+9 -- 7;+9 -- 10;+11 -- 2;+11 -- 12;+13 -- 2;+13 -- 5;+13 -- 14;+15 -- 5;+15 -- 8;+15 -- 16;+17 -- 8;+17 -- 10;+17 -- 18;+19 -- 12;+19 -- 14;+20 -- 14;+20 -- 16;+20 -- 21;+22 -- 16;+22 -- 18;+22 -- 23;+24 -- 18;+24 -- 25;+26 -- 21;+26 -- 23;+27 -- 23;+27 -- 25;+27 -- 28;+29 -- 28;+}
+ data/dot/tj_oh_p131.dot view
@@ -0,0 +1,26 @@+graph+ g {+graph [layout=neato,epsilon=0.000001];+node [shape=plaintext,fontsize=10,fontname="century schoolbook"];+0 [label="6,10,14"];+1 [label="6,11,13"];+2 [label="7,9,14"];+3 [label="7,10,13"];+4 [label="7,11,12"];+5 [label="8,9,13"];+6 [label="8,10,12"];+7 [label="9,10,11"];+0 -- 1;+0 -- 2;+0 -- 3;+1 -- 3;+1 -- 4;+2 -- 3;+2 -- 5;+3 -- 4;+3 -- 5;+3 -- 6;+4 -- 6;+5 -- 6;+6 -- 7;+}
+ data/dot/tj_oh_p162.dot view
@@ -0,0 +1,83 @@+graph+ g {+edge [len=1.75];+graph [layout=neato,epsilon=0.000001];+node [shape=plaintext,fontsize=10,fontname="century schoolbook"];+0 [label="0,1,2,6"];+1 [label="0,2,5,6"];+2 [label="1,2,4,6"];+3 [label="1,2,6,8"];+4 [label="0,1,3,5"];+5 [label="0,1,5,7"];+6 [label="1,3,4,5"];+7 [label="1,3,5,8"];+8 [label="0,1,4,8"];+9 [label="0,4,5,8"];+10 [label="1,4,5,7"];+11 [label="1,5,7,8"];+12 [label="0,2,3,4"];+13 [label="0,2,3,8"];+14 [label="0,2,4,7"];+15 [label="0,3,4,6"];+16 [label="2,3,4,8"];+17 [label="0,2,7,8"];+18 [label="0,3,6,8"];+19 [label="0,4,6,7"];+20 [label="2,4,7,8"];+21 [label="2,4,5,6"];+22 [label="2,5,6,8"];+23 [label="0,6,7,8"];+24 [label="3,4,6,8"];+25 [label="4,6,7,8"];+26 [label="1,2,3,7"];+27 [label="1,3,6,7"];+28 [label="2,3,5,7"];+29 [label="3,5,6,7"];+0 -- 1;+0 -- 2;+0 -- 3;+1 -- 21;+1 -- 22;+2 -- 3;+2 -- 21;+3 -- 22;+4 -- 5;+4 -- 6;+4 -- 7;+5 -- 10;+5 -- 11;+6 -- 7;+6 -- 10;+7 -- 11;+8 -- 9;+10 -- 11;+12 -- 13;+12 -- 14;+12 -- 15;+12 -- 16;+13 -- 16;+13 -- 17;+13 -- 18;+14 -- 17;+14 -- 19;+14 -- 20;+15 -- 18;+15 -- 19;+15 -- 24;+16 -- 20;+16 -- 24;+17 -- 20;+17 -- 23;+18 -- 23;+18 -- 24;+19 -- 23;+19 -- 25;+20 -- 25;+21 -- 22;+23 -- 25;+24 -- 25;+26 -- 27;+26 -- 28;+27 -- 29;+28 -- 29;+}
+ data/scl/dr_itb_etude_1.scl view
@@ -0,0 +1,41 @@+! dr_itb_etude_1.scl+!+...+36+!+1/1+1/1+1/1+1/1+4/3+16/11+16/11+8/5+8/5+16/9+16/9+2/1+2/1+16/7+16/7+16/7+8/3+8/3+3/1+16/5+16/5+32/9+32/9+4/1+4/1+9/2+9/2+5/1+16/3+11/2+6/1+32/5+32/5+7/1+7/1+8/1
+ data/scl/et12.scl view
@@ -0,0 +1,17 @@+! et12.scl+!+12 tone equal temperament+12+!+100.0+200.0+300.0+400.0+500.0+600.0+700.0+800.0+900.0+1000.0+1100.0+2/1
+ data/scl/et19.scl view
@@ -0,0 +1,24 @@+! et19.scl+!+19 tone equal temperament+19+!+63.1578947368421+126.3157894736842+189.4736842105263+252.63157894736838+315.78947368421046+378.94736842105254+442.1052631578946+505.2631578947367+568.4210526315787+631.5789473684208+694.7368421052629+757.894736842105+821.0526315789471+884.2105263157891+947.3684210526312+1010.5263157894733+1073.6842105263154+1136.8421052631575+2/1
+ data/scl/et31.scl view
@@ -0,0 +1,36 @@+! et31.scl+!+31 tone equal temperament+31+!+38.70967741935484+77.41935483870968+116.12903225806451+154.83870967741933+193.54838709677415+232.25806451612897+270.9677419354838+309.6774193548386+348.3870967741934+387.09677419354824+425.80645161290306+464.5161290322579+503.2258064516127+541.9354838709676+580.6451612903224+619.3548387096773+658.0645161290322+696.7741935483871+735.483870967742+774.1935483870968+812.9032258064517+851.6129032258066+890.3225806451615+929.0322580645163+967.7419354838712+1006.4516129032261+1045.161290322581+1083.8709677419358+1122.5806451612907+1161.2903225806456+2/1
+ data/scl/et53.scl view
@@ -0,0 +1,58 @@+! et53.scl+!+53 tone equal temperament+53+!+22.641509433962263+45.283018867924525+67.9245283018868+90.56603773584906+113.20754716981133+135.8490566037736+158.49056603773585+181.1320754716981+203.77358490566036+226.4150943396226+249.05660377358487+271.6981132075471+294.3396226415094+316.98113207547163+339.6226415094339+362.26415094339615+384.9056603773584+407.54716981132066+430.1886792452829+452.83018867924517+475.4716981132074+498.1132075471697+520.7547169811319+543.3962264150941+566.0377358490564+588.6792452830186+611.3207547169809+633.9622641509432+656.6037735849054+679.2452830188677+701.8867924528299+724.5283018867922+747.1698113207544+769.8113207547167+792.452830188679+815.0943396226412+837.7358490566035+860.3773584905657+883.018867924528+905.6603773584902+928.3018867924525+950.9433962264147+973.584905660377+996.2264150943392+1018.8679245283015+1041.5094339622638+1064.150943396226+1086.7924528301883+1109.4339622641505+1132.0754716981128+1154.716981132075+1177.3584905660373+2/1
+ data/scl/et72.scl view
@@ -0,0 +1,77 @@+! et72.scl+!+72 tone equal temperament+72+!+16.666666666666668+33.333333333333336+50.0+66.66666666666666+83.33333333333331+99.99999999999997+116.66666666666663+133.3333333333333+149.99999999999994+166.6666666666666+183.33333333333326+199.99999999999991+216.66666666666657+233.33333333333323+249.9999999999999+266.6666666666665+283.33333333333314+299.9999999999998+316.6666666666664+333.33333333333303+349.99999999999966+366.6666666666663+383.3333333333329+399.99999999999955+416.6666666666662+433.3333333333328+449.99999999999943+466.66666666666606+483.3333333333327+499.9999999999993+516.666666666666+533.3333333333326+549.9999999999992+566.6666666666658+583.3333333333325+599.9999999999991+616.6666666666657+633.3333333333323+649.999999999999+666.6666666666656+683.3333333333322+699.9999999999989+716.6666666666655+733.3333333333321+749.9999999999987+766.6666666666654+783.333333333332+799.9999999999986+816.6666666666653+833.3333333333319+849.9999999999985+866.6666666666652+883.3333333333318+899.9999999999984+916.666666666665+933.3333333333317+949.9999999999983+966.6666666666649+983.3333333333316+999.9999999999982+1016.6666666666648+1033.3333333333314+1049.9999999999982+1066.666666666665+1083.3333333333317+1099.9999999999984+1116.6666666666652+1133.333333333332+1149.9999999999986+1166.6666666666654+1183.3333333333321+2/1
+ data/scl/et96.scl view
@@ -0,0 +1,101 @@+! et96.scl+!+96 tone equal temperament+96+!+12.5+25.0+37.5+50.0+62.5+75.0+87.5+100.0+112.5+125.0+137.5+150.0+162.5+175.0+187.5+200.0+212.5+225.0+237.5+250.0+262.5+275.0+287.5+300.0+312.5+325.0+337.5+350.0+362.5+375.0+387.5+400.0+412.5+425.0+437.5+450.0+462.5+475.0+487.5+500.0+512.5+525.0+537.5+550.0+562.5+575.0+587.5+600.0+612.5+625.0+637.5+650.0+662.5+675.0+687.5+700.0+712.5+725.0+737.5+750.0+762.5+775.0+787.5+800.0+812.5+825.0+837.5+850.0+862.5+875.0+887.5+900.0+912.5+925.0+937.5+950.0+962.5+975.0+987.5+1000.0+1012.5+1025.0+1037.5+1050.0+1062.5+1075.0+1087.5+1100.0+1112.5+1125.0+1137.5+1150.0+1162.5+1175.0+1187.5+2/1
+ data/scl/hs17.scl view
@@ -0,0 +1,22 @@+! hs17.scl+!+17 tone harmonic series+17+!+2/1+3/1+4/1+5/1+6/1+7/1+8/1+9/1+10/1+11/1+12/1+13/1+14/1+15/1+16/1+17/1+2/1
+ data/scl/hs19.scl view
@@ -0,0 +1,24 @@+! hs19.scl+!+19 tone harmonic series+19+!+2/1+3/1+4/1+5/1+6/1+7/1+8/1+9/1+10/1+11/1+12/1+13/1+14/1+15/1+16/1+17/1+18/1+19/1+2/1
+ data/scl/hs21.scl view
@@ -0,0 +1,26 @@+! hs21.scl+!+21 tone harmonic series+21+!+2/1+3/1+4/1+5/1+6/1+7/1+8/1+9/1+10/1+11/1+12/1+13/1+14/1+15/1+16/1+17/1+18/1+19/1+20/1+21/1+2/1
+ data/scl/hs23.scl view
@@ -0,0 +1,28 @@+! hs23.scl+!+23 tone harmonic series+23+!+2/1+3/1+4/1+5/1+6/1+7/1+8/1+9/1+10/1+11/1+12/1+13/1+14/1+15/1+16/1+17/1+18/1+19/1+20/1+21/1+22/1+23/1+2/1
+ data/scl/young-lm_piano_1964.scl view
@@ -0,0 +1,17 @@+! young-lm_piano_1964.scl+!+LaMonte Young's Well-Tuned Piano (1964)+12+!+279/256+9/8+147/128+21/16+93/64+189/128+3/2+49/32+7/4+31/16+63/32+2/1
hmt.cabal view
@@ -1,48 +1,65 @@ Name: hmt-Version: 0.15+Version: 0.16 Synopsis: Haskell Music Theory Description: Haskell music theory library License: GPL Category: Music-Copyright: Rohan Drape, 2006-2014+Copyright: Rohan Drape, 2006-2017 Author: Rohan Drape Maintainer: rd@slavepianos.org Stability: Experimental Homepage: http://rd.slavepianos.org/t/hmt-Tested-With: GHC == 7.8.2+Tested-With: GHC == 8.0.1 Build-Type: Simple Cabal-Version: >= 1.8 Data-files: README- Help/hmt.help.lhs+ data/csv/mnd/*.csv+ data/dot/*.dot+ data/scl/*.scl Library- Build-Depends: array,- base == 4.*,+ Build-Depends: aeson,+ array,+ base >= 4.8 && < 5, bytestring, colour, containers, data-ordlist, directory,+ fgl, filepath, lazy-csv, logict,+ modular-arithmetic, multiset-comb, parsec, permutation, primes,+ random, safe, split,- utf8-string+ text GHC-Options: -Wall -fwarn-tabs- Exposed-modules: Music.Theory.Array.CSV- Music.Theory.Array.CSV.Midi+ Exposed-modules: Music.Theory.Array+ Music.Theory.Array.Cell_Ref+ Music.Theory.Array.CSV+ Music.Theory.Array.CSV.Midi.MND+ Music.Theory.Array.Direction Music.Theory.Array.MD+ Music.Theory.Bits Music.Theory.Bjorklund Music.Theory.Block_Design.Johnson_2007+ Music.Theory.Braille+ Music.Theory.Byte Music.Theory.Clef Music.Theory.Combinations Music.Theory.Contour.Polansky_1992+ Music.Theory.DB.Common+ Music.Theory.DB.CSV+ Music.Theory.DB.JSON+ Music.Theory.DB.Plain+ Music.Theory.Directory Music.Theory.Duration Music.Theory.Duration.Annotation Music.Theory.Duration.CT@@ -54,30 +71,52 @@ Music.Theory.Duration.Sequence.Notate Music.Theory.Dynamic_Mark Music.Theory.Either+ Music.Theory.Enum Music.Theory.Function+ Music.Theory.Gamelan+ Music.Theory.Graph.Deacon_1934+ Music.Theory.Graph.Dot+ Music.Theory.Graph.FGL+ Music.Theory.Graph.Johnson_2014 Music.Theory.Instrument.Choir+ Music.Theory.Instrument.Names Music.Theory.Interval Music.Theory.Interval.Barlow_1987 Music.Theory.Interval.Name Music.Theory.Interval.Spelling+ Music.Theory.IO Music.Theory.Key Music.Theory.List+ Music.Theory.Map Music.Theory.Math+ Music.Theory.Math.Convert+ Music.Theory.Math.OEIS Music.Theory.Maybe Music.Theory.Meter.Barlow_1987 Music.Theory.Metric.Buchler_1998 Music.Theory.Metric.Morris_1980 Music.Theory.Metric.Polansky_1996+ Music.Theory.Monad+ Music.Theory.Ord+ Music.Theory.Parse Music.Theory.Permutations Music.Theory.Permutations.List Music.Theory.Permutations.Morris_1984 Music.Theory.Pitch+ Music.Theory.Pitch.Chord Music.Theory.Pitch.Name Music.Theory.Pitch.Note+ Music.Theory.Pitch.Note.Name Music.Theory.Pitch.Spelling Music.Theory.Pitch.Spelling.Cluster+ Music.Theory.Pitch.Spelling.Key+ Music.Theory.Pitch.Spelling.Table+ Music.Theory.Random.I_Ching+ Music.Theory.Read Music.Theory.Set.List Music.Theory.Set.Set+ Music.Theory.Show+ Music.Theory.String Music.Theory.Tempo_Marking Music.Theory.Tiling.Canon Music.Theory.Tiling.Johnson_2004@@ -89,26 +128,39 @@ Music.Theory.Time_Signature Music.Theory.Tuple Music.Theory.Tuning- Music.Theory.Tuning.Alves Music.Theory.Tuning.Alves_1997+ Music.Theory.Tuning.DB+ Music.Theory.Tuning.DB.Alves+ Music.Theory.Tuning.DB.Gann+ Music.Theory.Tuning.DB.Microtonal_Synthesis+ Music.Theory.Tuning.DB.Riley+ Music.Theory.Tuning.DB.Werckmeister Music.Theory.Tuning.ET- Music.Theory.Tuning.Gann+ Music.Theory.Tuning.Euler+ Music.Theory.Tuning.Gann_1993+ Music.Theory.Tuning.Load Music.Theory.Tuning.Meyer_1929- Music.Theory.Tuning.Microtonal_Synthesis Music.Theory.Tuning.Polansky_1978 Music.Theory.Tuning.Polansky_1984 Music.Theory.Tuning.Polansky_1985c Music.Theory.Tuning.Polansky_1990- Music.Theory.Tuning.Riley+ Music.Theory.Tuning.Rosenboom_1979 Music.Theory.Tuning.Scala+ Music.Theory.Tuning.Scala.Interval+ Music.Theory.Tuning.Scala.Mode+ Music.Theory.Tuning.Sethares_1994 Music.Theory.Tuning.Syntonic- Music.Theory.Tuning.Werckmeister Music.Theory.Unicode+ Music.Theory.Wyschnegradsky Music.Theory.Xenakis.S4 Music.Theory.Xenakis.Sieve Music.Theory.Z+ Music.Theory.Z.Boros_1990+ Music.Theory.Z.Clough_1979+ Music.Theory.Z.Drape_1999 Music.Theory.Z.Forte_1973 Music.Theory.Z.Read_1978+ Music.Theory.Z.TTO Music.Theory.Z.SRO Music.Theory.Z12 Music.Theory.Z12.Castren_1994