summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2015-12-09 12:00:49 -0500
committerAndrew Cady <d@jerkface.net>2015-12-09 12:00:49 -0500
commit704806bc3e3ef54b3c9fbcd04c071b2af7dca59f (patch)
tree7fcc501219aec642a3abff547796603b2306ad69
parent1bed0c53f8bdd6c3c5fb1346524ab133a45763dd (diff)
Fix triad "fill" note velocity; output to channel 0
That is, set the velocity to the average of the velocity of the individual triad keys. Also, output the triads to channel 0 instead of channel 1. Previously, all output had been changed to channel 1 to facilitate playing live on channel 0 on top of playback on channel 1. However, it was discovered that the external MIDI synthesizer built into my MIDI keyboard does not listen on channel 1.
-rw-r--r--midi-dump.hs38
1 files changed, 33 insertions, 5 deletions
diff --git a/midi-dump.hs b/midi-dump.hs
index 6c2c8b8..9407fae 100644
--- a/midi-dump.hs
+++ b/midi-dump.hs
@@ -171,7 +171,8 @@ alsaDelayNoteEv :: TimeSpec -> Event.Data -> MidiController ()
171alsaDelayNoteEv delay nevdata = do 171alsaDelayNoteEv delay nevdata = do
172 ms <- getMidiSender 172 ms <- getMidiSender
173 publicAddr <- asks _publicAddr 173 publicAddr <- asks _publicAddr
174 liftIO $ ms $ Event.simple publicAddr nevdata `delayEvent` delay 174 liftIO $ ms $ Event.simple publicAddr nevdata `delayEvent` delay'
175 where delay' = max 0 delay
175 176
176 177
177queueAction :: (Queue Event.Data -> MidiController (Queue Event.Data)) -> MidiController () 178queueAction :: (Queue Event.Data -> MidiController (Queue Event.Data)) -> MidiController ()
@@ -186,7 +187,7 @@ whenFlag :: MonadReader r m => (r -> Bool) -> m () -> m ()
186whenFlag flag f = asks flag >>= flip when f 187whenFlag flag f = asks flag >>= flip when f
187 188
188mkNote :: Word8 -> Event.Note 189mkNote :: Word8 -> Event.Note
189mkNote pitch = Event.simpleNote (Event.Channel 0) (Event.Pitch pitch) (Event.Velocity 128) 190mkNote pitch = Event.simpleNote (Event.Channel 0) (Event.Pitch pitch) (Event.Velocity 127)
190 191
191processCommand :: String -> MidiController () 192processCommand :: String -> MidiController ()
192processCommand "exit" = modify $ \s -> s { _wantExit = True } 193processCommand "exit" = modify $ \s -> s { _wantExit = True }
@@ -202,7 +203,7 @@ processCommand "C'" = do
202{- 203{-
203processCommand "C'" = do 204processCommand "C'" = do
204 -- changing the duration seems to do nothing 205 -- changing the duration seems to do nothing
205 let mkNote pitch = Event.simpleNote (Event.Channel 0) (Event.Pitch pitch) (Event.Velocity 128) 206 let mkNote pitch = Event.simpleNote (Event.Channel 0) (Event.Pitch pitch) (Event.Velocity 127)
206 setDuration d note = note { Event.noteDuration = Event.Duration d } 207 setDuration d note = note { Event.noteDuration = Event.Duration d }
207 let notes = (Event.NoteEv Event.NoteOn . setDuration 4290000000 . mkNote) <$> [60, 64, 67] 208 let notes = (Event.NoteEv Event.NoteOn . setDuration 4290000000 . mkNote) <$> [60, 64, 67]
208 forM_ notes (delayNoteEv (TimeSpec 0 0)) 209 forM_ notes (delayNoteEv (TimeSpec 0 0))
@@ -215,10 +216,17 @@ type MidiController = MidiControllerT IO
215playRecording :: Playable p => p -> MidiController () 216playRecording :: Playable p => p -> MidiController ()
216playRecording = playEvents . playableEvents 217playRecording = playEvents . playableEvents
217 218
219-- fixedOutputChannel :: Maybe _
220fixedOutputChannel = Just 0
221
222-- setOutputChannel :: Codec.Midi.Message -> Codec.Midi.Message
223setOutputChannel = case fixedOutputChannel of Just n -> setChannel n
224 Nothing -> id
225
218playEvents :: [RecordedEvent] -> RWST LoopEnv () LoopState IO () 226playEvents :: [RecordedEvent] -> RWST LoopEnv () LoopState IO ()
219playEvents evts@(_:_) = 227playEvents evts@(_:_) =
220 mapM_ (uncurry delayNoteEv) (zip (subtract (head delays) <$> delays) events) 228 mapM_ (uncurry delayNoteEv) (zip (subtract (head delays) <$> delays) events)
221 where (delays, events) = unzip $ reverse $ unConvertEvents $ (fmap.fmap) (setChannel 1) evts 229 where (delays, events) = unzip $ reverse $ unConvertEvents $ (fmap.fmap) setOutputChannel evts -- TODO: do not use fixed channel
222playEvents _ = return () 230playEvents _ = return ()
223 231
224getMidiSender :: MidiController MidiHook 232getMidiSender :: MidiController MidiHook
@@ -271,7 +279,8 @@ processMidi = do
271filterTriads :: MidiPitchMap -> MidiController () 279filterTriads :: MidiPitchMap -> MidiController ()
272filterTriads newKeys = do 280filterTriads newKeys = do
273 let newTriad = detectTriad newKeys 281 let newTriad = detectTriad newKeys
274 vel = Event.Velocity 128 282 (Just (vel, _)) = detectTriad' newKeys
283 -- vel = Event.Velocity 127
275 oldTriad <- gets _triad 284 oldTriad <- gets _triad
276 when (newTriad /= oldTriad) $ do 285 when (newTriad /= oldTriad) $ do
277 forM_ oldTriad (sendTriadEvents Nothing) 286 forM_ oldTriad (sendTriadEvents Nothing)
@@ -287,6 +296,7 @@ triadBase (Minor n) = n
287-- Set) 296-- Set)
288sendTriadEvents :: Maybe Event.Velocity -> Triad -> MidiController () 297sendTriadEvents :: Maybe Event.Velocity -> Triad -> MidiController ()
289sendTriadEvents vel triad = do 298sendTriadEvents vel triad = do
299 liftIO $ print vel
290 forM_ notes (delayNoteEv (TimeSpec 0 0)) 300 forM_ notes (delayNoteEv (TimeSpec 0 0))
291 return () 301 return ()
292 302
@@ -297,6 +307,24 @@ sendTriadEvents vel triad = do
297 fromVel (Just v) pitch = Event.NoteEv Event.NoteOn $ Event.simpleNote (Event.Channel 0) (Event.Pitch pitch) v 307 fromVel (Just v) pitch = Event.NoteEv Event.NoteOn $ Event.simpleNote (Event.Channel 0) (Event.Pitch pitch) v
298 fromVel Nothing pitch = Event.NoteEv Event.NoteOff $ Event.simpleNote (Event.Channel 0) (Event.Pitch pitch) (Event.Velocity 0) 308 fromVel Nothing pitch = Event.NoteEv Event.NoteOff $ Event.simpleNote (Event.Channel 0) (Event.Pitch pitch) (Event.Velocity 0)
299 309
310detectTriad' :: MidiPitchMap -> Maybe (Event.Velocity, Triad)
311detectTriad' pitches = listToMaybe $ concatMap f (Map.keys pitches)
312 where
313 f pitch = do
314 let first_ = Map.lookup pitch pitches
315 major3 = Map.lookup (addPitch 4 pitch) pitches
316 minor3 = Map.lookup (addPitch 3 pitch) pitches
317 fifth_ = Map.lookup (addPitch 7 pitch) pitches
318 let major = foldM (fmap . (+)) (0::Int) $ (fmap . fmap) (fromIntegral . Event.unVelocity) [first_, major3, fifth_]
319 let minor = foldM (fmap . (+)) (0::Int) $ (fmap . fmap) (fromIntegral . Event.unVelocity) [first_, minor3, fifth_]
320 case major of
321 Just n -> [(Event.Velocity $ fromIntegral $ n `div` 3, Major $ snd pitch)]
322 Nothing ->
323 case minor of
324 Just n -> [(Event.Velocity $ fromIntegral $ n `div` 3, Minor $ snd pitch)]
325 Nothing -> []
326 addPitch n (c, Event.Pitch p) = (c, Event.Pitch $ p + n)
327
300detectTriad :: MidiPitchMap -> Maybe Triad 328detectTriad :: MidiPitchMap -> Maybe Triad
301detectTriad pitches = listToMaybe $ concatMap f (Map.keys pitches) 329detectTriad pitches = listToMaybe $ concatMap f (Map.keys pitches)
302 where 330 where