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 :)

777 Comments

  1. pplux said,

    April 17, 2007 @ 18:44 pm

    Oh si!
    Queremos más!!!! :)
    Preguntas:
    – sólo puede sonar una cosa a la vez?
    – cómo sincronizas el sonido con la demo? (esto supongo que para otra entrada XD)

  2. slack said,

    April 17, 2007 @ 18:56 pm

    Las respuestas detalladas vendrán en otros posts más adelante. Asi a bote pronto:

    – No, puedes mezclar varias cosas sumando las señales.
    – tiempo transcurrido = numero de samples generados / sampling rate. :)

    Aparte de eso puedes utilizar para sincronizar la información de la propia musica. Si quieres el clasico flash cuando suena un bombo, cuando llega el momento de sintetizar el bombo haces flash=true; en alguna parte y lo lees desde otro lado

  3. javi said,

    April 19, 2007 @ 14:15 pm

    Hace un tiempo hice un pequeño documento sobre síntesis de sonido:

    http://qualopec.googlepages.com/4ksynth

  4. Ras said,

    April 20, 2007 @ 10:15 am

    ¿Nos enseñarás a crear sonidos binaurales? :-)

  5. slack said,

    April 20, 2007 @ 12:32 pm

    Va a ser que no. Principalmente porque no sé :-)

  6. javi said,

    April 20, 2007 @ 23:50 pm

    @pplux: para sincronizar la forma que yo usé en la 4kb que hice fue generar la música a un wav, lo miré en un editor de audio, vi los tiempos en los cuales quería hacer algo y después en el código a piñón:

    if(Gtime 38.6f && Gtime

  7. Miguel said,

    April 24, 2007 @ 11:02 am

    Que bien, ruido blanco.

    Por si no lo sabes, más caracteristicas del ruido blanco:

    Puede ser usado para desorientar a personas antes de un interrogatorio y como técnica de privación sensorial. Por otra parte, el ruido blanco de baja intensidad puede favorecer la relajación y el sueño. En las tiendas pueden comprarse CDs con largas secuencias de ruido blanco.

  8. herotyc said,

    April 25, 2007 @ 00:28 am

    Hey, interesante slack! No dudaré en probar y jugar con el código que propones cuando tenga un instante.

    Por lo del ruido blanco, deberías escuchar(tranquilamente) “Biosphere – substrata”… ambient del bueno.

RSS feed for comments on this post

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