SDL en C bajo GNU/Linux 009 – Cientos de tipos de módulos de sonido


  
xmp es un player para línea de comandos que soporta la tela 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.
  
Si deseas saber más sobre lo que son los módulos musicales y como iniciarte en el mundo de la composición musical con trackers puedes mirar estos artículos:
  

  1. Milkytracker – Creación de módulos musicales Vol.1
  2. Milkytracker – Creación de módulos musicales Vol.2
  3. Milkytracker – Creación de módulos musicales Vol.3
  4. Milkytracker – Creación de módulos musicales Vol.4

  
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: http://xmp.sourceforge.net/
API documentación: http://xmp.sourceforge.net/libxmp.html
Ejemplos: http://xmp.sourceforge.net/examples/
Descargar libxmp: libxmp-4.4.1.tar o aquí.

Instalar libxmp-dev en Debian/Ubuntu:

apt-get install libxmp-dev

Entre los modulos que soporta 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 esta librería.
  
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.
  
Puedes bajarlo de aquí con su makefile adaptado: https://mierda.tv/descargas/playmod1.zip
 
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:
 

#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;
}

  

Lo compilamos con make en el directorio en el que tenemos el makefile.
 
 
Para ejecutarlo y probar he dejado 3 módulos de diferente tipo en el directorio res (it, mod, xm). De modo que para probar si chuta así:

cd bin
./playmod res/modulo2.it 

  
Veremos algo como esto:


  
Y escucharemos el modulo que le hemos pasado como parámetro.
  
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. Des-pa-ci-to.
  

Información sobre los módulos importante.

  
Hace casi un mes que programé un player para módulos formato protracker (para el sistema operativo AmigaOS4.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: http://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 traves de ingenieria inversa: http://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 modulos y poco más.
  
Salvo que queramos realizar un editor tracker en SDL lo normal es que usemos la librería para simplemente reproducir música.
  
Saludos cordiales.

próximo Publicación

Atrás Publicación

Dejar una contestacion

© 2018 [ MIERDA TV ]

Tema de Anders Norén