MIDI-controlled application

Hi Haskellers! I'm writing my first non-trivial Haskell application. I have an electronic drum set that generates MIDI events that I process with Haskell. A simple application of this kind might have fixed drums associated with fixed commands (I've done that). The next step would be to display menus (with very large font...) that show commands and the associated drums. The menu structure should be derived from the commands active in each context. Up to this point, I implemented this already in Java. But now after some successful attempts in Haskell, I plan for more features: the user should ultimately be able to record his own "triggers", i.e. short drum rhythms, and associate them with actions. Since I'm still a beginner with only some basic experience in Monads, Arrows and their transformers, there is infinite knowledge to be gained by working on this problem (both library and concrete apps). Currently I'm using a monad that combines Parsec (with MIDI event stream) and a Writer (that writes commands that should result in IO). It's done in a way that during running the monad, many parses can be done and failing parses roll back the parser state so that a new parse can be tried. Now my questions: I have read about Yampa, but I have not mastered it yet. E.g. I don't understand switches. Could my "triggers" be realized with Yampa's events and switches? Would you recommend any other approach? Is there something similar somewhere? Regards Tim

Hi Tim Events in FRP / Yampa are typically key presses / mouse movement, so a MIDI controller generating Note-on / Note-off events would be a direct analogue to key presses. More problematic is that FRP models hybrid (continuous and discrete) systems. For me at least, MIDI seems essentially discrete - a stream of control events. In MIDI files control events are twinned with a time stamp so they can be played. Presumably events are instantaneous in real-time interactive MIDI - not something I've looked at. Working with an FRP system like Yampa might add a lot of complexity, which admittedly you should be able to ignore - but initially it might be difficult to identify what parts are needed for a "mostly" discrete system like MIDI. (If you are time-stamping MIDI events yourself you will presumably need to sample a running clock which seems like a continuous behaviour...) Unfortunately I can't think of any systems in Haskell that are "more discrete than continuous" so you might have to choose a FRP system anyway. Incidentally, I've been working on a MIDI "animation language" for the last couple of days based on the animation language in Paul Hudak's book. I've wanted continuous behaviours to model modulating volumes (crescendos, decrescendos) and panning, but I've found the work tough going for modelling the note lists where I want the system discrete in both input (specification) and output. Best wishes Stephen

Hi Stephen,
2011/12/27 Stephen Tetley
Hi Tim
More problematic is that FRP models hybrid (continuous and discrete) systems. For me at least, MIDI seems essentially discrete - a stream of control events. In MIDI files control events are twinned with a time stamp so they can be played. Presumably events are instantaneous in real-time interactive MIDI - not something I've looked at.
The events all feature a time stamp and my drum set produces lots of "CRTClock" events for synchronization. I didn't use the time stamps in my Java application but I would have to for recording/recognizing rhythms.
Working with an FRP system like Yampa might add a lot of complexity, which admittedly you should be able to ignore
Yes, I'm a bit afraid of that.
but initially it might be difficult to identify what parts are needed for a "mostly" discrete system like MIDI. (If you are time-stamping MIDI events yourself you will presumably need to sample a running clock which seems like a continuous behaviour...)
Unfortunately I can't think of any systems in Haskell that are "more discrete than continuous" so you might have to choose a FRP system anyway.
I just had a glance at Peakachu. It seemed easier than Yampa to me. I liked the Program abstraction. Perhaps I can use this...
Incidentally, I've been working on a MIDI "animation language" for the last couple of days based on the animation language in Paul Hudak's book. I've wanted continuous behaviours to model modulating volumes (crescendos, decrescendos) and panning, but I've found the work tough going for modelling the note lists where I want the system discrete in both input (specification) and output.
This reminds me of the Yampa based synthesizer from the paper "Switched-On Yampa". I just looked into it.
Best wishes
Stephen
Thanks Tim

Stephen Tetley wrote:
Events in FRP / Yampa are typically key presses / mouse movement, so a MIDI controller generating Note-on / Note-off events would be a direct analogue to key presses.
More problematic is that FRP models hybrid (continuous and discrete) systems. For me at least, MIDI seems essentially discrete - a stream of control events. In MIDI files control events are twinned with a time stamp so they can be played. Presumably events are instantaneous in real-time interactive MIDI - not something I've looked at.
Working with an FRP system like Yampa might add a lot of complexity, which admittedly you should be able to ignore - but initially it might be difficult to identify what parts are needed for a "mostly" discrete system like MIDI. (If you are time-stamping MIDI events yourself you will presumably need to sample a running clock which seems like a continuous behaviour...)
Unfortunately I can't think of any systems in Haskell that are "more discrete than continuous" so you might have to choose a FRP system anyway.
Concerning FRP, I would like to advertise my reactive-banana library here, which tries to follow Conal Elliott's semantics with behaviors and events. http://www.haskell.org/haskellwiki/Reactive-banana I intend to do audio / MIDI programming in the future, so it's going to be well-supported for your particular purpose, even. That said, I haven't started to use it for MIDI myself yet, so I appreciate any kind of feedback! If you want to learn reactive-banana, I recommend that you have a look at the source code of the model implementation in Reactive.Banana.Model. It's intended to be really simple to understand and it's the authoritative reference for the semantics of the actual implementation (which is far from simple to understand). As you can see, the model uses infinite lists. The advantage of the actual implementation, especially for MIDI, is that it is *real-time*, something which is tricky to do with infinite lists. Still, you could probably use the model as a guide for cooking up your own FRP library.
Incidentally, I've been working on a MIDI "animation language" for the last couple of days based on the animation language in Paul Hudak's book. I've wanted continuous behaviours to model modulating volumes (crescendos, decrescendos) and panning, but I've found the work tough going for modelling the note lists where I want the system discrete in both input (specification) and output.
Consider me interested. How does your approach compare to Conal-style FRP with behaviors and events? Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com

If you're afraid of Yampa (I was ;p), Ertugrul Söylemez released recently
the Netwire http://hackage.haskell.org/package/netwire-3.1.0 library on
hackage.
I went through its internals and I find it simpler to grasp and to use than
Yampa as Ertugrul chose to replace the switch functions by the use of
ArrowChoice. Yet I don't know if the latter wholly supersedes the former.
Plus I like the fact it doesn't depend on IO (you can handle automatons in
pure code).
And if you're to stick with Yampa, you might wanna look at
Animas.http://hackage.haskell.org/package/Animas-0.2
It's a fork of Yampa. I don't the advantages it brings or what I changes,
but its documentation on hackage is far more complete.
2011/12/27 Tim Baumgartner
Hi Haskellers!
I'm writing my first non-trivial Haskell application. I have an electronic drum set that generates MIDI events that I process with Haskell. A simple application of this kind might have fixed drums associated with fixed commands (I've done that). The next step would be to display menus (with very large font...) that show commands and the associated drums. The menu structure should be derived from the commands active in each context. Up to this point, I implemented this already in Java. But now after some successful attempts in Haskell, I plan for more features: the user should ultimately be able to record his own "triggers", i.e. short drum rhythms, and associate them with actions. Since I'm still a beginner with only some basic experience in Monads, Arrows and their transformers, there is infinite knowledge to be gained by working on this problem (both library and concrete apps).
Currently I'm using a monad that combines Parsec (with MIDI event stream) and a Writer (that writes commands that should result in IO). It's done in a way that during running the monad, many parses can be done and failing parses roll back the parser state so that a new parse can be tried.
Now my questions: I have read about Yampa, but I have not mastered it yet. E.g. I don't understand switches. Could my "triggers" be realized with Yampa's events and switches? Would you recommend any other approach? Is there something similar somewhere?
Regards Tim
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Tue, Dec 27, 2011 at 3:54 AM, Tim Baumgartner < baumgartner.tim@googlemail.com> wrote:
Hi Haskellers!
I'm writing my first non-trivial Haskell application. I have an
electronic drum set that generates MIDI events that I process with Haskell. A simple application of this kind might have fixed drums associated with fixed commands (I've done that). [...]
Currently I'm using a monad that combines Parsec (with MIDI event stream)
and a Writer (that writes commands that should result in IO). It's done in a way that during running the monad, many parses can be done and failing parses roll back the parser state so that a new parse can be tried.
Care to share your code? amindfv / Tom

Hi Tom! [...]
Currently I'm using a monad that combines Parsec (with MIDI event
stream) and a Writer (that writes commands that should result in IO). It's done in a way that during running the monad, many parses can be done and failing parses roll back the parser state so that a new parse can be tried.
Care to share your code?
Yes, great! Have you worked with MIDI in Haskell? Perhaps parsing/recognizing it? I think it will take a few more days (hopefully not weeks) until I know what will be the foundation for my app. But then I will create a project online and send you a message. In case anybody has time to look at it, I just pasted my aforementioned monad on hpaste. I thought about it some more and came to the conclusion that for user-defined "triggers" (aka parsers), this approach is probably sub optimal... After Heinrich's suggestion, I worked through the slot machine example from reactive-banana. It's a great introduction to FRP for me. The declarative style is very appealing. I will try how it fits with my ideas. Some of my code (thaugh probably obsolete): http://hpaste.org/55795 Regards Tim
participants (5)
-
Heinrich Apfelmus
-
Stephen Tetley
-
Tim Baumgartner
-
Tom Murphy
-
Yves Parès