I am working on a small virtual organ program, where I have multiple MIDI controller keyboards which can be connected to one or more synthesizer channels to emit various sounds simultaneously.
At this point, I am able to read events from a single MIDI controller and send the events to the correct synthesizer channel (I'm using Timidity at the moment). I would like to read keypresses from the computer keyboard and use those to adjust which synthesizers receive which MIDI events. In other words, I press a note on my MIDI controller and the note plays a sound on the synthesizer I have set up. When I press the letter 'a' on my computer keyboard, I would like to add another synthesizer, so that subsequent notes played on the MIDI controller send events to the original synthesizer and to a new synthesizer. I was able to build a script to read in events from the computer keyboard (via the module Term::ReadKey). I read these keypresses in a react block with a whenever: react { whenever key-pressed(:!echo) { # Eventually will connect or disconnect a synthesizer for the relevant MIDI controller. # Currently just prints out the key that was pressed. given .fc { when 'q' { done } default { .raku.say } } } } The MIDI events are being read via the module Audio::PortMIDI in a loop block: my $pm = Audio::PortMIDI.new; my $stream = $pm.open-input($input-device-number, 32); my $voice = $pm.open-output($output-device-number, 32); # Read events from the MIDI controller and write to the synthesizer. loop { if $stream.poll { my @notes = $stream.read(1); $voice.write(@notes); } } I'm struggling to figure out how to combine the react block for the computer keyboard events and the loop block for the MIDI events. I would like to be able to accept events from both devices concurrently. It seems like I might need to turn the loop into a Supply of some kind, but I'm not sure how I would go about doing that. If I understand correctly, once it is a supply, I could add it to the react block as another whenever event. I have found examples of how to create a Supply using a loop and a Promise that is kept after a specific amount of time (https://stackoverflow.com/questions/57486372/concurrency-react-ing-to-more-than-one-supply-at-a-time), but I have not found anything that is polling from a data stream. My attempt of polling the stream in a whenever block errors out, without me ever pressing a key, which makes it seem like it is trying to read when there are no keypress events available. whenever so $stream.poll { my @notes = $stream.read(1); ... } Type check failed for return value; expected Str but got Any (Any) in sub with-termios at /home/kolibrie/.raku/sources/C758559420AEADF99B8D412BDFADA739CAC14C2A (Term::ReadKey) line 20 in block at /home/kolibrie/.raku/sources/C758559420AEADF99B8D412BDFADA739CAC14C2A (Term::ReadKey) line 51 Any insights would be greatly appreciated. -kolibrie
signature.asc
Description: PGP signature