Archive for Code

ResaCON 2009

Todo surgió de esta idea:

Con lo interesantes que se ponen las conversaciones a veces cuando nos vamos de cena, ¿por qué no montamos una con y nos contamos las cosas que hacemos como $DEITY manda?

Después de un periodo de incertidumbre y de apurar un poco con las fechas (una deadline es una deadline al fin y al cabo), el pasado fin de semana tuvo lugar la ResaCON 2009: once amigos y yo, cada uno con una presentación bajo el brazo, una pantalla grande, una nevera con refrescos y algo para picar. El resultado fue espectacular: se habló de gráficos, IA, emulación, videojuegos, lenguajes de programación, robotitos, proyectos personales varios, silverlight, profiling y hasta de creación de empresas… todo ello en un ambiente familiar y distendido.

Por supuesto luego hubo tiempo para irnos de cena y de fiesta :D

En definitiva, he disfrutado de lo lindo y espero que repitamos el año que viene (¡muchas gracias a todos, moláis un gritón!) . En los próximos días subiré a algún sitio las presentaciones que me dejen subir, permanezcan en sintonía. De momento os dejo con un enlace a mi presentación de introducción a Clojure.

Comments (3)

Valgrind: tracking the origin of undefined values

Today I was wondering if one of those warnings about uninitialized values was located in library code or in my own code, and I noticed a new message in Valgrind’s output:

Use –track-origins=yes to see where uninitialised values come from

This feature was first added to Valgrind 3.4.0 back in January, and it’s great! I wish I had known it before, because it would have spent me a few headaches in the past months, so I decided to write it here just in case I can help someone :)

Comments

crash handling

Estaba yo preguntándome esta tarde si sería posible lanzar de forma automática gdb cuando un programa cascara, sin necesidad de ponerse a depurar después, reproducir el bug, etc, al estilo del manejador de errores que instala Visual Studio en Windows que pregunta si se desea depurar la aplicación.

Me ha salido algo como esto (HTML horrible para el coloreado de sintaxis patrocinado por Vim):

#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

void attach_gdb(int signum)
{
    pid_t gdbpid;
    pid_t debuggee_pid = getpid();
    int gdb_exit_status;
    char pidbuf[100];
    char exebuf[100]; // should be safe unless PIDs reach ~90 digits ;P
    sprintf(pidbuf, "%d", debuggee_pid);
    sprintf(exebuf, "/proc/%d/exe", debuggee_pid);
    printf("Signal %d received. Attaching GDB to process. PID=%d\n", signum, debuggee_pid);

    if ((gdbpid = fork()) == 0)
    {
        execlp("gdb", "gdb", exebuf, pidbuf, NULL);
        perror("execlp");
        exit(1);
    }

    waitpid(gdbpid, &gdb_exit_status, 0); // hold on, we want to be debugged
    exit(1);
}

void __attribute__((constructor)) setup_handler()
{
    struct sigaction sa, old_sa;
    sa.sa_handler = attach_gdb;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags=0;
    // Register the handler for all actions which dump core by default
    sigaction(SIGSEGV, &sa, &old_sa);
    sigaction(SIGFPE, &sa, &old_sa);
    sigaction(SIGABRT, &sa, &old_sa);
    sigaction(SIGILL, &sa, &old_sa);
    sigaction(SIGQUIT, &sa, &old_sa);
}

Si se compila como librería dinámica y se enlaza a cualquiera de nuestros programas (o se precarga con LD_PRELOAD) lanza un gdb asociado al proceso al recibir cualquiera de las señales que causarían un core dump y terminación del programa :D.

¿Alguna idea para mejorarlo y que sea práctico? ¿Existe ya algo asi en un paquete Debian que hace mil cosas molonas más? (seguro que sí XD).

Comments (1)

Jugando con Qt

El otro día me encontré con edb (una especie de OllyDbg para linux) y al ver la buena pinta que tenía me acordé de lo bonito que sería tener una interfaz gráfica para depurar en mi emulador de GameBoy. Me he puesto a juguetear con Qt y me está gustando. Está muy bien documentada y es bastante agradable de usar, una vez se pasa el susto de ver esas cosas raras como “public slots:” en mitad de la declaración de una clase en C++.

De momento he conseguido integrar el emu en una ventana de Qt, el redibujado va bastante más rápido de lo que me esperaba, y tengo el emulador en un hilo y la parte gráfica en otro. Ahora me falta empezar de verdad con el debugger. Ahi va un shot :)

qtboi screenshot

Comments (3)

wenboi

Llevo algún tiempo escribiendo a ratos un emulador de Game Boy. Me picaba el tema de la emulación y shash me había comentado que la Game Boy era facililla de emular y me pasó algo de documentación. Pues bien, ha llegado el momento de que vea la luz. Con todos ustedes… wenboi!

wenboi screenshot

Todavía está en pañales pero ya se puede empezar una partida de Tetris y colocar piezas, y es éste el hito que me ha llevado a poner la etiqueta de “version 0.1” y hablar un poquito del emulador aqui ;)

Por si alguien quiere cotillear, he creado una pequeña homepage de wenboi con información sobre el acceso al repositorio de Git y tambien he dado de alta a wenboi en Ohloh para que me analicen el repositorio, me saquen graficos de actividad y me digan que pongo pocos comentarios en el código. También hay un pequeño devlog que no sé si actualizaré demasiado.

Happy hacking!

Comments (1)

ctypes

El otro día me encontré con un módulo interesante de python que no conocía: ctypes. Sirve para comunicarse con librerías en C: permite cargar librerías dinámicas y llamar a sus funciones, definir tipos equivalentes a los de C para pasarlos de un lado a otro e incluso especificar funciones python como callbacks de C. Vamos, que se pueden crear bindings a librerías externas escribiendo únicamente código python.

Ahi va un ejemplillo tonto usando la libavformat:

#!/usr/bin/python
import sys
from ctypes import *
import ctypes.util

av = CDLL(ctypes.util.find_library("avformat"))
filename = sys.argv[1]
# pFormatCtx deberia ser un puntero a AVFormatContext, 
# pero esto es solo un ejemplo simple :)
pFormatCtx = c_void_p() 

av.av_register_all()
av.av_open_input_file(byref(pFormatCtx), filename, None, 0, None)
av.dump_format(pFormatCtx, 0, filename, 0)

Por supuesto para hacer algo más serio habría que declarar en python las estructuras como AVFormatContext que se definen en las cabeceras correspondientes y cosas así, pero entonces el programa de ejemplo sería demasiado engorroso como para leerlo en un blog ;). El ejemplo muestra una salida como esta:

$ ./av.py test.avi 
Input #0, avi, from 'test.avi':
  Duration: N/A, bitrate: N/A
  Stream #0.0: Video: mpeg4, 512x420,   inf fps(c)
  Stream #0.1: Audio: vorbis, 22050 Hz, stereo, 24 kb/s

Referencias:

Comments (3)

Síntesis musical para mí (o para torpes en general :) III

3) Más ondas básicas

No solo de senos vive el hombre (salvo que nos pongamos a hacer síntesis aditiva), así que vamos a ver unas cuantas ondas más que podemos utilizar como base para construir sonidos.

  • Onda cuadrada:

    Get the Flash Player to see this player.

    Se obtiene alternando dos valores (en nuestro caso +1 y -1) con la frecuencia deseada. Expresado en código, podría ser algo como esto:

    // Generacion del i-esimo sample de una onda cuadrada 
    // de frecuencia f
    float t = i/sampling_rate; // instante i en segundos
    float periodo = 1.0f / f; // periodo de la onda en segundos
    if (fmodf(t,periodo) < periodo/2.0f)
        y[i] = 1.0f;
    else
        y[i] = -1.0f;
    

    Onda cuadrada.

    Otra posibilidad es hacer que las zonas a +1 y -1 no tengan la misma longitud (pulse width modulation)

  • Onda de diente de sierra:

    Get the Flash Player to see this player.

    En cada periodo, aumenta linealmente desde -1 a 1, cayendo bruscamente a -1 en el comienzo del siguiente periodo. Dicho en C viene a ser:

    // Sample i-esimo, frecuencia f
    float t = i/sampling_rate;
    float periodo = 1.0f / f;
    y[i] = 2.0f*(fmodf(t, periodo)/periodo)-1.0f;
    

    Onda de diente de sierra.

  • Onda triangular:

    Get the Flash Player to see this player.

    Es parecida a la anterior, pero durante la mitad del periodo crece linealmente de -1 a 1, y durante la otra mitad decrece linealmente volviendo a -1, sin discontinuidad.

    // Sample i-esimo, frecuencia f
    float t = i/sampling_rate;
    float periodo = 1.0 / f;
    float semiperiodo = periodo/2.0f;
    if (fmodf(t,periodo) < periodo/2.0f)
        y[i] = 2.0f*(fmodf(t,semiperiodo)/semiperiodo)-1.0f;
    else
        y[i] = 1.0f-2.0f*fmod(t,semiperiodo)/semiperiodo;
    

    Onda triangular.

En el programa de ejemplo de este capítulo (ahora con un 100% más de Makefile) está todo esto en forma compilable para poder probarlo fácilmente. Por cierto, ninguno de los ejemplos está optimizado porque pretenden ser lo más claros posible, si alguien tiene sugerencias sobre como implementar mejor cualquier cosa nos lo podemos pasar muy bien comentándolas :)

En fin, esto es todo por hoy. En el próximo post, cosillas sobre espectros de frecuencias y aliasing (supongo que la pereza me obligará a dejarme los filtros para dentro de dos posts :)

EDIT: A peticion de pplux, ahi van los enlaces a los posts anteriores:

Comments (4)

Síntesis musical para mí (o para torpes en general :) II

2) Senos!!!

Después del ruido del capitulo anterior, vamos a pasar a algo ligeramente más interesante: la onda senoidal. Como podéis ver si seguís el enlace a la pagina sobre la onda senoidal en la wikipedia, junto con dibujitos y explicaciones interesantes, la formula es:

y = A·sin(w·t + fase)

donde A es la amplitud de la onda (la distancia entre una cresta y un valle), w es la frecuencia en radianes/segundo y t es el tiempo. Vamos a ignorar la fase porque no nos hace falta :)

Como nos gusta trabajar con frecuencias en hercios, multiplicamos por 2·pi. Además, tenemos que t = samples generados / frecuencia de muestreo. Por lo tanto en el código tendremos algo como:

y[i] = A*sin(2*pi*frecuencia*(i/sampling_rate))

para el sample i-ésimo desde el inicio del sonido. Vamos a ver el trozo de código correspondiente (lo que falta es, básicamente, la inicialización del capítulo anterior):

void play(void *userdata, Uint8 *stream, int len)
{
    int num_samples = len / 2;
    Sint16 *dst_buf = (Sint16*) stream;
    for (int i=0; i<num_samples ; ++i)
        buffer[i] = sin(2.0*M_PI*440.0f*(i+pos)/(float)SAMPLING_RATE);
    
    // Clipping y conversion a Sint16
    for (int i=0; i<num_samples; ++i)
    {
        float v = buffer[i];
        if (v > 1.0f)
            v = 1.0f;
        else if (v< -1.0f)
            v = -1.0f;

        dst_buf[i] = (Sint16)(32767.0f*v);
    }
    pos += num_samples;

}

Detalles destacables de esta función:

  • se trabaja con un buffer de floats y se convierte a entero al final. No mola ir perdiendo precisión por el camino, sobre todo cuando hagamos cosas mas complejas
  • hay clipping a [-1.0, 1.0]. Ahora mismo es completamente innecesario porque sin() devuelve valores en ese intervalo, pero cuando empecemos a mezclar varios sonidos vendrá bien :)
  • en la llamada a sin(), el 440.0f es la frecuencia de la nota que suena (un La4), y pos es una variable global que guarda el índice del ultimo sample generado entre llamadas a play(). Es feo, pero para un ejemplo pequeño va bien.

En el próximo episodio (ahora es tarde y tengo sueño), veremos otros osciladores típicos y cosas interesantes que se pueden hacer con ellos.

EDIT: herotyc me ha enviado una versión stand-alone del ejemplo de este capítulo. ¡Muchas gracias! :)

Comments (14)

Síntesis musical para mí (o para torpes en general :)

Por petición popular (hola pplux) voy a hacer una pequeña introducción a la síntesis de audio desde el punto de vista de un coder sin experiencia previa en DSP que pretende hacer un sintetizador para intros de 4k (yo). Por supuesto, incluirá ejemplos de código. C99 y SDL for teh win.

0) Disclaimer
Esto no tiene por qué ser la forma correcta de hacer las cosas. Hasta donde yo sé funciona, pero seguro que hay muchos fallos en muchos sitios. Son bienvenidos los comentarios, tanto para corregirme los fallos como para comentar cualquier otra cosa al respecto :). Y como se suele decir en estos casos, si alguno de los ejemplos de código rompe algo o deja sordo a alguien yo no me hago responsable.

1) Haciendo ruido

En primer lugar, el clásico trozo de codigo de inicialización que todo el mundo copia y pega y nadie lee:

#include "SDL.h"

#define BUFFER_SIZE 1024    // Longitud del buffer, en samples

// Este comentario esta extraido de SDL_audio.h, porque me ha molado
/* This function is called when the audio device needs more data.
 * 'stream' is a pointer to the audio data buffer
 * 'len' is the length of that buffer in bytes.
 * Once the callback returns, the buffer will no longer be valid.
 * Stereo samples are stored in a LRLRLR ordering.
 */
void play(void *userdata, Uint8 *stream, int len)
{
    int num_samples = len / 2;
    Sint16 *buf = (Sint16*) stream;
    for (int i = 0; i<num_samples ; ++i)
        buf[i] = rand()%65535-32768;

}

int main(int argc, char **argv)
{
    SDL_AudioSpec desired;
    desired.freq     = 44100;        // Frecuencia de muestreo                             
    desired.format   = AUDIO_S16SYS; // Formato de las muestras
    desired.channels = 1;            // Numero de canales
    desired.samples  = BUFFER_SIZE;  // Tamaño del buffer en samples
                                     // (potencia de 2)
    desired.callback = play;         // Callback
    desired.userdata = NULL;         // Puntero a datos
    
    SDL_Init(SDL_INIT_AUDIO);        
    SDL_OpenAudio(&desired, NULL);
    SDL_PauseAudio(0);
    getchar();
    SDL_PauseAudio(1);
    SDL_CloseAudio();
    SDL_Quit();
}


La parte importante esta en buf[i] = rand()%65535-32768; Como hemos elegido AUDIO_S16SYS significa que utilizamos muestras de 16 bits con signo [-32768, 32767], con endianismo dependiente del sistema (como accedemos al buffer con punteros a entero de 16 bits, el endianismo no será problema). Generamos numeros aleatorios en ese rango y ya tenemos ruido blanco saliendo de nuestros altavoces.

No se pierdan el proximo episodio.

EDIT: He cambiado el titulo, de “sintesis de audio” a “sintesis musical” porque lo primero era demasiado general :)

Comments (777)

Historias de hackers y espías

Una de las cosas más interesantes que conozco es oir a un hacker contar batallitas. Esta noche, entre uvas, comida y demás jolgorio, Gus me ha comentado que habia estado viendo un vídeo en el que un tal tmbinc contaba como saltarse las protecciones de la Wii, con momentos de grandes risas durante la explicación.

Dicho vídeo procede de una charla más larga, llamada “Console Hacking 2006” (ogm, 140Mb), que a su vez formaba parte del 23C3 (23ª edición del Chaos Communication Congress, organizado por el célebre Chaos Computer Club), que ha tenido lugar del 27 al 30 de diciembre. Pues bien, todo el congreso ha sido emitido por streaming de video y las grabaciones de las ponencias se pueden descargar desde los mirrors. Esto supone horas y horas de charla interesante sobre temas como seguridad informática, lingüística, sociedad, videojuegos, software libre, comunicaciones, hardware…

Por cierto, me molaria MUCHO, pero MUCHO MUCHO, asistir al proximo CCC. ¿Alguien se anima?

En otro orden de cosas, llevo un par de dias leyendo sobre las number stations, estaciones de radio (no comerciales) de onda corta que emiten mensajes cifrados, en forma de ristras de números leídos por voces monótonas e incansables, supuestamente controladas por los gobiernos de algunos países para enviar información a sus espías.

The Conet Project es una recopilación de grabaciones de diferentes estaciones de números. Algunos radioaficionados se dedican a hacer seguimientos a estas estaciones, les ponen nombre basándose en lo que suena en esas frecuencias antes o después de las retahílas de números (por ejemplo, existe una conocida como “Magnetic Fields” porque utilizan el tema de Jarre con ese nombre como preludio), y controlan los horarios y frecuencias de emisión. Mi buen amigo stage7, tras una conversación con él sobre el tema, consiguió grabar un fragmento de la emision de la estación conocida como “Lincolnshire Poacher“, supuestamente controlada por el MI5 británico y que emite desde Chipre. Resulta curioso que en pleno siglo 21 siga siendo efectivo un método de envio de mensajes tan rústico.
Todo esto da un poco de miedo ¿no? :)

¡Feliz año nuevo!

P.D.: ¿He dicho ya que me gustaría mucho asistir al próximo CCC? :D

Comments (2)

« Previous entries Next Page » Next Page »

This blog is protected by Dave\'s Spam Karma 2: 17770 Spams eaten and counting...