viernes, 31 de diciembre de 2010

Grabación de una batería acústica en estudio

La información que aquí vais a encontrar es fruto y resumen de una estupenda conferencia de Pepe Loeches en la sede de SAE en Madrid y que podéis ver completa en YouTube. He aquí mi experiencia con la grabación de las baterías siguiendo las recomendaciones de este magnífico profesional. Normalmente todo esto solía tomarlo bastante a la ligera porque evidentemente el equipo con el que cuentan estos profesionales no es el mío ni mucho menos, pero lo más importante es captar lo esencial y aplicarlo a tu gusto. Por otro lado, aunque apliques tu propio criterio, es estúpido creer que vas a inventar la rueda, y que los 40 años de este profesional no los necesitas... Pues bien, allá vamos... surgen muchas dudas cuando empiezas con esto que normalmente son referidas a:
  • Que micros pongo
  • Que posición pongo a los micros
  • Que ganancias pongo a los micros
O al menos estos son los problemas que yo me encontraba, y después de probar, leer y documentarme he llegado a la conclusión de que hay cosas más relevantes.
A la hora de grabar una batería es un error pensar que en la mezcla podemos solucionar los errores de la grabación. Para mi gusto es importante conseguir en la medida de lo posible una naturalidad con el mejor sonido que tu kit te permita y evitar de esta forma excesos en ecualización, compresión o puertas de ruido. Es decir:

Si lo que grabas suena mal no lo arreglarás a base de edición

Seguramente las pistas "soplaran" al intentar conseguir frecuencias que no tienes, o le faltará pegada etc. Tal vez consigas un sonido aceptable a base de ecualización, compresión... pero cuando añadas el resto de instrumentos los defectos se notarán mucho más. Por eso recomiendo:

Comprate una llave torque

Es muy difícil afinar una batería correctamente y este tipo de llaves te permiten acertar con esto y no hacerlo solo de oído... además no son caras.

Si puedes monta parches nuevos

Si no, al menos sustituye los que tengas mas machacados. Los parches rugosos duran más y bien afinados no tienen nada que envidiarle a los de doble capa y aceite. La clave está en afinar bien.

Quita los parches traseros

Tanto en bombo como en timbales, los parches traseros crean reverberaciones y armónicos que no necesitamos, y hacen que la afinación sea más complicada. Esto es lo más importante... por favor, pruébalo, esto es clave.

Quita los parches delanteros y...

Engrasa los tornillos y vuelve a montar los parches. Entonces afinas la batería. La tensión de los parches en la afinación dependerá de tu criterio sobre todo, pero deberías tener en cuenta el estilo de música que vas a tocar. En mi caso para tocar rock, tengo los timbales un tanto graves (menos tensión) y la caja algo más tensa. Además no apago de ninguna forma los armónicos de la caja, me gustan y le proporcionan una viveza y pegada increíbles.

La afinación del bombo es muy importante. Debes dejar el parche todo lo flojo que puedas sin chasquear y apagarlo apoyando una manta sobre el parche. Así que afloja todos los tensores del bombo y comienza a apretar todos por igual y de forma homogénea. En el momento en el que notes que el parche coge algo de tensión, para. Ya tienes el bombo afinado.

Cuida la sala de grabación

Intenta apagar la sala y evitar reflexiones y cosas extrañas. Tu debes controlar el sonido que grabas.

Grabar en plano

No entiendo porque grabar la señal ecualizada o comprimida. Existen muchos plugins buenísimos para hacer esto a posteriori, y lo que pierdas en la señal procesada que grabes, no podrás recuperarlo... no tiene sentido comprimir o ecualizar antes de grabar.

Si haces esto habrás conseguido ya mejorar el sonido de tu batería sensiblemente. Es importante a la hora de afinar que tengas en cuenta que una batería suena en su conjunto. No es una unión de varios instrumentos, sino que el sonido de la caja y el bombo resuena en los timbales y viceversa, y todo junto es lo que proporciona el sonido final de tu batería.

Que micros pongo

En mi caso yo utilizo ocho pistas para grabar. Puedes necesitar más en función del tamaño de tu kit, pero debes tener en cuenta que son más variables que van a influir en el sonido puesto que todos los micros recogen la señal de todos los componentes. No puedes confiar en que una puerta de ruido te va a permitir aislar el sonido de la caja para tocarlo como quieras... queda mal porque perderías naturalidad, y siempre tendrás la caja en los platos puesto que no puedes ir cortando las colas de cada golpe de platillos.

Poner micros a cada plato puede ser interesante, pero en la mayoría de los casos hay señal de platos de sobra. Yo utilizo micros de ambiente que al abrir en estéreo y subir un poco en ecualizacion a partir de los 5Khz me dán lo que necesito.

Por otro lado he probado en ocasiones a poner un micro más, debajo de la caja. A mi la verdad es que no me ha servido para nada. Si la caja no suena bien intenta apagarla un poco y por supuesto afinarla como es debido, pero un micro debajo solo me ha dado quebraderos de cabeza.
Así que yo microfoneo con:
  • Un micro para bombo: El AKG D 112 de toda la vida, micro dinámico
  • Un micro para caja: Un SM57 (...dinámico)
  • Un micro para charles: Un micro tbone de condensador y membrana pequeña
  • Un micro para cada timbal: QToms de Shure, también dinámicos
  • Dos micros de ambiente: De condensador (unos shure de membrana grande)

Ten en cuenta que la base de una batería suele ser bombo, caja y charles.

Que posición de micros pongo

Respecto a esto mis dudas estaban en la distancia de los micros. Evidentemente los micros de ambiente son distintos al resto, y para estos tomo una distancia de aproximadamente 1,5 metros, uno a cada lado de la batería y por encima de ella.
El resto no los pongo demasiado cerca de los parches, pero si orientados hacia el aro del parche, no al centro. Orientarlos al aro proporciona más pegada.

La posición del micro del bombo una vez que has quitado el parche es dentro del bombo, en el centro del casco en todos los sentidos. Es decir, tanto en altura como en profundidad. Debe estar orientado al lugar donde la maza golpea, que es el centro del parche, y respecto a la profundidad, en el centro del ancho del casco de tu bombo.

Que ganancias doy a los micros

Evidentemente evitando clipear, una ganancia todo lo alta que puedas pero que te permita distinguir en la medida de lo posible el componente de la batería que está recogiendo ese micro, es decir, que la señal suba más al dar sobre el timbal o caja cuando golpeas.

Espero que todo esto os sirva como a mí, que estoy seguro de que si, si seguís todas las recomendaciones.

lunes, 20 de diciembre de 2010

Comprimiendo Streams en GZIP con java.util.zip

Bueno, pues algo muy sencillo pero que espero que facilite la vida a más de uno. La cuestión es que tienes "algo" que puede ser en el caso más sencillo una cadena, y que quieres enviar por red por ejemplo, o tus propias movidas.

Como decía un gran sabio en una conferencia sobre protocolos cuando hacían debates sobre XML-RPC y REST...

"En ocasiones uso sockets."

Pues bien... aún así estas dos funciones aumentarían la velocidad de usar solo sockets, y podrían en un determinado momento ayudaros mucho (como a mí cuando las terminé) para optimizar lo que enviéis... como os dé la gana.
Aunque se pueden usar otros algoritmos de compresión, GZIP es el de mejor relación de compresión/computación, y no tienes que añadir ninguna librería. Te permitirán aumentar la eficiencia en el envío o almacenamiento bastante así que ahí van:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
...


/**
* Obtiene el array de bytes comprimido a partir de otro array de bytes
* que se quiere comprimir.
* @param file los datos descomprimidos
* @return los datos comprimidos.
* @throws IOException de vez en cuando
*/
public byte[] comprimirGZIP(byte[] file) throws IOException {
ByteArrayOutputStream gzdata = new ByteArrayOutputStream();
GZIPOutputStream gzipper = new GZIPOutputStream(gzdata);
ByteArrayInputStream data = new ByteArrayInputStream(file);
byte[] readed = new byte[1024];
int actual = 1;
while ((actual = data.read(readed)) > 0) {
gzipper.write(readed, 0, actual);
}
gzipper.finish();
data.close();
byte[] compressed = gzdata.toByteArray();
gzdata.close();
return compressed;
}

/**
* Obtiene el array de bytes descomprimido a partir de otro array de bytes
* comprimido
* @param file los datos comprimidos
* @return los datos descomprimidos.
* @throws IOException de vez en cuando
*/
public byte[] descomprimirGZIP(byte[] file) throws IOException {
ByteArrayInputStream gzdata = new ByteArrayInputStream(file);
GZIPInputStream gunzipper = new GZIPInputStream(gzdata, file.length);
ByteArrayOutputStream data = new ByteArrayOutputStream();
byte[] readed = new byte[1024];
int actual = 1;
while ((actual = gunzipper.read(readed)) > 0) {
data.write(readed, 0, actual);
}
gzdata.close();
gunzipper.close();
byte[] returndata = data.toByteArray();
csvdata.close();
return returndata;
}

Para pensarlo un poco...

Me envian este correo con enlace a la página de "El confidencial"...

En Europa, los jóvenes protestan; en España, se van de botellón

En Reino Unido, en Francia, en Italia, en Grecia,...los jóvenes se
movilizan por la crisis y los recortes sociales, mientras que en España
la participación de los jóvenes brilla por su ausencia. También ha de
señalarse que esa falta de reacción frente a las situaciones que les
incomodan no ha tenido lugar cuando ha afectado a asuntos de ocio.
Parece que la indignación que surge cuando se prohíbe el botellón o
cuando se cierran pronto los locales de copas sí cristaliza en
manifestaciones.

¿Tendrán algo que ver las reformas de la educación? ¿Porque también en España aún tiene éxito "Gran Hermano"?... uffff....

domingo, 28 de noviembre de 2010

Lo peor de la sociedad

Estoy impresionado desde hace varias horas con un documental de TVE2 que me he tragado. No porque no supiera algunos datos, sino por la impresionante facilidad con la que la gente deja que sus hijos sean pasto de publicistas y sean inducidos a convertirse en otro borrego que solo ve televisión.

Y es sabido por todos que es así, "somos lo que compramos"... que ya decía alguien más interesante que yo, pero no tenía consciencia de el punto en el que nos encontramos hasta haber visto el dichoso documental.

Ha sido impresionante ver hasta que punto llega esa obsesión y ahora si que me preocupa tanto programa del corazón, reality show, y en concreto tantos gimnasios llenos de gente que tiene su mundo en la pantalla de la televisión y tantos telediarios con noticias de estrenos de películas (que antes simplemente criticaba conformado).

El problema es que no veo la televisión, y si lo hago, intento ver poca, por eso no soy consciente de ello. Ya se sabe que la prensa está totalmente contaminada con campañas de marketing, las películas con publicidad de los gobiernos... y de empresas privadas, etc. y que todo forma parte de una enorme campaña de publicidad que corroe las vidas de las personas, y las hace convertirse en máquinas de comprar sin necesidad real, lo que en muchas ocasiones no se puede pagar.

Pero ahora me doy cuenta de la magnitud del peligro real, y de la cantidad de personas que realmente viven en un programa de televisión constante, y creen que el estreno de la ultima película de vampiros adolescentes es la noticia importante del día. Pensaba que en realidad el mundo era más inteligente.

Y el pronóstico no es muy alentador, teniendo en cuenta las campañas de marketing más caras y que mejor resultado dan, las campañas políticas.

Es un largometraje documental británico de 2009 titulado "Fábrica de Famosos", dirigido por Chris Atkins y producida por S2S Productions.

Integrar el pago electrónico con paypal en java

Es increíble lo complicado que a veces puede resultar encontrar información sencilla sobre algo concreto. A la hora de la integración de una aplicación con sistemas de pago electrónico puedes encontrar algunos de los mejores ejemplos. Lo que voy a explicar es producto de un número demasiado elevado de horas buscando, leyendo, consultando y quebrándome la cabeza.

Y no solo con el caso específico de PayPal, sino con el resto de plataformas de pago con las que me he encontrado. Estoy pensando seriamente en crear un grupo en facebook "En contra de las explicaciones ambiguas para integrar plataformas de pago".

Bueno pues lo primero es saber si es complicado lo que tienes que hacer, porque lo que voy a contar es un pago estandar, es decir, una vez que en tu app ya sabes la cantidad que hay que pagar, quieres que se haga. Si quieres hacer pagos o gestionar tus cobros, o cosas más complejas con la interfaz SOAP, no es este tu artículo, jeje... Lo que vas a encontrar es lo que llaman:

  • Pago Express
  • Interfaz para NVP (abreviado de name-value pair)
  • Pago Estándar

Siempre hay un entorno de pruebas, como ya esperabas, y que funcionará exactamente igual que en el entorno real. Esta es una de las diferencias (entre otras) con plataformas con las que he trabajado y PayPal.

En esta última, el proceso que en principio creemos sencillo, que es el de obtener un número de tarjeta ficticio que sea aceptado por la validación de la tarjeta en la plataforma de pruebas, me implicó crear una cuenta ficticia de cliente en Paypal Sandbox y asociarle tarjetas.

Después de mucho clickar y urgar por el sandbox, trás intentar comprender que tipo de pago quiero realizar (..ufff) o ver mil veces el esquema de pago, tienes que tener una cuenta de empresa (o también llamado comerciante) e ir al menú "Perfil" para encontrar lo que buscas.
  • Preferencias de notificación de pago instantánea (IPN)
  • Configuración de pago codificado

1. Preferencias de notificación de pago instantánea IPN

En la primera opción tienes que indicar la url a la que se notifica el pago mediante petición POST. Esto quiere decir que cuando el pago se confirma, desde paypal se hará una solicitud a esa url que pongas, e incluirá además de una copia de los valores en la petición que mandamos desde nuestra web (desde el navegador del usuario) algunos parámetros más como el identificador de operación, que es el que a ti te interesa. ¿Problemas con el IPN? Se pueden deber a varios factores:

  • El pago no se confirma: Esto ocurre con cantidades elevadas, paypal desde hace poco está obligado a retener las cantidades elevadas (no recuerdo ahora el intervalo exacto) y las contrasta. Tu tendrás que acceder a tu cuenta de paypal (del sandbox) y confirmar el pago manualmente. Probablemente ya te habrá caducado la sesión, y tendrás que tirarte un rato logeandote de nuevo, pero de tanto hacerlo, tienes la contraseña grabada a fuego en tu cerebro... ¿verdad? :P
  • La url de respuesta no es correcta: Claro suele pasar... cámbiala

2. Configuración de pago codificado

En la segunda opción, configuras el certificado que vas a usar para "firmar un botón". Esta impresionante acción, como todas, al final no es para tanto y no es más que tomar una cadena con la información del pago, firmarla, y añadir el texto de la firma (...en PEM) a un formulario que se dirija a Paypal y que los navegantes presionan en tu página cuando quieren realizar el pago. Y con esto pues ya está, ahora:
  • Te descargas El SDK para java, descomprimes e incluyes las librerías en tu aplicación en /WEB-INF/lib
  • Descárgate todos los jars de las librerías criptográficas bouncycastle latest releases e incluyes las librerías en tu aplicación en /WEB-INF/lib
  • Creas tus certificados para firmar e identificarte con paypal: Para esto necesitas instalar OpenSSL (en ubuntu con "sudo apt-get install openssl"... en windows... no lo sé...) y ejecutar:

    #Generas la clave privada, el CSR
    openssl genrsa -out prvkey.pem 1024
    #La auto firmas y obtienes un certificado público
    openssl req -new -key prvkey.pem -x509 -days 365 -out pubcert.pem
    #Generas un almacen de certificados pkcs12 con ellos
    openssl pkcs12 -export -inkey prvkey.pem -in pubcert.pem -out prvkey.p12


    Después de todo esto te aparecen un montón de ficheros de los cuales solo te hace falta el almacén de certificados prvkey.p12 y el certificado de paypal que debes descargarlo desde paypal en la opción de "Configuración de pago codificado".

Pues nada, ten a buen recaudo la contraseña para el acceso al almacen de certificados y el archivo p12 por que ahora viene cuando se usa.

Realización del pago, datos del pago y firma

Bueno pues ya estás en tu aplicación y estás desarrollando la parte en la que se realiza el pago, entonces, tu objetivo va a ser crear una página donde se indique al cliente lo que va a pagar y se muestre un botón que ponga "Pagar con Paypal". El código HTML del formulario lo pones tú, pero asegúrate de que tienes dos campos:

<input type="hidden" name="cmd" value="_s-xclick" />
<input type="hidden" name="encrypted" value="<%= signedPaymentStr %>" />


que se envían a la url que te pasan desde paypal (algo de documentación tendrás que leer).

Los datos del pago van en la cadena firmada del campo encrypted, y básicamente tendrás que rellenarlos creando una cadena con algunos parámetros. Aquí os dejo el código de un metodito que devuelve directamente la cadena que buscamos. Cópialo, pégalo y míra el Javadoc, te resultará fácil. Ten en cuenta que el pago está configurado para EUROS!!...



import com.paypal.wpstoolkit.util.PPCrypto;
import java.util.Properties;
import org.apache.log4j.Logger;

.....
.....



/**
*
* Obtiene la cadena del botón encriptada para una compra. Una cadena de
* ejemplo sería:
*
* cert_id=...
* cmd=_xclick
* business=....
* item_name=Lorem Ipsum Dolor sit amet...
* item_number=1234
* custom=sc-id-789
* amount=500.00
* currency_code=EUR
* tax=41.25
* shipping=20.00
* address_override=1
* address1=Calle inventada
* city=Ciudad
* state=Estado
* zip=23452345
* country=ES
* no_note=1
* cancel_return=http://url.de.retorno
* @param paymentData Variables adicionales que se quieran adjuntar.
* @param concepto Descripción de concepto por el que se va a pagar.
* @param codigoVenta Identificador de la venta
* @param cantidad Cantidad en euros que se va a cobrar
* @param impuesto Cantidad que se va a cobrar de impuestos
* @param direccion Dirección del pagador
* @param numero numero de la direccion postal
* @param cp Codigo postal
* @param localidad Localidad de la dirección postal
* @param pais País de la dirección postal
* @param nombre Nombre del pagador
* @param apellidos Apellidos del pagador
* @param pruebas Booleano que indica si se dirigirá al entorno de pruebas o no
* @return cadena de la firma de los datos.
* @throws Exception
*/
public String getButtonEncryptionValue(String paymentData,
String concepto, String codigoVenta, Float cantidad, Float impuesto,
String direccion, String numero, String piso, String puerta,
String cp, String localidad, String pais, String nombre,
String apellidos, String email, Boolean pruebas) throws Exception {

Properties oProps = new Properties();
ClassLoader oCL = Thread.currentThread().getContextClassLoader();

InputStream oIStr = oCL.
getResourceAsStream("archivodeconfiguracionenclasspathquesiempreexiste.properties");
oProperties.load(oIStr);
oIStr.close();

String env = ".sandbox";
if (!pruebas) {
env = "";
}

String signedStr = null;

String _keyPass = "password_que_tienes_que_poner_bien";
String user = "userquetienesqueponerbien";
String certId = oProps.getProperty("propiedad_con_el_valor_que_te_da_paypal_al_registrarte");
String returnURL = oProps.getProperty("propiedad_url_de_vuelta_en_navegador_despues_de_pagar");
String returnCURL = oProps.getProperty("propieda_de_la_url_si_cancela_el_pago");
if (piso == null) {
piso = "";
}
if (puerta == null) {
puerta = "";
}
if (_data == null) {
_data = "";
}
if (numero != null && numero.length() > 0) {
direccion += " nº " + numero;
}
if (piso != null && piso.length() > 0) {
direccion += " - " + piso + "º";
}
if (puerta != null && puerta.length() > 0) {
direccion += " " + puerta;
}

paymentData += "cert_id=" + certId + ","
+"item_name=" + concepto.replaceAll(",", "") + ","
+"item_number=" + codigoVenta + ","
+"amount=" + String.format("%1.2f", cantidad).replaceAll(",", ".") + ","
+"tax=" + String.format("%1.2f", impuesto).replaceAll(",", ".") + ","
+"address_override=1,"
+"address1=" + direccion.replaceAll(",", "") + ","
+"city=" + localidad + ","
+"zip=" + cp + ","
+"country=" + pais + ","
+"first_name=" + nombre + ","
+"last_name=" + apellidos + ","
+"payer_email=" + email + ","
+"cmd=_xclick,"
+"business=" + user + ","
+"currency_code=EUR,"
+"lc=" + pais + ","
+"cbt=Volver a la página,"
+"return=" + returnURL + ","
+"cancel_return=" + returnCURL + "";

logger.info("Encoding data: " + paymentData);

paymentData = paymentData.replace(',', '\n');
try {
signedStr = new String(PPCrypto.getButtonEncryptionValue(paymentData.getBytes("UTF-8"),
oProps.getProperty("ruta_al_archivo_p12"),
oProps.getProperty("ruta_al_certificado_de_paypal"),
_keyPass));
} catch (Exception ex) {
logger.error("Excepcion firmando: " + ex.getMessage());
}
return signedStr;
}