tag:blogger.com,1999:blog-76532799593820226802024-03-05T02:40:03.072-05:00Ari RussoAri Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.comBlogger25125tag:blogger.com,1999:blog-7653279959382022680.post-39485133695711555172014-01-03T18:47:00.007-05:002015-04-11T21:18:45.578-04:00MovedCurrent/future posts can be found here: <a href="http://arirusso.com/">http://arirusso.com</a>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com0tag:blogger.com,1999:blog-7653279959382022680.post-85796554261081747052012-10-21T18:44:00.002-04:002012-10-22T00:52:55.931-04:00HTML5 Spectrum Analyzer: In 3dI've created a new 3d version of my HTML5 audio spectrum analyzer using <a href="https://github.com/mrdoob/three.js">Three.js</a>. <br />
<br />
<img border="0" height="113" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUbg4mtQvx4KjOvWxJD32nAk0wCqdSNtCLtJ8uKav3Wlc5uJAiy9w8LGrG082NrVRC8ZsOzkw77Vxneibn2Nuz4fZ5upMcfejNnzunu1UnoqjmanF4PKRwtcnFQis4bN33rpxBsiHeLII/s200/Screen+Shot+2012-10-21+at+6.55.12+PM.png" width="200" />
<br />
<br />
<a href="http://three-spectrum.herokuapp.com/">Check it out here</a><br />
<br />
Where it <a href="http://tx81z.blogspot.com/2012/10/quick-project-d3-html5-web-audio.html">used a d3 bar chart before</a>, the frequency amplitude is now represented in changing the size of some classy wood-paneled 3d cubes.<br />
<br />
You can use mouse and scroll over the scene itself to orbit the camera around the cubes. <br />
<br />
Like the older version, the default audio is some music I made but you can enter any URL <a href="http://tx81z.blogspot.com/2012/10/html5-spectrum-analyzer-live-audio-input.html">or use live input in Chrome Canary</a>. All of the other slider controls are the same too.<br />
<br />
<a href="https://github.com/arirusso/three-audio-spectrum">3d version on Github</a><br />
<br />
<br />
<br />Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com1tag:blogger.com,1999:blog-7653279959382022680.post-30974794227180935742012-10-04T19:00:00.004-04:002012-10-04T19:25:31.527-04:00HTML5 Spectrum Analyzer: Live Audio InputThis week, I've added live audio input to the <a href="http://tx81z.blogspot.com/2012/10/quick-project-d3-html5-web-audio.html">HTML5 spectrum analyzer</a>.<br />
<br />
<a href="http://d3-spectrum.herokuapp.com/">http://d3-spectrum.herokuapp.com</a><br />
<br />
Click the button that says <i>Use audio input </i>and then click <i>Allow</i> when prompted to give your browser access to your computer's audio input. You can then click <i>Use audio file</i> to switch back to the audio file.<br />
<br />
I've also added an intensity control that allows you to juice up the visual intensity without sacrificing volume or accuracy.<br />
<br />
<h4>
Of course, it may not work in your browser:</h4>
<br />
Is it ever that simple? At time of writing HTML5 live audio input is only supported in <a href="https://tools.google.com/dlpage/chromesxs">Chrome Canary</a>. You need to go to <i>about:flags</i> in the URL bar, and then enable <i>Web Audio Input</i> near the bottom of the list<br />
<br />
<a href="https://github.com/arirusso/d3-audio-spectrum">Spectrum Analyzer on github</a>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com1Irvine, CA, USA33.6839473 -117.794694233.578246299999996 -117.95262269999999 33.7896483 -117.6367657tag:blogger.com,1999:blog-7653279959382022680.post-74419265460524617392012-10-01T20:52:00.000-04:002012-10-04T19:27:47.540-04:00Quick Project: D3 / HTML5 Web Audio Spectrum AnalyzerFor fun this last week I made a spectrum analyzer using <a href="http://d3js.org/">D3</a> and the <a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html">HTML5 Web Audio API</a>. Been meaning to check those out for a while, and spectrum analyzer seemed like the natural way to kill two birds.<br />
<br />
Here it is running on Heroku with some of my music as the example track<br />
<br />
<a href="http://d3-spectrum.herokuapp.com/">http://d3-spectrum.herokuapp.com</a><br />
<br />
And the github page here:<br />
<br />
<a href="https://github.com/arirusso/d3-audio-spectrum">https://github.com/arirusso/d3-audio-spectrum</a><br />
<br />
Increasing the curve setting gives the spectrum a more logarithmic display, traditionally more common for audio spectrum analyzers.<br />
<br />
The other controls are pretty straightforward<br />
<br />
Enjoy<br />
<br />
Updates:<br />
<a href="http://bit.ly/QK5M5g">Adding live audio input in Chrome Canary (10/4/2012)</a>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com7Brooklyn, NY40.65 -73.9540.2660285 -74.581714 41.0339715 -73.318286tag:blogger.com,1999:blog-7653279959382022680.post-33273621586915174802012-04-29T22:05:00.001-04:002012-04-30T15:17:42.148-04:00Quick Project #2: Ruby Methods for Protecting Against Timing Attacks<p>Breaking with my usual style, Quick Project #2 doesn't necessarily relate to music programming.</p>
<p>Today I came across <a href="http://carlos.bueno.org/2011/10/timing.html">a nice little article and demo</a> on <a href="http://reddit.com/r/compsci">r/compsci</a> about <a href="http://en.wikipedia.org/wiki/Timing_attack">timing attacks</a>.</p>
<p>Timing attacks are something that I had learned about a few years ago but for whatever reason had dropped from the forefront of my engineering consciousness. In order to bash myself over the head with it (and provide a universal solution), I created Ruby wrapper methods for <em>Object#send</em> and block evaluation that are padded with a fixed timing delay.</p>
<p>Here 'tis, including some basic String comparison examples at the bottom:</p>
<p><a href="https://gist.github.com/2554841">https://gist.github.com/2554841</a></p>
<p>To use it, just pass in a "safe" duration (in seconds) that likely exceeds any possible amount of time it could take to evaluate the code. In the following example I use the greatly exaggerated value of .75 seconds. In the wild, you'll most likely be working in smaller durations</p>
<pre name="code" class="brush:ruby gutter:false toolbar:false">
is_match = ExpressionTimer.block(0.75) { "password attempt!" == "my password!" }
</pre>
<p>When the example is run, no matter how quickly the block actually evaluates, it will always take exactly 3/4s of a second to return. As a result, actual timing information is lost in the ether and can not be gleaned by any outside observer.</p>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com1tag:blogger.com,1999:blog-7653279959382022680.post-47381746035540229662012-04-25T00:39:00.000-04:002012-04-29T23:16:17.905-04:00Quick Project #1: Extract Audio Samples From Online Video<p>As I get ready to move once again (this time to the Ridgewood/Bushwick border) there's not a whole lotta time for personal projects. Yesterday I decided that I would find a quick one and do it no matter how useless it was.</p>
<p>Turned out, I came up with something that's going to be pretty useful (for me). Last week, a coworker pointed me to <a href="https://github.com/marcel">marcel</a>'s awesome Ruby <a href="https://gist.github.com/2100703">giftube</a> script which extracts animated gifs from online videos. I've been looking to incorporate more audio samples in my music for quite some time, so I forked his script and changed it to extract audio samples instead of gifs, complete with mp3 conversion.</p>
<p>Here's the result:</p>
<p><a href="https://gist.github.com/2473383">https://gist.github.com/2473383</a></p>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com0tag:blogger.com,1999:blog-7653279959382022680.post-18717127153918312062012-03-25T18:46:00.001-04:002012-03-25T18:54:25.816-04:00MicroOSC: a Ruby DSL for OSC<p>Being on my way to the west coast and out of arm's reach of the synths, I've had a few hours to switch gears and put together a quick Ruby gem, <a href="http://github.com/arirusso/micro-osc">MicroOSC</a>. It's a utility and DSL for dealing with <a href="http://en.wikipedia.org/wiki/Open_Sound_Control">OSC</a> messaging.</p>
<pre name="code" class="brush:ruby gutter:false toolbar:false">
gem install micro-osc
</pre>
<p>I applied the same principle to OSC that I applied to MIDI with <a href="http://tx81z.blogspot.com/2011/08/micromidi-ruby-dsl-for-midi.html">MicroMIDI</a>: distilling the simplest messenger interface that I could think of.</p>
<p>Unlike MIDI, OSC deals with generic user-defined messages. This eliminates the need for describing different concrete message types, something that added a lot complexity to MicroMIDI. </p>
<p>MicroOSC can function as a server, a client or both. In this example, I'll demonstrate them separately, having the two programs talk to each other over a local network.</p>
<p>Here is a server:</p>
<pre name="code" class="brush:ruby gutter:false toolbar:false">
require "osc"
OSC.using(:input_port => 8000) do
receive("/greeting") { |val| p "received #{val}" }
p "Ready to receive OSC messages on port(s) #{input_ports.join(', ')}..."
wait_for_input
end
</pre>
<p>Once you have this running, you should see "Ready to receive OSC messages..." in your Ruby console. Switch to another window and run this client program:</p>
<pre name="code" class="brush:ruby gutter:false toolbar:false">
require "osc"
o = OSC.using(:output => { :host => "localhost", :port => 8000 })
o.out("/greeting", "hullo!")
</pre>
<p>After running it, flip back to your server program and see “received hullo!”, confirming that your two programs were in fact talking to each other!</p>
<p>Notice that in the second program I didn't use a Ruby block style. Doing it this way would generally be better for live coding, and probably some other scenarios as well.</p>
<p>That's it!</p>
<p>Look for another post with real-world examples, advanced techniques and combining with MicroMIDI soon.</p>
<p><a href="http://github.com/arirusso/micro-osc">http://github.com/arirusso/micro-osc</a></p>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com0Brooklyn, NY, USA40.65 -73.9540.553624 -74.1079285 40.746376 -73.7920715tag:blogger.com,1999:blog-7653279959382022680.post-10935109114057633182012-02-24T13:00:00.001-05:002012-03-25T18:47:20.563-04:00ShiftIt's break time for my programming projects while I actually play and record some music. I also started a new job with <a href="http://github.com/paperlesspost">Paperless Post</a> that I'm dedicating a lot of my programming energies to.<br />
<br />
I'll post here soon when I have anything of note to show for what I'm doing.
<br /><br />
Here's <a href="http://vimeo.com/28116717">a video</a> of me on some hardware synths that a friend posted last year. It sounds somewhat similar to what I'm doing now.<br /><br />
<iframe src="http://player.vimeo.com/video/28116717?title=0&byline=0&portrait=0" width="400" height="225" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
<br />
<br />
I can never stay away too long; I'm sure I'll be back to grinding out some music tools once I have a few tracks done. Just not enough time for both at the moment...<br />
<br />Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com2tag:blogger.com,1999:blog-7653279959382022680.post-61866081115435670922011-10-19T23:53:00.001-04:002011-11-07T13:01:01.409-05:00OSC Access: Build OSC into Ruby objects<p>I've created a Ruby library called <a href="http://github.com/arirusso/osc-access">OSC Access</a> for binding <a href="http://en.wikipedia.org/wiki/Open_Sound_Control">OSC</a> directly into Ruby classes and objects.</p>
<p>It conveniently wraps a lot of functionality from <a href="http://github.com/aberant/osc-ruby">osc-ruby</a>, handling server/client sharing and management as well as other tasks commonly associated with OSC.</p>
<pre name="code" class="brush:ruby gutter:false toolbar:false">
gem install osc-access
</pre>
<p>All of OSC Access' functionality is available by including the OSCAccessible module into a class. The module gives you a lot of functionality but you'll want to know about these three methods in particular to get up and running
<ul>
<li><a href="http://tx81z.blogspot.com/2011/10/osc-access-build-osc-into-ruby-objects.html#osc_receive">osc_receive</a></li>
<li><a href="http://tx81z.blogspot.com/2011/10/osc-access-build-osc-into-ruby-objects.html#osc_send">osc_send</a></li>
<li><a href="http://tx81z.blogspot.com/2011/10/osc-access-build-osc-into-ruby-objects.html#osc_start">osc_start</a></li>
</ul>
<br />
<h3><a name="osc_receive">osc_receive</a></h3>
<p>All OSC input is handled by using the <em>osc_receive</em> method. Here's an example of using <em>osc_receive</em> in a simple way:</p>
<pre name="code" class="brush:ruby gutter:false toolbar:false">
class Instrument
include OSCAccessible
osc_receive("/1/fader1") do |instance, val|
instance.velocity = val
end
def velocity=(val)
puts "setting velocity to #{val}"
...
end
end
i = Instrument.new
i.osc_start(:input_port => 8000).join
</pre>
<p>When this example is run, the method <em>velocity=</em> is called on all instances of the <em>Instrument</em> class whenever OSC messages for the address <em>/1/fader1</em> are received.</p>
<p>A couple of things to note here...</p>
<p>In order to enable OSC input, an input port must be specified for each instance. I've done that in this example using the <em>osc_start</em> method but there is also a method <em>osc_input</em> which just takes a port number. You can also add multiple input ports and share ports across various objects. (<a href="https://github.com/arirusso/osc-access/blob/master/examples/multiplex.rb">see example...</a>)</p>
<p>Another thing to note is that <em>val</em> is, by default, the value of the first argument of the received OSC message. (OSC messages can have an unlimited number of arguments). You can modify which arg is used, or pass in all of them, by setting the <em>:arg</em> option on <em>osc_receive</em>. </p>
<p>You can also use <em>osc_receive</em> as an instance method. (<a href="https://github.com/arirusso/osc-access/blob/master/examples/instance_methods.rb">see example...</a>) However, more usefully, you can create a Hash map spec of <em>osc_receive</em> calls and pass it to an instance like this:</p>
<pre name="code" class="brush:ruby gutter:false toolbar:false">
map = {
"/1/fader1" => {
:translate => { :remote => 0..1, :local => 0..127 }
:action => Proc.new { |instance, val| instance.pitch = val }
}
}
class Instrument
include OSCAccessible
def pitch=(val)
puts "setting pitch to #{val}"
...
end
end
i = Instrument.new
i.osc_start(:map => map, :input_port => 8000).join
</pre>
<p>This kind of approach gives you more flexibility by decoupling the OSC spec for your object from the class -- like a controller and model in MVC.</p>
<p><em>Osc_receive</em> has a few options:</p>
<h4>:translate</h4>
<p>There's another difference between those two examples: the <em>:translate</em> option means that <em>val</em> will be translated from a number between 0 to 1 to the analogous value between 0 and 127 before being passed to the code block. So for example if the first argument of the received OSC message is equal to 0.5, <em>val</em> will be equal to 63.</p>
<h4>:thru</h4>
<p>By setting the <em>:thru</em> option to <em>true</em>, any messages that are received for <em>/1/fader1</em> are sent immediately to the output (as well as calling the <em>:action</em> block). For example, using the <em>Instrument</em> class from the last example:</p>
<pre name="code" class="brush:ruby gutter:false toolbar:false">
map = {
"/1/fader1" => {
:thru => true
:translate => { :remote => 0..1, :local => 0..127 }
:action => Proc.new { |instance, val| instance.pitch = val }
}
}
i = Instrument.new
i.osc_start(:map => map, :input_port => 8000, :output => { :host => "192.168.1.9", :port => 9000 }).join
</pre>
<p>As you can see, I also specified an OSC output host and port for this example. If you're ever missing input or output port or host info, your object simply will not perform IO -- it won't raise any kind of exception.</p>
<h3><a name="osc_send">osc_send</a></h3>
<p><em>Osc_send</em> gives you the ability to output arbitrary OSC messages. The first argument is the address of the message and any arguments after that are the content. Here is an example of our class definition from this first example with output added</p>
<pre name="code" class="brush:ruby gutter:false toolbar:false">
class Instrument
include OSCAccessible
osc_receive("/1/fader1") do |instance, val|
instance.velocity = val
instance.osc_send("/velocity", val)
end
def velocity=(val)
puts "setting velocity to #{val}"
...
end
end
i = Instrument.new
i.osc_start(:map => map, :input_port => 8000, :output => { :host => "192.168.1.9", :port => 9000 }).join
i.osc_send("/greeting", "hi!")
</pre>
<p>In this example, I'm sending a message from both <em>osc_receive</em>'s action block and in the main program block after <em>i</em> is instantiated.</p>
<h3><a name="osc_start">osc_start</a></h3>
<p><em>Osc_start</em> starts all of the OSC servers that are connected to your objects. You must call it on an instance before osc_receive will function.</p>
<p>I'll be adding OSC Access to <a href="http://tx81z.blogspot.com/2011/07/diamond-midi-arpeggiator-in-ruby.html">Diamond</a> and coming up with a way to use it with <a href="http://tx81z.blogspot.com/2011/08/micromidi-ruby-dsl-for-midi.html">MicroMIDI</a> in the next few days. Thanks for reading.
<br />
<p><a href="http://github.com/arirusso/osc-access">http://github.com/arirusso/osc-access</a></p>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com2Brooklyn, NY, USA40.65 -73.9540.553624 -74.1079285 40.746376 -73.7920715tag:blogger.com,1999:blog-7653279959382022680.post-14145296370960670082011-10-03T22:04:00.000-04:002011-10-04T18:13:06.324-04:00Selecting a MIDI Device With Unimidi<p>There are a couple of recent changes to how MIDI devices can be selected with <a href="http://github.com/arirusso/unimidi">Unimidi</a>. </p>
<b>Prompting the User</b>
<p>The first is the addition of a handy console prompt that asks the user to select a device and waits for input. The code looks like this</p>
<pre name="code" class="ruby:nocontrols:nogutter">
require "unimidi"
@input = UniMIDI::Input.gets</pre>
<p>on my computer, this results in</p>
<pre>
Select a MIDI input
1) IAC Device
2) Roland UM-2 (1)
3) Roland UM-2 (2)
> </pre>
<p>Note that when the user makes a selection, the device is returned enabled so you don't need to call <em>@input.open</em> on it.</p>
<b>Hard Coded</b>
<p>There's also been some changes to how hard coded selection can be done. As with the user prompt, now you can select and open a device at one fell swoop. Here's a couple of examples which both open the same output. (<em>Device#use</em> and <em>Device#open</em> are the same)</p>
<pre name="code" class="ruby:nocontrols:nogutter">
@output = UniMIDI::Output.open(0)
@output = UniMIDI::Output.use(:first)
</pre>
And of course, you can select and open the device separately if you wish
<pre name="code" class="ruby:nocontrols:nogutter">
@input = UniMIDI::Input.all[0].open
@input = UniMIDI::Input.first.open
</pre>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com0Brooklyn, NY, USA40.65 -73.9540.553624 -74.1079285 40.746376 -73.7920715tag:blogger.com,1999:blog-7653279959382022680.post-807270973153347092011-09-29T23:01:00.002-04:002011-09-30T14:25:52.876-04:00A Note About Live Coding in IRB with OSX<p>Apparently some versions of <a href="http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html">readline</a> for OSX cause IRB to block thread-passing while it's waiting for user input at the prompt.</p>
<p>If you're experiencing problems live coding in IRB, such as starting the <a href="http://tx81z.blogspot.com/2011/07/diamond-midi-arpeggiator-in-ruby.html">Diamond</a> arpeggiator and nothing happening, it could be because of this. Unfortunately, as far as I know, the only way to fix it is to disable readline. You can do this by adding this line to ~/.irbrc</p>
<pre name="code" class="ruby:nocontrols:nogutter">
IRB.conf[:USE_READLINE] = false
</pre>
<p>This is annoying, because then you'll no longer have the ability to recall previously used commands and things like that. I've been meaning to get text editor based live coding up and running so maybe this is the time</p>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com0Brooklyn, NY, USA40.65 -73.9540.553624 -74.1079285 40.746376 -73.7920715tag:blogger.com,1999:blog-7653279959382022680.post-69234155272704521212011-09-18T13:14:00.000-04:002011-09-27T15:19:57.243-04:00More MicroMIDI Tricks<a href="http://github.com/arirusso/micromidi">MicroMIDI</a> has a few less obvious features that may be useful once you have the basics down. <br />
<br />
<b>Sans block</b> <br />
<br />
In addition to how I worked in the <a href="http://tx81z.blogspot.com/2011/08/micromidi-ruby-dsl-for-midi.html">other examples</a>, MicroMIDI can be used outside of the context of a Ruby block. This allows you to integrate it as a more conventional Ruby library. <br />
<br />
Here is the first example from <a href="http://tx81z.blogspot.com/2011/08/micromidi-midi-messages-and-output.html">this post</a> redone without a block<br />
<pre name="code" class="ruby:nocontrols:nogutter">@o = UniMIDI::Output.use(:first)
midi = MIDI::IO.new(@o)
midi.note("C")
midi.off
midi.cc(5, 120)
midi.play("C3", 0.5)
</pre>Note that you can also re-open the IO object in a block later using the <em>edit</em> method
<pre name="code" class="ruby:nocontrols:nogutter">
midi.edit do
play "G3", 1
end
</pre>
<b>Performance Shortcuts</b> <br />
<br />
There are also performance shortcuts that generate messages based on past messages or common conventions. <br />
<ul>
<li><i>off</i> - this generates a note-off message based on the last note-on message created</li>
<li><i>quiet!</i> - sends note-off messages to all MIDI channels on all outputs</li>
<li><i>repeat</i> - generates a copy of the last message created</li>
</ul>
<br />
<b>Super Sticky Mode</b>
<br />
<br />
Again in <a href="http://tx81z.blogspot.com/2011/08/micromidi-midi-messages-and-output.html">this post</a>, I explained how MicroMIDI uses <em>sticky values</em>. There is also a <em>super sticky</em> mode that allows you to change the values inline with each message you create. Here's an example:<br />
<pre name="code" class="ruby:nocontrols:nogutter">MIDI.using(@o) do
super_sticky
channel 1
note "C4"
off
octave 5
velocity 60
note "E", :channel => 2
off
note "C3"
off
end</pre>
<br />
When this program is run, these messages are sent to @o:<br />
<br />
* note C4 (channel 1, vel 100)<br />
* note-off C4 (channel 1, vel 100)<br />
* note E5 (channel 2, vel 60)<br />
* note-off E5 (channel 2, vel 60)<br />
* note C3 (channel 2, vel 60)<br />
* note-off C3 (channel 2, vel 60)<br />
<br />
As you can see, when I sent <em>:channel => 2</em> to the second <em>note</em> command, the MIDI channel remained for the commands that followed rather than just being transient for that command.
<br /><br />
<b>Message Cache</b>
<br /><br />
MicroMIDI keeps a timestamped log of the messages you create. You can access this log using the cache command, like this:<pre name="code" class="ruby:nocontrols:nogutter">M do
note "C4"
cc 5, 120
play "C2", 3
puts cache
end
</pre>
This code gives you this output:
<pre name="code" class="ruby:nocontrols:nogutter">
{ :message=>#<MIDIMessage::NoteOn:0x007fbb6092baf8
@const=#<MIDIMessage::Constant:0x007fbb60930eb8 @key="C4", @value=60>,
@status=[9, 0],
@data=[60, 100],
@channel=0,
@note=60,
@velocity=100,
@name="C4",
@verbose_name="Note On: C4">,
:timestamp=>2.513885498046875
}
{ :message=>#<MIDIMessage::ControlChange:0x007fbb60924e10
@const=#<MIDIMessage::Constant:0x007fbb6093df00 @key="Portamento Time", @value=5>,
@status=[11, 0],
@data=[5, 120],
@channel=0, @index=5,
@value=120,
@name="Portamento Time",
@verbose_name="Control Change: Portamento Time">,
:timestamp=>2.7201175689697266 }
{ :message=>#<MIDIMessage::NoteOn:0x007fbb60921558
@const=#<MIDIMessage::Constant:0x007fbb60931f48 @key="C2", @value=36>,
@status=[9, 0],
@data=[36, 100],
@channel=0,
@note=36,
@velocity=100,
@name="C2",
@verbose_name="Note On: C2">,
:timestamp=>2.961874008178711
}
{ :message=>#<MIDIMessage::NoteOff:0x007fbb60917c38
@const=#<MIDIMessage::Constant:0x007fbb60931f48 @key="C2", @value=36>,
@status=[8, 0],
@data=[36, 100],
@channel=0,
@note=36,
@velocity=100,
@name="C2",
@verbose_name="Note Off: C2">,
:timestamp=>3003.7591457366943
}
</pre>
<br /><br />
<a href="http://github.com/arirusso/micromidi">http://github.com/arirusso/micromidi</a>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com0Brooklyn, NY, USA40.65 -73.9540.553624 -74.1079285 40.746376 -73.7920715tag:blogger.com,1999:blog-7653279959382022680.post-75915325873016171322011-09-10T19:25:00.000-04:002011-09-27T15:20:10.356-04:00Generating Sysex Messages with MicroMIDIRecently, the idea of converting MIDI Control Change messages to Sysex on the fly has come up a couple of times. One could use this to control a synth such as a Roland MKS or Yamaha DX7 that only accepts Sysex for control with a regular MIDI knob controller. <br />
<br />
The following is a simplified example of doing this with <a href="http://github.com/arirusso/micromidi">MicroMIDI</a>.<pre name="code" class="ruby:nocontrols:nogutter">@i = UniMIDI::Input.use(:first)
@o = UniMIDI::Output.use(:first)
MIDI.using(@i, @o) do
node :roland, :model_id => 0x42, :device_id => 0x10
*@my_map =
[0x40, 0x7F, 0x00],
[0x41, 0x7F, 0x00],
[0x42, 0x7F, 0x00]
receive :cc do |message|
command @my_map[message.index - 1], message.value
end
join
end</pre><b>Defining a Node</b><br />
<br />
I won't get into too much background on Sysex but there are two concepts that one must understand in order to generate Sysex with MicroMIDI.
<br /><br />
The first concept is what I call a <em>Sysex Node</em>: there are up to three bytes of data used in each Sysex message to identify the synth/module/destination/node/etc where the message is intended to be sent. This is not unlike the MIDI channel in a regular short message except that it's three bytes. Two of those bytes pinpoint the make and model of the synth while the third byte identifies the individual synth (device ID) in case you have multiple Yamaha DX7's or whatever the case. <br />
<br />
MicroMIDI allows you to define these bytes as a sticky value using the <em>node</em> function. <br />
<br />
Since I'm only using one synth for the entire example, I call the <em>node</em> function before setting up the input event to catch Control Change messages. (If you are using multiple synths and multiple events you would call node in each event block). The arguments represent the <em>Manufacturer ID</em> and the optional <em>Model ID</em> and <em>Device ID</em>. The Manufacturer can be referred to by a symbol (as above) or a string if its name is found in the manufacturer constants in <a href="https://github.com/arirusso/midi-message/blob/master/lib/midi.yml">midi.yml</a> (by all means, add yours and do a pull request).
<br />
<br />
Now here's the annoying part: different brands and synth models use this Node data differently. For instance, I believe some devices don't understand messages with a model ID in them. In those cases just leave out whatever needs to be omitted from your messages. As I learn more about this myself, perhaps I can have this function streamline accepting the proper data for major synth types.<br />
<br />
<b>Command vs Request</b>
<br /><br />
The other concept to understand is that Sysex messages can (in theory) either be a command or request. This is pretty simple, and if you are creating a controller program you'll deal mostly in commands. In the case of the example above, we send a command<pre name="code" class="ruby:nocontrols:nogutter">command @my_map[message.index - 1], message.value</pre> When using the <em>command</em> function, the first argument is the sysex address and the second is the value to assign. The value can either be a number, as in this case, or an array of bytes.
When making a request, the first argument is also the address but the second argument is the size of the response (in bytes) that you expect to receive<pre name="code" class="ruby:nocontrols:nogutter">
request 0x43, 43</pre>
<b>If all else fails...</b>
<br /><br />
Due to the fact that Sysex hasn't had a truly concrete spec, some devices will use messages that don't really adhere to the command/request format. In those cases, you can just use the generic <em>sysex</em> command like this<pre name="code" class="ruby:nocontrols:nogutter">
sysex 0x1, 0x2, 0x3, 0x4
</pre>
With no node specified, this will give you a message composed of<pre name="code" class="ruby:nocontrols:nogutter">F0 01 02 03 04 F7</pre>
In other words, <em>sysex</em> will create a message and not perform any validation or add a checksum to it. You can still use <em>node</em> with these message-- it will append those bytes immediately after the <em>F0</em> start byte as it would with a command or request.<br /><br />
tldr, Sysex is tricky to to objectify<br /><br />
If you'd like to gain a deeper understanding of how sysex messages work, <a href="http://www.2writers.com/eddie/TutSysEx.htm">this is a good tutorial</a> (if Roland-centric) and I often referred back to it while creating MicroMIDI and the libraries that support it.
<br /><br />
<a href="http://github.com/arirusso/micromidi">http://github.com/arirusso/micromidi</a>
<br /><br />
<a href="http://tx81z.blogspot.com/2011/09/more-micromidi-tricks.html">Next: More MicroMIDI Tricks</a>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com0Miami Beach, FL, USA25.790654 -80.130045525.733466 -80.2090095 25.847842 -80.0510815tag:blogger.com,1999:blog-7653279959382022680.post-59963763841864185112011-08-31T22:40:00.000-04:002011-09-27T15:20:20.235-04:00MicroMIDI: ShorthandMost <a href="http://github.com/arirusso/micromidi">MicroMIDI</a> methods and common symbol arguments have shorthand aliases intended to reduce keystrokes while <a href="http://en.wikipedia.org/wiki/Live_coding">live coding</a>. The following is the example from the <a href="http://tx81z.blogspot.com/2011/08/micromidi-custom-events.html">last post</a>, re-done using only shorthand.<br />
<pre name="code" class="ruby:nocontrols:nogutter">@i = UniMIDI::Input.use(:first)
@o = UniMIDI::Output.use(:first)
M(@i, @o) do
tu :n
rc :n { |m| tp(m, :oct, 1) if %w{C E G}.include?(m.note_name) }
j
end</pre>
<br />
See the alias definitions <a href="http://github.com/arirusso/micromidi/blob/master/lib/micromidi/instructions/shorthand.rb">here</a> for the complete list.
<br /><br />
<a href="http://github.com/arirusso/micromidi">http://github.com/arirusso/micromidi</a>
<br /><br />
<a href="http://tx81z.blogspot.com/2011/09/generating-sysex-messages-with.html">Next: Generating Sysex Messages</a>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com0Brooklyn, NY, USA40.65 -73.94999999999998940.555797999999996 -74.061632499999988 40.744202 -73.83836749999999tag:blogger.com,1999:blog-7653279959382022680.post-66949201325150784772011-08-31T22:38:00.003-04:002011-10-03T11:57:32.199-04:00MicroMIDI: Custom EventsWhile <a href="http://github.com/arirusso/micromidi">MicroMIDI</a> has built-in functions such as <em>transpose</em> to process MIDI input, these functions may not always suit your purpose musically.<br />
<br />
In those situations, you can bind your own input events.<br />
<br />
Here is an example similar to the one in the <a href="http://tx81z.blogspot.com/2011/08/micromidi-midi-thru-and-midi-processing.html">last post</a> except that only the notes C, E, and G are transposed<br />
<pre name="code" class="ruby:nocontrols:nogutter">require "micromidi"
@input = UniMIDI::Input.use(:first)
@output = UniMIDI::Output.use(:first)
MIDI.using(@input, @output) do
thru_except :note
receive :note do |message|
message.octave += 1 if %w{C E G}.include?(message.note_name)
output message
end
join
end</pre>
<br />
For the sake of expressiveness, there are many permutations of each of these methods. I recommend reading the rdoc for the <a href="http://rubydoc.info/github/arirusso/micromidi/master/MicroMIDI/Instructions">MicroMIDI Instructions classes</a> to get a handle on what's possible.
<br /><br />
<a href="http://github.com/arirusso/micromidi">http://github.com/arirusso/micromidi</a>
<br /><br />
<a href="http://tx81z.blogspot.com/2011/08/micromidi-shorthand.html">Next: Shorthand with MicroMIDI</a>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com4Brooklyn, NY, USA40.65 -73.94999999999998940.555797999999996 -74.061632499999988 40.744202 -73.83836749999999tag:blogger.com,1999:blog-7653279959382022680.post-37763665755896106002011-08-31T22:38:00.002-04:002011-09-27T15:21:51.801-04:00MicroMIDI: MIDI Thru and ProcessingThe simplest way to work with MIDI input in <a href="http://github.com/arirusso/micromidi">MicroMIDI</a> is to use its built-in shortcuts for MIDI Thru and processor classes.<br />
<br />
Here's an example where both kinds of shortcuts are used. An input and output are passed in, all messages that are received by the input are sent to the output (Thru) with the exception of notes which will be transposed up one octave before being sent to the output. The <em>transpose</em> function is an example of a processor.<br />
<pre name="code" class="ruby:nocontrols:nogutter">@i = UniMIDI::Input.use(:first)
@o = UniMIDI::Output.use(:first)
MIDI.using(@i, @o) do
thru_except :note { |msg| transpose(msg, :octave, 1) }
join
end</pre>
<br />
<a href="http://github.com/arirusso/micromidi">http://github.com/arirusso/micromidi</a>
<br /><br />
<a href="http://tx81z.blogspot.com/2011/08/micromidi-custom-events.html">Next: Custom Events with MicroMIDI</a>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com1Brooklyn, NY, USA40.65 -73.94999999999998940.555797999999996 -74.061632499999988 40.744202 -73.83836749999999tag:blogger.com,1999:blog-7653279959382022680.post-10181358496353163792011-08-31T22:38:00.001-04:002011-10-03T12:02:56.455-04:00MicroMIDI: MIDI Messages and Output<p>Here's an example where <a href="http://github.com/arirusso/unimidi">MicroMIDI</a> sends some MIDI messages to an output. (<a href="http://github.com/arirusso/unimidi/blob/master/examples/select_a_device.rb">see an example here which explains selecting an output...</a>)</p>
<pre name="code" class="ruby:nocontrols:nogutter">require "micromidi"
@o = UniMIDI::Output.use(:first)
MIDI.using(@o) do
note "C"
off
cc 5, 120
play "C3", 0.5
end </pre>
<p>Running this code sends the following to <em>@o</em>: </p>
<p>* note C2 (2 is the default octave)<br />
* note-off for C2, since that was the last note sent<br />
* sets controller number 5 to 120<br />
* note C3, waits half of a second and then note-off for C3<br />
</p><p>
By default, any time you call a method that returns a MIDI message object, it's automatically sent to any outputs that are passed in. You can toggle this feature by calling</p>
<pre name="code" class="ruby:nocontrols:nogutter">output false
</pre>
<p>or</p>
<pre name="code" class="ruby:nocontrols:nogutter">output true
</pre>
<p>You can also prevent only a single command from sending output by setting the <em>output</em> option:</p><pre name="code" class="ruby:nocontrols:nogutter">note "c", :output => false</pre>
<b>Sticky Values</b><br />
<p>
If you work with MIDI often, you may have noticed that there was no mention of <em>MIDI channel</em> or <em>velocity</em> in the last example. Most of the time, sending a note-on or note-off message requires those values. In addition, for the first message I didn't specify what octave the note C should be.<br />
</p>
In MicroMIDI, channel, velocity and octave are sticky values. When you open a MicroMIDI block, those values default to 0, 100 and 2 respectively. These sticky values will be used by any commands that need them. You can also pass a channel or velocity value to a command, temporarily overriding the sticky value. Providing the octave to a note ala <em>note "c4"</em> will override the sticky octave.<p>
Here's an example where the sticky values are used, changed and overriden.</p>
<pre name="code" class="ruby:nocontrols:nogutter">MIDI.using(@o) do
channel 1
note "C4"
off
octave 5
velocity 60
note "E", :channel => 2
off
channel 3
note "C3"
off
end </pre>
<p>What winds up being sent to <em>@o</em> is:</p>
<p>
* note C4 (channel 1, vel 100)<br />
* note-off C4 (channel 1, vel 100)<br />
* note E5 (channel 2, vel 60)<br />
* note-off E5 (channel 2, vel 60)<br />
* note C3 (channel 3, vel 60)<br />
* note-off C3 (channel 3, vel 60)
</p><p>
<a href="http://github.com/arirusso/micromidi">http://github.com/arirusso/micromidi</a></p>
<p>
<a href="http://tx81z.blogspot.com/2011/08/micromidi-midi-thru-and-midi-processing.html">Next: MIDI Thru and Processing with MicroMIDI</a></p>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com0Brooklyn, NY, USA40.65 -73.94999999999998940.555797999999996 -74.061632499999988 40.744202 -73.83836749999999tag:blogger.com,1999:blog-7653279959382022680.post-29477182668463560912011-08-31T22:38:00.000-04:002011-09-27T15:29:25.532-04:00MicroMIDI: a Ruby DSL for MIDIAfter a month of moving I'm finally getting back into some music projects. I've got some more flashy things in the works but first here is a Ruby DSL called <a href="http://github.com/arirusso/micromidi">MicroMIDI</a> that brings all of the MIDI projects mentioned in <a href="http://tx81z.blogspot.com/2011/06/high-level-midi-io-with-ruby.html">this post</a> together along with some new tricks in to a package a bit more suited for live coding and one-off scripts. <br />
<br />
Being that it's an interface for four libraries, there's a lot of functionality. I break down each concept in the following posts:<br />
<ul>
<li><a href="http://tx81z.blogspot.com/2011/08/micromidi-midi-messages-and-output.html">Output</a></li>
<li><a href="http://tx81z.blogspot.com/2011/08/micromidi-midi-thru-and-midi-processing.html">MIDI thru and processing</a></li>
<li><a href="http://tx81z.blogspot.com/2011/08/micromidi-custom-events.html">Binding custom input events</a></li>
<li><a href="http://tx81z.blogspot.com/2011/08/micromidi-shorthand.html">Shorthand</a></li>
<li><a href="http://tx81z.blogspot.com/2011/09/generating-sysex-messages-with.html">Sysex</a></li>
<li><a href="http://tx81z.blogspot.com/2011/09/more-micromidi-tricks.html">Etc</a></li>
</ul>
<br />
<a href="http://github.com/arirusso/micromidi">http://github.com/arirusso/micromidi</a>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com2Brooklyn, NY, USA40.65 -73.94999999999998940.555797999999996 -74.061632499999988 40.744202 -73.83836749999999tag:blogger.com,1999:blog-7653279959382022680.post-3599816540292963622011-07-03T22:21:00.000-04:002011-09-29T23:04:28.119-04:00Live coding with DiamondI've created a screencast video to show some basic live coding functionality with <a href="http://github.com/arirusso/diamond">Diamond</a>. In it, I use Diamond to send MIDI to a 2-voice modular synth and kick drum module.<br />
<br />
<iframe frameborder="0" height="250" src="http://player.vimeo.com/video/25983971?title=0&byline=0&portrait=0" width="400"></iframe><br />
<br />
(sound starts around 55 seconds in)<br />
<br />
Here is a quick explanation of what was happening in the video.<br />
<br />
Some people prefer to do <a href="http://github.com/maca/live">live coding with a text editor</a>, which is great because you can work a lot faster. However, for the sake of keeping this tutorial to the point, I'll assume you're working in IRB.<br />
<br />
First, I'll start up IRB and set up an arpeggiator using the similar options as in <a href="http://tx81z.blogspot.com/2011/07/diamond-midi-arpeggiator-in-ruby.html">the last post</a>. That should look something like this:<br />
<pre name="code" class="ruby:nocontrols:nogutter">require "diamond"
@output = UniMIDI::Output.use(:first)
arp = Diamond::Arpeggiator.new(175, :interval => 7, :midi => @output, :range => 4, :rate => 8)
chord = ["C3", "G3", "Bb3", "A4"]
arp << chord
arp.start
</pre>
At that point we start hearing arpeggios. Since the arpeggiator is started in a background thread by default, and I can make changes to it while it plays. <br />
<pre name="code" class="ruby:nocontrols:nogutter">arp.rate = 16
arp.gate = 20
arp.range = 3
# etc
</pre>
<br />
In the video, I use the <em>Arpeggiator#rest_every</em> method to insert musical rests in to the arpeggio sequence. If I do<br />
<pre name="code" class="ruby:nocontrols:nogutter">arp.rest_every(5)
</pre>
notes become muted on every fifth beat.<br />
<br />
<b>Syncing multiple Arpeggiators</b><br />
<br />
Another thing I do in the video is sync multiple arpeggiators to each other.<br />
<br />
Assuming I still have that setup running, I'm going to add another arpeggiator.<br />
<pre name="code" class="ruby:nocontrols:nogutter">arp2 = Diamond::Arpeggiator.new(138, :rate => 2, :output_channel => 1)
arp2 << ["C3", "G4", "A4"]
</pre>
Because I used the <em>:output_channel => 1</em> option, any notes coming from <em>arp2</em> will be outputted on MIDI channel 1.
Now I can sync this new arpeggiator to the old one -- the clock of the first arpeggiator, <em>arp</em> will drive <em>arp2</em>.
<br />
<pre name="code" class="ruby:nocontrols:nogutter">arp.sync(arp2)
</pre>
By default, the sync will wait for the next time the arpeggiator pattern repeats to take hold. You can override this by passing in <em>:now => true</em> which will activate the sync on the next downbeat.
<br />
<pre name="code" class="ruby:nocontrols:nogutter">arp.sync(arp2, :now => true)
</pre>
You can sync as many arpeggiators as you like.
<br />
<p>Trouble getting this working in OSX? <a href="http://tx81z.blogspot.com/2011/09/note-about-live-coding-in-irb-with-osx.html">One solution here</a>.
<p>Thanks for reading</p>
<br />
<a href="http://github.com/arirusso/diamond">http://github.com/arirusso/diamond</a>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com0Brooklyn, NY, USA40.65 -73.94999999999998940.555797999999996 -74.061632499999988 40.744202 -73.83836749999999tag:blogger.com,1999:blog-7653279959382022680.post-66158726958478538202011-07-03T21:21:00.000-04:002011-11-07T13:20:26.256-05:00Diamond, MIDI Arpeggiator in Ruby<a href="http://github.com/arirusso/diamond"><img border="0" height="206" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiA5kn2sI0dLYJ_FkHHRJSruNQ8jpSsGQZ3_PnElwevDJyrfVgr-7xpnPmSp8qeQFp7TYVPzDzIpCXcv5EA_Kw3RUwNQGl8TqypVy_ppXxy-bcox8V16LY_j7O7-LVjB-ztcJZ1FEo9wnc/s320/687474703a2f2f696d616765732e7472656574726f75626c652e6e65742f696d616765732f6469616d6f6e642e6a7067.jpeg" width="244" /></a><br />
<br />
<a href="http://github.com/arirusso/diamond">Diamond</a> is a MIDI arpeggiator in Ruby. <br />
<br />
It features all of the classic functions of a MIDI arpeggiator plus the ability to <a href="http://en.wikipedia.org/wiki/Live_coding">live code</a>, algorithmically generate and modify patterns, chain and sync instances and more<br />
<br />
<iframe frameborder="0" height="250" src="http://player.vimeo.com/video/25983971?title=0&byline=0&portrait=0" width="400"></iframe><br />
<div>
</div>
This is a quick screencast video I did while live coding Diamond. (<a href="http://tx81z.blogspot.com/2011/07/live-coding-with-diamond.html">read more about this here...</a>)<br />
(Sounds starts around 55 seconds in)<br />
<br />
<b>Getting started</b><br />
<br />
Ruby 1.9.2 or JRuby in 1.9 mode are required. <br />
<br />
It installs with a typical gem installation...<br />
<pre name="code" class="brush:ruby gutter:false toolbar:false">gem install diamond</pre>
Here is a very basic example to get started:<br />
<pre name="code" class="brush:ruby gutter:false toolbar:false">require "diamond"</pre>
First, select a MIDI output using <a href="http://github.com/arirusso/unimidi">unimidi</a>. (<a href="http://tx81z.blogspot.com/2011/10/selecting-midi-device-with-unimidi.html">more...</a>)<br />
<pre name="code" class="brush:ruby gutter:false toolbar:false">@output = UniMIDI::Output.gets</pre>
The Arpeggiator has a number of optional parameters (<a href="http://rubydoc.info/github/arirusso/diamond/master/Diamond/Arpeggiator:initialize">more...</a>). For the sake of keeping this demo simple, here is a straightforward setup:<br />
<pre name="code" class="brush:ruby gutter:false toolbar:false">opts = {
:gate => 90,
:range => 4,
:interval => 7,
:midi => @output,
:pattern => Diamond::Pattern["UpDown"],
:rate => 8
}
</pre>
(<a href="http://rubydoc.info/github/arirusso/diamond/master/Diamond/Arpeggiator:initialize">read more about what these options mean</a>)<br />
<br />
Now create an Arpeggiator object, passing in a tempo value and the options chosen before. In this case the tempo will be 138 BPM<br />
<pre name="code" class="brush:ruby gutter:false toolbar:false">arp = Diamond::Arpeggiator.new(138, opts)</pre>
Of course, an Arpeggiator needs notes to work with. As you might expect, it's easy to use a MIDI input for that (<a href="http://github.com/arirusso/diamond/blob/master/examples/midi_note_input.rb">see example</a>). However, again for the sake of simplicity here's a chord in Ruby<br />
<pre name="code" class="brush:ruby gutter:false toolbar:false">chord = ["C3", "G3", "Bb3", "A4"]</pre>
Use <em>Arpeggiator#add</em> and <em>Arpeggiator#remove</em> to change the notes that the arpeggiator sees. (<em>Arpeggiator#<<</em> is the same as <em>add</em>)<br />
<pre name="code" class="brush:ruby gutter:false toolbar:false">arp.add(chord)
arp.add("C5")
arp << "A4"
</pre>
By default, the arpeggiator will run in a background thread so if you are working in <a href="http://en.wikipedia.org/wiki/Interactive_Ruby_Shell">IRB</a> this will allow you to live code, sync it other arpeggiators, or just run another foreground process. (To start in the foreground, just pass <em>:focus => true</em> to <em>Arpeggiator#start</em>)<br />
<pre name="code" class="brush:ruby gutter:false toolbar:false">arp.start</pre>
At that point, the arpeggiator starts playing. All of its <a href="http://rubydoc.info/github/arirusso/diamond/master/Diamond/Arpeggiator:initialize">options</a> can be controlled on the on the fly.<br />
<pre name="code" class="brush:ruby gutter:false toolbar:false">arp.rate = 16
arp.gate = 20
arp.remove("C5", "A4")</pre>
Here are examples showing how to use some of Diamond's other features <br />
<ul>
<li> <a href="http://github.com/arirusso/diamond/blob/master/examples/midi_input.rb">Feeding notes to Diamond using a MIDI controller</a></li>
<li> <a href="http://github.com/arirusso/diamond/blob/master/examples/midi_message_objects.rb">Feeding notes to Diamond using MIDI Message objects</a></li>
<li><a href="http://tx81z.blogspot.com/2011/07/live-coding-with-diamond.html">Live coding Diamond and syncing multiple arpeggiators to each other</a></li>
<li> <a href="http://github.com/arirusso/diamond/blob/master/examples/sync_to_midi_clock.rb">Syncing Diamond to external MIDI clock</a></li>
</ul>
Thanks for reading <br />
<div>
</div>
<div>
</div>
<a href="http://github.com/arirusso/diamond">http://github.com/arirusso/diamond</a>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com11Brooklyn, NY, USA40.65 -73.94999999999998940.555797999999996 -74.061632499999988 40.744202 -73.83836749999999tag:blogger.com,1999:blog-7653279959382022680.post-20558857209417149412011-06-27T18:49:00.000-04:002011-10-05T14:52:24.351-04:00High-level realtime MIDI IO with Ruby<em>Update (9/8/2011): </em> I've created another library that wraps all of the concepts of this post in a Ruby DSL and adds shorthand notation and some other fun things. <a href="http://tx81z.blogspot.com/2011/08/micromidi-ruby-dsl-for-midi.html">Read about MicroMIDI here</a>
<br />
<hr />
<br />
Understandably, a few people have asked me for advice on how to input and output MIDI in a human friendly way with <a href="http://github.com/arirusso/unimidi">unimidi</a> so I've decided to put together a quick tutorial. I'll be focusing on two gem libraries that I wrote: <a href="http://github.com/arirusso/midi-message">midi-message</a>, which deals soley with MIDI message objects, and <a href="http://github.com/arirusso/midi-eye">midi-eye</a>, a library for reacting to MIDI input. Of course, it should be mentioned that there's no <em>one</em> way to do this with unimidi. You can use whatever MIDI objects you like or create your own classes-- unimidi just deals in raw low-level bytes. There are other libraries such as <a href="http://github.com/jimm/midilib">midilib</a> that provide an intriguing alternative and could work pretty easily with unimidi. Or one could get creative and go off with a totally unconventional approach as well. For the examples that follow, I'm using a MIDI input and output that I specify with unimidi. <br />
<pre class="ruby:nocontrols:nogutter" name="code">require 'unimidi'
@input = UniMIDI::Input.use(:first)
@output = UniMIDI::Output.use(:first)
</pre>
<p>If you copy and paste these, they will just open the first MIDI devices available on your computer. You should determine which MIDI devices you want to use and edit these statements to suit your setup. (<a href="http://tx81z.blogspot.com/2011/10/selecting-midi-device-with-unimidi.html">here's a blog post that goes into more detail on this</a>)</p>
<h4>Dealing with MIDI input using midi-eye</h4>
<p>My preferred way of dealing with MIDI input is to react to arriving messages with an event listener. Midi-eye makes this easy and its constructor accepts a unimidi input to attach to. Here is an example that will react to all incoming messages in the same way by printing them to the screen </p>
<pre class="ruby:nocontrols:nogutter" name="code">require 'midi-eye'
listener = MIDIEye::Listener.new(@input)
listener.on_message do |event|
puts event[:timestamp]
puts event[:message]
end
listener.start
</pre>
Chances are if you're working with MIDI input that you will want to cherry-pick certain messages, or at least react in a different way depending on what type of message you've received eg. a note message, control change, etc. To accomplish this, arguments can be passed to the <em>Listener#listen_for</em> method which will match against properties of the incoming messages <br />
<pre class="ruby:nocontrols:nogutter" name="code">listener.listen_for(:class => [MIDIMessage::NoteOn, MIDIMessage::NoteOff]) do |event|
# raise the note value by an octave
event[:message].note += 12
# send the altered note message to the output you chose earlier
@output.puts(event[:message])
end
listener.start
</pre>
In this example, I take all note messages (identified by their class), transpose them up one octave and send them to my MIDI output. You can add as many of these callbacks as you like, just keep calling <em>Listener#listen_for</em>. While that type of matching will be useful in a lot of cases, it is limited by the fact that it only matches positively against the properties and values you pass in. If you need more complex matching, I recommend putting a conditional statement within the callback. <br />
<pre class="ruby:nocontrols:nogutter" name="code">listener.listen do |event|
# is this a note above C3?
if event[:message].respond_to?(:note) && event[:message].note > 48
# if so, lower the note value by a fifth
event[:message].note -= 7
end
# and send the message to the unimidi output
@output.puts(event[:message])
end
listener.start
</pre>
<p>(<em>listen</em> and <em>listen_for</em> are actually the same method, I just think it looks cleaner to call <em>listen</em> when there is no matching happening)</p>
<h4>Threading</h4>
<p>
Pass <em>:background => true</em> to <em>listener.start</em> to have the listener work only in a background thread. This will allow you to run other listeners or foreground threads while that particular listener is running in the background.</p>
<h4>Output MIDI using midi-message</h4>
<p>
In those examples, I sent messages to an output-- but I didn't create those messages myself. The midi-message library allows you to create messages like that yourself in a flexible way.</p>
<pre class="ruby:nocontrols:nogutter" name="code">require 'midi-message'
include MIDIMessage</pre>
Here are three different MIDI note-on messages created using three different methods.<br />
<pre class="ruby:nocontrols:nogutter" name="code">messages = []
messages << NoteOn.new(0, 48, 64) # C3
messages << NoteOn["E3"].new(0, 100)
with(:channel => 0, :velocity => 100) do
messages << note_on("G3")
end
</pre>
With those message objects in hand, I pass each to <em>UniMIDI::Output#puts</em> the same way you saw earlier. <br />
<pre class="ruby:nocontrols:nogutter" name="code">messages.each { |message| @output.puts(message) }
</pre>
That's it... and it works the same for all types of MIDI messages including sysex. You can find some info on creating sysex messages <a href="http://github.com/arirusso/midi-message/blob/master/examples/sysex.rb">here</a>.<br />
<br />
<a href="https://github.com/arirusso/midi-eye">http://github.com/arirusso/midi-eye</a><br />
<a href="https://github.com/arirusso/midi-message">http://github.com/arirusso/midi-message</a><br />
<a href="https://github.com/arirusso/unimidi">http://github.com/arirusso/unimidi</a>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com2tag:blogger.com,1999:blog-7653279959382022680.post-9607317579198922692011-06-09T17:45:00.000-04:002011-10-12T12:13:44.467-04:00OSX: Unimidi, IAC and MIDI Patch BaySome quick instructions for routing MIDI between <a href="http://tx81z.blogspot.com/2011/06/unimidi-platform-independent-realtime.html">unimidi</a> and other programs in OSX...<br />
<br />
OSX (10.3 and above) has the ability built in to route MIDI between programs using something called Inter-Application Communication (IAC). IAC allows you to create a pair of virtual MIDI devices (an input and an output) that applications will see as though they are usual MIDI hardware devices. When you send MIDI instructions to the output, they show up at the input. Therefore, you can send MIDI to the output using one program and use the input in another program to receive the data.
<br /><br />
You can control the IAC settings using the built-in <a href="http://en.wikipedia.org/wiki/Audio_MIDI_Setup">Audio MIDI Setup</a> applications in the <em>utilities</em> folder. That program allows you to create, edit and delete these virtual device pairs.
<br /><br />
<img border="0" height="194" width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMajJuKGm8lhEoLtMEy-0JQWkOaNDji3_5WeVOytHLkE615f5nyag46BB_aLCBIuyp9IDKReZ0t94YDuL2EUa0bcDIaY_lbkDtewIKcwOLIAGpkfgcgDeIS0bWm7sZ1Jqnwywu6KyEWQ4/s320/audio_midi_ss04.jpg" />
<br /><br />
When Audio MIDI Setup is loaded you should see the window shown above. If you don't, select <em>Show MIDI Window</em> from the <em>Window</em> menu.
<br /><br />
Double-click the <em>IAC Driver</em> icon. Click <em>More Information</em> if the <em>Ports</em> menu is not showing. Make sure that there is at least one port listed -- this represents a single pair of virtual devices.
<br /><br />
When working with Ruby, select the <em>IAC Driver</em> from the list of unimidi inputs or outputs that corresponds to the port that you've created. For example, the first <em>IAC Driver</em> output in unimidi will correspond to the output for the first set of ports in Audio MIDI Setup.
<br /><br />You can list your unimidi devices by using <em>unimidi list</em> at the command line or using <em>UniMIDI::Device.all</em> in Ruby.
<br /><br />
Once you have these concepts down, you also have the option of using <a href="http://notahat.com/midi_patchbay">MIDI Patch Bay</a> for more complex routing and filtering.
<br />
<br />
<a href="http://vimeo.com/user6650587">Joe Le Brech</a> made a video of using MIDI Patch Bay and IAC to send notes to GarageBand <br />
<br />
<iframe frameborder="0" height="250" src="http://player.vimeo.com/video/24159013?title=0&byline=0&portrait=0" width="400"></iframe><br />
<br />
He wrapped all of his Ruby code in a script called output.rb so you really can't see exactly what's going on the Ruby end of things...but it should give you a general idea of how this works<br />
<br />Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com6Brooklyn, NY, USA40.65 -73.94999999999998940.555797999999996 -74.061632499999988 40.744202 -73.83836749999999tag:blogger.com,1999:blog-7653279959382022680.post-86551888434308500772011-06-07T13:21:00.000-04:002011-10-04T22:22:03.913-04:00Unimidi: Platform independent realtime MIDI IO in Ruby<a href="http://github.com/arirusso/unimidi">Unimidi</a> is a universal Ruby library for realtime MIDI IO.<br />
<br />
It currently works with MRI 1.9.2 on Linux, OSX, Windows/cygwin and under JRuby in 1.9 mode on any platform.<br />
<br />
<pre class="ruby:nocontrols:nogutter" name="code">gem install unimidi</pre>
<br />
No compilation is required, install the gem and start playing.<br />
<br />
Unimidi deals in raw bytes rather than high level message objects with the intention of allowing people to use whichever message objects or helpers they choose. There's a few libraries out there for that, including <a href="http://tx81z.blogspot.com/2011/08/micromidi-ruby-dsl-for-midi.html">one by me</a>.<br />
<br />
Under the hood, unimidi is essentially linkage to a set of platform specific C bindings (that use <a href="https://github.com/ffi/ffi/wiki/">ruby-ffi</a>). Or in the case of JRuby, some code that wraps javax.sound. These platform specific libraries are broken out in to their own gems and the appropriate one should install automatically when the unimidi gem is installed. In unusual cases where your platform isn't recognized, all of those gems will be installed. You can see which library goes with which platform on the <a href="http://github.com/arirusso/unimidi">unimidi github page</a>. It is possible to use those gems on their own, but currently none of them contain any features that aren't also made available through unimidi. <br />
<br />
Here's a couple of quick examples to get started<br />
<br />
<b>Sending notes to a MIDI output</b><br />
<br />
First, load unimidi and then define a set of note values and a duration value for how long the notes will be held out.<br />
<br />
<pre class="ruby:nocontrols:nogutter" name="code">require 'unimidi'
notes = [36, 40, 43, 48, 52, 55, 60, 64, 67] # C E G arpeggios
duration = 0.1</pre>
<br />
Next, select an output. To list all available outputs, you can do <i>unimidi list</i> from the command line or <i>UniMIDI::Device.list </i>in irb. In this case, the first output is selected and enabled. (<a href="http://tx81z.blogspot.com/2011/10/selecting-midi-device-with-unimidi.html">here is another post with more information about selecting a device</a>)<br />
<br />
<pre class="ruby:nocontrols:nogutter" name="code">output = UniMIDI::Output.open(:first)</pre>
<br />
Now open that output. Passing a block to open is optional but it ensures that the device is closed when the program is finished. This can alleviate some headaches when multitasking MIDI/audio programs. Note that it's also possible to select, open and use multiple inputs and outputs concurrently.<br />
<br />
<pre class="ruby:nocontrols:nogutter" name="code">output.open do |output|
notes.each do |note|
output.puts(0x90, note, 100) # note on message
sleep(duration) # wait
output.puts(0x80, note, 100) # note off message
end
end</pre>
<br />
Output#puts can also be used for sysex messages in the same manner as note messages, a la:<br />
<pre class="ruby:nocontrols:nogutter" name="code">output.puts(0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F, 0x00, 0x41, 0xF7)</pre>
Note that some OS's will silently reject invalid sysex or short messages.<br />
<br />
You can also Output#puts a string of hex bytes if you prefer to work that way<br />
<pre class="ruby:nocontrols:nogutter" name="code">output.puts("904040")
output.puts("F04110421240007F41F7")</pre>
<br />
<b>Working with input</b><br />
<br />
Input can be collected two ways. First, unimidi has a method <i>Input#gets</i> which waits for input before returning. It works exactly the way Ruby's <i>$stdin.gets</i> works when waiting for keyboard input.<br />
<br />
Here is a demonstration of Input#gets<br />
<br />
Select an input and open it...<br />
<br />
<pre class="ruby:nocontrols:nogutter" name="code">input = UniMIDI::Input.first
input.open do |input|
$stdout.puts "send some MIDI to your input now..."
loop do
m = input.gets
$stdout.puts(m)
end
end</pre>
<br />
When MIDI input is received, you'll see inspected Hash objects like this:<br />
<br />
<pre class="ruby:nocontrols:nogutter" name="code">{ :data => [144, 60, 100], :timestamp => 1024 }</pre>
<br />
In this case [144, 60, 100] is a note-on message for channel 0, note C4 (aka 60), with velocity 100. The timestamp is the number of milliseconds since the input was opened.<br />
<br />
The other more advanced way to receive input is by polling <i>Input#buffer</i> manually. As new messages are received, they are added to that buffer array. I normally use this with a pointer to keep track of the index of the last message seen. Polling this way would for example, allow you to create your own background thread to collect input while your program does other things. The library Topaz, <a href="http://tx81z.blogspot.com/2011/05/topaz-midi-syncable-tempo-in-ruby.html">which I wrote about in my last post</a>, collects clock messages from unimidi that way.<br />
<br />
Your computer should be able to receive data with 1-2 millisecond accuracy<br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<a href="http://github.com/arirusso/unimidi"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipxohnup6oP1XzSI5B4y9izwfz0uoT95NjH6H_olFAtiDn3ixwsz0LUg0TfiTUpm_XxDbUKAGvJ-E4cuzSKKxN3jhfoL7WRtFO5kXa236H_nEpByobufpvfJI2fykqUGtO8sT-Snkrq2c/s1600/phpuygZQ2AM.jpg" /></a></div>
<a href="http://github.com/arirusso/unimidi">http://github.com/arirusso/unimidi</a>Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com2Brooklyn, NY, USA40.65 -73.94999999999998940.555797999999996 -74.061632499999988 40.744202 -73.83836749999999tag:blogger.com,1999:blog-7653279959382022680.post-25225498574944301382011-05-26T23:33:00.000-04:002011-10-05T14:33:53.855-04:00Topaz: MIDI syncable tempo in Ruby<p>
<a href="http://github.com/arirusso/topaz">Topaz</a> is a Ruby based music tempo generator / analyzer </p>
<pre>gem install midi-topaz</pre>
<p>
It gives you the ability to time events to a given rate in beats per minute<br />
("sequencer" is some kind of imagined sequencer)</p>
<pre class="ruby:nocontrols:nogutter" name="code">@tempo = Topaz::Tempo.new(130) { sequencer.step! }</pre>
<p>
or synchronize them to incoming MIDI clock messages</p>
<pre class="ruby:nocontrols:nogutter" name="code">@input = UniMIDI::Input.first.open # a midi input
@tempo = Topaz::Tempo.new(@input) { sequencer.step! }</pre>
<p>Topaz can also act as a MIDI master clock. If a MIDI output object is passed to Topaz, MIDI start/stop/clock signals will automatically be sent to that output at the appropriate time</p>
<pre class="ruby:nocontrols:nogutter" name="code">@output = UniMIDI::Output.first.open # a midi output
@tempo = Topaz::Tempo.new(120, :midi => @output) { sequencer.step! }</pre>
<p>an input can be used along with multiple outputs simultaneously</p>
<pre class="ruby:nocontrols:nogutter" name="code">@tempo = Topaz::Tempo.new(@input, :midi => [@output1, @output2]) { sequencer.step! }</pre>
<p>once everything is all set, start the clock</p>
<pre class="ruby:nocontrols:nogutter" name="code">@tempo.start</pre>
<p>Note that if you are syncing to external clock, nothing will happen until Topaz receives a start or clock message</p>
<h5>
Other stuff to note...</h5>
<p>Whether or not you're using an internal or external clock source, the event block will be called at quarter note intervals by default. If you wish to change this, set the option :interval. In this case, 16th notes will occur at 138 beats per minute where one beat equals one quarter note</p>
<pre class="ruby:nocontrols:nogutter" name="code">@tempo = Topaz::Tempo.new(138, :interval => 16) { sequencer.step! }</pre>
<p>View the current tempo, which is calculated by Topaz if you're syncing to an external source.<br />
(this feature is in progress. you might receive some unreliable values - 5/26/2011)</p>
<pre class="ruby:nocontrols:nogutter" name="code">@tempo.tempo
=> 132.422000</pre>
<p>Run the generator in a background thread by passing :background => true to Tempo#start</p>
<pre class="ruby:nocontrols:nogutter" name="code">@tempo.start(:background => true)
@tempo.join # join later if you want</pre>
<p>Pass a block in that will stop the clock when it evaluates to true</p>
<pre class="ruby:nocontrols:nogutter" name="code">@tempo.stop_when { @i.eql?(20) }</pre>
<p><a href="http://github.com/arirusso/topaz">http://github.com/arirusso/topaz</a><br /></p>
<div class="separator" style="clear: both; text-align: left;">
<a href="http://github.com/arirusso/topaz" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggIXBFlBvof9POhBnbWqGVUtq5hP10fDOB3GGBlVediFKAC9jxrxQ68fs-iEarrdU0zsbfQ0gnziL8hsfb5gZd_BToWugp1Cvgqanu3wmZY6n0zCMTlKha5QQCamg1wOWG1KRjLzbqFDE/s320/topaz-car.jpg" width="320" /></a></div>
Ari Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com0Brooklyn, NY, USA40.65 -73.94999999999998940.555797999999996 -74.061632499999988 40.744202 -73.83836749999999tag:blogger.com,1999:blog-7653279959382022680.post-45436022908061192542011-05-25T14:20:00.000-04:002011-05-27T01:41:24.059-04:00blogginsHELLO<br />
<br />
I'm working on some music programming/performance tools that I'm going to post here<br />
<br />
My github page has the progress so far<br />
<br />
<a href="https://github.com/arirusso">http://github.com/arirusso</a><br />
<br />
I'll be going back and writing about those projects as well as the new stuff as it's readyAri Russohttp://www.blogger.com/profile/14065444496421087839noreply@blogger.com0