static int cdumb_read_metadata (DB_playItem_t *it) { DUH* duh = NULL; int is_it; int is_dos; int is_ptcompat; deadbeef->pl_lock (); { const char *fname = deadbeef->pl_find_meta (it, ":URI"); const char *ftype; duh = g_open_module(fname, &is_it, &is_dos, &is_ptcompat, 0, &ftype); } deadbeef->pl_unlock (); if (!duh) { unload_duh (duh); return -1; } DUMB_IT_SIGDATA * itsd = duh_get_it_sigdata(duh); deadbeef->pl_delete_all_meta (it); read_metadata_internal (it, itsd); unload_duh (duh); return 0; }
virtual alure::SharedPtr<alure::Decoder> createDecoder(alure::UniquePtr<std::istream> &file) { static const std::array<DUH*(*)(DUMBFILE*),3> init_funcs{{ dumb_read_it, dumb_read_xm, dumb_read_s3m }}; auto dfs = alure::MakeUnique<DUMBFILE_SYSTEM>(); dfs->open = nullptr; dfs->skip = cb_skip; dfs->getc = cb_read_char; dfs->getnc = cb_read; dfs->close = nullptr; dfs->seek = cb_seek; dfs->get_size = cb_get_size; DUMBFILE *dfile = dumbfile_open_ex(file.get(), dfs.get()); if(!dfile) return nullptr; ALuint freq = alure::Context::GetCurrent()->getDevice()->getFrequency(); DUH_SIGRENDERER *renderer; DUH *duh; for(auto init : init_funcs) { if((duh=init(dfile)) != nullptr) { if((renderer=duh_start_sigrenderer(duh, 0, 2, 0)) != nullptr) return alure::MakeShared<DumbDecoder>( std::move(file), std::move(dfs), dfile, duh, renderer, freq ); unload_duh(duh); duh = nullptr; } dumbfile_seek(dfile, 0, SEEK_SET); } if((duh=dumb_read_mod(dfile, 1)) != nullptr) { if((renderer=duh_start_sigrenderer(duh, 0, 2, 0)) != nullptr) return alure::MakeShared<DumbDecoder>( std::move(file), std::move(dfs), dfile, duh, renderer, freq ); unload_duh(duh); duh = nullptr; } dumbfile_close(dfile); return nullptr; }
// play a module using portaudio. void play(DUH *duh) { // init portaudio, redirecting stderr output temporarily; a lot of junk // gets printed otherwise. this won't work on windows, but who cares? int old_stderr = dup(2); int new_stderr = open("/dev/null", O_WRONLY); dup2(new_stderr, 2); PaError err = Pa_Initialize(); close(new_stderr); dup2(old_stderr, 2); close(old_stderr); if (err != paNoError) die("could not init PortAudio: %s\n", Pa_GetErrorText(err)); atexit(&pa_terminate); // get default device info PaDeviceIndex index = Pa_GetDefaultOutputDevice(); if (index == paNoDevice) die("could not get default output device\n"); callback_data cd; const PaDeviceInfo *dev = Pa_GetDeviceInfo(index); cd.sample_rate = dev->defaultSampleRate; cd.delta = 65536.0f / cd.sample_rate; // open and start output stream PaStream *stream; cd.sr = duh_start_sigrenderer(duh, 0, channels, 0); err = Pa_OpenDefaultStream(&stream, 0, channels, paInt16, dev->defaultSampleRate, paFramesPerBufferUnspecified, callback, &cd); if (err != paNoError) { duh_end_sigrenderer(cd.sr); unload_duh(duh); die("could not open default stream: %s\n", Pa_GetErrorText(err)); } if ((err = Pa_StartStream(stream)) != paNoError) { duh_end_sigrenderer(cd.sr); unload_duh(duh); die("could not start stream: %s\n", Pa_GetErrorText(err)); } init_sigrenderer(cd.sr); // play while (Pa_IsStreamActive(stream) == 1) Pa_Sleep(100); // clean up Pa_CloseStream(stream); duh_end_sigrenderer(cd.sr); }
static DB_playItem_t * cdumb_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) { const char *ext = strrchr (fname, '.'); if (ext) { ext++; } else { ext = ""; } int is_it; int is_dos; int is_ptcompat; const char *ftype = NULL; DUH* duh = g_open_module(fname, &is_it, &is_dos, &is_ptcompat, 0, &ftype); if (!duh) { return NULL; } DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); DUMB_IT_SIGDATA * itsd = duh_get_it_sigdata(duh); read_metadata_internal (it, itsd); dumb_it_do_initial_runthrough (duh); deadbeef->plt_set_item_duration (plt, it, duh_get_length (duh)/65536.0f); deadbeef->pl_add_meta (it, ":FILETYPE", ftype); // printf ("duration: %f\n", _info->duration); after = deadbeef->plt_insert_item (plt, after, it); deadbeef->pl_item_unref (it); unload_duh (duh); return after; }
void dumb_source_close(audio_source *src) { dumb_source *local = source_get_userdata(src); duh_end_sigrenderer(local->renderer); unload_duh(local->data); free(local); DEBUG("Libdumb Source: Closed."); }
void stopMusic() { if (playing != NULL) { al_stop_duh(player); unload_duh(playing); } playing = NULL; playingFile = ""; }
bool DeInit(void* context) { DumbContext* dumb = (DumbContext*)context; duh_end_sigrenderer(dumb->sr); unload_duh(dumb->module); delete dumb; return true; }
void destroy() { if (duhPlayer) { al_stop_duh(duhPlayer); duhPlayer = NULL; } if (tune) { unload_duh(tune); tune = NULL; } }
void Tracker_Stop(void) { if(bTracker_Initialized == false || playing == false) return; if(!trackmod || !sr) return; playing = false; // Not playing the song anymore to prevent Tracker_Update Con_Printf("Stopping %s\n", name); // Just print that we are stopping whatever track duh_end_sigrenderer(sr); // Stop the renderer safely unload_duh(trackmod); // Unload the song! }
// ----------------------------------------------------------------------------- // Closes and unloads any currently open mod // ----------------------------------------------------------------------------- void ModMusic::close() { if (dumb_player_ != nullptr) { duh_end_sigrenderer(dumb_player_); dumb_player_ = nullptr; } if (dumb_module_ != nullptr) { unload_duh(dumb_module_); dumb_module_ = nullptr; } }
/* ModMusic::close * Closes and unloads any currently open mod *******************************************************************/ void ModMusic::close() { if (dumb_player != NULL) { duh_end_sigrenderer(dumb_player); dumb_player = NULL; } if (dumb_module != NULL) { unload_duh(dumb_module); dumb_module = NULL; } }
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 }
static void cdumb_free (DB_fileinfo_t *_info) { trace ("cdumb_free %p\n", _info); dumb_info_t *info = (dumb_info_t *)_info; if (info) { if (info->renderer) { duh_end_sigrenderer (info->renderer); info->renderer = NULL; } if (info->duh) { unload_duh (info->duh); info->duh = NULL; } free (info); } }
/* return the player so you can use more advanced features if you want you can safely ignore the return value if all you want is to play a mod */ bool dumba5_load_and_play_module(const char * fn, int pattern, bool loop, int frequency, bool stereo) { bool ret; dumba5_duh = dumba5_load_module(fn); if(!dumba5_duh) { return false; } ret = dumba5_play_module(dumba5_duh, pattern, loop, frequency, stereo); if(!ret) { unload_duh(dumba5_duh); return false; } //printf("Module loaded and should be playing!\n"); return ret; }
bool MODDecoder::Close(CFErrorRef */*error*/) { if(!IsOpen()) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioDecoder.MOD"); LOG4CXX_WARN(logger, "Close() called on an AudioDecoder that hasn't been opened"); return true; } if(dsr) duh_end_sigrenderer(dsr), dsr = NULL; if(duh) unload_duh(duh), duh = NULL; if(df) dumbfile_close(df), df = NULL; mIsOpen = false; return true; }
/* read_duh(): reads a DUH from an already open DUMBFILE, and returns its * pointer, or null on error. The file is not closed. */ DUH *read_duh(DUMBFILE *f) { DUH *duh; int i; if (dumbfile_mgetl(f) != DUH_SIGNATURE) return NULL; duh = malloc(sizeof(*duh)); if (!duh) return NULL; duh->length = dumbfile_igetl(f); if (dumbfile_error(f) || duh->length <= 0) { free(duh); return NULL; } duh->n_signals = (int)dumbfile_igetl(f); if (dumbfile_error(f) || duh->n_signals <= 0) { free(duh); return NULL; } duh->signal = malloc(sizeof(*duh->signal) * duh->n_signals); if (!duh->signal) { free(duh); return NULL; } for (i = 0; i < duh->n_signals; i++) duh->signal[i] = NULL; for (i = 0; i < duh->n_signals; i++) { if (!(duh->signal[i] = read_signal(duh, f))) { unload_duh(duh); return NULL; } } return duh; }
void dumba5_stop_duh(DUMBA5_PLAYER * dp) { if(dp) { al_destroy_thread(dp->thread); if(dp->sigrenderer) { duh_end_sigrenderer(dp->sigrenderer); // al_drain_stream(dp->stream); al_destroy_audio_stream(dp->stream); } free(dp); /* if we are using the internal DUH, free it automatically, you are responsible for freeing your own DUHs */ if(dumba5_duh) { unload_duh(dumba5_duh); dumba5_duh = NULL; } } }
void playMusic(std::string file, float volume) { if (playingFile == file) { return; } if (playing != NULL) { al_stop_duh(player); unload_duh(playing); } std::string fileName = ResourceHandler::getInstance()->getRealFilename(file); if (!exists(fileName.c_str())) { throw DBSH07_EXCEPTION("Unable to load " + fileName); } playing = dumb_load_xm_quick(fileName.c_str()); player = al_start_duh(playing, 2, 0, volume, 4096, 44100); playingFile = file; pollMusic(); }
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; }
DUH *make_duh( long length, int n_tags, const char *const tags[][2], int n_signals, DUH_SIGTYPE_DESC *desc[], sigdata_t *sigdata[] ) { DUH *duh = malloc(sizeof(*duh)); int i; int fail; if (duh) { duh->n_signals = n_signals; duh->signal = malloc(n_signals * sizeof(*duh->signal)); if (!duh->signal) { free(duh); duh = NULL; } } if (!duh) { for (i = 0; i < n_signals; i++) if (desc[i]->unload_sigdata) if (sigdata[i]) (*desc[i]->unload_sigdata)(sigdata[i]); return NULL; } duh->n_tags = 0; duh->tag = NULL; fail = 0; for (i = 0; i < n_signals; i++) { duh->signal[i] = make_signal(desc[i], sigdata[i]); if (!duh->signal[i]) fail = 1; } if (fail) { unload_duh(duh); return NULL; } duh->length = length; { int mem = n_tags * 2; /* account for NUL terminators here */ char *ptr; for (i = 0; i < n_tags; i++) mem += strlen(tags[i][0]) + strlen(tags[i][1]); if (mem <= 0) return duh; duh->tag = malloc(n_tags * sizeof(*duh->tag)); if (!duh->tag) return duh; duh->tag[0][0] = malloc(mem); if (!duh->tag[0][0]) { free(duh->tag); duh->tag = NULL; return duh; } duh->n_tags = n_tags; ptr = duh->tag[0][0]; for (i = 0; i < n_tags; i++) { duh->tag[i][0] = ptr; strcpy(ptr, tags[i][0]); ptr += strlen(tags[i][0]) + 1; duh->tag[i][1] = ptr; strcpy(ptr, tags[i][1]); ptr += strlen(tags[i][1]) + 1; } } return duh; }
void dumba5_stop_module(void) { dumba5_stop_player(dumba5_player); unload_duh(dumba5_duh); }
int main(int argc, char *argv[]) { int retcode = 1; int nerrors = 0; streamer_t streamer; memset(&streamer, 0, sizeof(streamer_t)); // Signal handlers signal(SIGINT, sig_fn); signal(SIGTERM, sig_fn); // Initialize SDL2 if (SDL_Init(SDL_INIT_AUDIO) != 0) { fprintf(stderr, "%s\n", SDL_GetError()); return 1; } // Defaults streamer.freq = 44100; streamer.n_channels = 2; streamer.bits = 16; streamer.volume = 1.0f; streamer.quality = DUMB_RQ_CUBIC; // commandline argument parser options struct arg_lit *arg_help = arg_lit0("h", "help", "print this help and exits"); struct arg_dbl *arg_volume = arg_dbl0("v", "volume", "<volume", "sets the output volume (-8.0 to +8.0, default 1.0)"); struct arg_int *arg_samplerate = arg_int0( "s", "samplerate", "<freq>", "sets the sampling rate (default 44100)"); struct arg_int *arg_quality = arg_int0( "r", "quality", "<quality>", "specify the resampling quality to use"); struct arg_lit *arg_mono = arg_lit0("m", "mono", "generate mono output instead of stereo"); struct arg_lit *arg_eight = arg_lit0("8", "eight", "generate 8-bit instead of 16-bit"); struct arg_lit *arg_noprogress = arg_lit0("n", "noprogress", "hide progress bar"); struct arg_file *arg_output = arg_file0("o", "output", "<file>", "output file"); struct arg_file *arg_input = arg_file1(NULL, NULL, "<file>", "input module file"); struct arg_end *arg_fend = arg_end(20); void *argtable[] = {arg_help, arg_input, arg_volume, arg_samplerate, arg_quality, arg_mono, arg_eight, arg_noprogress, arg_fend}; const char *progname = "dumbplay"; // Make sure everything got allocated if (arg_nullcheck(argtable) != 0) { fprintf(stderr, "%s: insufficient memory\n", progname); goto exit_0; } // Parse inputs nerrors = arg_parse(argc, argv, argtable); // Handle help if (arg_help->count > 0) { fprintf(stderr, "Usage: %s", progname); arg_print_syntax(stderr, argtable, "\n"); fprintf(stderr, "\nArguments:\n"); arg_print_glossary(stderr, argtable, "%-25s %s\n"); goto exit_0; } // Handle libargtable errors if (nerrors > 0) { arg_print_errors(stderr, arg_fend, progname); fprintf(stderr, "Try '%s --help' for more information.\n", progname); goto exit_0; } // Handle the switch options streamer.input = arg_input->filename[0]; if (arg_eight->count > 0) { streamer.bits = 8; } if (arg_mono->count > 0) { streamer.n_channels = 1; } if (arg_noprogress->count > 0) { streamer.no_progress = true; } if (arg_volume->count > 0) { streamer.volume = arg_volume->dval[0]; if (streamer.volume < -8.0f || streamer.volume > 8.0f) { fprintf(stderr, "Volume must be between -8.0f and 8.0f.\n"); goto exit_0; } } if (arg_samplerate->count > 0) { streamer.freq = arg_samplerate->ival[0]; if (streamer.freq < 1 || streamer.freq > 96000) { fprintf(stderr, "Sampling rate must be between 1 and 96000.\n"); goto exit_0; } } if (arg_quality->count > 0) { streamer.quality = arg_quality->ival[0]; if (streamer.quality < 0 || streamer.quality >= DUMB_RQ_N_LEVELS) { fprintf(stderr, "Quality must be between %d and %d.\n", 0, DUMB_RQ_N_LEVELS - 1); goto exit_0; } } // Load source file. dumb_register_stdfiles(); streamer.src = dumb_load_any(streamer.input, 0, 0); if (!streamer.src) { fprintf(stderr, "Unable to load file %s for playback!\n", streamer.input); goto exit_0; } // Set up playback streamer.renderer = duh_start_sigrenderer(streamer.src, 0, streamer.n_channels, 0); streamer.delta = 65536.0f / streamer.freq; streamer.sbytes = (streamer.bits / 8) * streamer.n_channels; streamer.ssize = duh_get_length(streamer.src); // Stop producing samples on module end DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(streamer.renderer); dumb_it_set_loop_callback(itsr, &dumb_it_callback_terminate, NULL); dumb_it_set_xm_speed_zero_callback(itsr, &dumb_it_callback_terminate, NULL); dumb_it_set_resampling_quality(itsr, streamer.quality); // Set up the SDL2 format we want for playback. SDL_AudioSpec want; SDL_zero(want); want.freq = streamer.freq; want.format = (streamer.bits == 16) ? AUDIO_S16 : AUDIO_S8; want.channels = streamer.n_channels; want.samples = SAMPLES; want.callback = stream_audio; want.userdata = &streamer; // Find SDL2 audio device, and request the format we just set up. // SDL2 will tell us what we got in the "have" struct. SDL_AudioSpec have; streamer.dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0); if (streamer.dev == 0) { fprintf(stderr, "%s\n", SDL_GetError()); goto exit_1; } // Make sure we got the format we wanted. If not, stop here. if (have.format != want.format) { fprintf(stderr, "Could not get correct playback format.\n"); goto exit_2; } // Play file SDL_PauseAudioDevice(streamer.dev, 0); // Show initial state of the progress bar (if it is enabled) int time_start = SDL_GetTicks(); float seek = 0.0f; int ms_played = 0; if (!streamer.no_progress) { show_progress(PROGRESSBAR_LENGTH, seek, ms_played); } // Loop while dumb is still giving data. Update progressbar if enabled. while (!stop_signal && !streamer.ended) { if (!streamer.no_progress) { seek = ((float)streamer.spos) / ((float)streamer.ssize); ms_played = SDL_GetTicks() - time_start; show_progress(PROGRESSBAR_LENGTH, seek, ms_played); } SDL_Delay(100); } // We made it this far without crashing, so let's just exit with no error :) retcode = 0; // Free up resources and exit. if (streamer.sig_samples) { destroy_sample_buffer(streamer.sig_samples); } exit_2: SDL_CloseAudioDevice(streamer.dev); exit_1: if (streamer.renderer) { duh_end_sigrenderer(streamer.renderer); } if (streamer.src) { unload_duh(streamer.src); } exit_0: arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); SDL_Quit(); return retcode; }
bool MODDecoder::Open(CFErrorRef *error) { if(IsOpen()) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.AudioDecoder.MOD"); LOG4CXX_WARN(logger, "Open() called on an AudioDecoder that is already open"); return true; } // Ensure the input source is open if(!mInputSource->IsOpen() && !mInputSource->Open(error)) return false; dfs.open = NULL; dfs.skip = skip_callback; dfs.getc = getc_callback; dfs.getnc = getnc_callback; dfs.close = close_callback; df = dumbfile_open_ex(this, &dfs); if(NULL == df) { return false; } CFStringRef fileSystemPath = CFURLCopyFileSystemPath(GetURL(), kCFURLPOSIXPathStyle); CFStringRef extension = NULL; CFRange range; if(CFStringFindWithOptionsAndLocale(fileSystemPath, CFSTR("."), CFRangeMake(0, CFStringGetLength(fileSystemPath)), kCFCompareBackwards, CFLocaleGetSystem(), &range)) { extension = CFStringCreateWithSubstring(kCFAllocatorDefault, fileSystemPath, CFRangeMake(range.location + 1, CFStringGetLength(fileSystemPath) - range.location - 1)); } CFRelease(fileSystemPath), fileSystemPath = NULL; if(NULL == extension) { return false; } // Attempt to create the appropriate decoder based on the file's extension if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("it"), kCFCompareCaseInsensitive)) duh = dumb_read_it(df); else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("xm"), kCFCompareCaseInsensitive)) duh = dumb_read_xm(df); else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("s3m"), kCFCompareCaseInsensitive)) duh = dumb_read_s3m(df); else if(kCFCompareEqualTo == CFStringCompare(extension, CFSTR("mod"), kCFCompareCaseInsensitive)) duh = dumb_read_mod(df); CFRelease(extension), extension = NULL; if(NULL == duh) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 32, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL()); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MOD file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not a MOD file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioDecoderErrorDomain, AudioDecoderInputOutputError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } if(df) dumbfile_close(df), df = NULL; return false; } mTotalFrames = duh_get_length(duh); dsr = duh_start_sigrenderer(duh, 0, 2, 0); if(NULL == dsr) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 32, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL()); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MOD file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not a MOD file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioDecoderErrorDomain, AudioDecoderInputOutputError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } if(df) dumbfile_close(df), df = NULL; if(duh) unload_duh(duh), duh = NULL; return false; } // Generate interleaved 2 channel 44.1 16-bit output mFormat.mFormatID = kAudioFormatLinearPCM; mFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; mFormat.mSampleRate = DUMB_SAMPLE_RATE; mFormat.mChannelsPerFrame = DUMB_CHANNELS; mFormat.mBitsPerChannel = DUMB_BIT_DEPTH; mFormat.mBytesPerPacket = (mFormat.mBitsPerChannel / 8) * mFormat.mChannelsPerFrame; mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mFormat.mReserved = 0; // Set up the source format mSourceFormat.mFormatID = 'MOD '; mSourceFormat.mSampleRate = DUMB_SAMPLE_RATE; mSourceFormat.mChannelsPerFrame = DUMB_CHANNELS; // Setup the channel layout mChannelLayout = CreateChannelLayoutWithTag(kAudioChannelLayoutTag_Stereo); mIsOpen = true; return true; }
void _dat_unload_duh(void *duh) { unload_duh(duh); }