Síntesis de sonido – Síntesis sustractiva

En pocas palabras la síntesis sustractiva consiste en aplicar uno o varios filtros a una señal rica en armónicos, de ahí lo de “sustractiva”. Estos filtros remueven o atenúan los armónicos y los hay de diferentes tipos.: pasa altos, pasa bajos, pasa bandas, etc.

Muchos sintetizadores comparten el mismo esquema básico, en el cual uno o varios osciladores pasan por una sección de mezcla que permite al músico incorporar y combinar diferentes armónicos. La señal luego alimenta un filtro, en general pasabajos, pero también puede ser una combinación de varios tipos de filtros.  Los moduladores, o LFO, se incorporan para permitir modelar el sonido a través del tiempo. Un ejemplo tipo sería aplicarlo a la frecuencia de corte del filtro haciendo que esta varíe con el tiempo y consiguiendo un sonido dinámico.

Osciladores analógicos

Las formas de onda ricas en armónicos son la diente de sierra, contiene armónicos pares e impares que decaen en volumen a razón de 1/armónico. Los armónicos pares caen en las diferentes octavas de la fundamental, mientras que los impares caen en frecuencias que, en general, no son notas musicales.

La onda cuadrada, también rica en armónicos, contiene solo armónicos impares y también decae en volumen a razón de 1/armónico.

La onda triangular, también contiene solo armónicos impares, sin embargo decae en volumen como 1/sqr(armónico), es decir más rápido que los armónicos de la onda cuadrada.

La onda senoidal únicamente contiene la frecuencia fundamental.

La onda pulso, es un caso más genérico de la onda cuadrada y permite ajustar el siclo de trabajo o ancho del pulso. La onda cuadrada es una onda pulso con un 50% de ciclo de trabajo. El ajuste del ciclo de trabajo modifica la proporción de la onda que permanece en el ciclo positivo a la vez que introduce armónicos pares. Es importante notar que desde el punto de vista del timbre, este será idéntico por ejemplo en 25% o en 75%.

La onda impulso sería una onda pulso con un ciclo de trabajo casi de cero y el resultado teórico son todos los armónicos al mismo volumen.

El oscilador de ruido genera, precisamente, ruido, lo que se ve en frecuencia como una mezcla de todas las frecuencias que varían en amplitud en forma aleatoria.

Filtros

En la síntesis sustractiva los filtros son el componente que altera la composición de armónicos en la señal y usualmente se describen por el tipo de frecuencias a las cuales no afectan. Por ejemplo un filtro pasabajos atenúa altas frecuencias mientras que no altera las bajas frecuencias, tomando como referencia un punto llamado frecuencia de corte. Algunos parámetros que definen los filtros son:

  • La frecuencia de corte se define como el punto en el cual el filtro atenúa la señal en 3dB, marcando el punto en el que el filtro comienza a reducir la amplitud de las frecuencias.
  • La caída describe cuán rápido se produce esta atenuación puede describirse en función de los polos que actúan a esa frecuencia: 1 polo representa una caída de 6dB por octava mientras que un filtro de 4 polos presentará una caída de 24dB por octava.
    Resultado de imagen para filter slope
  • La resonancia es un impulso de amplitud en el punto de corte lo que puede exagerar la frecuencia de corte y es particularmente notorio cuándo la frecuencia de corte es modulada. La resonancia puede ser tan alta que el filtro puede comenzar a auto oscilar y convertirse efectivamente en un oscilador de onda senoidal.
    Resultado de imagen para filter resonance

Modulación

Las envolventes describen la variación de un parámetro a través del tiempo y comunmente definen 4 estados: ataque, caída, sostenimiento y liberación. Sin embargo pueden crearse muchas formas más utilizando combinaciones de estos estados.

Muchas envolvente incluyen opciones de re-disparo ya que tenemos muchas formas de reiniciar la envolvente cuándo se ejecutan rápidamente las notas. Un re-disparo digital inicia la envolvente de cero cada vez que presionamos la tecla, pero puede aparecer un glitch debido al cambio abrupto desde el punto en el que se encuentra a cero nuevamente. Un re-disparo analógico reinicia la envolvente desde donde la misma se encuentre. Esto puede suavizar la sucesión de notas pero puede eliminar el punch que la envolvente original genera.

Relacionado con la envolvente y la ejecución tenemos el modo de legato, que permite ejecutar una sucesión de notas en modo deslizado, sin que se dispare la envolvente en cada nota que se ejecute, siempre y cuando la primer nota se mantenga presionada.

Otro parámetro vinculado a la ejecución es el denominado keyboard tracking y es usado para alterar los parámetros de la envolvente dependiendo la nota ejecutada. Por ejemplo, puede ser usado para que la envolvente dure más tiempo en notas bajas y sea más breve en notas altas. También puede ser aplicado en otros parámetros, como la frecuencia de corte. Esto nos permite ajustar el filtro dependiendo de la nota tocada y que el efecto de filtrado sea relativamente idéntico en cualquier nota manteniendo el timbre, de otra manera en un filtro pasabajos estático, por ejemplo, llegaríamos a una nota tan alta que la misma fundamental se vería atenuada.

Adicionalmente es común utilizar LFO para modular parámetros. Esto son osciladores subsónicos (por debajo de los 20Hz). Particularmente son llamado LFO bipolares aquellos cuyo rango va de 1 a -1.

Sintetizador monofónico

Por definición un sintetizador monofónico es aquel capaz de emitir una sóla nota a la vez, lo cual le hace imposible reproducir acordes. Tienen sólo un oscilador, un filtro y un modulador. Cuándo se ejecuta la segunda nota automáticamente deja de emitirse la primera. Esto puede utilizarse para lograr efectos de legato: mientras que la primera nota no deje de ejecutarse la envolvente no se re disparará. Ejemplos:

Sintetizador polifónico

Permite tocar múltiples notas a la vez. Usualmente esto se logra en un sintetizador analógico agregando software adicional para cada voz. Esto puede hacer el equipo muy costoso y por eso al principio no reproducían más de dos voces. Los sintetizadores posteriores ya no estarían limitados por el hardware para cada ruta de señal, sino por la potencia de procesamiento para procesar la información. Hoy en día es posible reproducir cientos de voces. Ejemplos:

Conclusión

Como se observa todos estos sintetizadores comparten los mismos elementos:

  • Número de osciladores
  • Envolventes disponibles
  • Filtros

Lo que hace a cada uno único son las opciones que proveen para configurar y dar forma a la modulación.

 

 

Bomber – Día 2

Estuve trabajando en el Game Design y, por supuesto, se hace necesario algo de arte conceptual para visualizar la idea y el estilo general del juego. Ciertamente hay artistas bastante especiales en cuánto a estilo se refiere y yo soy uno de ellos. Aquí va lo que conseguí con mi Intuos en Photshop:

Estoy de acuerdo, no es un Picasso pero se notan algunos detalles importantes:

  • El viejo no es sólo cascarrabias, está loco de remate
  • Las verduras y hortalizas (ok, sólo hay una zanahoria, pero se entiende el “concepto”) están en su mundo y aman la música
  • Hay color y humor
  • Hay un avión… XD

Ahora me voy a concentrar en los personajes y las pequeñas mecánicas adicionales que podría introducir, además de soltar bombas sobre las verduras. Ya vemos que las zanahorias gustarán de escuchar música con auriculares, ¿que otras verduras podrían aparecer? ¿que características tendrá cada una? El arte iba a contener una lechuga alerta que estaría observando al viejo acercarse e intentaba alertar a la zanahoria pero… que pereza, está en mi cabeza, además el tiempo que había previsto para el arte ya había sido superado.

Nos vemos la próxima entrada!!

Síntesis de sonido – Introducción

La síntesis de sonido consiste en obtener sonidos a partir de medios no acústicos; variaciones de voltaje en el caso de la síntesis analógica, o por medio de programas de computadora en el caso de la síntesis digital que hace referencia a la analógica.

Wikipedia nos da una interesante, completa y sucinta primera aproximación a uno de los temas más apasionantes de la producción musical digital. Además de crear ritmos y melodías uno de los apartados creativos que más atrae a los productores es la creación de sonidos nuevos y originales.

Pero, ¿que es el sonido? Técnicamente el sonido puede ser descrito como la vibración a través de un medio. Esto significa que el sonido puede viajar por aire, agua o cualquier medio que pueda propagar ondas de energía. Además el sonido puede describirse por medio de varias propiedades clave.

Características del sonido

Frecuencia

Las ondas de propagación del sonido pueden visualizarse por ejemplo al tocar la cuerda de una guitarra. La cuerda se mueve de un lado al otro una y otra vez moviendo las partículas de aire a su alrededor al mismo ritmo o frecuencia. Así, la frecuencia es el número de periodos que se reproducen en un segundo. La frecuencia se mide en hertz (hz), de modo que 1 hz es un único periodo cuya duración es un segundo. La frecuencia también nos habla de la longitud de la onda, si conocemos la velocidad con la que esa onda se propaga en el medio. En el aire el sonido viaja a 343 m/s, por lo tanto una onda de 1 hz mide 343 metros. Una habitación debería tener ese enorme tamaño para acomodar un ciclo de esa frecuencia. Es por ello que las habitaciones pequeñas tiene una respuesta pobres a los sonidos muy bajos.

Tono (pitch)

Mientras que técnicamente el sonido se describe por frecuencias, los humanos lo percibimos con una característica subjetiva que llamamos tono. Un tono alto o agudo implica una frecuencia alta y un tono bajo o grave corresponde con una frecuencia baja. También estamos interesados en la relación entre los sonidos. Por ejemplo, cuándo la relación de frecuencia entre un sonido y otro es del doble, decimos entonces que hay una octava de diferencia.

Amplitud

La amplitud es la característica por la que percibimos el volumen. Al igual que el tono, es una característica subjetiva y lo que para uno puede parecer un volumen alto, a otra persona puede parecerle agradable. También, al igual que el tono, la percepción es logarítmica y no lineal. Dos personas aplaudiendo juntas no suenan el doble de fuerte que una sola. El volumen se mide en decibeles, una escala logarítmica que tiene en cuenta la característica del volumen.  Desde el punto de la síntesis estaremos más interesados en como cambia el volumen con el tiempo.

Duración y envolvente

Con la duración distinguimos sonidos entre largos y cortos. Tomando la duración y el volumen juntos podemos describir la envolvente del sonido, o como el volumen varía con el tiempo.  Lo describimos considerando distintos estados:

  • Ataque (attack), se produce en el momento que inicia el sonido. Algunos sonidos comienzan suavemente y otros, como una percusión, tienen un ataque muy breve.
  • Caída (decay) se produce entre el pico máximo que se alcanza durante el ataque y el volumen definitivo que tendrá el sonido antes de finalizar.
  • Sostenimiento (sustain) es el nivel (lo medimos en nivel y no en tiempo) que se alcanza luego de la caída.
  • Relajación (release) es el tiempo que demora el sonido en desaparecer luego de que la fuente de sonido ha dejado de existir (por ejemplo cuándo se suelta una tecla de un piano).

Armónicos y timbre

Los sonidos que escuchamos, con la excepción de una onda senoidal perfecta, están compuestos por diferentes frecuencias, además de la fundamental o principal, que es la menor y es lo que describimos como el tono de la nota.  Todas las demás frecuencias por encima de la fundamental se conocen como sobretonos, entre los cuales también se encuentran los armónicos. Los armónicos son múltiplos enteros de la fundamental y se encuentran en ondas como diente de sierra, onda cuadrada, onda triangular y en cualquier sonido que nos da un fuerte sentido del tono.

Poniendo juntos la envolvente del sonido y los armónicos obtenemos la huella digital de cada sonido o el timbre. El timbre es lo que describimos cuándo identificamos un sonido como diferente a otro, cuándo hablamos del color del sonido. Es lo que nos permite identificar un tipo de instrumento de otro.

El arte del diseño de sonido está en utilizar todas estas características para dar forma a nuevos e interesantes timbres.

Componentes básicos de la síntesis de sonido

Osciladores

Generan la forma de onda y son la materia prima de la síntesis.

Resultado de imagen para formas de onda

Los osciladores digitales nos permiten utilizar muestras de sonido como fuente, permitiendo realizar osciladores con cualquier forma de onda.

Filtros

Permiten moldear la carga de armónicos del sonido generado por los osciladores. Algunos filtros eliminan altas frecuencias, otros bajas frecuencias e incluso otros pueden exagerar algunas frecuencias o introducir nuevas.

Envolvente

Los generadores de envolvente modulan un parámetro con el tiempo y comúnmente se utilizan para controlar el volumen de un sonido o la frecuencia de corte de un filtro.

Construir un sintetizador básico con Reaktor 6

Reaktor es una software de Native Instruments que permite diseñar sintetizadores simples o altamente complejos, como el nuevo Form.

Un sintetizador simple incluirá una entrada de pitch y gate, que provendrá de un controlador MIDI. Esta entrada controlará un oscilador, cuya amplitud será controlada a su vez por una envolvente. Además agregaremos un filtro.

Partimos creando un nuevo Ensemble, que es el contenedor básico en Reaktor. Luego crearemos un nuevo instrumento para ordenar las cosas. En Reaktor un instrumento es una abstracción, podemos construir un instrumento en su interior o un filtro.

Hacemos doble click en el instrumento para poder comenzar a construir el sinte. Agregaremos un oscilador básico, por ejemplo un diente de sierra. Para ello utilizamos la tecla ENTER, que abre la ventana de búsqueda y comenzamos a escribir “sawtooth oscillator” y lo seleccionamos.

Vemos que tiene una entrada para pitch, o tono, y otra para la amplitud. Los colores en las entradas tienen su explicación:

  • Las entradas amarillas son entradas de eventos, estas entradas admiten valores que cambian a una velocidad mucho menor que las entradas de audio.
  • Las entradas blancas son entradas de audio y se calculan para cada muestra de sonido.

Para controlar este oscilador desde nuestro teclado MIDI necesitamos la macro “pitch and gate”. Las macros son como colecciones de elementos más básicos que cumplen una función común.

Podemos conectar en este mismo instante la salida de pitch, con la entrada de pitch del oscilador y agregar (botón derecho) una constante para la amplitud, con un valor de 1. Para escuchar algo lo que haremos es crear un puerto de salida (out port) y conectamos a él la salida del oscilador y, a su vez, volviendo al esquema principal, conectamos la salida del instrumento a ambos puertos Out, que reprentan la salida global. Automáticamente comenzaremos a escuchar el oscilador. Las notas cambiaran si tocamos pero nunca cesará el sonido.

Ya tenemos el oscilador, pero no tenemos ningún mecanismo aún para controlar la envolvente. Podemos agregar una envolvente básica utilizando la macro AHDSR.

Tan pronto lo agreguemos debemos acomodar un poco los elementos del panel, yendo a la vista del panel, desbloqueando con el candado y arrastrando los elementos hasta obtener un panel que nos guste. Esto conviene hacerlo cada vez que agregamos un elemento que tenga representación visual en el panel.

Conectamos la salida gate de “Pitch and gate” con la entrada de gate de la envolvente. Y ahora conectamos la salida de “Env” con la entrada de amplitud del oscilador y ya tenemos algo más interesante que responde a nuestro controlador.

Es interesante que no todos los objetos que encontremos y que querremos controlar tendrán una entrada de amplitud como la del oscilador. De modo que un mecanismo de conexión alternativo sería multiplicar la salida del oscilador, al cual le aplicamos como amplitud una constante, por la envolvente. De esta manera cuándo no presionamos ninguna tecla la salida será efectivamente cero, mientras que cuándo presionemos una tecla la envolvente moldeará la salida del oscilador.

Nos queda únicamente colocar el filtro. Si bien podemos poner el filtro a la salida, tiene más sentido colocarlo a la salida del oscilador, de tal forma que siempre esté actuando sobre la misma señal. Utilizaremos el componente “VA Filter”, que un filtro virtual analógico (VA) con una entrada para modular la frecuencia de corte. Acomodamos el panel y realizamos las conexiones.

Con esto ya tenemos un filtro básico para jugar un rato. Por supuesto, podemos agregar polifonía, más filtros, más osciladores, etc.

.NET Core 2 – Proyecto básico – Parte 1

En mi cruzada por moverme desde PHP+Symfony a otro framework basado en C#, me encontré por ahí con Core 2 y me pareció más que interesante, no sólo por el lenguaje y por ser promovido por Microsoft, sino sobre todo por la portabilidad, algo a lo que no nos tenían acostumbrados.

Lo siguiente es una guía básica de como crear un proyecto básico y mínimo a fin de que sirva como base. En este caso particular se muestra como realizarlo usando Visual Studio 2017 y tomando algunas decisiones que son de diseño y no estrictamente necesarias por el framework. Para una introducción más conceptual a ASP.NET Core lo mejor es dirigirse directamente al sitio oficial: https://docs.microsoft.com/en-us/aspnet/core/.

Comenzamos por crear un proyecto basado en la plantilla “ASP.NET Core Web Application”:

Tomaremos como base un simple proyecto tipo vidriera cuyo objetivo será mostrar una lista de productos de entre los cuales el cliente podrá visualizar su imagen, el valor y una descripción, además de aportar algo de feedback al vendedor. La aplicación incluirá un mecanismo simple de autenticación. Además, y si bien no es estrictamente necesario, en este proyecto usaremos el patrón MVC.

Al crear un nuevo proyecto VS2017 nos da la opción de seleccionar diferentes plantillas para incluir automáticamente: MVC, Angular o ReactJS, por ejemplo. En este caso partiremos de la plantilla vacía para poder entender la estructura de la aplicación.

Una vez seleccionadas las opciones VS2017 creará un proyecto ASP.NET Core vacío con la siguiente estructura que se ve en la siguiente imagen.

  • Dependencies: Dentro de esta carpeta veremos las dependencias del proyecto. ASP.NET Core es un paquete NuGet y, por lo tanto, veremos un metapaquete bajo esta carpeta, “Microsoft.AspNetCore.All”, que a su vez referencia todos los paquetes pertenecientes a ASP.NET Core. Estas referencias también pueden verse en claro XML si editamos el archivo BizShowcase.csproj.
  • wwwroot: Web root del proyecto, aquí guardaremos archivos estáticos para referenciarlos directamente.
  • Program.cs: Punto de entrada de la aplicación. ASP.NET Core es una aplicación de consola, de modo que veremos el método Main en esta clase. En esta clase se configura el servidor por defecto: Kestrel, un servidor interno que ejecutará la aplicación (este servidor puede usarse en combinación con IIS, apache o nginx).
  • Startup.cs: Clase de configuración de la aplicación. Se realizan principalmente dos cosas:
    • Se define el “request pipeline”, una cadena de componentes que se ejecutarán en orden para cada petición que se realice a la aplicación. Esta capa también es llamada “middleware”.
    • Se configuran los servicios que se utilizarán en la aplicación, y que luego se utilizarán utilizando el patrón de “inyección de dependencias“.

Configurando la aplicación

Comenzaremos configurando lo básico dentro de Startup.cs. Lo primero que haremos es habilitar MVC. ASP.NET Core es un framework muy liviano y, por lo tanto, casi no hay características habilitadas por defecto.

Para habilitar MVC utilizamos el método ConfigureServices de la clase Startup y agregamos la línea:

Con esto agregamos el servicio a la colección de servicios administrados por el motor de inyección de dependencias.

A continuación configuramos la cadena de componentes que manejarán las peticiones HTTP:

  • UseDeveloperExceptionPage es un componente que nos permite ver los errores en forma algo más detallada, lo que se conoce en ASP como la “pantalla amarilla de la muerte“. Este componente únicamente debe utilizarse durante el desarrollo y no en el deploy final para no exponer información del servidor y la aplicación a los internautas.
  • UseStatusCodePages nos permite ver de forma textual códigos de error de tipo 400 y 500.
  • UseStaticFiles permite que la aplicación sea capaz de servir archivos estáticos (js, css, png, etc.).
  • UseMvcWithDefaultRoute. Si la petición llega a este punto entonces comienza a manejarse por el módulo de MVC siguiendo los patrones y estructuras que veremos a continuación.

Creando la primer página en ASP.NET Core 2

Vamos a estructurar la aplicación utilizando el patrón MVC. Esto no es necesario para realizar una aplicación pero es un patrón de diseño que me resulta claro y efectivo a la hora de desarrollar aplicaciones web. En resumen: la petición llega a un Controlador, el cual se vale del Modelo de datos para renderizar una Vista. De esta forma el Controlador se encarga de la lógica y gestión, el Modelo representa los datos de la aplicación y la Vista es la interfaz con la que el usuario interactúa.

Modelo

El modelo se compondrá del dominio de datos y de la lógica para gestionar estos datos, no así de la lógica y manipulación de los datos desde el punto de vista del negocio, esto último será tarea del controlador. La idea es disponer de una clase para los datos y otra clase que encapsule a la aplicación el manejo o persistencia de esos datos.

Para el modelo de datos se usaran objetos POCO (plain old C# objects), los cuales crearemos en la subcarpeta Models, que actuará a su vez de namespace, para organizar mejor el código:

Sin embargo esta clase sola no es suficiente, necesitamos una clase que gestione la persistencia de los datos. Para ello vamos a crear primero una interfaz que defina la estructura de esa clase:

Y luego, crearemos una clase de prueba, ya que no voy a crear una base de datos en este momento:

Finalmente, necesitamos registrar nuestros servicios para que actúen también por inyección de dependencias y así tengamos objetos menos acoplados. Para ello agregamos lo siguiente en la clase Startup:

AddTransient quiere decir que cada vez que algún objeto requiera un IProductoRepo se creará un nuevo MockProductoRepo, es decir siempre se obtendrá una instancia nueva. De igual manera existe AddSingleton, que quiere decir que sólo una instancia del objeto podrá estar vigente durante la vida de la aplicación, y AddScoped, la cual crear una sola instancia pero por petición, cada petición tendrá su propia instancia.

Más adelante cuándo implementemos una base de datos y definamos el mecanismo de persistencia, crearemos una nueva versión de esta clase, SQLProductoRepo, por ejemplo, y regresaremos a Startup para reemplazar MockProductoRepo.

Controlador

El controlador es el administrador del patrón MVC, debe responder a las peticiones del usuario y actualizar el modelo en consecuencia.

Para crear el controlador, al igual que con el modelo, crearemos una carpeta Controllers dentro del proyecto, y dentro de ella la clase HomeController que heredará de Controller:

Al recibir una petición el módulo Mvc elige un Controlador para gestionar la petición y es un método, también llamada Action, de este controlador quién ejecuta la lógica con la que se tratará la petición. Ese método o Action devolverá una vista como resultado que se renderizará en el explorador del usuario.

Por supuesto, no podemos avanzar mucho más sin la vista.

Vista

La vista es una plantilla que contiene definiciones para la presentación de la información y código dinámico orientado a esa tarea. Usarán la extensión .cshtml, lo que ya nos da una idea básica de lo que contiene: código en C# y HTML. Esta sintaxis se llama Razor. Por supuesto, también es posible entregar páginas estáticas.

Por convención, las vistas se almacenarán en la subcarpeta Views y dentro de ella en una sucarpeta con el nombre de la clase controlador que la invoca, sin la palabra Controller. Para el ejemplo del apartado anterior la carpeta se llamaría Home. Nuevamente, por convención, dentro de esa carpeta la vista que se renderizará será la que tenga por nombre el nombre del método que la invoca, por ejemplo: Index.cshtml. Si tal vista no es encontrada se lanzará una excepción.

Para hacer una prueba simple y cerrar el circuito vamos a agregar la siguiente línea en el controlador:

Y dentro de la carpeta Views/Home creamos el archivo Index.cshtml con el siguiente contenido:

Ahora ya estamos en condiciones de ejecutar la aplicación y si, no es ninguna sorpresa, veremos “Hola mundo!” en el navegador.

ViewBag es una de las formas de pasar datos entre el controlador y la vista, dentro del objeto podemos crear dinámicamente tantos parámetros como deseemos (ya que ViewBag es dynamic) y ya vemos la sintaxis de Razor que nos permitirá acceder al objeto, simplemente precediendo el parámetro con el caracter arroba (@).

Sin embargo, la mayor parte de las vistas que querremos usar serán fuertemente tipadas ya que será conveniente pasar un modelo. Modificamos entonces la acción como sigue:

De esta forma pasamos la lista de productos a la vista, la cual ahora adopta la siguiente forma:

Algunas cuestiones para notar aquí:

  • En la primera línea indicamos el tipo que tendrá el modelo, el cual luego será referenciado por Model
  • Utilizamos ViewBag como antes para mostrar esta vez el título
  • Utilizamos la sintaxis Razor para hacer un loop por todos los productos y mostrar el nombre y precio de cada uno de ellos

Un detalle a notar es que esta vista contiene todo el código html de la página, lo cual no sería una buena práctica en un sitio grande y sólo deberíamos incluir en la vista el código que hace a la vista y dejar todo el marco, menúes, etc. para las plantillas. .Net Core 2 dispone de dos convenciones que nos llevarán a tal fin:

  • _Layout.cshtml es un archivo especial que se utilizará como plantilla y ya que será utilizado por varias vistas se coloca en una carpeta especial llamada Shared, también dentro de Views.
  • _ViewStart.cshtml es un archivo especial que se carga antes que cualquier vista. Lo utilizaremos para indicar cual es la plantilla a utilizar.

Entonces creamos el archivo _Layout.cshtml dentro de la carpeta Shared (la cual creamos a su vez dentro de Views):

En donde @RenderBody() será el punto donde se insertará la vista. Por supuesto, ya podemos quitar de Index.cshtml todo el código html sobrante y sólo quedarnos con el contenido.

A su vez, bajo Views creamos _ViewStart.cshtml para indicar en cada vista cual es la plantilla que debe utilizarse:

Si ahora corremos la aplicación veremos la lista de productos.

Básicamente ya tenemos resuelto el tema, sin embargo esto podría mejorarse un poco más. Estamos usando en este momento dos métodos para pasar información a la vista: ViewBag y el modelo. ¿No sería posible tener un tipo de dato que incorpore toda la información que precisa la vista? ¿Algo así como un modelo de la vista?

Resulta que no sólo es posible, sino muy común. Utilizaremos entonces la carpeta ViewModels para almacenar este tipo de información:

Entonces modificamos la acción del controlador de la siguiente manera:

Por supuesto, ahora el tipo del modelo en la vista ha cambiado, de modo que ajustamos la vista como sigue:

Dando estilo a la vista

Si bien la página muestra la información que queremos, el último detalle sería darle algo de estilo visual, ya que las aplicaciones no sólo tienen que ver con lo funcional sino también con lo estético. Para ello añadiremos Bootstrap.

Actualmente para agregar paquetes del lado del cliente .Net Core 2 utiliza Bower (Microsoft ha anunciado, sin embargo, que cambiará a npm). Lo que sigue es el procedimiento para añadir bootstrap utilizando Bower:

  1. Agregamos el archivo bower.json al proyecto, agregando un nuevo item al proyecto y buscando por bower, aparecerá “Bower Configuration File”.
  2. En bower.json, dentro de “dependencies” agregamos: “bootstrap”: “v3.3.7”
  3. Apenas grabamos el archivo automáticamente se descargará bootstrap y todas sus dependencias y si miramos la carpeta wwwroot veremos que se crea la subcarpeta “lib” y dentro de ella las subcarpetas “bootstrap” y “jquery”.

Dentro de wwwroot agregamos la carpeta “images” y allí colocaremos algunas imágenes para ilustrar los productos.

Creamos también una carpeta “content” y dentro el archivo site.css:

Por supuesto, ahora tengo que referenciar esta hoja de estilo, al igual que bootstrap, en la plantilla y aprovecho para agregar algunas clases de bootstrap:

Finalmente, modifico la vista para mejorar el aspecto visual:

Si ejecutamos una vez más la aplicación obtendremos el siguiente resultado:

Conclusión

Por supuesto para realizar una aplicación completa aún falta bastante, pero esto puede dejar una clara idea de como se estructura una aplicación .Net Core 2 y cual es su potencial. Desde mi punto de vista lo que han logrado con este framework es muy interesante y ciertamente prefieron desarrollar aplicaciones web en C# en lugar de en PHP. Seguramente en algunos días volveré sobre este tema y agregaremos a esta aplicación la conexión con una base de datos real.

Pecho, dedo, mano (toma 1)

Me quedó dando vueltas una canción popular en el último viaje a San Clemente del Tuyú y me dije: “¿porqué no?”, y surgió este pequeño experimento, apenas un juguete para agilizar los dedos, pero que se deja escuchar. Falta ajustar un poco la mezcla, pero eso lo dejamos para otra sesión.

Bomber – Día 1

Cuándo era chico, alrededor de 7 años, me inicié en la informática con una Sinclair CZ 1000 que había comprado mi padre. Entre los juegos que compré posteriormente (los cuales venían en cassette, por cierto) había uno que recuerdo por haber jugado bastante que se llamaba Bomber… o Bombardero. El juego era muy similar al que se encuentra tras el siguiente link: https://pilibit.itch.io/bomber, versión que desarrollé, si aplica el término, hace bastante tiempo.

El caso es que es un juego con una mecánica muy simple y, para mi, es como un “Hola mundo” que utilizo con los motores de desarrollo que caen a mis manos. En el caso de este proyecto voy a hacer una versión potenciada de Bomber que tenga un aspecto visual agradable, una estética de tipo cartoon, mucho sentido de humor y una historia que lo haga llevadero.

Para quienes hayan tenido la pereza de seguir el enlace, el juego es muy simple: un avión pasa de derecha a izquierda de la pantalla y en el momento que elijamos debemos presionar el único botón que disponemos como control para soltar la bomba que debe caer justo en el objetivo que se encuentra debajo. Hay 10 pasadas disponibles y sumamos puntos cada vez que damos al blanco. Simple, no hay más, sólo eso.

En esta nueva versión intentaré ir un escalón más allá y realizar algunos agregados:

  • Aspecto cartoon: El juego apunta a niños, por lo tanto habrá muy poco o nada de texto y todo será colorido y divertido.
  • Historia: Un viejo cascarrabias es un clásico anti-héroe para historias infantiles y acá haré uso de él. ¿Que sucede? Pues que nuestro viejo vive al lado de una casa que tiene un huerto muy particular: las verduras, legumbres y hortalizas están vivas… muy vivas, tanto que viven de fiesta en fiesta. Nuestro viejo ya tiene ojeras hasta el suelo de no poder dormir y toma una drástica decisión: desempolvar su viejo biplano militar y bombardear a las verduras. A lo largo de todo un día el viejo intentará destruir a las verduras y luego, tal vez, lograr conciliar el sueño.
  • Niveles: En lugar de ser un sólo nivel que se repite por siempre, el juego se estructurará en 4 fases: “De mañana”, “De mediodía”, “De tarde” y “De noche”, cada una con 10 niveles. Estos niveles contarán la historia, irán agregando dificultad y simples mecánicas adicionales que añadan variedad al juego.

Finalmente, el juego será desarrollado con Unity Godot y apuntará a las plataformas PC, WebGL y Android.

Próximamente algo de arte conceptual…

Combinar archivos en windows desde la línea de comandos

Sin demasiada introducción, el formato que deberemos usar desde la línea de comandos es el siguiente:

Podrían usarlo directamente sin más, o tal vez podamos entender un poco de que se trata:

FOR

(dentro de un comando por lotes debe usarse %%variable, en línea de comandos puede usarse %variable).

Básicamente este bucle ejecuta el “comando” para el “conjunto” de archivos especificado. Específicamente en este caso, en cada iteración almacena el nombre del archivo en %f y ejecuta sobre ese archivo el comando type “%f” y agrega la salida al nuevo archivo merge_files.txt.

TYPE

Este comando reproduce el contenido del archivo pasado por parámetro.

>>

El comando APPEND agrega la salida del “comando” al “archivo”.

 

El Oficinista enojado / The Angry Office Worker

Para arrancar el 2018 con algo nuevo, me estoy introduciendo en el mundo de los Art Toy, haciendo en particular un curso de Needle Felting, para materializar esos juguetes en fieltro.

Mientras practico las ténicas de fieltrado, estoy planificando un primer muñeco, meramente de práctica:

La evolución del proyecto podrá seguirse desde mi perfile en Behance.

Deseo

Pensar que estos últimos minutos han sido una tortura es poco; 5 solamente han pasado, 55 quedan por delante, 3300 segundos de agonía que apenas se van reduciendo mientras deambulo por mis pensamientos. La gente camina delante mío ignorando completamente lo que me sucede. Pero de alguna forma es justo, yo también ignoro lo que les sucede a ellos. Quizás a simple viste luzcan tranquilos y hasta felices, absortos en sus propias vidas, agradecidos del tiempo que les toca vivir. A simple vista. Sin embargo por debajo de la superficie es donde la verdadera realidad de la persona se manifiesta, donde la agonía hace nido, guarda víveres y se prepara para quedarse una larga temporada. Para cuando nos damos cuenta de su existencia es demasiado tarde y ya ha pasado un tiempo allí, modificando su entorno y adaptándolo a sus necesidades, haciendo casi imposible deshacerse de ella. Las primeras manifestaciones son apenas unos malestares a la altura del estómago, muy leves, no es dolor siquiera, pero lo suficientemente perceptibles como para generar un extraña incomodidad, para ir ensombreciendo todo lo que nos ocurre durante el día. En ese estado no sabemos lo que es, sólo sentimos desgano y circulamos en piloto automático. Tiempo después el daño se ha acentuado y esa leve sensación desconocida se ha convertido en una expresión amarga, en aburrimiento y en la carencia absoluta de metas e intereses. En este estado es claro que ya todos nuestros conocidos, parientes, amigos, pareja e hijos lo han notado. Algunos tal vez expresen algún tipo de interés haciendo la observación que refiere a un “cambio”, pero la mayoría sólo deja de expresarse o se aleja: nos hemos convertido en una persona tóxica, desagradable, que los deprime. A veces esto último es cierto, pero a veces somos la excusa temporal que encuentran para la manifestación que apenas nace de su propia agonía haciendo nido. Es imposible saberlo, pero es posible que así sea.

50 minutos restantes, los agónicos aún siguen circulando sin notarme y la espera aún continúa. Tal vez debiera emplear estos últimos instantes en preguntarme “porqué”, pero no lo sé. Llegué hasta aquí de alguna forma, mediante alguna línea de pensamiento, ¿tiene sentido reproducir todo aquello, analizarlo y encontrarle alguna razón? Podría tenerlo salvo por un pequeño problema: el deseo. Es posible, o supongamos que lo fuera, que todas las justificaciones que me trajeron aquí sean equivocadas, todas y cada una de ellas y podría dedicar horas enteras en derribar cada una con argumentos sólidos e irrefutables. Sin embargo la decisión final podría no modificarse y podría, llegado el caso, decidir actuar en contra de toda razón y a voluntad simplemente porque quiero hacerlo. El deseo suele ser tan poderoso que todo el resto es irrelevante. Las razones, las excusas, las explicaciones que nos damos para actuar son una mentira que intenta enmarcar el deseo en el tipo de vida que decidimos llevar como sociedad, necesitamos justificar lo que hacemos, necesitamos ser humanos y eso implicar ser seres pensantes, que razonan, que no actúan por impulso. Eso nos diferencia de los animales después de todo.

Me pregunto si tal vez el deseo no es el remedio de la agonía. Más aún, podría ser tal vez que la agonía sea una consecuencia directa de la vida que llevamos. Sin embargo hay personas con real apariencia de felicidad y realización, y ellas también viven presas de la misma sociedad. ¿Será que algunos son inmunes? Tal vez pero conjeturar eso sería inútil porque no puedo demostrarlo. Lo que sí puede ser posible y comienzo a verle más sentido es que puede que hayan aprendido a utilizar el deseo de forma correcta. Es posible que si uno vive de determinada manera no sea necesario justificar las acciones que son fruto del deseo porque, en esos caso, el deseo está perfectamente alineado con el camino planteado y entonces es imposible distinguir una acción fruto del deseo de una que fuera consecuencia de un razonamiento lógico. Me entusiasma esta idea porque tiene todo el sentido del mundo… pero a la vez me atemoriza. ¿Cual es la fórmula o el secreto para lograr esa alineación? Más aún, y aún conociendo de que manera el camino que nos planteamos y el deseo  confluyen, ¿es posible llegar a ese estado habiendo vivido una vida que carece de ese equilibrio? Una respuesta negativa en ese estado, y la sola idea de que pueda existir, no hace otra cosa que alimentar mi agonía. Pero a la vez pienso en los próximos 40 minutos y siento esa excitación que sólo el deseo sabe generar.

Algunas personas que pasan me miran extrañadas y, claro, sé la razón, seguramente estoy hablando en voz alta otra vez. A veces no puedo evitarlo cuando estoy demasiado inmerso en mis pensamientos, desenmarañando ideas que no tienen un sentido o lógica aparente, moldeándolas para que puedan ser claras y precisas. Pero claro, a la luz de lo que he descubierto me parece que eso está reñido con la idea del deseo, de alinear mi vida con él, de seguir una senda donde mi deseo y su satisfacción se vean como la secuencia lógica de acciones que debería seguir para no desviarme. En este momento no lo parece y siento que mis acciones me llevan a desenlaces horribles, sin embargo el deseo me moviliza en ese rumbo.

Es claro… que imbécil, es claro. Es lo que siempre sucede, ahora lo veo. Queda menos de media hora y mis nervios están comenzando a actuar. ¡Cómo puedo ser tan tonto! A medida que se acerca el momento y al yo saber que no debería hacerlo, aunque ya establecí que sí porque por algo estoy aquí, me siento más nervioso y mi mente comienza a arrojarme ideas que nublan mi juicio, me está llevando a razonar, de una forma convincente, que si bien debo satisfacer mi deseo no es este el mejor momento porque mi actual rumbo no está alineado con mi deseo y, por lo tanto, con mi siguiente curso de acción. Repensar lo ya pensado puede llevar a decisiones contrarias, esto  es claro. Sin embargo cuando esta reelaboración de las ideas se produce en las inmediaciones del instante de tiempo límite no tenemos ninguna forma de saber que el razonamiento es puro, lo más probable es que no lo sea y que esté viciado por los nervios de último momento. Es decir, este no es el mejor momento para hacer caso a la razón. Ante la duda es mejor no cambiar de rumbo o, para decirlo de otro modo, las decisiones deben basarse en ideas sólidas y acabadas y este no sería el caso.

Mientras las persianas suben, rechinando como siempre, veo al señor Giorgio ponerse el delantal y preparar sus elementos. El momento es inminente, lo sé. El momento es inevitable, también lo sé. Llegar temprano fue buena idea aunque casi cometa un error. Es verdad, todo indicaría que luego voy a arrepentirme, pero estos minutos previos me han mostrado nuevas ideas para reelaborar mi vida de forma tal que el deseo esté alineado con ella, ¿porqué debo reprimirme? Si el deseo me hace actuar de determinada forma y esas acciones me producen placer, entonces no es el deseo lo que está mal, sino mi vida que luego me obliga a pensar que lo que hice era lo incorrecto. Debo cambiar la concepción de lo que soy. ¿Y si mi vida fuera distinta, una tal que conviva en armonía con mis deseos? Tal vez entonces desaparecería la reprimenda posterior, no habría culpa luego de la satisfacción del deseo y, por lo tanto, viviría en dicha permanente. ¡Es emocionante! Sólo debo cambiar unas pocas ideas fundamentales y así seré completamente feliz.

Ya es hora:

– Buenos días señor Giorgio.

– Buenos días caballero, me pareció raro no verlo por aquí ayer.

– Tuve un inconveniente, pero creo que eso no va a pasar más. Es más, creo que a partir de hoy voy a venir todos los días. Me siento muy bien.

– Pues bien por usted. Será un placer serle de utilidad, ¿que se le ofrece el día de hoy?

– Veamos: deme un especial, como siempre, y también voy a llevar 6 donas, pero de las rellenas con dulce de leche y cubiertas con chocolate… ah, y una porción de ese pastel, se ve muy bien.

– Buena elección, la especialidad de mi mujer, lo hicimos esta mañana, muy fresco.

– No puedo esperar para saborearlo.

Y no voy a hacerlo, nunca más esperaré o me privaré. Hoy soy un hombre nuevo. 253 kilos no son excusa para no ser feliz, me acepto como soy y a disfrutar. Así es… a disfrutar.