xmp es un player para l铆nea de comandos que soporta un mont贸n de m贸dulos musicales y al mismo tiempo es una librer铆a (est谩 desarrollado sobre esa librer铆a) que nos permite utilizarla para por ejemplo reproducir m贸dulos en nuestros programas.
En este articulo simplemente vamos a integrar la librer铆a xmp.h junto con SDL.h y ver como podemos trabajar con cientos de tipos diferentes de m贸dulos e integrarlos en nuestros programas/demos/juegos/… con SDL2.
Informaci贸n sobre xmp y libxmp (versi贸n 4.4.1):
Website: xmp.sourceforge.net/
API documentaci贸n: xmp.sourceforge.net/libxmp.html
Ejemplos: xmp.sourceforge.net/examples/
Descargar libxmp: libxmp-4.4.1 aqu铆.
Instalar libxmp-dev en Debian/Ubuntu:
apt-get install libxmp-dev
Entre los m贸dulos que soporta (m谩s de 90) este player y su librer铆a podemos destacar estos:
- Protracker
- OctaMED
- MilkyTracker
- Fast Tracker
- Fast Tracker II
- Impulse Tracker
- DIGI Booster
- Scream Tracker 2
- Scream Tracker 3
- Ice Tracker
- Oktalyzer
- Composer 669
- Digitrakker
- Farandole Composer
- Funktracker
- Imago Orpheus
- Liquid Tracker
- Multitracker
- Poly Tracker
- Real Tracker
- TakeTracker
- Ultra Tracker
- X-Tracker
- Game Music Creator (GMC)
- Galaxy Music System
- Digital Tracker
- Flextrax
- Graoumf Tracker
- Octalyser
- TCB Tracker
- Archimedes Tracker
- …
Al margen de que con SDL2 base se puede reproducir wav y que con otras librer铆as podemos reproducir ogg, mp3, … la idea es poder secuenciar m贸dulos m谩s que otra cosa. Eso nos permite tener acceso a los instrumentos e incluso mutear canales.
Yo prefiero usar xmp.h ahora mismo para poder incluir m煤sica molona que se genera en tiempo de ejecuci贸n. No obstante en futura entradas veremos que para un ogg o un mp3 no necesitamos a帽adir nada extra.
Lo primero es probar que la cosa funciona bien. Si hemos instalado la librer铆a (tanto sdl base como libxmp-dev) vamos a ver uno de los ejemplos que ofrecen junto a la librer铆a xmp.
Descargar el c贸digo de ejemplo con m贸dulos de sonido y todos los directorios necesarios: playmod.tar.gz
El makefile que solemos usar ha sufrido en este caso una alteraci贸n (-lxmp) para poder compilar:
CC := gcc CFLAGS := -Wall LINKER_FLAGS = `sdl2-config --cflags --libs` -lxmp test: make clean make build build: $(CC) $(CFLAGS) -o bin/playmod playmod.c $(LINKER_FLAGS) run: ./bin/playmod clean: -rm bin/playmod
Y aqu铆 va el c贸digo de ejemplo que viene con libxmp (que guardamos en un archivo llamado playmod.c:
#include <stdio.h> #include <stdlib.h> #include <SDL.h> #include <xmp.h> static int playing; static void fill_audio(void *udata, Uint8 *stream, int len) { if (xmp_play_buffer((xmp_context)udata, stream, len, 0) < 0) playing = 0; } static int sdl_init(xmp_context ctx) { SDL_AudioSpec a; if (SDL_Init(SDL_INIT_AUDIO) < 0) { fprintf(stderr, "sdl: can't initialize: %s\n", SDL_GetError()); return -1; } a.freq = 44100; a.format = AUDIO_S16; a.channels = 2; a.samples = 2048; a.callback = fill_audio; a.userdata = ctx; if (SDL_OpenAudio(&a, NULL) < 0) { fprintf(stderr, "%s\n", SDL_GetError()); return -1; } return 0; } static void sdl_deinit() { SDL_CloseAudio(); } int main(int argc, char **argv) { xmp_context ctx; struct xmp_module_info mi; struct xmp_frame_info fi; int i; ctx = xmp_create_context(); if (sdl_init(ctx) < 0) { fprintf(stderr, "%s: can't initialize sound\n", argv[0]); exit(1); } for (i = 1; i < argc; i++) { if (xmp_load_module(ctx, argv[i]) < 0) { fprintf(stderr, "%s: error loading %s\n", argv[0], argv[i]); continue; } if (xmp_start_player(ctx, 44100, 0) == 0) { /* Show module data */ xmp_get_module_info(ctx, &mi); printf("%s (%s)\n", mi.mod->name, mi.mod->type); /* Play module */ playing = 1; SDL_PauseAudio(0); while (playing) { SDL_Delay(10); xmp_get_frame_info(ctx, &fi); printf("%3d/%3d %3d/%3d\r", fi.pos, mi.mod->len, fi.row, fi.num_rows); fflush(stdout); } xmp_end_player(ctx); } xmp_release_module(ctx); printf("\n"); } xmp_free_context(ctx); sdl_deinit(); return 0; }
En el directorio res dentro de bin he dejado algunos modulos de ejemplo ( 56k.es/wp-content/uploads/2021/01/mods.zip ). No necesitas descargarlos si has bajado el tar.gz con el c贸digo de ejemplo.
Lo compilamos con make en el directorio en el que tenemos el makefile. (make build)
De modo que para probar si chuta as铆:
cd bin ./playmod res/lickit.mod
Veremos algo como esto:
Lo cierto es que el ejemplo sirve para saber que la cosa chuta pero no es lo 贸ptimo. Lo ideal es usarlo en nuestro programa para elegir desde este cuando sonar谩 un modulo y que modulo ser谩.
Con paciencia poco a poco.
Informaci贸n sobre los m贸dulos importante.
Hace un tiempo que program茅 un player para m贸dulos formato protracker (para AmigaOS 4.1).
Me toc贸 buscar mucha documentaci贸n sobre como funcionan realmente estos m贸dulos. Este texto rescatado de textfiles.com me sirvi贸 de mucha ayuda: www.textfiles.com/programming/AMIGA/protrack.ami.
Aunque tiene extensi贸n ami es un texto plano que puedes abrir con cualquier editor.
Tambi茅n puede ser de utilidad este texto con conclusiones sacadas a trav茅s de ingenier铆a inversa: www.textfiles.com/programming/FORMATS/modulesg.txt
Lo interesante es que cuando cargas un archivo y lo atacas podr谩s ir posicion谩ndote para sacar la informaci贸n que necesitas para reproducirlo. En ese archivo se define por ejemplo donde se almacena el titulo de un modulo. el nombre de los samples, …:
Offset Bytes Description ------ ----- ----------- 0 20 Songname. Remember to put trailing null bytes at the end... 20 22 Samplename for sample 1. Pad with null bytes.
Es bueno conocer como son estos archivos y su estructura, no obstante como estamos tirando de libxmp no necesitaremos conocer tanto y vamos a poder realizar la mayor铆a de cosas sin siquiera saber mucho sobre los m贸dulos. Nos dedicaremos a cargar m煤sica, pausar m煤sica, pararla, extraer informaci贸n de los m贸dulos y poco m谩s.
Si andas en GNU+Linux aqu铆 tienes un post que lo mismo te permite entender m谩s a fondo el formato mod protracker: 56k.es/fanta/anatomia-binaria-de-un-mod-protracker-con-dd/
Salvo que queramos realizar un editor tracker en SDL lo normal es que usemos la librer铆a para simplemente reproducir m煤sica.
Y que si queremos un tracker en SDL milkytracker es crema.
Saludos cordiales.