Pues un nuevo plugin gracioso que se me ha ocurrido. Está pensado para los que les gustaría hacerse sus pinitos en el procesado de audio pero tampoco quieren meterse en c++, sdks y otras historias.
Son tres archivos:
- Emisor.dll es el plugin, que se pone en alguna pista del DAW con información de onda.
- ReceptorAsm.dll es un ensamblado de .net, que no tiene nada que ver con el ensamblador, pero lo de asm es para despistar, para contribuir al despiste general que hay en todo lo referente a la informática. Se puede usar en vb.net, c#, delphi#, o cualquier lenguaje .net, así como lenguajes capaces de cargar objetos com+.
- Receptor.dll es una dll como las de siempre. Se puede usar en c, c++, vb, pascal-delphi..., cualquier lenguaje capaz de cargar dlls, creo que java también.
Entonces, lo primero es cargar Emisor.dll en una pista de un DAW. Luego, para usar ReceptorAsm, en un proyecto nuevo de .net se añade el ensamblado a las referencias y ya se puede crear tal que
Receptor r = new Receptor();
Vemos que r tiene la propiedad, que es un evento, onDatoLegado. La seleccionamos, y tras el += y el tab nos sale la función
void r_onDatoLlegado(float[] in1, float[] in2, float[] out1, float[] out2, int size, int samplePos)
{
}
Si le damos al F5, a partir de ese momento llegará a esa función la información de onda de la pista donde esté el plugin Emisor. Llegará en in1[] el canal izquierdo y en in2[] el derecho. Para devolver al DAW el sonido procesado no hay más que llenar el floa[] out1, canal izquierdo, y el out2[], canal derecho. Tal que
for (int h = 0; h < size; h++)
{
out1[h] = in1[h];
out2[h] = in2[h];
}
Eso manda la señal tal y como llega, sin procesar.
En size está es tamaño del float[], el Length, y el samplePos es la posición del sample actual del DAW, por si hace falta.
El Receptor.dll, al ser una dll, hay que cargarla como se cargan las dlls. Se puede hacer de forma explícita o implícita. Tiene una sola función exportada, que es la que hay que llamar. De forma explícita se hace llamando a LoadLibrary y GetProcAddress de esa función. De forma implícita es definir la función como externa.
Un ejemplo de carga implícita para c#:
public delegate void Funcion(IntPtr in1, IntPtr in2, IntPtr out1, IntPtr out2, int samples, int samplePos);
Ya tenemos definida la función que recibirá la onda.
[DllImport(@[Path y nombre de la dll], CallingConvention= CallingConvention.StdCall)] public static extern bool Iniciar(Funcion funcion);
Y ahora tenemos definida la función de la dll que hay que usar, Iniciar, a la que hay que pasarle como parámetro una función
Funcion funcion;
que será esa, del tipo Función, definido lo primero.
Hay que crear el objeto Funcion
public Form1()
{
InitializeComponent();
funcion = new Funcion(uncion);
}
Tenemos que implementar la función del objeto funcion, en este caso uncion
public void uncion(IntPtr in1, IntPtr in2, IntPtr out1, IntPtr out2, int samples, int samplePos)
{
}
y entonces podemos llamar la función de la dll Iniciar con el parámetro que quiere
Iniciar(funcion);
y llegará a la función uncion la forma de onda del DAW. Llega como IntPtr, como se ve. Luego se pueden usar la clase Marshall para acceder a los datos, con su Copy o su Read, o declarar la función uncion como unsafe y hacer
unsafe public void uncion(IntPtr in1, IntPtr in2, IntPtr out1, IntPtr out2, int samples, int samplePos)
{
float* fin1 = (float*)in1.ToPointer();
float* fin2 = (float*)in2.ToPointer();
float* fout1 = (float*)out1.ToPointer();
float* fout2 = (float*)out2.ToPointer();
for (int h = 0; h < samples; h++)
{
fout1[h] = fin1[h];
fout2[h] = fin2[h];
}
}
para procesar y pasar los datos al DAW.
Veamos ahora un ejemplo en delphi, también con carga implícita. Este es más cortito.
Declaramos la función de la dll que hay que llamar y la que recibirá los datos
function Iniciar(a : Integer) : Boolean; stdcall; external [path y nombre de la dll];
function Recibido( in1, in2, out1, out2 : PSingle; size,samplePos : Integer):boolean; stdcall;
Implementamos la función
function Recibido(in1, in2, out1, out2 : PSingle; size, samplePos : Integer):boolean; stdcall
begin
end;
Y ya podemos llamar la función de la dll
Iniciar(Integer(@Recibido));
Los datos llegan como PSingle y para acceder a ellos
for i:=0 to size-1 do
begin
out1^ := in2^;
out2^ := in1^;
Inc(in1);Inc(in2); Inc(out1);Inc(ou2);
end;
Delphi no admite la indexación de punteros, así que hay que andar con Inc por aquí, Dec por allá. Por cierto que en este ejemplo se hace un intercambio de canales, el izquierdo a la derecha y el derecho a la izquierda.
Este sí que no es demo ni nada, así que no hace falta que llaméis al amigo pirata, ya podéis dejar el teléfono.
Son tres archivos:
- Emisor.dll es el plugin, que se pone en alguna pista del DAW con información de onda.
- ReceptorAsm.dll es un ensamblado de .net, que no tiene nada que ver con el ensamblador, pero lo de asm es para despistar, para contribuir al despiste general que hay en todo lo referente a la informática. Se puede usar en vb.net, c#, delphi#, o cualquier lenguaje .net, así como lenguajes capaces de cargar objetos com+.
- Receptor.dll es una dll como las de siempre. Se puede usar en c, c++, vb, pascal-delphi..., cualquier lenguaje capaz de cargar dlls, creo que java también.
Entonces, lo primero es cargar Emisor.dll en una pista de un DAW. Luego, para usar ReceptorAsm, en un proyecto nuevo de .net se añade el ensamblado a las referencias y ya se puede crear tal que
Receptor r = new Receptor();
Vemos que r tiene la propiedad, que es un evento, onDatoLegado. La seleccionamos, y tras el += y el tab nos sale la función
void r_onDatoLlegado(float[] in1, float[] in2, float[] out1, float[] out2, int size, int samplePos)
{
}
Si le damos al F5, a partir de ese momento llegará a esa función la información de onda de la pista donde esté el plugin Emisor. Llegará en in1[] el canal izquierdo y en in2[] el derecho. Para devolver al DAW el sonido procesado no hay más que llenar el floa[] out1, canal izquierdo, y el out2[], canal derecho. Tal que
for (int h = 0; h < size; h++)
{
out1[h] = in1[h];
out2[h] = in2[h];
}
Eso manda la señal tal y como llega, sin procesar.
En size está es tamaño del float[], el Length, y el samplePos es la posición del sample actual del DAW, por si hace falta.
El Receptor.dll, al ser una dll, hay que cargarla como se cargan las dlls. Se puede hacer de forma explícita o implícita. Tiene una sola función exportada, que es la que hay que llamar. De forma explícita se hace llamando a LoadLibrary y GetProcAddress de esa función. De forma implícita es definir la función como externa.
Un ejemplo de carga implícita para c#:
public delegate void Funcion(IntPtr in1, IntPtr in2, IntPtr out1, IntPtr out2, int samples, int samplePos);
Ya tenemos definida la función que recibirá la onda.
[DllImport(@[Path y nombre de la dll], CallingConvention= CallingConvention.StdCall)] public static extern bool Iniciar(Funcion funcion);
Y ahora tenemos definida la función de la dll que hay que usar, Iniciar, a la que hay que pasarle como parámetro una función
Funcion funcion;
que será esa, del tipo Función, definido lo primero.
Hay que crear el objeto Funcion
public Form1()
{
InitializeComponent();
funcion = new Funcion(uncion);
}
Tenemos que implementar la función del objeto funcion, en este caso uncion
public void uncion(IntPtr in1, IntPtr in2, IntPtr out1, IntPtr out2, int samples, int samplePos)
{
}
y entonces podemos llamar la función de la dll Iniciar con el parámetro que quiere
Iniciar(funcion);
y llegará a la función uncion la forma de onda del DAW. Llega como IntPtr, como se ve. Luego se pueden usar la clase Marshall para acceder a los datos, con su Copy o su Read, o declarar la función uncion como unsafe y hacer
unsafe public void uncion(IntPtr in1, IntPtr in2, IntPtr out1, IntPtr out2, int samples, int samplePos)
{
float* fin1 = (float*)in1.ToPointer();
float* fin2 = (float*)in2.ToPointer();
float* fout1 = (float*)out1.ToPointer();
float* fout2 = (float*)out2.ToPointer();
for (int h = 0; h < samples; h++)
{
fout1[h] = fin1[h];
fout2[h] = fin2[h];
}
}
para procesar y pasar los datos al DAW.
Veamos ahora un ejemplo en delphi, también con carga implícita. Este es más cortito.
Declaramos la función de la dll que hay que llamar y la que recibirá los datos
function Iniciar(a : Integer) : Boolean; stdcall; external [path y nombre de la dll];
function Recibido( in1, in2, out1, out2 : PSingle; size,samplePos : Integer):boolean; stdcall;
Implementamos la función
function Recibido(in1, in2, out1, out2 : PSingle; size, samplePos : Integer):boolean; stdcall
begin
end;
Y ya podemos llamar la función de la dll
Iniciar(Integer(@Recibido));
Los datos llegan como PSingle y para acceder a ellos
for i:=0 to size-1 do
begin
out1^ := in2^;
out2^ := in1^;
Inc(in1);Inc(in2); Inc(out1);Inc(ou2);
end;
Delphi no admite la indexación de punteros, así que hay que andar con Inc por aquí, Dec por allá. Por cierto que en este ejemplo se hace un intercambio de canales, el izquierdo a la derecha y el derecho a la izquierda.
Este sí que no es demo ni nada, así que no hace falta que llaméis al amigo pirata, ya podéis dejar el teléfono.