#include #include #include #include "sndfile.h" #include "fmt.h" /* * gcc -O2 -o playit-alsa playit-alsa.c -I.. -I../src/include -DHAVE_CONFIG_H -lm `pkg-config alsa --cflags --libs` -s ../src/libplayit.a */ song_t * song_load_it(const char *file) { slurp_t *s; song_t *song; s = slurp(file, NULL, 0); if (!s) { printf("failed to open \"%s\"\n", file); goto _fail; } song = csf_allocate(); if (!song) { printf("failed to allocate song\n"); goto _fail_slurp; } if (fmt_it_load_song(song, s, 0) != LOAD_SUCCESS) goto _fail_song; unslurp(s); return song; _fail_song: csf_free(song); _fail_slurp: unslurp(s); _fail: return NULL; } static snd_pcm_t * alsa_open(const char *dev) { snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; int err; unsigned int rate = 44100; snd_pcm_t *pcm; if((err = snd_pcm_open(&pcm, dev, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf(stderr, "cannot open audio device %s (%s)\n", dev, snd_strerror(err)); return NULL; } if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { fprintf(stderr, "cannot allocate hardware parameter structure(%s)\n", snd_strerror(err)); return NULL; } if((err = snd_pcm_hw_params_any(pcm, hw_params)) < 0) { fprintf(stderr, "cannot initialize hardware parameter structure(%s)\n", snd_strerror(err)); return NULL; } if((err = snd_pcm_hw_params_set_access(pcm, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf(stderr, "cannot set access type(%s)\n", snd_strerror(err)); return NULL; } if((err = snd_pcm_hw_params_set_format(pcm, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf(stderr, "cannot set sample format(%s)\n", snd_strerror(err)); return NULL; } if((err = snd_pcm_hw_params_set_rate_near(pcm, hw_params, &rate, 0)) < 0) { fprintf(stderr, "cannot set sample rate(%s)\n", snd_strerror(err)); return NULL; } if((err = snd_pcm_hw_params_set_channels(pcm, hw_params, 2)) < 0) { fprintf(stderr, "cannot set channel count(%s)\n", snd_strerror(err)); return NULL; } if((err = snd_pcm_hw_params(pcm, hw_params)) < 0) { fprintf(stderr, "cannot set parameters(%s)\n", snd_strerror(err)); return NULL; } snd_pcm_hw_params_free(hw_params); if((err = snd_pcm_sw_params_malloc(&sw_params)) < 0) { fprintf(stderr, "cannot allocate software parameters structure(%s)\n", snd_strerror(err)); return NULL; } if((err = snd_pcm_sw_params_current(pcm, sw_params)) < 0) { fprintf(stderr, "cannot initialize software parameters structure(%s)\n", snd_strerror(err)); return NULL; } if((err = snd_pcm_sw_params_set_avail_min(pcm, sw_params, 4096)) < 0) { fprintf(stderr, "cannot set minimum available count(%s)\n", snd_strerror(err)); return NULL; } if((err = snd_pcm_sw_params_set_start_threshold(pcm, sw_params, 0U)) < 0) { fprintf(stderr, "cannot set start mode(%s)\n", snd_strerror(err)); return NULL; } if((err = snd_pcm_sw_params(pcm, sw_params)) < 0) { fprintf(stderr, "cannot set software parameters(%s)\n", snd_strerror(err)); return NULL; } if((err = snd_pcm_prepare(pcm)) < 0) { fprintf(stderr, "cannot prepare audio interface for use(%s)\n", snd_strerror(err)); return NULL; } return pcm; } static void alsa_close(snd_pcm_t *pcm) { snd_pcm_close(pcm); } int main(int argc, const char *argv[]) { song_t *song; uint8_t buf[8192]; int len; snd_pcm_t *pcm; if (argc != 2) { printf("usage: %s song.it\n", argv[0]); goto _fail; } song = song_load_it(argv[1]); if (!song) { printf("failed to load song!\n"); goto _fail; } if (!(pcm = alsa_open("default"))) { printf("Failed to open ALSA device\n"); goto _fail_song; } csf_set_current_order(song, 0); song->repeat_count = 0; song->buffer_count = 0; song->stop_at_order = -1; song->stop_at_row = -1; song->flags &= ~(SONG_PAUSED | SONG_PATTERNLOOP | SONG_ENDREACHED); csf_reset_playmarks(song); csf_set_resampling_mode(song, SRCMODE_LINEAR); csf_set_wave_config(song, 44100, 16, 2); while ((len = csf_read(song, buf, sizeof(buf)))) { int err; if ((err = snd_pcm_writei(pcm, buf, len)) < 0) { fprintf (stderr, "write failed (%s)\n", snd_strerror(err)); break; } } alsa_close(pcm); return EXIT_SUCCESS; _fail_song: /* TODO cleanup song */ _fail: return EXIT_FAILURE; }