Experiments with ruby-processing (processing-2.2.1) and JRubyArt for processing-3.0

Sunday, 8 February 2015

MDArray gem is available to JRubyArt (handy for image processing)

Sketch makes use of MDArray convenience index function. Requires to be run as "k9 run sobel.rb" to get image stuff to work, but interestingly mdarray gem also just loads...(cf ruby-processing)
require 'jruby_art'
require 'mdarray'

class Strobel < Processing::App
  attr_reader :img, :edge

  def setup
    size 300, 225
    @img = load_image('engine.png')
    @edge = create_image(300, 225, ALPHA)
    edge.load_pixels
    img.load_pixels
    generate(img)
  end

  def draw
    image edge, 0, 0
    filter(GRAY)
  end

  def generate(from_image)
    sbx = MDArray.int([3, 3], [-1, 0, 1, -2, 0, 2, -1, 0, 1])
    sby = MDArray.int([3, 3], [1, 2, 1, 0, 0, 0, -1, -2, -1])
    edg = MDArray.int([225, 300])  # this seems Irish, but is correct
    pxls = from_image.pixels
    (1...from_image.width - 2).each do |x|
      (1...from_image.height - 2).each do |y|
        pixel_x = (sbx[0, 0] * pxls[x - 1 + width * (y - 1)]) + (sbx[0, 1] * pxls[x + width * (y - 1)]) + (sbx[0, 2] * pxls[x + 1+ width * (y - 1)]) +
          (sbx[1, 0] * pxls[x - 1+ width * y])   + (sbx[1, 1] * pxls[x + width * y])   + (sbx[1, 2] * pxls[x + 1+ width * y]) +
          (sbx[2, 0] * pxls[x - 1+ width * y + 1]) + (sbx[2, 1] * pxls[x + width * y + 1]) + (sbx[2, 2] * pxls[x + 1 + width * (y + 1)])
        pixel_y = (sby[0, 0] * pxls[x - 1+ width * (y - 1)]) + (sby[0, 1] * pxls[x + width * (y - 1)]) + (sby[0, 2] * pxls[x + 1+ width * (y - 1)]) +
          (sby[1, 0] * pxls[x - 1+ width * y])   + (sby[1, 1] * pxls[x + width * y])   + (sby[1, 2] * pxls[x + 1+ width * y]) +
          (sby[2, 0] * pxls[x - 1+ width * (y + 1)]) + (sby[2, 1] * pxls[x + width * (y + 1)]) + (sby[2, 2] * pxls[x + 1+ width * (y + 1)])
        val = Math.hypot(pixel_x, pixel_y).ceil
        edg[y, x] = val
      end
    end
    edge.pixels = edg.to_a # load pixels from MDArray
  end

  def mouse_pressed
    save('engine_edge.png')
  end
end

Strobel.new(title: 'Sobel Edge Detect')
before
edge detected

Saturday, 31 January 2015

Installing netbeans ruby-plugin and jruby_art gem

Please note for installation of gems, and some other operations netbeans can be a bit slow:- Download and unzip the plugin yields ~/arch/build/updates/*.* note location, which you will need to navigate to when installing "downloaded" plugins (from netbeans menu). Select all the *.nbm modules and the jruby.jar. And install see below:-























Then install the downloaded gem as install local (local install required to load --pre gem) and you are good to go a real ide to develop jruby_art who needs a processing mode?


























See crude Templates here
To install templates navigate to .netbeans/config/Templates (create a Templates folder if it does not exist) create a sub folder 'Ruby' put the outer .nbattrs file here, create a folder jruby_art and place the other .nbattrs file there along with both ruby sketch files. Templates should now show up in a Ruby sub-folder.

Friday, 30 January 2015

JRubyArt vs ruby-processing


IMPORTANT THIS DOCUMENT IS OUTDATED BUT BY NOW YOU SHOULD ALREADY BE USING JRubyArt or propane

External Dependencies

  • ruby-processing requires an installed version of vanilla-processing
  • jruby_art includes processings core jars in gem

Runnable from netbeans

  • ruby-processing sketches would need a Rakefile or some other script to run 
  • jruby_art sketches mainly just run (except for bare-sketches), opens possibility of incredibly simple/minimal installation from netbeans (no need for MRI ruby or an installed jruby, might suit windows users)

Core processing libraries (sound, video etc)

  • ruby-processing has builtin support 
  • jruby_art now has built in support (but path to libraries is configurable), can also be modular via gem see pbox2d as exemplar

Contributed processing libraries

  • ruby-processing has builtin support for libraries installed by processing ide 
  • jruby_art does not assume that vanilla processing is installed. Wrapping libraries in separate gem would be ideal see pbox2d and toxicgem

Vec2D, Vec3D, Arcball and DEGLUT

  • ruby-processing requires load_library 
  • jruby_art automatically loaded into jruby runtime

Processing::Proxy module

  • in ruby-processing Proxy can be used to mimic processings inner classes, probably v. bad juju convenience isn't everything 
  • in jruby_art a different Proxy is used to access some processing methods eg "pre", "post", "draw" via reflection

Thursday, 29 January 2015

Netbeans, the perfect ide for jruby_art

The perfect ide for jruby_art is netbeans, because all sketches just run (since the netbeans ruby plugin is using a built in jruby-complete) with the jruby command see below (actually bare sketches need k9 command). It is probably easier at this point to download jruby_art-0.2.0.pre.gem and do a local install. Thus it is quite possible to develop jruby_art without a jruby/ruby install, just using the jruby provided by the jruby netbeans plugin (this might actually make sense on windows). However you won't get the examples so make sure you get them here.

Monday, 26 January 2015

Cranky keyboard (unless you are a northern European) sound library example

# This example shows how to make a simple sampler and sequencer with the Sound
# library. In this sketch 5 different short samples are loaded and played back
# at different pitches, in this when 5 different octaves. The sequencer
# triggers and event every 200-1000 mSecs randomly. Each time a sound is
# played a colored rect with a random color is displayed.
load_library :sound

include_package 'processing.sound'

# Define the number of samples
NUM_SOUNDS = 5
attr_reader :device, :file, :value

def setup
  size(640, 360)
  background(255)
  # Create a Sound renderer and an array of empty soundfiles
  @device = AudioDevice.new(self, 48_000, 32)
  @file = []
  @value = Array.new(3, 0)
  # Load 5 soundfiles from a folder in a for loop. By naming the files 1., 2.,
  # 3., n.aif it is easy to iterate through the folder and load all files in
  # one line of code.
  NUM_SOUNDS.times do |i|
    file << SoundFile.new(self, format('%d.aif', (i + 1)))
  end
end

def draw
  background(*value) # splat array values
end

def key_pressed
  defined = true
  case key
  when 'a'
    file[0].play(0.5, 1.0)
  when 's'
    file[1].play(0.5, 1.0)
  when 'd'
    file[2].play(0.5, 1.0)
  when 'f'
    file[3].play(0.5, 1.0)
  when 'g'
    file[4].play(0.5, 1.0)
  when 'h'
    file[0].play(1.0, 1.0)
  when 'j'
    file[1].play(1.0, 1.0)
  when 'k'
    file[2].play(1.0, 1.0)
  when 'l'
    file[3].play(1.0, 1.0)
  when 'ö'
    file[4].play(1.0, 1.0)
  when 'ä'
    file[0].play(2.0, 1.0)
  when 'q'
    file[1].play(2.0, 1.0)
  when 'w'
    file[2].play(2.0, 1.0)
  when 'e'
    file[3].play(2.0, 1.0)
  when 'r'
    file[4].play(2.0, 1.0)
  when 't'
    file[0].play(3.0, 1.0)
  when 'z'
    file[1].play(3.0, 1.0)
  when 'u'
    file[2].play(3.0, 1.0)
  when 'i'
    file[3].play(3.0, 1.0)
  when 'o'
    file[4].play(3.0, 1.0)
  when 'p'
    file[0].play(4.0, 1.0)
  when 'ü'
    file[1].play(4.0, 1.0)
  else
    defined = false # only set background color value, if key is defined
  end
  @value = [rand(0..255), rand(0..255), rand(0..255)] if defined
end

Sunday, 25 January 2015

Another sound library example translated to ruby-processing


The original sketch was a blank-screen here is lame attempt to make it a bit more interesting, note use of ruby-processings map1d convenience method in favour of vanilla processings map convenience method (map is used for a different function in ruby, and python and a host of other languages for that matter). This one of those sketches that needs to use jruby-complete (some permission thing according to headius).
#
# This is a sound file player.
# NB: requires jruby-complete to run
# either --nojruby flag or use config
#

load_library :sound
include_package 'processing.sound'

attr_reader :sound_file

def setup
  size 640, 360
  background 255
  no_stroke
  # Load a soundfile
  @sound_file = SoundFile.new(self, 'vibraphon.aiff')
  report_settings
  # Play the file in a loop
  sound_file.loop
end

def draw
  red = map1d(mouse_x, (0..width), (30..255))
  green = map1d(mouse_y, (height..0), (30..255))
  fill(red, green, 0, 100)
  ellipse(mouse_x, mouse_y, 10, 10)
  manipulate_sound
end

def manipulate_sound
  # Map mouse_x from 0.25 to 4.0 for playback rate. 1 equals original playback
  # speed 2 is an octave up 0.5 is an octave down.
  sound_file.rate(map1d(mouse_x, (0..width), (0.25..4.0)))
  # Map mouse_y from 0.2 to 1.0 for amplitude
  sound_file.amp(map1d(mouse_y, (0..width), (0.2..1.0)))
  # Map mouse_y from -1.0 to 1.0 for left to right
  sound_file.pan(map1d(mouse_y, (0..height), (-1.0..1.0)))
end

def report_settings
  # These methods return useful infos about the file
  p format('SFSampleRate= %d Hz', sound_file.sample_rate)
  p format('SFSamples= %d samples', sound_file.frames)
  p format('SFDuration= %d seconds', sound_file.duration)
end

Testing the new processing sound library in ruby-processing

There is a new processing sound library for processing-3.0 (that also works with processing-2.0), I thought I would give it a run-out in ruby-processing:-
# This example shows how to create a cluster of sine oscillators, change the
# frequency and detune them depending on the position of the mouse in the
# renderer window. The Y position determines the basic frequency of the
# oscillator and X the detuning of the oscillator. The basic frequncy ranges
# between 150 and 1150 Hz

load_library :sound

include_package 'processing.sound'

# The number of oscillators
NUM_SINES = 5

# A for calculating the amplitudes
attr_reader :sine_volume, :sine_waves

def setup
  size 500, 500
  background 255
  no_stroke
  create_oscillators
end

def create_oscillators
  # Create the oscillators and amplitudes
  @sine_waves = []
  @sine_volume = []
  NUM_SINES.times do |i|
    # The overall amplitude shouldn't exceed 1.0
    # The ascending waves will get lower in volume the higher the frequency
    sine_volume << (1.0 / NUM_SINES) / (i + 1)
    # Create the Sine Oscillators and start them
    wav = SinOsc.new(self)
    wav.play
    sine_waves << wav
  end
end

def draw
  fill mouse_x, mouse_y, 0, 100
  ellipse(mouse_x, mouse_y, 10, 10)
  # Use mouse_y to get values from 0.0 to 1.0
  yoffset = (height - mouse_y) / height.to_f
  # Set that value logarithmically to 150 - 1150 Hz
  frequency = 1000**yoffset + 150
  # Use mouse_x from -0.5 to 0.5 to get a multiplier for detuning the
  # oscillators
  detune = mouse_x.to_f / width - 0.5
  # Set the frequencies, detuning and volume
  sine_waves.each_with_index do |wav, i|
    wav.freq(frequency * (i + 1 + i * detune))
    wav.amp(sine_volume[i])
  end
end

Followers

About Me

My photo
I have developed JRubyArt and propane new versions of ruby-processing for JRuby-9.1.5.0 and processing-3.2.2