
cuando leí por primera vez sobre MRuby, quería jugar con él. Lo primero que vino a mi mente fue un plugin VST. Podría construir un wraper pequeña y pasar todas las funciones para el intérprete de Ruby. Voy a describir como lo hice.
lista
en primer lugar, tenemos que configurar algunas cosas. Vamos a empezar con MRuby.
MRuby
tenemos que clonar el repositorio MRuby:
$ git clone https://github.com/mruby/mruby $ cd mruby
después de eso, tenemos que configurar nuestro build MRuby. Tenemos que modificar build_config. rb. Al final del archivo, vamos a añadir nuestra especificación de construcción.
MRuby:: Build.new ('mrubyvst') de | conf | toolchain: gcc CONF. gembox 'por defecto' conf.gem: núcleo = > mruby eval ' ' conf.gem: github = > ' iij/mruby-dir' conf.gem: github = > 'iij, mruby-it' extremo
en este caso, especificamos que utilizamos una cadena de herramientas gcc. Además, se incluyen todos los estándar y algunas otras joyas. En MRuby, gemas se compilan en. Por lo tanto, si desea cambiar un conjunto de joyas, tienes que recompilar el mruby compilación. Vamos a necesitar mruby eval para permitir la carga del script ruby scripts rubís, mruby-dir lista el contenido del directorio y mruby acceso a archivos, etc.
estamos listos, debemos compilarlo.
$ rake
at the end of the build process, we will see:
== == == == == == == == == == == == == == == == == == == == == == == == Config Name: mrubyvst Output Directory: build/mrubyvst Included Gems: mruby-sprintf-standard Kernel # sprintf method mruby-print-standard print/puts/p mruby-math-Math standard module mruby-time-standard Time class mruby-struct Struct class mruby-standard-enum-ext-Enumerable module extension mruby-string-ext-String class extension mruby-numeric-ext-Numeric class extension mruby-array-ext-Array class extension mruby-ext-Hash hash-class extension mruby-range-ext-Range class extension mruby-proc-ext-Proc class extension mruby-symbol-ext-Symbol class extension mruby-random-Random clase clase mruby-ext objeto extensión mruby objectspace de ObjectSpace clase clase mruby fibra mruby-enumerador genérico clase mruby-enum-perezoso-enumerador:: objeto de clase Lazy mruby-nivel superior-ext-nivel superior (principal)... mruby compilador de compilador biblioteca mruby mruby-bin-mirb-mirb comando-binarios: mruby mirb-bin-mruby-mruby-binarios: mruby comando mruby-bin-tira-irep volcado debug sección...-binarios: mruby tira mruby-núcleo-ext-núcleo módulo extensión mruby-clase-ext-clase/módulo de extensión mruby-eval-standard Kernel # método eval mruby dir mruby él
gran , solo construimos MRuby. Vamos a continuar.
VST SDK
que queremos construir el plugin VST. Descargar el SDK y descomprimirlo en algún lugar en su computadora.
DAW
también necesitan un DAW que se carga nuestro plugin. He probado con Ableton Live 9. Hay una versión de prueba, pero también una demostración. En modo demo no puede guardar su proyecto, pero no necesitamos esta función. Hay versiones de 32 bits y 64 bits, vamos a construir la versión de 64 bits, por lo que necesitamos un 64 bits DAW.
edificio de VST
lo siguiente es un plugin VST sí mismo. Clonar el repositorio, configurarlo y empezar en el DAW.
$ git clone https://github.com/fazibear/mrubyvst $ cd mrubyvst $ rake init
echa un vistazo en Rakefile, hay constantes en la parte superior.
MRUBY_DIR = expand_path (' archivo... / mruby ') VST_SDK_DIR = expand_path (' archivo... / vst sdk ' SCRIPT_PATH = archivo). expand_path (./mrubyvst.rb ') VST_CLASS = 'MRubyVST' PROGRAMS_COUNT = 10 PARAMETERS_COUNT = 4
tienes que cambiar MRUBY_DIR y VST_SDK_DIR para arreglar la situación de estas bibliotecas en su computadora. Script_path puntos en un archivo que se cargará en Ruby VM en arranque y VST_CLASS es el nombre de la clase que se cree una instancia de la MRuby. ¡Ahora podemos construirlo!
rastrillo $
apenas hacemos la construcción. ¿Obras? No. Tenemos que copiar o vincular a un directorio especial, para que el DAW puede encontrarlo. En el Mac, VST plugins están en ~/Library/Audio/Plug-Ins/VST /. Pero espere: hay un script que lo haga por usted.
enlace de rake de $
construirá tu link VST este directorio. También puede deshacer el enlace.
$
unlink rastrillo
a partir de un DAW
estamos listos para lanzar el DAW. Si no sabes cómo utilizar el plugin VST, aquí es un pequeño tutorial. Buena suerte.
que es como debe sonar el VST en Ableton Live (en otro DAW, parecerá diferente)
gran! El plugin funciona, ahora vamos a mirar detalles de implementación.
aplicación
mirar el archivo mrubyvst.
#include "public.sdk/source/vst2/audioeffectx h" #include #include "mruby" #include "mruby .h / compilación." #include "mruby/h string.h" #include "mruby / matriz." #include "mruby por hora clase" «mruby #include variable h h» //---class MRubyVst: AudioEffectX pública {público: MRubyVst (audioMasterCallback audioMaster); ~ MRubyVst (); Procesamiento virtual void processReplacing (float * entradas *, flotador ** salidas, VstInt32 sampleFrames); Programa virtual void setProgram (índice de VstInt32); getProgramNameIndexed virtual bool (VstInt32 categoría, índice de VstInt32, char * texto); Parámetros virtuales void setParameter (índice de VstInt32, float valor); flotador virtual getParameter (índice de VstInt32); virtual void getParameterLabel (índice de VstInt32, char * label); virtual void getParameterDisplay (índice de VstInt32, char * texto); virtual void getParameterName (índice de VstInt32, char * texto); Información virtual bool getEffectName (char * nombre); virtual bool getVendorString (char * texto); virtual bool getProductString (char * texto); VstInt32 virtual getVendorVersion (); Ayudantes de anularán registro (const char * txt); protegido: std:: mutex m; mrb_state * mrb; vst_instance de mrb_value; };
en VST, hay cuatro grupos de cosas que debemos implementar.
lo más importante es el proceso. En este método, vamos a cambiar un entrada de datos de audio. Pero veamos este método más adelante. El segundo grupo es los programas. El programa es un estado de todos los parámetros. Y los parámetros son variables únicas que depende del procesamiento del sonido. El último es información. VST tiene que devolver algunos pedazos de información para identificarte.
vamos a ver. En la parte superior vemos mrubyvst, es el nombre de nuestro plugin. Desplegable con empty. rb es un campo. Hay una lista de programas. Y a la derecha, hay 4 parámetros con nombres y valores. Tenemos que decidir la cantidad de programas y parámetros que necesitamos antes de compilación. En nuestro ejemplo, hay 10 programas y 4 parámetros.
. ¿Y Ruby? Este es el archivo de encabezado de C++. Es cierto, que tenemos que crear un contenedor pequeño que transmiten información hacia y desde la máquina virtual de Ruby. Mantener la calma.
Init
el constructor es un gran lugar para inicializar nuestro Ruby. Después de eso, tenemos que cargar el script Ruby y crear una instancia de nuestra clase MRubyVST. Además, tenemos que definir algunas constantes en esta clase.
MRubyVst:: MRubyVst (audioMasterCallback audioMaster): AudioEffectX (audioMaster, PROGRAMS_COUNT, PARAMETERS_COUNT) {setUniqueID (666); canProcessReplacing (); setNumInputs (2); setNumOutputs (2); MRB = mrb_open (); File * archivo = fopen (SCRIPT_PATH, "r"); Si (archivo! = NULL) {mrb_load_file (", archivo); mrb_value vst_class = mrb_vm_const_get (mrb_intern_lit, mrb (mrb, VST_CLASS)); mrb_const_set (mrb, vst_class, mrb_intern_lit ("," PROGRAMS_COUNT "), mrb_fixnum_value (PROGRAMS_COUNT)); mrb_const_set (mrb, vst_class, mrb_intern_lit ("," PARAMETERS_COUNT "), mrb_fixnum_value (PARAMETERS_COUNT)); mrb_const_set (mrb, vst_class, mrb_intern_lit (mrb, "Símuta"), mrb_float_value (mrb, getSampleRate ())); mrb_const_set (mrb, vst_class, mrb_intern_lit (mrb, "SCRIPT_PATH"), mrb_str_new_cstr (mrb (SCRIPT_PATH))); vst_instance = mrb_instance_new (", vst_class); fclose (fichero); }}
la parte más importante es la línea 8. Esto es donde comenzamos nuestra VM de rubí incrustado. Entonces, nos está abriendo un archivo y, si existe, continúa nuestra VM.
ahora se carga nuestro script Ruby. Línea 14 conseguirá nuestra clase Ruby y nos permite definir algunas constantes. Después de eso, podemos crear una instancia de lo y cierre el archivo.
el Script Ruby
clase MRubyVST attr_reader: proveedor, producto,: p: effect_name,: versión = Mruby def initialize '@vendor' @product = 'MrubyVST' @effect_name = 'MRubyEffects' @version = 0 @programs_dir = "# {archivo. dirnamy (SCRIPT_PATH)} / programas "terminar las entradas def programas dir. (@programs_dir)-['.', '..'] end def load_program (path) Module.new. instance_eval (file.open (ruta). leer) fin def change_program (index) @program = load_program (" # {@programs_dir} / # {programas [index]} ") si programas [index] terminan def program_name (índice) programas [index] || "- vacío-" extremo def set_parameter (índice, valor) @program. set_parameter (índice, valor) si @program fin def nombre_parámetro (índice) @program. nombre_parámetro (índice) si @program fin def parameter_value (índice) @program. parameter_value (índice) si @program fin def parameter_display_value (index) @program. parameter_display_value (índice) si @program fin def parameter_label (index) @program. parameter_label (índice) si @program fin def proceso (fecha) @program .process (fecha) si @program fin def registro (str) io = file.open ('/tmp/mrubyvst.log' 'a') io. escritura (str + "n") io. cierre extremo
este es el script Ruby. Toda la información está aquí. Proveedor, producto, versión, etcetera. Nuestro plugin utilizará software para cargar varios módulos de rubí. Cuando el usuario está cambiando de un programa, vamos a instanciar una nueva clase y pasan la mayor parte de los métodos para este módulo. La lista de programas es sólo un archivo del directorio de programas. ¿El submódulo simple se parece a esto:
clase GainVST def inicializar @gain = 1,0 final def set_parameter (índice, valor) @gain = valor si índice = 0 end def nombre_parámetro (index) índice == 0? 'Ganar': 'vacía' fin def parameter_value (índice) @gain si índice == 0 end def parameter_display_value (index) @gain. to_s si índice == 0 end def parameter_label (index) 'dB' si índice == 0 end def (fecha) [0] fecha. mapa de procesos. {| izquierda | izquierda * @gain} datos [1] mapa! {| justo | justo * @gain} fin fecha de final GainVST.new
es un plugin simple ganancia. Esto cambiará el volumen audio de entrada, dependiendo de la configuración de la ganancia. El valor predeterminado es 1. Estos métodos ¿qué? Vamos a utilizar sólo un parámetro con índice 0 (cero)
-nombre_parámetro : devuelve un parámetro de nombre con dado índice
-parameter_value : devuelve un valor de parámetro con el índice dado
-parameter_display_value : devuelve un valor del parámetro con el índice dado como una cadena, se puede dar formato lo forma que desee
-parameter_label : Devuelve el parámetro de la etiqueta
– set_parameter: definir un valor de parámetro con el índice dado
– proceso : proceso entrada salida de datos y devuelve. En este caso, se multiplican todos los valores de entrada con un valor de ganancia.
MRuby envoltura
ahora debemos volver a nuestro wraper. Y aplicar métodos que pasen datos para ruby y la espalda. Mayoría de los métodos parecen muy similar, ver aquí:
bool MRubyVst:: getProgramNameIndexed (VstInt32 categoría, índice de VstInt32, char * texto) {lock m. (); Si (! mrb_nil_p (vst_instance) && mrb_respond_to (mrb, vst_instance, mrb_intern_lit («mrb program_name"))) {mrb_value mrb_name = mrb_funcall (", vst_instance, "", 1, mrb_fixnum_value program_name (Indice)); Si (! mrb_nil_p (mrb_name)) {vst_strncpy (texto, RSTRING_PTR (mrb_name), kVstMaxProgNameLen); m. de desbloqueo (); verdaderas; desbloqueo de m.}} (); devuelven el valor false; }
como MRuby no es seguro para subprocesos, necesitamos utilizar la exclusión mutua. Hacer un bloqueo de cuando empezar a usar el MRuby y desbloquear el final. Comprobar si nuestra instancia VST no es null y si ella responde al método program_name. Ahora podemos invocarlo si el resultado no es nulo, podemos leer lo y copia al VST puede leer, volver verdaderos significados que copiamos algo. No es complicado averiguar cuándo y cómo los datos se convierten. Ahora, echa un vistazo a lo más importante. Procesamiento de audio.
void MRubyVst::p rocessReplacing (float * entradas *, flotador ** salidas, VstInt32 sampleFrames) {lock m. (); Si (! mrb_nil_p (vst_instance) && mrb_respond_to (mrb, vst_instance, mrb_intern_lit ("," proceso "))) {int ai = mrb_gc_arena_save (mrb); Float * in1 = entrada [0]; Float * in2 = entradas [1]; Float * out1 = salidas [0]; Float * out2 = salidas [1]; mrb_value mrb_inputs = mrb_ary_new (mrb); mrb_value mrb_input_1 = mrb_ary_new (mrb); mrb_value mrb_input_2 = mrb_ary_new (mrb); para (int i = 0; i sampleFrames; i ++ <) {mrb_ary_push (mrb_input_1, mrb_float_value, mrb (mrb, (* in1 ++))); mrb_ary_push (mrb, mrb_input_2, mrb_float_value (mrb, (* in2 ++))); } mrb_ary_push (mrb, mrb_inputs, mrb_input_1); mrb_ary_push (mrb, mrb_inputs, mrb_input_2); mrb_value mrb_outputs = mrb_funcall (", vst_instance,"proceso", 1, mrb_inputs); mrb_value mrb_outputs = mrb_inputs; Si (! mrb_nil_p (mrb_outputs)) {mrb_value mrb_output_1 = mrb_ary_shift (", mrb_outputs); mrb_value mrb_output_2 = mrb_ary_shift (", mrb_outputs); para (int i = 0; i sampleFrames; i ++ <) {(* out1 ++) = mrb_float (mrb_ary_shift (", mrb_output_1)); (* out2 ++) = mrb_float (mrb_ary_shift (", mrb_output_2)); mrb_gc_arena_restore}} (mrb, ai); } m. desbloqueo (); }
hay algunas cosas que te vas de aquí. Tenemos que instruir al recolector de basura de Ruby para eliminar los datos no utilizados. Esto es lo que las líneas 4 y 36. Todos los objetos creados entre estas líneas pueden ser recogido de basura. Por lo tanto, no será fugas de memoria. A continuación, tenemos que convertir una amplia gama de flotadores en una amplia gama de flotadores. Crear una matriz de rubí para cada entrada y añadir a él un flotador convertido. Ahora podemos invocar un método de proceso parametrizada. El resultado de este método es convertido a float matriz en C y luego pasa a DAW.
últimas palabras
sí, funciona. Por supuesto, el plugin simple ganancia requiere mucha más CPU que el escrito en C, pero, como usted sabe, tenemos que hacer un paquete en un objeto Ruby y extraer al final. Ahora usted puede hacer lo que quieras con la reproducción de audio en Ruby. Hay algunos ejemplos de plugins como el enhancer pan y estéreo. Pero también puede crear su propio. Intente ejecutar el servidor web en él. Cualquier cosa. En Ruby, es más simple y más divertido.
MRubyByExample
era difícil depurar el comportamiento MRuby en VST. Así que hice un pequeño script para probarlo. Si usted quiere jugar con el MRuby, Ud. puede chequear este repositorio y esta documentación. Tal vez encuentran algo interesante.
espero que fue útil para usted. ¡Gracias por leerme!
***
artículo publicado originalmente en https://blog.fazibear.me/processing-audio-with-ruby-330796afd06 #. p216mhk82
Comments
0 comments
Twitter
RSS