summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2015-12-06 07:53:56 -0500
committerAndrew Cady <d@jerkface.net>2015-12-06 07:53:56 -0500
commit52bc07bc5a70ac43b0e1070d7fbb0d468d4e8139 (patch)
tree98057e48c24d40bc6d520bc420b44cc2345a72fe
parentb4f30bddff95f56d3418db0a130331d9666a706e (diff)
Store recordings as Sound.MIDI.Message.T
My intent in doing this was to have a format suitable for reading and writing to the database; the old format (using "show" on the Sound.ALSA.Sequencer.Event.T) could not be read back. Unfortunately, this new format cannot be read back _OR WRITTEN_! At least not without more conversion (of my list of pairs into a Thielemann's specialized event-list). My new plan is to use HCodec's Codec.Midi.Message instead. But I'll commit this before I get to that.
-rw-r--r--Midi.hs39
-rw-r--r--midi-dump.hs4
2 files changed, 32 insertions, 11 deletions
diff --git a/Midi.hs b/Midi.hs
index 4609d04..b4f4fc0 100644
--- a/Midi.hs
+++ b/Midi.hs
@@ -1,7 +1,8 @@
1{-# LANGUAGE ExplicitForAll #-}
1module Midi where 2module Midi where
2import BasePrelude 3import BasePrelude
3import qualified Data.ByteString as BS 4import qualified Data.ByteString as BS
4import Data.ByteString.Char8 (pack) 5-- import Data.ByteString.Char8 (pack)
5import Prelude hiding (id, (.)) 6import Prelude hiding (id, (.))
6-- import Sound.MIDI.ALSA 7-- import Sound.MIDI.ALSA
7import System.Clock 8import System.Clock
@@ -9,6 +10,10 @@ import Database.SQLite.Simple
9import Database.SQLite.Simple.FromRow () 10import Database.SQLite.Simple.FromRow ()
10 11
11import qualified Sound.ALSA.Sequencer.Event as Event 12import qualified Sound.ALSA.Sequencer.Event as Event
13-- import Sound.MIDI.ALSA
14import Sound.MIDI.ALSA.Query
15import qualified Sound.MIDI.ALSA.Construct as Construct
16import Sound.MIDI.Message
12 17
13-- import qualified Sound.ALSA.Sequencer 18-- import qualified Sound.ALSA.Sequencer
14-- import qualified Sound.ALSA.Sequencer.Address 19-- import qualified Sound.ALSA.Sequencer.Address
@@ -17,11 +22,11 @@ import qualified Sound.ALSA.Sequencer.Event as Event
17-- import qualified Sound.ALSA.Sequencer.Time as Time 22-- import qualified Sound.ALSA.Sequencer.Time as Time
18-- import qualified Sound.ALSA.Sequencer.RealTime as RealTime 23-- import qualified Sound.ALSA.Sequencer.RealTime as RealTime
19 24
20type RecordedEvent = (TimeSpec, Event.T) 25-- type RecordedEvent = (TimeSpec, Event.Data)
26type RecordedEvent = (TimeSpec, Sound.MIDI.Message.T)
21 27
22data Recording = StartRecording TimeSpec | 28data Recording = StartRecording TimeSpec |
23 RecordingInProgress TimeSpec TimeSpec [RecordedEvent] 29 RecordingInProgress TimeSpec TimeSpec [RecordedEvent]
24 deriving Show
25 30
26data CompleteRecording = CompleteRecording { 31data CompleteRecording = CompleteRecording {
27 _recStart :: TimeSpec, 32 _recStart :: TimeSpec,
@@ -29,7 +34,7 @@ data CompleteRecording = CompleteRecording {
29 _recFirst :: TimeSpec, 34 _recFirst :: TimeSpec,
30 _recLast :: TimeSpec, 35 _recLast :: TimeSpec,
31 _recEvents :: [RecordedEvent] 36 _recEvents :: [RecordedEvent]
32} deriving Show 37}
33 38
34instance FromRow CompleteRecording where 39instance FromRow CompleteRecording where
35 fromRow = cons <$> field <*> field <*> field <*> field <*> field <*> field <*> field <*> field <*> field 40 fromRow = cons <$> field <*> field <*> field <*> field <*> field <*> field <*> field <*> field <*> field
@@ -41,19 +46,35 @@ instance ToRow CompleteRecording where
41 where 46 where
42 (CompleteRecording (TimeSpec s ns) (TimeSpec s' ns') (TimeSpec s'' ns'') (TimeSpec s''' ns''') midi) = reco 47 (CompleteRecording (TimeSpec s ns) (TimeSpec s' ns') (TimeSpec s'' ns'') (TimeSpec s''' ns''') midi) = reco
43 48
49maybesnd :: forall t t1. (t, Maybe t1) -> Maybe (t, t1)
50maybesnd (_, Nothing) = Nothing
51maybesnd (x, Just y) = Just (x, y)
44 52
45recordEvents :: Recording -> [RecordedEvent]-> Recording 53convertEvents :: [(TimeSpec, Event.Data)] -> [(TimeSpec, Sound.MIDI.Message.T)]
46recordEvents (RecordingInProgress x y orig) new = RecordingInProgress x y $ new ++ orig 54convertEvents = mapMaybe (maybesnd . fmap conv)
55 where
56 conv :: Event.Data -> Maybe Sound.MIDI.Message.T
57 conv x@(Event.NoteEv _ _) = uncurry Construct.note <$> note x
58 conv _ = Nothing
59
60unConvertEvents :: [(TimeSpec, Sound.MIDI.Message.T)] -> [(TimeSpec, Event.Data)]
61unConvertEvents = mapMaybe (maybesnd . fmap conv)
62 where
63 conv :: Sound.MIDI.Message.T -> Maybe Event.Data
64 conv msg = uncurry Construct.note <$> note msg
65
66recordEvents :: Recording -> [(TimeSpec, Event.Data)]-> Recording
67recordEvents (RecordingInProgress x y orig) new = RecordingInProgress x y $ convertEvents new ++ orig
47recordEvents i@(StartRecording _) [] = i 68recordEvents i@(StartRecording _) [] = i
48recordEvents (StartRecording x) new@(_:_) = RecordingInProgress x y new 69recordEvents (StartRecording x) new@(_:_) = RecordingInProgress x y (convertEvents new)
49 where y = fst $ last new 70 where y = fst $ last new
50 71
51stopRecording :: Recording -> TimeSpec -> Maybe CompleteRecording 72stopRecording :: Recording -> TimeSpec -> Maybe CompleteRecording
52stopRecording (RecordingInProgress x y ls@((z,_):_)) end = Just $ CompleteRecording x end y z ls 73stopRecording (RecordingInProgress x y ls@((z,_):_)) end = Just $ CompleteRecording x end y z ls
53stopRecording _ _ = Nothing 74stopRecording _ _ = Nothing
54 75
55
56midiToBytes :: [RecordedEvent] -> BS.ByteString 76midiToBytes :: [RecordedEvent] -> BS.ByteString
57midiToBytes = pack . show 77-- midiToBytes = pack . show
78midiToBytes = undefined
58bytesToMidi :: BS.ByteString -> [RecordedEvent] 79bytesToMidi :: BS.ByteString -> [RecordedEvent]
59bytesToMidi = undefined 80bytesToMidi = undefined
diff --git a/midi-dump.hs b/midi-dump.hs
index e6d2aca..b531b97 100644
--- a/midi-dump.hs
+++ b/midi-dump.hs
@@ -197,7 +197,7 @@ type MidiController = MidiControllerT IO
197playRecording :: Recording -> MidiController () 197playRecording :: Recording -> MidiController ()
198playRecording (RecordingInProgress _ _ evts@(_:_)) = 198playRecording (RecordingInProgress _ _ evts@(_:_)) =
199 mapM_ (uncurry delayNoteEv) (zip (subtract (head delays) <$> delays) events) 199 mapM_ (uncurry delayNoteEv) (zip (subtract (head delays) <$> delays) events)
200 where (delays, events) = unzip $ fmap Event.body <$> reverse evts 200 where (delays, events) = unzip $ reverse $ unConvertEvents evts
201playRecording _ = return () 201playRecording _ = return ()
202 202
203getMidiSender :: MidiController MidiHook 203getMidiSender :: MidiController MidiHook
@@ -219,7 +219,7 @@ processMidi = do
219 liftIO $ threadDelay 15000 -- 15ms. Seems like a lot, but it sounds OK. Cuts CPU down to 2%. 219 liftIO $ threadDelay 15000 -- 15ms. Seems like a lot, but it sounds OK. Cuts CPU down to 2%.
220 else do 220 else do
221 now <- getAbsTime 221 now <- getAbsTime
222 let newEvents = map ((,) now) events 222 let newEvents = map ((,) now . Event.body) events
223 223
224 liftIO $ printChordLn newKeys 224 liftIO $ printChordLn newKeys
225 modify $ \s -> s { keysDown = newKeys, _recording = recordEvents (_recording s) newEvents, _lastTick = now } 225 modify $ \s -> s { keysDown = newKeys, _recording = recordEvents (_recording s) newEvents, _lastTick = now }