示例#1
0
文件: cdumb.c 项目: saivert/deadbeef
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;
}
示例#2
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;
    }
示例#3
0
文件: modplay.c 项目: jangler/modplay
// 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);
}
示例#4
0
文件: cdumb.c 项目: saivert/deadbeef
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;
}
示例#5
0
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.");
}
示例#6
0
文件: music.cpp 项目: olofn/db_public
void stopMusic() {
	if (playing != NULL) {
		al_stop_duh(player);
		unload_duh(playing);
	}
	
	playing = NULL;
	playingFile = "";
}
示例#7
0
bool DeInit(void* context)
{
  DumbContext* dumb = (DumbContext*)context;
  duh_end_sigrenderer(dumb->sr);
  unload_duh(dumb->module);
  delete dumb;

  return true;
}
示例#8
0
 void destroy()
 {
   if (duhPlayer) {
     al_stop_duh(duhPlayer);
     duhPlayer = NULL;
   }
   if (tune) {
     unload_duh(tune);
     tune = NULL;
   }
 }
示例#9
0
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!
}
示例#10
0
// -----------------------------------------------------------------------------
// 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;
	}
}
示例#11
0
/* 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;
    }
}
示例#12
0
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
}
示例#13
0
文件: cdumb.c 项目: saivert/deadbeef
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;
}
示例#15
0
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;
}
示例#16
0
文件: readduh.c 项目: kode54/Cog
/* 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;
		}
	}
}
示例#18
0
文件: music.cpp 项目: olofn/db_public
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();
}
示例#19
0
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;
}
示例#20
0
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);
}
示例#22
0
文件: dumbplay.c 项目: codefoco/dumb
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;
}
示例#23
0
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;
}
示例#24
0
文件: datunld.c 项目: codefoco/dumb
void _dat_unload_duh(void *duh) { unload_duh(duh); }