diff options
author | Andrew Cady <d@jerkface.net> | 2015-12-09 12:00:49 -0500 |
---|---|---|
committer | Andrew Cady <d@jerkface.net> | 2015-12-09 12:00:49 -0500 |
commit | 704806bc3e3ef54b3c9fbcd04c071b2af7dca59f (patch) | |
tree | 7fcc501219aec642a3abff547796603b2306ad69 | |
parent | 1bed0c53f8bdd6c3c5fb1346524ab133a45763dd (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.hs | 38 |
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 () | |||
171 | alsaDelayNoteEv delay nevdata = do | 171 | alsaDelayNoteEv 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 | ||
177 | queueAction :: (Queue Event.Data -> MidiController (Queue Event.Data)) -> MidiController () | 178 | queueAction :: (Queue Event.Data -> MidiController (Queue Event.Data)) -> MidiController () |
@@ -186,7 +187,7 @@ whenFlag :: MonadReader r m => (r -> Bool) -> m () -> m () | |||
186 | whenFlag flag f = asks flag >>= flip when f | 187 | whenFlag flag f = asks flag >>= flip when f |
187 | 188 | ||
188 | mkNote :: Word8 -> Event.Note | 189 | mkNote :: Word8 -> Event.Note |
189 | mkNote pitch = Event.simpleNote (Event.Channel 0) (Event.Pitch pitch) (Event.Velocity 128) | 190 | mkNote pitch = Event.simpleNote (Event.Channel 0) (Event.Pitch pitch) (Event.Velocity 127) |
190 | 191 | ||
191 | processCommand :: String -> MidiController () | 192 | processCommand :: String -> MidiController () |
192 | processCommand "exit" = modify $ \s -> s { _wantExit = True } | 193 | processCommand "exit" = modify $ \s -> s { _wantExit = True } |
@@ -202,7 +203,7 @@ processCommand "C'" = do | |||
202 | {- | 203 | {- |
203 | processCommand "C'" = do | 204 | processCommand "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 | |||
215 | playRecording :: Playable p => p -> MidiController () | 216 | playRecording :: Playable p => p -> MidiController () |
216 | playRecording = playEvents . playableEvents | 217 | playRecording = playEvents . playableEvents |
217 | 218 | ||
219 | -- fixedOutputChannel :: Maybe _ | ||
220 | fixedOutputChannel = Just 0 | ||
221 | |||
222 | -- setOutputChannel :: Codec.Midi.Message -> Codec.Midi.Message | ||
223 | setOutputChannel = case fixedOutputChannel of Just n -> setChannel n | ||
224 | Nothing -> id | ||
225 | |||
218 | playEvents :: [RecordedEvent] -> RWST LoopEnv () LoopState IO () | 226 | playEvents :: [RecordedEvent] -> RWST LoopEnv () LoopState IO () |
219 | playEvents evts@(_:_) = | 227 | playEvents 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 |
222 | playEvents _ = return () | 230 | playEvents _ = return () |
223 | 231 | ||
224 | getMidiSender :: MidiController MidiHook | 232 | getMidiSender :: MidiController MidiHook |
@@ -271,7 +279,8 @@ processMidi = do | |||
271 | filterTriads :: MidiPitchMap -> MidiController () | 279 | filterTriads :: MidiPitchMap -> MidiController () |
272 | filterTriads newKeys = do | 280 | filterTriads 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) |
288 | sendTriadEvents :: Maybe Event.Velocity -> Triad -> MidiController () | 297 | sendTriadEvents :: Maybe Event.Velocity -> Triad -> MidiController () |
289 | sendTriadEvents vel triad = do | 298 | sendTriadEvents 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 | ||
310 | detectTriad' :: MidiPitchMap -> Maybe (Event.Velocity, Triad) | ||
311 | detectTriad' 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 | |||
300 | detectTriad :: MidiPitchMap -> Maybe Triad | 328 | detectTriad :: MidiPitchMap -> Maybe Triad |
301 | detectTriad pitches = listToMaybe $ concatMap f (Map.keys pitches) | 329 | detectTriad pitches = listToMaybe $ concatMap f (Map.keys pitches) |
302 | where | 330 | where |