int dumb_source_init(audio_source *src, const char* file, int channels, int freq, int resampler) { dumb_source *local = malloc(sizeof(dumb_source)); // Load file and initialize renderer char *ext = strrchr(file, '.') + 1; if(strcasecmp(ext, "psm") == 0) { local->data = dumb_load_psm(file, 0); } else if(strcasecmp(ext, "s3m") == 0) { local->data = dumb_load_s3m(file); } else if(strcasecmp(ext, "mod") == 0) { local->data = dumb_load_mod(file, 0); } else if(strcasecmp(ext, "it") == 0) { local->data = dumb_load_it(file); } else if(strcasecmp(ext, "xm") == 0) { local->data = dumb_load_xm(file); } else { PERROR("Libdumb Source: No suitable module decoder found."); goto error_0; } if(!local->data) { PERROR("Libdumb Source: Error while loading module file!"); goto error_0; } local->renderer = duh_start_sigrenderer(local->data, 0, channels, 0); local->vlen = duh_get_length(local->data); local->vpos = 0; local->sig_samples = NULL; local->sig_samples_size = 0; // Set resampler here dumb_it_set_resampling_quality(duh_get_it_sigrenderer(local->renderer), resampler); // Audio information source_set_frequency(src, freq); source_set_bytes(src, 2); source_set_channels(src, channels); source_set_resampler(src, resampler); // Set callbacks source_set_userdata(src, local); source_set_update_cb(src, dumb_source_update); source_set_close_cb(src, dumb_source_close); // Some debug info DEBUG("Libdumb Source: Loaded file '%s' succesfully.", file); // All done return 0; error_0: free(local); return 1; }
void Tracker_Play(byte track, qboolean looping) { if(bTracker_Initialized == false) return; alGenSources((ALuint)1, &oss_source); alSourcef(oss_source, AL_PITCH, 1); alSourcef(oss_source, AL_GAIN, 1); alSource3f(oss_source, AL_POSITION, 0, 0, 0); alSource3f(oss_source, AL_VELOCITY, 0, 0, 0); alSourcei(oss_source, AL_LOOPING, AL_FALSE); alGenBuffers((ALuint)1, &oss_buffer); dumb_register_stdfiles(); // Initialize loading files // Attempt to load every format imaginable, TODO: better method? sprintf (name, "%s/music/track%d.it", com_gamedir, track); trackmod = dumb_load_it(name); if (!trackmod) { sprintf (name, "%s/music/track%d.xm", com_gamedir, track); trackmod = dumb_load_xm(name); if (!trackmod) { sprintf (name, "%s/music/track%d.s3m", com_gamedir, track); trackmod = dumb_load_s3m(name); if (!trackmod) { sprintf (name, "%s/music/track%d.mod", com_gamedir, track); trackmod = dumb_load_mod(name); if (!trackmod) { fprintf(stderr, "Unable to open %s!\n", name); return; } } } } // Let us know which track you are playing Con_Printf("Playing %s\n", name); sr = duh_start_sigrenderer(trackmod, 0, n_channels, 0); // start rendering, action happens in Tracker_Update if (!sr) { // If it doesn't want to render, stop it before it's too late unload_duh(trackmod); // Unload the track safely fprintf(stderr, "Unable to play file!\n"); return; } delta = 61536.0f / freq; // This affects the speed bufsize = depth == 16 ? 2048 : 4096; // Buffer size, small buffer = laggy music; big buff = laggy game bufsize /= n_channels; // Tell him we are hopefully stereo playing = true; // Announce that we have a track playing }
SOUNDCLIP *my_load_mod(const char *filname, int repet) { DUH *modPtr = NULL; // determine the file extension const char *lastDot = strrchr(filname, '.'); if (lastDot == NULL) return NULL; // get the first char of the extensin int charAfterDot = toupper(lastDot[1]); // use the appropriate loader if (charAfterDot == 'I') { modPtr = dumb_load_it(filname); } else if (charAfterDot == 'X') { modPtr = dumb_load_xm(filname); } else if (charAfterDot == 'S') { modPtr = dumb_load_s3m(filname); } else if (charAfterDot == 'M') { modPtr = dumb_load_mod(filname); } if (modPtr == NULL) return NULL; thismod = new MYMOD(); thismod->done = 0; thismod->tune = modPtr; thismod->vol = 255; thismod->repeat = (repet != 0); return thismod; }
int main(int argc, const char *const *argv) /* I'm const-crazy! */ { DUH *duh; /* Encapsulates the music file. */ AL_DUH_PLAYER *dp; /* Holds the current playback state. */ /* Initialise Allegro */ if (allegro_init()) return EXIT_FAILURE; /* Check that we have one argument (plus the executable name). */ if (argc != 2) usage(argv[0]); /* Tell Allegro where to find configuration data. This means you can * put any settings for Allegro in dumb.ini. See Allegro's * documentation for more information. */ set_config_file("dumb.ini"); /* Initialise Allegro's keyboard input. */ if (install_keyboard()) { allegro_message("Failed to initialise keyboard driver!\n"); return EXIT_FAILURE; } /* This function call is appropriate for a program that will play one * sample or one audio stream at a time. If you have sound effects * too, you may want to increase the parameter. See Allegro's * documentation for details on what the parameter means. Note that * newer versions of Allegro act as if set_volume_per_voice() was * called with parameter 1 initially, while older versions behave as * if -1 was passed, so you should call the function if you want * consistent behaviour. */ set_volume_per_voice(0); /* Initialise Allegro's sound output system. */ if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL)) { allegro_message("Failed to initialise sound driver!\n%s\n", allegro_error); return EXIT_FAILURE; } /* dumb_exit() is a function defined by DUMB. This operation arranges * for dumb_exit() to be called last thing before the program exits. * dumb_exit() does a bit of cleaning up for you. atexit() is * declared in stdlib.h. */ atexit(&dumb_exit); /* DUMB defines its own wrappers for file input. There is a struct * called DUMBFILE that holds function pointers for the various file * operations needed by DUMB. You can decide whether to use stdio * FILE objects, Allegro's PACKFILEs or something else entirely. No * wrapper is installed initially, so you must call this or * dumb_register_stdfiles() or set up your own before trying to load * modules by file name. (If you are using another method, such as * loading an Allegro datafile with modules embedded in it, then DUMB * never opens a file by file name so this doesn't apply.) */ dumb_register_packfiles(); /* Load the module file into a DUH object. Quick and dirty: try the * loader for each format until one succeeds. Note that 15-sample * mods have no identifying features, so dumb_load_mod() may succeed * on files that aren't mods at all. We therefore try that one last. */ duh = dumb_load_it(argv[1]); if (!duh) { duh = dumb_load_xm(argv[1]); if (!duh) { duh = dumb_load_s3m(argv[1]); if (!duh) { duh = dumb_load_mod(argv[1]); if (!duh) { allegro_message("Failed to load %s!\n", argv[1]); return EXIT_FAILURE; } } } } /* Read the quality values from the config file we told Allegro to * use. You may want to hardcode these or provide a more elaborate * interface via which the user can control them. */ dumb_resampling_quality = get_config_int("sound", "dumb_resampling_quality", 4); dumb_it_max_to_mix = get_config_int("sound", "dumb_it_max_to_mix", 128); /* If we're not in DOS, show a window and register our close hook * function. */ # ifndef ALLEGRO_DOS { const char *fn = get_filename(argv[1]); gfx_half_width = strlen(fn); if (gfx_half_width < 22) gfx_half_width = 22; gfx_half_width = (gfx_half_width + 2) * 4; /* set_window_title() is not const-correct (yet). */ set_window_title((char *)"DUMB Music Player"); if (set_gfx_mode(GFX_DUMB_MODE, gfx_half_width*2, 80, 0, 0) == 0) { acquire_screen(); textout_centre(screen, font, fn, gfx_half_width, 20, 14); textout_centre(screen, font, "Press any key to exit.", gfx_half_width, 52, 11); release_screen(); } else gfx_half_width = 0; } /* Silly check to get around the fact that someone stupidly removed * an old function from Allegro instead of deprecating it. The old * function was put back a version later, but we may as well use the * new one if it's there! */ # if ALLEGRO_VERSION*10000 + ALLEGRO_SUB_VERSION*100 + ALLEGRO_WIP_VERSION >= 40105 set_close_button_callback(&closehook); # else set_window_close_hook(&closehook); # endif # endif /* We want to continue running if the user switches to another * application. */ set_display_switch_mode(SWITCH_BACKGROUND); /* We have the music loaded, but it isn't playing yet. This starts it * playing. We construct a second object, the AL_DUH_PLAYER, to * represent the playing music. This means you can play the music * twice at the same time should you want to! * * Specify the number of channels (2 for stereo), which 'signal' to * play (always 0 for modules), the volume (1.0f for default), the * buffer size (4096 generally works well) and the sampling frequency * (ideally match the final output frequency Allegro is using). An * Allegro audio stream will be started. */ dp = al_start_duh(duh, 2, 0, 1.0f, get_config_int("sound", "buffer_size", 4096), get_config_int("sound", "sound_freq", 44100)); /* Register our callback functions so that they are called when the * music loops or stops. See docs/howto.txt for more information. * There is no threading issue: DUMB will only process playback * in al_poll_duh(), which we call below. */ { DUH_SIGRENDERER *sr = al_duh_get_sigrenderer(dp); DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(sr); dumb_it_set_loop_callback(itsr, &loop_callback, NULL); dumb_it_set_xm_speed_zero_callback(itsr, &xm_speed_zero_callback, NULL); } /* Main loop. */ for (;;) { /* Check for keys in the buffer. If we get one, discard it * and exit the main loop. */ if (keypressed()) { readkey(); break; } /* Poll the music. We exit the loop if al_poll_duh() has * returned nonzero (music finished) or the window has been * closed. al_poll_duh() might return nonzero if you have set * up a callback that tells the music to stop. */ if (al_poll_duh(dp) || closed) break; /* Give other threads a look-in, or allow the processor to * sleep for a bit. YIELD() is defined further up in this * file. */ YIELD(); } /* Remove the audio stream and deallocate the memory being used for * the playback state. We set dp to NULL to emphasise that the object * has gone. */ al_stop_duh(dp); dp = NULL; /* Free the DUH object containing the actual music data. */ unload_duh(duh); duh = NULL; /* All done! */ return EXIT_SUCCESS; }