<commit_before>module Midi where

import Codec.Midi
import Expr

musicToTrack :: Music -> [[(Ticks, Message)]]
musicToTrack (Music m) = concatMap partToTrack m

midiFromMusic :: Music -> Int -> Midi
midiFromMusic m tempo = Midi
    { fileType = MultiTrack
    , timeDiv = TicksPerBeat tempo
    , tracks = musicToTrack m }

export :: Midi -> String -> IO ()
export themidi filename = exportFile filename themidi

-- best function
exportMusic :: Int -> String -> Music -> IO ()
exportMusic tempo filename music = export (midiFromMusic music tempo) filename

-- returns lenght of longest atom
longestAtom :: Part -> Int
longestAtom (Part p) = maximum $ map sizeOfAtom p
  where
    sizeOfAtom (AtomChord (Chord a _)) = length a
    sizeOfAtom _ = 1

-- Returns a [[Track]] of length l and takes care of rest padding if Atom is
-- not of length l
appendRests :: Int -> Atom -> [[(Ticks, Message)]]
appendRests l (AtomNote n@(Note (Pitch _) d))
    = noteToTrack n : (replicate (l - 1) (restToTrack (Rest d)))
appendRests l (AtomRest r@(Rest _))
    = restToTrack r : (replicate (l - 1) (restToTrack r))
appendRests l (AtomChord c@(Chord a d))
    = chordToTrack c ++ (replicate (l - (length a)) (restToTrack (Rest d)))

-- Takes a part and outputs [[Track]] with padding using partToTracKHelp
partToTrack :: Part -> [[(Ticks, Message)]]
partToTrack p@(Part atoms) = partToTrackHelp (replicate (longestAtom p) []) atoms

-- Appends all Atoms to a list of tracks with Rest padding
partToTrackHelp :: [[(Ticks, Message)]] -> [Atom] -> [[(Ticks, Message)]]
partToTrackHelp container []
    = zipWith (++) container $ replicate (length container) [(0, TrackEnd)]
partToTrackHelp container (x:xs)
    = partToTrackHelp (zipWith (++) container (appendRests (length container) x)) xs

-- Turn Atom into list of Ticks and Messages
atomToTrack :: Atom -> [[(Ticks, Message)]]
atomToTrack (AtomNote n) = [noteToTrack n]
atomToTrack (AtomRest r) = [restToTrack r]
atomToTrack (AtomChord c) = chordToTrack c

-- Takes Chord and outputs a list of Tracks with its notes
chordToTrack :: Chord -> [[(Ticks, Message)]]
chordToTrack (Chord pitches (Duration d)) = chords
  where
    chords = [ckvtToTrack 0 p 60 d  | (Pitch p) <- pitches] -- ++ [(0, TrackEnd)]

-- Takes Note and outputs a Track with the note
noteToTrack :: Note -> [(Ticks, Message)]
noteToTrack (Note (Pitch p) (Duration d)) = ckvtToTrack 0 p 60 d

-- Takes Rest and outputs a Track with the rest
restToTrack :: Rest -> [(Ticks, Message)]
restToTrack (Rest (Duration d)) = ckvtToTrack 0 0 0 d

-- Takes root, duration, pitch list and returns a midi track of the pitches in
-- sequence for duration
nSeqTrack :: [Note] -> [(Ticks, Message)]
nSeqTrack = concatMap noteToTrack

-- Takes Channel Pitch Velocity Ticks and outputs a Track with the note
-- constructed from them
ckvtToTrack :: Channel -> Key -> Velocity -> Ticks -> [(Ticks, Message)]
ckvtToTrack chan pitch vel dur
    = [(0, NoteOn chan pitch vel), (dur, NoteOff chan pitch vel)]
<commit_msg>fixed tempo<commit_after>module Midi where

import Codec.Midi
import Expr

musicToTrack :: Music -> Int -> [[(Ticks, Message)]]
musicToTrack (Music m) tempo = map (addTM tempo) (concatMap partToTrack m)

addTM :: Int -> [(Ticks, Message)] -> [(Ticks, Message)]
addTM tempo tracks = [(0, TempoChange tempo)] ++ tracks

midiFromMusic :: Music -> Int -> Midi
midiFromMusic m tempo = Midi
    { fileType = MultiTrack
    , timeDiv = TicksPerBeat 16 -- depends on how we convert durations i think
    , tracks = musicToTrack m $ quot 60000000 tempo}

export :: Midi -> String -> IO ()
export themidi filename = exportFile filename themidi

-- best function
exportMusic :: Int -> String -> Music -> IO ()
exportMusic tempo filename music = export (midiFromMusic music tempo) filename

-- returns lenght of longest atom
longestAtom :: Part -> Int
longestAtom (Part p) = maximum $ map sizeOfAtom p
  where
    sizeOfAtom (AtomChord (Chord a _)) = length a
    sizeOfAtom _ = 1

-- Returns a [[Track]] of length l and takes care of rest padding if Atom is
-- not of length l
appendRests :: Int -> Atom -> [[(Ticks, Message)]]
appendRests l (AtomNote n@(Note (Pitch _) d))
    = noteToTrack n : (replicate (l - 1) (restToTrack (Rest d)))
appendRests l (AtomRest r@(Rest _))
    = restToTrack r : (replicate (l - 1) (restToTrack r))
appendRests l (AtomChord c@(Chord a d))
    = chordToTrack c ++ (replicate (l - (length a)) (restToTrack (Rest d)))

-- Takes a part and outputs [[Track]] with padding using partToTracKHelp
partToTrack :: Part -> [[(Ticks, Message)]]
partToTrack p@(Part atoms) = partToTrackHelp (replicate (longestAtom p) []) atoms

-- Appends all Atoms to a list of tracks with Rest padding
partToTrackHelp :: [[(Ticks, Message)]] -> [Atom] -> [[(Ticks, Message)]]
partToTrackHelp container []
    = zipWith (++) container $ replicate (length container) [(0, TrackEnd)]
partToTrackHelp container (x:xs)
    = partToTrackHelp (zipWith (++) container (appendRests (length container) x)) xs

-- Turn Atom into list of Ticks and Messages
atomToTrack :: Atom -> [[(Ticks, Message)]]
atomToTrack (AtomNote n) = [noteToTrack n]
atomToTrack (AtomRest r) = [restToTrack r]
atomToTrack (AtomChord c) = chordToTrack c

-- Takes Chord and outputs a list of Tracks with its notes
chordToTrack :: Chord -> [[(Ticks, Message)]]
chordToTrack (Chord pitches (Duration d)) = chords
  where
    chords = [ckvtToTrack 0 p 60 d  | (Pitch p) <- pitches] -- ++ [(0, TrackEnd)]

-- Takes Note and outputs a Track with the note
noteToTrack :: Note -> [(Ticks, Message)]
noteToTrack (Note (Pitch p) (Duration d)) = ckvtToTrack 0 p 80 d

-- Takes Rest and outputs a Track with the rest
restToTrack :: Rest -> [(Ticks, Message)]
restToTrack (Rest (Duration d)) = ckvtToTrack 0 0 0 d

-- Takes root, duration, pitch list and returns a midi track of the pitches in
-- sequence for duration
nSeqTrack :: [Note] -> [(Ticks, Message)]
nSeqTrack = concatMap noteToTrack

-- Takes Channel Pitch Velocity Ticks and outputs a Track with the note
-- constructed from them
ckvtToTrack :: Channel -> Key -> Velocity -> Ticks -> [(Ticks, Message)]
ckvtToTrack chan pitch vel dur
    = [(0, NoteOn chan pitch vel), (dur, NoteOff chan pitch vel)]
{'fraction_non_alphanumeric': 0.12316857188858477, 'fraction_numerical': 0.006601191434551602, 'mean_word_length': 3.989558232931727, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 52, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2698091', 'n_tokens_mistral': 2070, 'n_tokens_neox': 1988, 'n_words': 776}