Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MRuby within VST

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

MRuby within VST

Avatar for Michał Kalbarczyk

Michał Kalbarczyk

April 08, 2015
Tweet

More Decks by Michał Kalbarczyk

Other Decks in Programming

Transcript

  1. .is_a? • minimalistic / embedable • ISO/IEC 30170 • developed

    by Matz • funded by the Japanese ministry of Economy
  2. $ time mruby fib.rb 63245986 real 2m53.117s user 2m52.396s sys

    0m0.122s $ time ruby fib.rb 63245986 real 1m22.941s user 1m20.038s sys 0m0.751s .performance
  3. • ~ 30 • before build • github MRuby::Build.new do

    |conf| conf.gem :github => 'iij/mruby-pack' conf.gem :github => 'iij/mruby-io' conf.gem :github => 'iij/mruby-dir' conf.gem :github => 'iij/mruby-socket' conf.gem :github => 'mattn/mruby-http' end .mrbgems
  4. # with brew $ brew install mruby # with ruby-build

    (rbenv) $ ruby-build mruby-1.1.0 # with ruby-install $ ruby-install mruby # build yourself $ git clone [email protected]:mruby/mruby.git $ cd mruby $ rake .install
  5. #include <stdlib.h> #include <stdio.h> /* Include the mruby header */

    #include <mruby.h> #include <mruby/compile.h> int main(void) { mrb_state *mrb = mrb_open(); char code[] = "p 'hello world!'"; printf("Executing Ruby code with mruby!\n"); mrb_load_string(mrb, code); return 0; } .embed
  6. # execute file $ mruby hello_world.rb # REPL $ mirb

    # execute string $ mruby -e '3.times { puts "hello" }' # compile to bytecode $ mrbc hello_world.rb # compile to C $ mrbc -Bhello hello_world.rb .run
  7. alert = Cocoa::MyAlertView._alloc._initWithTitle "Hello", :message, "I am MobiRuby", :delegate, nil,

    :cancelButtonTitle, "I know!", :otherButtonTitles, "What's?", nil alert._setDelegate alert alert._show .mobiruby
  8. # location /proxy { # mruby_set $backend "/path/to/proxy.rb"; # proxy_pass

    http://$backend; # } backends = [ "test1", "test2", "test3", ] r = Redis.new "192.168.12.251", 6379 r.get backends[rand(backends.length)] .ngx_mruby
  9. # Apache httpd.conf # mrubyTranslateNameMiddle "/path/to/proxy.rb" # backends = [

    "http://192.168.0.101:8888/", "http://192.168.0.102:8888/", "http://192.168.0.103:8888/", "http://192.168.0.104:8888/", ] # write balancing algorithm here. r = Apache::Request.new() r.handler = "proxy-server" r.proxyreq = Apache::PROXYREQ_REVERSE r.filename = "proxy:" + backends[rand(backends.length)] + r.uri Apache::return(Apache::OK) .mod_mruby
  10. # trusterd.conf.rb SERVER_NAME = "Trusterd" SERVER_VERSION = "0.0.1" SERVER_DESCRIPTION =

    "#{SERVER_NAME}/#{SERVER_VERSION}" root_dir = "/usr/local/trusterd" s = HTTP2::Server.new({ :port => 8081, :document_root => "#{root_dir}/htdocs", :server_name => SERVER_DESCRIPTION, :tls => false, }) s.run .trusterd
  11. ?

  12. What we need ? class MRubyVst : public AudioEffectX {

    public: MRubyVst(audioMasterCallback audioMaster); ~MRubyVst(); // Informations virtual bool getEffectName(char* name); virtual bool getVendorString(char* text); virtual bool getProductString(char* text); virtual VstInt32 getVendorVersion(); // Parameters virtual void setParameter(VstInt32 index, float value); virtual float getParameter(VstInt32 index); virtual void getParameterLabel(VstInt32 index, char* label); virtual void getParameterDisplay(VstInt32 index, char* text); virtual void getParameterName(VstInt32 index, char* text); // Processing virtual void processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames); // Program virtual void setProgram(VstInt32 index); virtual bool getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text); protected: mrb_state *mrb; mrb_value vst_instance; };
  13. What we need ? class MRubyVst : public AudioEffectX {

    public: MRubyVst(audioMasterCallback audioMaster); ~MRubyVst(); // Informations virtual bool getEffectName(char* name); virtual bool getVendorString(char* text); virtual bool getProductString(char* text); virtual VstInt32 getVendorVersion(); // Parameters virtual void setParameter(VstInt32 index, float value); virtual float getParameter(VstInt32 index); virtual void getParameterLabel(VstInt32 index, char* label); virtual void getParameterDisplay(VstInt32 index, char* text); virtual void getParameterName(VstInt32 index, char* text); // Processing virtual void processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames); // Program virtual void setProgram(VstInt32 index); virtual bool getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text); protected: mrb_state *mrb; mrb_value vst_instance; };
  14. What we need ? class MRubyVst : public AudioEffectX {

    public: MRubyVst(audioMasterCallback audioMaster); ~MRubyVst(); // Informations virtual bool getEffectName(char* name); virtual bool getVendorString(char* text); virtual bool getProductString(char* text); virtual VstInt32 getVendorVersion(); // Parameters virtual void setParameter(VstInt32 index, float value); virtual float getParameter(VstInt32 index); virtual void getParameterLabel(VstInt32 index, char* label); virtual void getParameterDisplay(VstInt32 index, char* text); virtual void getParameterName(VstInt32 index, char* text); // Processing virtual void processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames); // Program virtual void setProgram(VstInt32 index); virtual bool getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text); protected: mrb_state *mrb; mrb_value vst_instance; };
  15. What we need ? class MRubyVst : public AudioEffectX {

    public: MRubyVst(audioMasterCallback audioMaster); ~MRubyVst(); // Informations virtual bool getEffectName(char* name); virtual bool getVendorString(char* text); virtual bool getProductString(char* text); virtual VstInt32 getVendorVersion(); // Parameters virtual void setParameter(VstInt32 index, float value); virtual float getParameter(VstInt32 index); virtual void getParameterLabel(VstInt32 index, char* label); virtual void getParameterDisplay(VstInt32 index, char* text); virtual void getParameterName(VstInt32 index, char* text); // Processing virtual void processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames); // Program virtual void setProgram(VstInt32 index); virtual bool getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text); protected: mrb_state *mrb; mrb_value vst_instance; };
  16. What we need ? class MRubyVst : public AudioEffectX {

    public: MRubyVst(audioMasterCallback audioMaster); ~MRubyVst(); // Informations virtual bool getEffectName(char* name); virtual bool getVendorString(char* text); virtual bool getProductString(char* text); virtual VstInt32 getVendorVersion(); // Parameters virtual void setParameter(VstInt32 index, float value); virtual float getParameter(VstInt32 index); virtual void getParameterLabel(VstInt32 index, char* label); virtual void getParameterDisplay(VstInt32 index, char* text); virtual void getParameterName(VstInt32 index, char* text); // Processing virtual void processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames); // Program virtual void setProgram(VstInt32 index); virtual bool getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text); protected: mrb_state *mrb; mrb_value vst_instance; };
  17. What we need ? class MRubyVst : public AudioEffectX {

    public: MRubyVst(audioMasterCallback audioMaster); ~MRubyVst(); // Informations virtual bool getEffectName(char* name); virtual bool getVendorString(char* text); virtual bool getProductString(char* text); virtual VstInt32 getVendorVersion(); // Parameters virtual void setParameter(VstInt32 index, float value); virtual float getParameter(VstInt32 index); virtual void getParameterLabel(VstInt32 index, char* label); virtual void getParameterDisplay(VstInt32 index, char* text); virtual void getParameterName(VstInt32 index, char* text); // Processing virtual void processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames); // Program virtual void setProgram(VstInt32 index); virtual bool getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text); protected: mrb_state *mrb; mrb_value vst_instance; };
  18. // mrubyvst.cpp MRubyVst::MRubyVst(audioMasterCallback audioMaster): AudioEffectX(audioMaster, 10, 4) { setUniqueID('mrbv'); canProcessReplacing();

    setNumInputs(2); setNumOutputs(2); mrb = mrb_open(); FILE *file = fopen(".../mrubyvst.rb", "r"); if (file != NULL) { mrb_load_file(mrb, file); mrb_value vst_class = mrb_vm_const_get(mrb, mrb_intern_lit(mrb, "MRubyVST")); vst_instance = mrb_instance_new(mrb, vst_class); fclose(file); } } MRubyVst::~MRubyVst() { mrb_close(mrb); } Initialize VST
  19. settin’ stuff // mrubyvst.cpp MRubyVst::MRubyVst(audioMasterCallback audioMaster): AudioEffectX(audioMaster, 10, 4) {

    setUniqueID('mrbv'); canProcessReplacing(); setNumInputs(2); setNumOutputs(2); mrb = mrb_open(); FILE *file = fopen(".../mrubyvst.rb", "r"); if (file != NULL) { mrb_load_file(mrb, file); mrb_value vst_class = mrb_vm_const_get(mrb, mrb_intern_lit(mrb, "MRubyVST")); vst_instance = mrb_instance_new(mrb, vst_class); fclose(file); } } MRubyVst::~MRubyVst() { mrb_close(mrb); }
  20. initalize MRuby // mrubyvst.cpp MRubyVst::MRubyVst(audioMasterCallback audioMaster): AudioEffectX(audioMaster, 10, 4) {

    setUniqueID('mrbv'); canProcessReplacing(); setNumInputs(2); setNumOutputs(2); mrb = mrb_open(); FILE *file = fopen(".../mrubyvst.rb", "r"); if (file != NULL) { mrb_load_file(mrb, file); mrb_value vst_class = mrb_vm_const_get(mrb, mrb_intern_lit(mrb, "MRubyVST")); vst_instance = mrb_instance_new(mrb, vst_class); fclose(file); } } MRubyVst::~MRubyVst() { mrb_close(mrb); }
  21. open rb file // mrubyvst.cpp MRubyVst::MRubyVst(audioMasterCallback audioMaster): AudioEffectX(audioMaster, 10, 4)

    { setUniqueID('mrbv'); canProcessReplacing(); setNumInputs(2); setNumOutputs(2); mrb = mrb_open(); FILE *file = fopen(".../mrubyvst.rb", "r"); if (file != NULL) { mrb_load_file(mrb, file); mrb_value vst_class = mrb_vm_const_get(mrb, mrb_intern_lit(mrb, "MRubyVST")); vst_instance = mrb_instance_new(mrb, vst_class); fclose(file); } } MRubyVst::~MRubyVst() { mrb_close(mrb); }
  22. load into VM // mrubyvst.cpp MRubyVst::MRubyVst(audioMasterCallback audioMaster): AudioEffectX(audioMaster, 10, 4)

    { setUniqueID('mrbv'); canProcessReplacing(); setNumInputs(2); setNumOutputs(2); mrb = mrb_open(); FILE *file = fopen(".../mrubyvst.rb", "r"); if (file != NULL) { mrb_load_file(mrb, file); mrb_value vst_class = mrb_vm_const_get(mrb, mrb_intern_lit(mrb, "MRubyVST")); vst_instance = mrb_instance_new(mrb, vst_class); fclose(file); } } MRubyVst::~MRubyVst() { mrb_close(mrb); }
  23. get MRubyVST const // mrubyvst.cpp MRubyVst::MRubyVst(audioMasterCallback audioMaster): AudioEffectX(audioMaster, 10, 4)

    { setUniqueID('mrbv'); canProcessReplacing(); setNumInputs(2); setNumOutputs(2); mrb = mrb_open(); FILE *file = fopen(".../mrubyvst.rb", "r"); if (file != NULL) { mrb_load_file(mrb, file); mrb_value vst_class = mrb_vm_const_get(mrb, mrb_intern_lit(mrb, "MRubyVST")); vst_instance = mrb_instance_new(mrb, vst_class); fclose(file); } } MRubyVst::~MRubyVst() { mrb_close(mrb); }
  24. new MRubyVST instance // mrubyvst.cpp MRubyVst::MRubyVst(audioMasterCallback audioMaster): AudioEffectX(audioMaster, 10, 4)

    { setUniqueID('mrbv'); canProcessReplacing(); setNumInputs(2); setNumOutputs(2); mrb = mrb_open(); FILE *file = fopen(".../mrubyvst.rb", "r"); if (file != NULL) { mrb_load_file(mrb, file); mrb_value vst_class = mrb_vm_const_get(mrb, mrb_intern_lit(mrb, "MRubyVST")); vst_instance = mrb_instance_new(mrb, vst_class); fclose(file); } } MRubyVst::~MRubyVst() { mrb_close(mrb); }
  25. close MRuby VM // mrubyvst.cpp MRubyVst::MRubyVst(audioMasterCallback audioMaster): AudioEffectX(audioMaster, 10, 4)

    { setUniqueID('mrbv'); canProcessReplacing(); setNumInputs(2); setNumOutputs(2); mrb = mrb_open(); FILE *file = fopen(".../mrubyvst.rb", "r"); if (file != NULL) { mrb_load_file(mrb, file); mrb_value vst_class = mrb_vm_const_get(mrb, mrb_intern_lit(mrb, "MRubyVST")); vst_instance = mrb_instance_new(mrb, vst_class); fclose(file); } } MRubyVst::~MRubyVst() { mrb_close(mrb); }
  26. # mrubyvst.rb class MRubyVST attr_reader :vendor, :product, :effect_name def initialize

    @vendor = 'Mruby' @product = 'MrubyVST' @effect_name = 'MRubyEffects' end end MRubyVST getters
  27. // mrubyvst.cpp bool MRubyVst::getEffectName(char* name) { if(mrb_respond_to(mrb, vst_instance,cmrb_intern_lit(mrb, "effect_name"))){ mrb_value

    mrb_name = mrb_funcall(mrb, vst_instance, "effect_name", 0); if (!mrb_nil_p(mrb_name)) { vst_strncpy(name, RSTRING_PTR(mrb_name), kVstMaxEffectNameLen); return true; } } return false; } bool MRubyVst::getProductString(char* text) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "product"))){ mrb_value mrb_product = mrb_funcall(mrb, vst_instance, "product", 0); if (!mrb_nil_p(mrb_product)) { vst_strncpy(text, RSTRING_PTR(mrb_product), kVstMaxProductStrLen); return true; } } return false; } bool MRubyVst::getVendorString(char* text) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "vendor"))){ mrb_value mrb_vendor = mrb_funcall(mrb, vst_instance, "vendor", 0); if (!mrb_nil_p(mrb_vendor)) { vst_strncpy(text, RSTRING_PTR(mrb_vendor), kVstMaxVendorStrLen); return true; } } return false; } implement getters
  28. // mrubyvst.cpp bool MRubyVst::getEffectName(char* name) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "effect_name"))){

    mrb_value mrb_name = mrb_funcall(mrb, vst_instance, "effect_name", 0); if (!mrb_nil_p(mrb_name)) { vst_strncpy(name, RSTRING_PTR(mrb_name), kVstMaxEffectNameLen); return true; } } return false; } respond_to?
  29. effect_name() // mrubyvst.cpp bool MRubyVst::getEffectName(char* name) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb,

    "effect_name"))){ mrb_value mrb_name = mrb_funcall(mrb, vst_instance, "effect_name", 0); if (!mrb_nil_p(mrb_name)) { vst_strncpy(name, RSTRING_PTR(mrb_name), kVstMaxEffectNameLen); return true; } } return false; }
  30. nil? // mrubyvst.cpp bool MRubyVst::getEffectName(char* name) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb,

    "effect_name"))){ mrb_value mrb_name = mrb_funcall(mrb, vst_instance, "effect_name", 0); if (!mrb_nil_p(mrb_name)) { vst_strncpy(name, RSTRING_PTR(mrb_name), kVstMaxEffectNameLen); return true; } } return false; }
  31. to_str // mrubyvst.cpp bool MRubyVst::getEffectName(char* name) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb,

    "effect_name"))){ mrb_value mrb_name = mrb_funcall(mrb, vst_instance, "effect_name", 0); if (!mrb_nil_p(mrb_name)) { vst_strncpy(name, RSTRING_PTR(mrb_name), kVstMaxEffectNameLen); return true; } } return false; }
  32. # mrubyvst.rb class MRubyVST def initialize @parameter = 0.0 end

    def set_parameter(index, value) @parameter = value end def parameter_value(index) @parameter end end handle parameters
  33. // mrubyvst.cpp void MRubyVst::setParameter(VstInt32 index, float value) { if(mrb_respond_to(mrb, vst_instance,

    mrb_intern_lit(mrb, "set_parameter"))){ mrb_funcall(mrb, vst_instance, "set_parameter", 2, mrb_fixnum_value(index), mrb_float_value(mrb, value)); } } float MRubyVst::getParameter(VstInt32 index) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "parameter_value"))){ mrb_value mrb_param_value = mrb_funcall(mrb, vst_instance, "parameter_value", 1, mrb_fixnum_value(index)); if (!mrb_nil_p(mrb_param_value)) { return mrb_float(mrb_param_value); } } return 0; } handle parameters
  34. // mrubyvst.cpp void MRubyVst::setParameter(VstInt32 index, float value) { if(mrb_respond_to(mrb, vst_instance,

    mrb_intern_lit(mrb, "set_parameter"))){ mrb_funcall(mrb, vst_instance, "set_parameter", 2, mrb_fixnum_value(index), mrb_float_value(mrb, value)); } } set_parameter
  35. respond_to? // mrubyvst.cpp void MRubyVst::setParameter(VstInt32 index, float value) { if(mrb_respond_to(mrb,

    vst_instance, mrb_intern_lit(mrb, "set_parameter"))){ mrb_funcall(mrb, vst_instance, "set_parameter", 2, mrb_fixnum_value(index), mrb_float_value(mrb, value)); } }
  36. set_parameter() // mrubyvst.cpp void MRubyVst::setParameter(VstInt32 index, float value) { if(mrb_respond_to(mrb,

    vst_instance, mrb_intern_lit(mrb, "set_parameter"))){ mrb_funcall(mrb, vst_instance, "set_parameter", 2, mrb_fixnum_value(index), mrb_float_value(mrb, value)); } }
  37. // mrubyvst.cpp float MRubyVst::getParameter(VstInt32 index) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "parameter_value"))){

    mrb_value mrb_param_value = mrb_funcall(mrb, vst_instance, “parameter_value", 1, mrb_fixnum_value(index)); if (!mrb_nil_p(mrb_param_value)) { return mrb_float(mrb_param_value); } } return 0; } parameter_value
  38. respond_to? // mrubyvst.cpp float MRubyVst::getParameter(VstInt32 index) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb,

    "parameter_value"))){ mrb_value mrb_param_value = mrb_funcall(mrb, vst_instance, “parameter_value", 1, mrb_fixnum_value(index)); if (!mrb_nil_p(mrb_param_value)) { return mrb_float(mrb_param_value); } } return 0; }
  39. parameter_value() // mrubyvst.cpp float MRubyVst::getParameter(VstInt32 index) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb,

    "parameter_value"))){ mrb_value mrb_param_value = mrb_funcall(mrb, vst_instance, “parameter_value", 1, mrb_fixnum_value(index)); if (!mrb_nil_p(mrb_param_value)) { return mrb_float(mrb_param_value); } } return 0; }
  40. nil? // mrubyvst.cpp float MRubyVst::getParameter(VstInt32 index) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb,

    "parameter_value"))){ mrb_value mrb_param_value = mrb_funcall(mrb, vst_instance, “parameter_value", 1, mrb_fixnum_value(index)); if (!mrb_nil_p(mrb_param_value)) { return mrb_float(mrb_param_value); } } return 0; }
  41. to_f // mrubyvst.cpp float MRubyVst::getParameter(VstInt32 index) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb,

    "parameter_value"))){ mrb_value mrb_param_value = mrb_funcall(mrb, vst_instance, “parameter_value", 1, mrb_fixnum_value(index)); if (!mrb_nil_p(mrb_param_value)) { return mrb_float(mrb_param_value); } } return 0; }
  42. # mrubyvst.rb class MRubyVST (...) def parameter_name(index) "Gain" end def

    parameter_display_value(index) @parameter.to_s end def parameter_label(index) "dB" end end handle parameters
  43. // mrubyvst.cpp void MRubyVst::getParameterName(VstInt32 index, char* label) { if(mrb_respond_to(mrb, vst_instance,

    mrb_intern_lit(mrb, "parameter_name"))){ mrb_value mrb_label = mrb_funcall(mrb, vst_instance, "parameter_name", 1, mrb_fixnum_value(index)); if (!mrb_nil_p(mrb_label)) { vst_strncpy(label, RSTRING_PTR(mrb_label), kVstMaxParamStrLen); } } } void MRubyVst::getParameterDisplay(VstInt32 index, char* text) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "parameter_display_value"))){ mrb_value mrb_display = mrb_funcall(mrb, vst_instance, "parameter_display_value", 1, mrb_fixnum_value(index)); if (!mrb_nil_p(mrb_display)) { vst_strncpy(text, RSTRING_PTR(mrb_display), kVstMaxParamStrLen); } } } void MRubyVst::getParameterLabel(VstInt32 index, char* label) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "parameter_label"))){ mrb_value mrb_label = mrb_funcall(mrb, vst_instance, "parameter_label", 1, mrb_fixnum_value(index)); if (!mrb_nil_p(mrb_label)) { vst_strncpy(label, RSTRING_PTR(mrb_label), kVstMaxParamStrLen); } } } handle parameters
  44. # mrubyvst.rb class MRubyVST (...) def process(data) data[0].map!{ |left |

    left * @parameter } data[1].map!{ |right| right * @parameter } data end end process audio data
  45. // mrubyvst.cpp void MRubyVst::processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames) {

    if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "process"))){ float* in1 = inputs[0]; float* in2 = inputs[1]; float* out1 = outputs[0]; float* out2 = outputs[1]; mrb_value mrb_input_1 = mrb_ary_new(mrb); mrb_value mrb_input_2 = mrb_ary_new(mrb); for (int i=0;i<sampleFrames;i++) { mrb_ary_push(mrb, mrb_input_1, mrb_float_value(mrb, (*in1++))); mrb_ary_push(mrb, mrb_input_2, mrb_float_value(mrb, (*in2++))); } mrb_value mrb_inputs = mrb_ary_new(mrb); mrb_ary_push(mrb, mrb_inputs, mrb_input_1); mrb_ary_push(mrb, mrb_inputs, mrb_input_2); mrb_value mrb_outputs = mrb_funcall(mrb, vst_instance, "process", 1, mrb_inputs); if (!mrb_nil_p(mrb_outputs)) { mrb_value mrb_output_1 = mrb_ary_shift(mrb, mrb_outputs); mrb_value mrb_output_2 = mrb_ary_shift(mrb, mrb_outputs); for (int i=0;i<sampleFrames;i++) { (*out1++) = mrb_float(mrb_ary_shift(mrb, mrb_output_1)); (*out2++) = mrb_float(mrb_ary_shift(mrb, mrb_output_2)); } } } } process audio data
  46. // mrubyvst.cpp void MRubyVst::processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames) {

    if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "process"))){ float* in1 = inputs[0]; float* in2 = inputs[1]; float* out1 = outputs[0]; float* out2 = outputs[1]; mrb_value mrb_input_1 = mrb_ary_new(mrb); mrb_value mrb_input_2 = mrb_ary_new(mrb); for (int i=0;i<sampleFrames;i++) { mrb_ary_push(mrb, mrb_input_1, mrb_float_value(mrb, (*in1++))); mrb_ary_push(mrb, mrb_input_2, mrb_float_value(mrb, (*in2++))); } mrb_value mrb_inputs = mrb_ary_new(mrb); mrb_ary_push(mrb, mrb_inputs, mrb_input_1); mrb_ary_push(mrb, mrb_inputs, mrb_input_2); from C to Ruby
  47. to_ary // mrubyvst.cpp void MRubyVst::processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames)

    { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "process"))){ float* in1 = inputs[0]; float* in2 = inputs[1]; float* out1 = outputs[0]; float* out2 = outputs[1]; mrb_value mrb_input_1 = mrb_ary_new(mrb); mrb_value mrb_input_2 = mrb_ary_new(mrb); for (int i=0;i<sampleFrames;i++) { mrb_ary_push(mrb, mrb_input_1, mrb_float_value(mrb, (*in1++))); mrb_ary_push(mrb, mrb_input_2, mrb_float_value(mrb, (*in2++))); } mrb_value mrb_inputs = mrb_ary_new(mrb); mrb_ary_push(mrb, mrb_inputs, mrb_input_1); mrb_ary_push(mrb, mrb_inputs, mrb_input_2);
  48. to_ary // mrubyvst.cpp void MRubyVst::processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames)

    { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "process"))){ float* in1 = inputs[0]; float* in2 = inputs[1]; float* out1 = outputs[0]; float* out2 = outputs[1]; mrb_value mrb_input_1 = mrb_ary_new(mrb); mrb_value mrb_input_2 = mrb_ary_new(mrb); for (int i=0;i<sampleFrames;i++) { mrb_ary_push(mrb, mrb_input_1, mrb_float_value(mrb, (*in1++))); mrb_ary_push(mrb, mrb_input_2, mrb_float_value(mrb, (*in2++))); } mrb_value mrb_inputs = mrb_ary_new(mrb); mrb_ary_push(mrb, mrb_inputs, mrb_input_1); mrb_ary_push(mrb, mrb_inputs, mrb_input_2);
  49. array of arrays // mrubyvst.cpp void MRubyVst::processReplacing(float** inputs, float** outputs,

    VstInt32 sampleFrames) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "process"))){ float* in1 = inputs[0]; float* in2 = inputs[1]; float* out1 = outputs[0]; float* out2 = outputs[1]; mrb_value mrb_input_1 = mrb_ary_new(mrb); mrb_value mrb_input_2 = mrb_ary_new(mrb); for (int i=0;i<sampleFrames;i++) { mrb_ary_push(mrb, mrb_input_1, mrb_float_value(mrb, (*in1++))); mrb_ary_push(mrb, mrb_input_2, mrb_float_value(mrb, (*in2++))); } mrb_value mrb_inputs = mrb_ary_new(mrb); mrb_ary_push(mrb, mrb_inputs, mrb_input_1); mrb_ary_push(mrb, mrb_inputs, mrb_input_2);
  50. mrb_value mrb_outputs = mrb_funcall(mrb, vst_instance, "process", 1, mrb_inputs); if (!mrb_nil_p(mrb_outputs))

    { mrb_value mrb_output_1 = mrb_ary_shift(mrb, mrb_outputs); mrb_value mrb_output_2 = mrb_ary_shift(mrb, mrb_outputs); for (int i=0;i<sampleFrames;i++) { (*out1++) = mrb_float(mrb_ary_shift(mrb, mrb_output_1)); (*out2++) = mrb_float(mrb_ary_shift(mrb, mrb_output_2)); } } } } from Ruby to C
  51. getting data mrb_value mrb_outputs = mrb_funcall(mrb, vst_instance, "process", 1, mrb_inputs);

    if (!mrb_nil_p(mrb_outputs)) { mrb_value mrb_output_1 = mrb_ary_shift(mrb, mrb_outputs); mrb_value mrb_output_2 = mrb_ary_shift(mrb, mrb_outputs); for (int i=0;i<sampleFrames;i++) { (*out1++) = mrb_float(mrb_ary_shift(mrb, mrb_output_1)); (*out2++) = mrb_float(mrb_ary_shift(mrb, mrb_output_2)); } } } }
  52. get channel arrays mrb_value mrb_outputs = mrb_funcall(mrb, vst_instance, "process", 1,

    mrb_inputs); if (!mrb_nil_p(mrb_outputs)) { mrb_value mrb_output_1 = mrb_ary_shift(mrb, mrb_outputs); mrb_value mrb_output_2 = mrb_ary_shift(mrb, mrb_outputs); for (int i=0;i<sampleFrames;i++) { (*out1++) = mrb_float(mrb_ary_shift(mrb, mrb_output_1)); (*out2++) = mrb_float(mrb_ary_shift(mrb, mrb_output_2)); } } } }
  53. read channel arrays mrb_value mrb_outputs = mrb_funcall(mrb, vst_instance, "process", 1,

    mrb_inputs); if (!mrb_nil_p(mrb_outputs)) { mrb_value mrb_output_1 = mrb_ary_shift(mrb, mrb_outputs); mrb_value mrb_output_2 = mrb_ary_shift(mrb, mrb_outputs); for (int i=0;i<sampleFrames;i++) { (*out1++) = mrb_float(mrb_ary_shift(mrb, mrb_output_1)); (*out2++) = mrb_float(mrb_ary_shift(mrb, mrb_output_2)); } } } }
  54. # mrubyvst.rb class MRubyVST def initialize @programs_dir = "#{File.dirname(SCRIPT_PATH)}/programs" end

    def programs Dir.entries(@programs_dir) - ['.', '..'] end def load_program(path) Module.new.instance_eval(File.open(path).read) end def change_program(index) @program = load_program("#{@programs_dir}/#{programs[index]}") if programs[index] end def program_name(index) programs[index].to_s end end programs!
  55. get programs # mrubyvst.rb class MRubyVST def initialize @programs_dir =

    "#{File.dirname(SCRIPT_PATH)}/programs" end def programs Dir.entries(@programs_dir) - ['.', '..'] end def load_program(path) Module.new.instance_eval(File.open(path).read) end def change_program(index) @program = load_program("#{@programs_dir}/#{programs[index]}") if programs[index] end def program_name(index) programs[index].to_s end end
  56. load program # mrubyvst.rb class MRubyVST def initialize @programs_dir =

    "#{File.dirname(SCRIPT_PATH)}/programs" end def programs Dir.entries(@programs_dir) - ['.', '..'] end def load_program(path) Module.new.instance_eval(File.open(path).read) end def change_program(index) @program = load_program("#{@programs_dir}/#{programs[index]}") if programs[index] end def program_name(index) programs[index].to_s end end
  57. change program # mrubyvst.rb class MRubyVST def initialize @programs_dir =

    "#{File.dirname(SCRIPT_PATH)}/programs" end def programs Dir.entries(@programs_dir) - ['.', '..'] end def load_program(path) Module.new.instance_eval(File.open(path).read) end def change_program(index) @program = load_program("#{@programs_dir}/#{programs[index]}") if programs[index] end def program_name(index) programs[index].to_s end end
  58. program name # mrubyvst.rb class MRubyVST def initialize @programs_dir =

    "#{File.dirname(SCRIPT_PATH)}/programs" end def programs Dir.entries(@programs_dir) - ['.', '..'] end def load_program(path) Module.new.instance_eval(File.open(path).read) end def change_program(index) @program = load_program("#{@programs_dir}/#{programs[index]}") if programs[index] end def program_name(index) programs[index].to_s end end
  59. // mrubyvst.cpp void MRubyVst::setProgram(VstInt32 index) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "change_program"))){

    mrb_funcall(mrb, vst_instance, "change_program", 1, mrb_fixnum_value(index)); } curProgram = index; updateDisplay(); } bool MRubyVst::getProgramNameIndexed(VstInt32 category, VstInt32 index, char* text) { if(mrb_respond_to(mrb, vst_instance, mrb_intern_lit(mrb, "program_name"))){ mrb_value mrb_name = mrb_funcall(mrb, vst_instance, "program_name", 1, mrb_fixnum_value(index)); if (!mrb_nil_p(mrb_name)) { vst_strncpy(text, RSTRING_PTR(mrb_name), kVstMaxProgNameLen); return true; } } return false; } programs support
  60. // mrubyvst.h #define PROGRAMS_COUNT 10 #define PARAMETERS_COUNT 4 #define SCRIPT_PATH

    "/Users/fazibear/dev/mrubyvst/mrubyvst.rb" #define VST_CLASS "MRubyVST" // mrubyvst.cpp mrb_value vst_class = mrb_vm_const_get(mrb, mrb_intern_lit(mrb, VST_CLASS)); mrb_const_set(mrb, vst_class, mrb_intern_lit(mrb, "PROGRAMS_COUNT"), mrb_fixnum_value(PROGRAMS_COUNT)); mrb_const_set(mrb, vst_class, mrb_intern_lit(mrb, "PARAMETERS_COUNT"), mrb_fixnum_value(PARAMETERS_COUNT)); mrb_const_set(mrb, vst_class, mrb_intern_lit(mrb, "SAMPLE_RATE"), mrb_float_value(mrb, getSampleRate())); mrb_const_set(mrb, vst_class, mrb_intern_lit(mrb, "SCRIPT_PATH"), mrb_str_new_cstr(mrb, (SCRIPT_PATH))); define parameters
  61. add it to class // mrubyvst.h #define PROGRAMS_COUNT 10 #define

    PARAMETERS_COUNT 4 #define SCRIPT_PATH "/Users/fazibear/dev/mrubyvst/mrubyvst.rb" #define VST_CLASS "MRubyVST" // mrubyvst.cpp mrb_value vst_class = mrb_vm_const_get(mrb, mrb_intern_lit(mrb, VST_CLASS)); mrb_const_set(mrb, vst_class, mrb_intern_lit(mrb, "PROGRAMS_COUNT"), mrb_fixnum_value(PROGRAMS_COUNT)); mrb_const_set(mrb, vst_class, mrb_intern_lit(mrb, "PARAMETERS_COUNT"), mrb_fixnum_value(PARAMETERS_COUNT)); mrb_const_set(mrb, vst_class, mrb_intern_lit(mrb, "SAMPLE_RATE"), mrb_float_value(mrb, getSampleRate())); mrb_const_set(mrb, vst_class, mrb_intern_lit(mrb, "SCRIPT_PATH"), mrb_str_new_cstr(mrb, (SCRIPT_PATH)));
  62. class GainVST def initialize @gain = 1.0 end def set_parameter(index,

    value) @gain = value if index = 0 end def parameter_name(index) index == 0 ? 'Gain' : 'empty' end def parameter_value(index) @gain if index == 0 end def parameter_display_value(index) @gain.to_s if index == 0 end def parameter_label(index) 'dB' if index == 0 end def process(data) data[0].map!{ |left | left * @gain} data[1].map!{ |right| right * @gain} data end end GainVST.new GainVST
  63. class PanVST def initialize @pan = 0.5 @left = 1

    @right = 1 end def set_parameter(index, value) if index == 0 @pan = value rad = (45 - (@pan * 45 * 2)) * Math::PI / 180 @left = Math.cos(rad) + Math.sin(rad) @right = Math.cos(rad) - Math.sin(rad) end end def parameter_name(index) index == 0 ? "Pan" : "empty" end def parameter_value(index) @pan if index == 0 end def parameter_display_value(index) if index == 0 case @pan when 0.5 then "center" when 0..0.5 then "#{(100 - @pan*200).to_i}% L" when 0.5..1 then "#{(@pan*200 - 100).to_i}% R" end end end def process(data) data[0].map!{ |left | left * @left } data[1].map!{ |right| right * @right } data end end PanVST.new PanVST
  64. • http://www.mruby.org • https://github.com/fazibear/mrubyvst • https://github.com/fazibear/mrubybyexample • http://fazibear.github.io/mruby-snippets/mruby_main.html • https://www.ableton.com

    • http://www.steinberg.net/en/company/developers.html • http://trusterd.org • http://mobiruby.org • https://github.com/matsumoto-r/ngx_mruby • https://github.com/matsumoto-r/mod_mruby • https://github.com/mruby/mgem-list links