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

MRuby within VST

MRuby within VST

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