--5mCyUwZo2JvN/JJP Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 --5mCyUwZo2JvN/JJP Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iF0EABECAB0WIQQcdVBq2runIfiYui1iVlJyleoqBAUCX+9ouAAKCRBiVlJyleoq BMv7AKCQEwkstfaxCaYZNb/ZAZASxMx4DACdEdssvoXJ6tuNWPcsEhi/s/KaQHM= =8jW8 -----END PGP SIGNATURE----- --5mCyUwZo2JvN/JJP--
![]() |
0 |
![]() |
--Apple-Mail=_76CE5E84-B7F5-400A-BB93-DC60A2CFD513 Content-Type: multipart/alternative; boundary="Apple-Mail=_CFC66AC3-4456-42B1-A6D5-93D0326864C5" --Apple-Mail=_CFC66AC3-4456-42B1-A6D5-93D0326864C5 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii As it seems that Audio::PortMIDI lacks non-blocking interface, I think a = solution would be to read events in a dedicated thread and re-submit = them into a Supplier. Something like: my Supplier $midi-events; start { loop { my $ev =3D $midi.read; $midi-events.emit: $ev; } } $midi-events can then be used in your react block. BTW, I think calling = method 'poll' must not be needed because `read` should block until = actual event is available. At least this is how I understand the normal = order of things. Best regards, Vadim Belman > On Jan 1, 2021, at 1:23 PM, Nathan Gray <kolibrie@graystudios.org> = wrote: >=20 > 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. >=20 > 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). >=20 > 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. >=20 > 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: >=20 > 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 } > } > } > } >=20 > The MIDI events are being read via the module Audio::PortMIDI in > a loop block: >=20 > my $pm =3D Audio::PortMIDI.new; > my $stream =3D $pm.open-input($input-device-number, 32); > my $voice =3D $pm.open-output($output-device-number, 32); > # Read events from the MIDI controller and write to the = synthesizer. > loop { > if $stream.poll { > my @notes =3D $stream.read(1); > $voice.write(@notes); > } > } >=20 > 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. >=20 > 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. >=20 > 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-mor= e-than-one-supply-at-a-time), > but I have not found anything that is polling from a data stream. >=20 > 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. >=20 > whenever so $stream.poll { > my @notes =3D $stream.read(1); > ... > } >=20 > 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 >=20 > Any insights would be greatly appreciated. >=20 > -kolibrie --Apple-Mail=_CFC66AC3-4456-42B1-A6D5-93D0326864C5 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=us-ascii <html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; = charset=3Dus-ascii"></head><body style=3D"word-wrap: break-word; = -webkit-nbsp-mode: space; line-break: after-white-space;" class=3D"">As = it seems that Audio::PortMIDI lacks non-blocking interface, I think a = solution would be to read events in a dedicated thread and re-submit = them into a Supplier. Something like:<div class=3D""><br = class=3D""></div><div class=3D""><div class=3D""><font face=3D"Andale = Mono" class=3D""><span style=3D"font-style: normal;" class=3D"">my = Supplier $midi-events;</span></font></div><div class=3D""><font = face=3D"Andale Mono" class=3D""><span style=3D"font-style: normal;" = class=3D""><br class=3D""></span></font></div><div class=3D""><font = face=3D"Andale Mono" class=3D""><span style=3D"font-style: normal;" = class=3D"">start {</span></font></div><div class=3D""><font face=3D"Andale= Mono" class=3D""><span style=3D"font-style: normal;" class=3D""> = loop {</span></font></div><div class=3D""><font face=3D"Andale = Mono" class=3D""><span style=3D"font-style: normal;" class=3D""> = my $ev =3D $midi.read;</span></font></div><div = class=3D""><font face=3D"Andale Mono" class=3D""><span = style=3D"font-style: normal;" class=3D""> = $midi-events.emit: $ev;</span></font></div><div class=3D""><font = face=3D"Andale Mono" class=3D""><span style=3D"font-style: normal;" = class=3D""> }</span></font></div><div class=3D""><font = face=3D"Andale Mono" class=3D""><span style=3D"font-style: normal;" = class=3D"">}</span></font></div><div class=3D""><br class=3D""></div><div = class=3D""><br class=3D""></div><div class=3D"">$midi-events can then be = used in your react block. BTW, I think calling method 'poll' must not be = needed because `read` should block until actual event is available. At = least this is how I understand the normal order of things.</div><div = class=3D""> </div><div class=3D""> <div class=3D"">Best regards,</div>Vadim Belman </div> <div><br class=3D""><blockquote type=3D"cite" class=3D""><div = class=3D"">On Jan 1, 2021, at 1:23 PM, Nathan Gray <<a = href=3D"mailto:kolibrie@graystudios.org" = class=3D"">kolibrie@graystudios.org</a>> wrote:</div><br = class=3D"Apple-interchange-newline"><div class=3D""><div class=3D""><div = class=3D"content-isolator__container">I am working on a small virtual = organ program, where I have<br class=3D"">multiple MIDI controller = keyboards which can be connected to one<br class=3D"">or more = synthesizer channels to emit various sounds<br = class=3D"">simultaneously.<br class=3D""><br class=3D"">At this point, I = am able to read events from a single MIDI<br class=3D"">controller and = send the events to the correct synthesizer channel<br class=3D"">(I'm = using Timidity at the moment).<br class=3D""><br class=3D"">I would like = to read keypresses from the computer keyboard and<br class=3D"">use = those to adjust which synthesizers receive which MIDI events.<br = class=3D"">In other words, I press a note on my MIDI controller and the = note<br class=3D"">plays a sound on the synthesizer I have set up. = When I press the<br class=3D"">letter 'a' on my computer keyboard, = I would like to add another<br class=3D"">synthesizer, so that = subsequent notes played on the MIDI<br class=3D"">controller send events = to the original synthesizer and to a new<br class=3D"">synthesizer.<br = class=3D""><br class=3D"">I was able to build a script to read in events = from the computer<br class=3D"">keyboard (via the module Term::ReadKey). = I read these keypresses<br class=3D"">in a react block with a = whenever:<br class=3D""><br class=3D""> react {<br = class=3D""> whenever = key-pressed(:!echo) {<br class=3D""> = # = Eventually will connect or disconnect a synthesizer for the relevant = MIDI controller.<br class=3D""> = # = Currently just prints out the key that was pressed.<br class=3D""> = given = ..fc {<br class=3D""> = &n= bsp; when 'q' { done }<br class=3D""> = &n= bsp; default { .raku.say }<br class=3D""> = }<br = class=3D""> }<br class=3D""> = }<br class=3D""><br class=3D"">The MIDI events are = being read via the module Audio::PortMIDI in<br class=3D"">a loop = block:<br class=3D""><br class=3D""> my $pm =3D = Audio::PortMIDI.new;<br class=3D""> my $stream =3D = $pm.open-input($input-device-number, 32);<br class=3D""> = my $voice =3D $pm.open-output($output-device-number, = 32);<br class=3D""> # Read events from the MIDI = controller and write to the synthesizer.<br class=3D""> = loop {<br class=3D""> = if $stream.poll {<br class=3D"">= my = @notes =3D $stream.read(1);<br class=3D""> = $voice.w= rite(@notes);<br class=3D""> = }<br class=3D""> = }<br class=3D""><br class=3D"">I'm struggling to = figure out how to combine the react block for<br class=3D"">the computer = keyboard events and the loop block for the MIDI<br class=3D"">events. = I would like to be able to accept events from both<br = class=3D"">devices concurrently.<br class=3D""><br class=3D"">It seems = like I might need to turn the loop into a Supply of some<br = class=3D"">kind, but I'm not sure how I would go about doing that. = If I<br class=3D"">understand correctly, once it is a supply, I = could add it to the<br class=3D"">react block as another whenever = event.<br class=3D""><br class=3D"">I have found examples of how to = create a Supply using a loop and<br class=3D"">a Promise that is kept = after a specific amount of time<br class=3D"">(<a = href=3D"https://stackoverflow.com/questions/57486372/concurrency-react-ing= -to-more-than-one-supply-at-a-time" = class=3D"">https://stackoverflow.com/questions/57486372/concurrency-react-= ing-to-more-than-one-supply-at-a-time</a>),<br class=3D"">but I have not = found anything that is polling from a data stream.<br class=3D""><br = class=3D"">My attempt of polling the stream in a whenever block errors = out,<br class=3D"">without me ever pressing a key, which makes it seem = like it is<br class=3D"">trying to read when there are no keypress = events available.<br class=3D""><br class=3D""> = whenever so $stream.poll {<br class=3D""> = my @notes =3D = $stream.read(1);<br class=3D""> = ...<br class=3D""> = }<br class=3D""><br class=3D"">Type check failed for = return value; expected Str but got Any (Any)<br class=3D""> in sub = with-termios at = /home/kolibrie/.raku/sources/C758559420AEADF99B8D412BDFADA739CAC14C2A = (Term::ReadKey) line 20<br class=3D""> in block at = /home/kolibrie/.raku/sources/C758559420AEADF99B8D412BDFADA739CAC14C2A = (Term::ReadKey) line 51<br class=3D""><br class=3D"">Any insights would = be greatly appreciated.<br class=3D""><br class=3D"">-kolibrie<br = class=3D""></div></div></div></blockquote></div><br = class=3D""></div></body></html>= --Apple-Mail=_CFC66AC3-4456-42B1-A6D5-93D0326864C5-- --Apple-Mail=_76CE5E84-B7F5-400A-BB93-DC60A2CFD513 Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=signature.asc Content-Type: application/pgp-signature; name=signature.asc Content-Description: Message signed with OpenPGP -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEEF1hitHHOemrwyOqx5FPkstg07jMFAl/vg/kACgkQ5FPkstg0 7jN4nA//YksetDhGJ1DbXearfvqU5KFfDh/QVAH3tGSqO7l1VzZcoAObAj+iqcyX rsP1x172T3DgBoJGJhXCj1QYECnVPDLSIEC33tTAsURS94A0/7+ekk8JGMj6Ka4k zXzMsbWVZg1UgbPrUZm3pwjDLr1px+QdGpPwMx31dEggG88ZRX6KkQo+LThr9Gqd zfDG8u2r9se9oEseTZw7aRxvw4n5fLztxocMZ8qUJpX4qGG/sKuu5BT9UznGBcVL Ihvs1v0vZX3xH5FIxp0oOJImu0wCjFD1xeNJ3ruZxCW2k5hBsuC8DUW6XKioB8Dn tGa2aoH+LpI7Ie5Gv4QwaCe7TMAxP4pQz2iLv+37spV4+SjVo3ShjlMbi0i2kVnh Oqe5r3TxBUO/iwfJIdu3ttverE40A/IGczo6lNq6b+IyyX+MKfGcjGFTj1JQqKWj IuwtSI5zghtKirtuhC5akyEgYl+Pl1FzITXvGqVdP28ndOO5qQuTmKLOq2XEMH5m BDKtQ/xga6LZF76eYPjt+LJVlqzIPDJp3IAP0q/OlXqhpolATnMHbTFA1MvYAr98 Ai9wj826UdCKiklCrWO2GI6Q8FZo4TTV3PfaR/V2Eu2bh+1xULvDCaCVcNm1ptBI SRvNuQGWjXba+mdR6e42pGA07ojKkkBrpNzKhyBn5lhMCCN3/Ck= =GtEW -----END PGP SIGNATURE----- --Apple-Mail=_76CE5E84-B7F5-400A-BB93-DC60A2CFD513--
![]() |
0 |
![]() |
--000000000000ee65bf05b7dce956 Content-Type: text/plain; charset="UTF-8" I think the simplest way to turn that into a Supply is to use the `supply` keyword my $pm = Audio::PortMIDI.new; my $input = supply { my $stream = $pm.open-input($input-device-number, 32); DONE { $stream.close; } loop { emit $stream.read(1); } } react { whenever key-pressed(:!echo) { given .fc { when 'q' { done } default { .raku.say } } } my $voice = $pm.open-output($output-device-number, 32); whenever $input { $voice.write(|$_); } } On Fri, Jan 1, 2021 at 12:31 PM Nathan Gray <kolibrie@graystudios.org> wrote: > 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 > --000000000000ee65bf05b7dce956 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">I think the simplest way to turn that into a Supply is to = use the `supply` keyword<div><br>=C2=A0 =C2=A0 my $pm =3D Audio::PortMIDI.n= ew;<br></div><div><br></div><div><br></div><div>=C2=A0 =C2=A0 my $input =3D= supply {<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 my $stream =3D $pm.open-input($inp= ut-device-number, 32);</div><div><br></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0= DONE {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 $stream.close;<= /div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 }</div><div><br></div><div>=C2=A0 =C2= =A0 =C2=A0 =C2=A0 loop {<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 emit $stream.read(1);<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 }</div><div= >=C2=A0 =C2=A0 }</div><div><br></div><div><br>=C2=A0 =C2=A0 react {<br>=C2= =A0 =C2=A0 =C2=A0 =C2=A0 whenever key-pressed(:!echo) {<br>=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 given .fc {<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 when 'q' { done }<br>=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 default { .raku.say }<br>=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 }</div><br>=C2= =A0 =C2=A0 =C2=A0 =C2=A0 my $voice =3D $pm.open-output($output-device-numbe= r, 32);<div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 whenever $input {</div><div>=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0$voice.write(|$_);</div><div>=C2=A0= =C2=A0 =C2=A0 =C2=A0 }<br>=C2=A0 =C2=A0 }<br></div></div><br><div class=3D= "gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">On Fri, Jan 1, 2021 at = 12:31 PM Nathan Gray <<a href=3D"mailto:kolibrie@graystudios.org">kolibr= ie@graystudios.org</a>> wrote:<br></div><blockquote class=3D"gmail_quote= " style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);= padding-left:1ex">I am working on a small virtual organ program, where I ha= ve<br> multiple MIDI controller keyboards which can be connected to one<br> or more synthesizer channels to emit various sounds<br> simultaneously.<br> <br> At this point, I am able to read events from a single MIDI<br> controller and send the events to the correct synthesizer channel<br> (I'm using Timidity at the moment).<br> <br> I would like to read keypresses from the computer keyboard and<br> use those to adjust which synthesizers receive which MIDI events.<br> In other words, I press a note on my MIDI controller and the note<br> plays a sound on the synthesizer I have set up.=C2=A0 When I press the<br> letter 'a' on my computer keyboard, I would like to add another<br> synthesizer, so that subsequent notes played on the MIDI<br> controller send events to the original synthesizer and to a new<br> synthesizer.<br> <br> I was able to build a script to read in events from the computer<br> keyboard (via the module Term::ReadKey).=C2=A0 I read these keypresses<br> in a react block with a whenever:<br> <br> =C2=A0 =C2=A0 react {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 whenever key-pressed(:!echo) {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 # Eventually will connect or disc= onnect a synthesizer for the relevant MIDI controller.<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 # Currently just prints out the k= ey that was pressed.<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 given .fc {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 when 'q' { = done }<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 default { .raku.say= }<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br> =C2=A0 =C2=A0 }<br> <br> The MIDI events are being read via the module Audio::PortMIDI in<br> a loop block:<br> <br> =C2=A0 =C2=A0 my $pm =3D Audio::PortMIDI.new;<br> =C2=A0 =C2=A0 my $stream =3D $pm.open-input($input-device-number, 32);<br> =C2=A0 =C2=A0 my $voice =3D $pm.open-output($output-device-number, 32);<br> =C2=A0 =C2=A0 # Read events from the MIDI controller and write to the synth= esizer.<br> =C2=A0 =C2=A0 loop {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 if $stream.poll {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 my @notes =3D $stream.read(1);<br= > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 $voice.write(@notes);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br> =C2=A0 =C2=A0 }<br> <br> I'm struggling to figure out how to combine the react block for<br> the computer keyboard events and the loop block for the MIDI<br> events.=C2=A0 I would like to be able to accept events from both<br> devices concurrently.<br> <br> It seems like I might need to turn the loop into a Supply of some<br> kind, but I'm not sure how I would go about doing that.=C2=A0 If I<br> understand correctly, once it is a supply, I could add it to the<br> react block as another whenever event.<br> <br> I have found examples of how to create a Supply using a loop and<br> a Promise that is kept after a specific amount of time<br> (<a href=3D"https://stackoverflow.com/questions/57486372/concurrency-react-= ing-to-more-than-one-supply-at-a-time" rel=3D"noreferrer" target=3D"_blank"= >https://stackoverflow.com/questions/57486372/concurrency-react-ing-to-more= -than-one-supply-at-a-time</a>),<br> but I have not found anything that is polling from a data stream.<br> <br> My attempt of polling the stream in a whenever block errors out,<br> without me ever pressing a key, which makes it seem like it is<br> trying to read when there are no keypress events available.<br> <br> =C2=A0 =C2=A0 whenever so $stream.poll {<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 my @notes =3D $stream.read(1);<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 ...<br> =C2=A0 =C2=A0 }<br> <br> Type check failed for return value; expected Str but got Any (Any)<br> =C2=A0 in sub with-termios at /home/kolibrie/.raku/sources/C758559420AEADF9= 9B8D412BDFADA739CAC14C2A (Term::ReadKey) line 20<br> =C2=A0 in block=C2=A0 at /home/kolibrie/.raku/sources/C758559420AEADF99B8D4= 12BDFADA739CAC14C2A (Term::ReadKey) line 51<br> <br> Any insights would be greatly appreciated.<br> <br> -kolibrie<br> </blockquote></div> --000000000000ee65bf05b7dce956--
![]() |
0 |
![]() |
--EuxKj2iCbKjpUGkD Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Fri, Jan 01, 2021 at 03:20:09PM -0500, Vadim Belman wrote: > As it seems that Audio::PortMIDI lacks non-blocking interface, I think a = solution would be to read events in a dedicated thread and re-submit them i= nto a Supplier. Something like: >=20 > my Supplier $midi-events; >=20 > start { > loop { > my $ev =3D $midi.read; > $midi-events.emit: $ev; > } > } >=20 >=20 > $midi-events can then be used in your react block. BTW, I think calling m= ethod 'poll' must not be needed because `read` should block until actual ev= ent is available. At least this is how I understand the normal order of thi= ngs. Vadim, Thank you for your reply. I tried out not calling $midi.poll, but found that $midi.read would return undef events (rather than blocking until it received an event). So I added it back in. Thank you for the example of how to set up a supply. On Fri, Jan 01, 2021 at 02:51:57PM -0600, Brad Gilbert wrote: > I think the simplest way to turn that into a Supply is to use the `supply` > keyword >=20 > my $pm =3D Audio::PortMIDI.new; >=20 >=20 > my $input =3D supply { > my $stream =3D $pm.open-input($input-device-number, 32); >=20 > DONE { > $stream.close; > } >=20 > loop { > emit $stream.read(1); > } > } >=20 >=20 > react { > whenever key-pressed(:!echo) { > given .fc { > when 'q' { done } > default { .raku.say } > } > } >=20 > my $voice =3D $pm.open-output($output-device-number, 32); > whenever $input { > $voice.write(|$_); > } > } Brad, Thank you for your reply. I was able to get my code working thanks to the examples from you and Vadim. Here is what I ended up with: my $pm =3D Audio::PortMIDI.new; # Set up supply to read MIDI events. my $input =3D supply { my $stream =3D $pm.open-input($input-device-number, 32); LAST { $stream.close; } loop { emit $stream.read(1) if $stream.poll; } } # Set up handle to send MIDI events to the synthesizer. my $voice =3D $pm.open-output($output-device-number, 32); react { # Read key presses from the computer keyboard. # TODO: change $voice as needed based on computer keyboard input. whenever key-pressed(:!echo) { given .fc { when 'q' { done } default { .raku.say } } } # Read MIDI events and send to the synthesizer. whenever $input { $voice.write(|$_); } } -kolibrie --EuxKj2iCbKjpUGkD Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iF0EABECAB0WIQQcdVBq2runIfiYui1iVlJyleoqBAUCX/C+qQAKCRBiVlJyleoq BDE3AKCAX9jytqo8FJw2p49Uo9Q5v4ic/gCeLHwk9i1iK00CoLEbh2jSizqA0fo= =hQdM -----END PGP SIGNATURE----- --EuxKj2iCbKjpUGkD--
![]() |
0 |
![]() |