// 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); }
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."); }
bool DeInit(void* context) { DumbContext* dumb = (DumbContext*)context; duh_end_sigrenderer(dumb->sr); unload_duh(dumb->module); delete dumb; return true; }
void al_stop_duh(AL_DUH_PLAYER *dp) { if (dp) { if (dp->sigrenderer) { duh_end_sigrenderer(dp->sigrenderer); stop_audio_stream(dp->stream); } free(dp); } }
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; } }
void seek(int patnum) { if ((!done) && (duhPlayer)) { al_stop_duh(duhPlayer); done = 0; DUH_SIGRENDERER *sr = dumb_it_start_at_order(tune, 2, patnum); duhPlayer = al_duh_encapsulate_sigrenderer(sr, VOLUME_TO_DUMB_VOL(vol), 8192, 22050); if (!duhPlayer) duh_end_sigrenderer(sr); else al_duh_set_loop(duhPlayer, repeat); } }
/* 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; } }
/* Destroy the specified player. */ void dumba5_destroy_player(DUMBA5_PLAYER * pp) { if(pp) { al_destroy_thread(pp->thread); al_destroy_mutex(pp->mutex); if(pp->sigrenderer) { duh_end_sigrenderer(pp->sigrenderer); // al_drain_stream(dp->stream); al_destroy_audio_stream(pp->stream); } free(pp); } }
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); } }
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; }
static int cdumb_startrenderer (DB_fileinfo_t *_info) { dumb_info_t *info = (dumb_info_t *)_info; // reopen if (info->renderer) { duh_end_sigrenderer (info->renderer); info->renderer = NULL; } info->renderer = duh_start_sigrenderer (info->duh, 0, 2, 0); if (!info->renderer) { return -1; } DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer (info->renderer); dumb_it_set_loop_callback (itsr, &dumb_it_callback_terminate, NULL); int q = conf_resampling_quality; if (q < 0) { q = 0; } else if (q >= DUMB_RQ_N_LEVELS) { q = DUMB_RQ_N_LEVELS - 1; } dumb_it_set_resampling_quality (itsr, q); dumb_it_set_xm_speed_zero_callback (itsr, &dumb_it_callback_terminate, NULL); dumb_it_set_global_volume_zero_callback (itsr, &dumb_it_callback_terminate, NULL); int rq = conf_ramping_style; if (rq < 0) { rq = 0; } else if (rq > 2) { rq = 2; } dumb_it_set_ramp_style(itsr, rq); dumb_it_sr_set_global_volume (itsr, conf_global_volume); return 0; }
int al_poll_duh(AL_DUH_PLAYER *dp) { unsigned short *sptr; long n; long size; int n_channels; if (!dp || !dp->sigrenderer) return 1; if (!(dp->flags & ADP_PLAYING)) return 0; sptr = get_audio_stream_buffer(dp->stream); if (!sptr) return 0; n = duh_render(dp->sigrenderer, 16, 1, dp->volume, 65536.0 / dp->freq, dp->bufsize, sptr); if (n == 0) { if (++dp->silentcount >= 2) { duh_end_sigrenderer(dp->sigrenderer); free_audio_stream_buffer(dp->stream); stop_audio_stream(dp->stream); dp->sigrenderer = NULL; return 1; } } n_channels = duh_sigrenderer_get_n_channels(dp->sigrenderer); n *= n_channels; size = dp->bufsize * n_channels; for (; n < size; n++) sptr[n] = 0x8000; free_audio_stream_buffer(dp->stream); return 0; }
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; } } }
/* DEPRECATED */ void duh_end_renderer(DUH_SIGRENDERER *dr) { duh_end_sigrenderer(dr); }
void * dumba5_update_thread(ALLEGRO_THREAD * thread, void * arg) { DUMBA5_PLAYER * dp = (DUMBA5_PLAYER *)arg; ALLEGRO_EVENT_QUEUE * queue; unsigned short *fragment; long n; long size; int n_channels; queue = al_create_event_queue(); al_register_event_source(queue, al_get_audio_stream_event_source(dp->stream)); while(1) { ALLEGRO_EVENT event; al_wait_for_event(queue, &event); if(event.type == ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT) { fragment = (unsigned short *)al_get_audio_stream_fragment(dp->stream); if(!fragment) { return NULL; } n = duh_render(dp->sigrenderer, 16, 0, dp->volume, 65536.0 / dp->freq, dp->bufsize, fragment); if (n == 0) { if (++dp->silentcount >= 2) { duh_end_sigrenderer(dp->sigrenderer); if(!al_set_audio_stream_fragment(dp->stream, fragment)) { } al_destroy_audio_stream(dp->stream); dp->sigrenderer = NULL; return NULL; } } n_channels = duh_sigrenderer_get_n_channels(dp->sigrenderer); n *= n_channels; size = dp->bufsize * n_channels; for (; n < size; n++) { fragment[n] = 0x8000; } if(!al_set_audio_stream_fragment(dp->stream, fragment)) { } } if(al_get_thread_should_stop(thread)) { break; } } al_destroy_event_queue(queue); return NULL; }
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; }