diff options
author | Andrew Cady <d@jerkface.net> | 2015-12-06 22:37:02 -0500 |
---|---|---|
committer | Andrew Cady <d@jerkface.net> | 2015-12-06 22:45:40 -0500 |
commit | c1a28c4f18dbcf7dda4251a1f0dd98d7d7377d2b (patch) | |
tree | 714cf1e7a6c9bcaf7e43535b3bfb5e47ae524f8b | |
parent | 161f46c1aa0a5f34ff6f44eb5905b1a4679b0398 (diff) |
Deserialization with Sound.MIDI.Message
This format is still inefficient -- because the time is still
represented as a string that is parsed as an Integer -- but it's
certainly much more efficient than before. And more importantly, it can
be both written and read.
-rw-r--r-- | Midi.hs | 25 |
1 files changed, 22 insertions, 3 deletions
@@ -2,7 +2,8 @@ | |||
2 | module Midi where | 2 | module Midi where |
3 | import BasePrelude | 3 | import BasePrelude |
4 | import qualified Data.ByteString as BS | 4 | import qualified Data.ByteString as BS |
5 | import Data.ByteString.Char8 (pack) | 5 | import qualified Data.ByteString.Lazy as LBS |
6 | import Data.ByteString.Char8 (pack, unpack) | ||
6 | import Prelude hiding (id, (.)) | 7 | import Prelude hiding (id, (.)) |
7 | -- import Sound.MIDI.ALSA | 8 | -- import Sound.MIDI.ALSA |
8 | import System.Clock | 9 | import System.Clock |
@@ -17,6 +18,7 @@ import Sound.MIDI.Message | |||
17 | 18 | ||
18 | import Codec.Midi | 19 | import Codec.Midi |
19 | import Codec.ByteString.Builder | 20 | import Codec.ByteString.Builder |
21 | import Codec.ByteString.Parser | ||
20 | 22 | ||
21 | -- import qualified Sound.ALSA.Sequencer | 23 | -- import qualified Sound.ALSA.Sequencer |
22 | -- import qualified Sound.ALSA.Sequencer.Address | 24 | -- import qualified Sound.ALSA.Sequencer.Address |
@@ -97,6 +99,23 @@ stopRecording (RecordingInProgress x y ls@((z,_):_)) end = Just $ CompleteRecord | |||
97 | stopRecording _ _ = Nothing | 99 | stopRecording _ _ = Nothing |
98 | 100 | ||
99 | midiToBytes :: [RecordedEvent] -> BS.ByteString | 101 | midiToBytes :: [RecordedEvent] -> BS.ByteString |
100 | midiToBytes = pack . show . map (first timeSpecAsNanoSecs) . (fmap . fmap) (toLazyByteString . buildMessage) | 102 | midiToBytes = pack . show . overFirsts toDeltas . map (first timeSpecAsNanoSecs) . (fmap . fmap) (toLazyByteString . buildMessage) . reverse |
101 | bytesToMidi :: BS.ByteString -> [RecordedEvent] | 103 | bytesToMidi :: BS.ByteString -> [RecordedEvent] |
102 | bytesToMidi = undefined | 104 | bytesToMidi = unpack >>> read >>> overFirsts fromDeltas >>> map (first fromInteger) >>> (fmap . fmap) f >>> reverse |
105 | where f :: LBS.ByteString -> Codec.Midi.Message | ||
106 | f = runParser (parseMessage Nothing) >>> either error id | ||
107 | |||
108 | overFirsts :: ([a1] -> [a]) -> [(a1, b)] -> [(a, b)] | ||
109 | overFirsts f = uncurry zip . first f . unzip | ||
110 | |||
111 | toDeltas :: Num n => [n] -> [n] | ||
112 | toDeltas xs = zipWith (-) xs (0:xs) | ||
113 | |||
114 | fromDeltas :: Num n => [n] -> [n] | ||
115 | fromDeltas = helper 0 | ||
116 | where | ||
117 | helper _ [] = [] | ||
118 | helper n (x:xs) = (n+x) : helper (n+x) xs | ||
119 | |||
120 | -- fromDeltas :: Num n => [n] -> [n] | ||
121 | -- fromDeltas = foldr (\a b -> a:map (a +) b) [] | ||