static PyObject * py_ao_driver_info(PyObject *self, PyObject *args) { int driver_id = 0; char *driver_name; ao_info *info; PyObject *retdict; if (self != NULL) { /* It's a method */ ao_Object *ao_self = (ao_Object *) self; info = ao_driver_info(ao_self->driver_id); } else { /* Maybe it's a string */ if ((PyArg_ParseTuple(args, "s", &driver_name))) { driver_id = ao_driver_id(driver_name); if (driver_id == -1) { PyErr_SetString(Py_aoError, "Invalid driver name"); } } else { /* Maybe it's an int */ PyErr_Clear(); if (!(PyArg_ParseTuple(args, "i", &driver_id))) return NULL; } info = ao_driver_info(driver_id); } if (!info) { PyErr_SetString(Py_aoError, "Error getting info"); return NULL; } retdict = PyDict_New(); PyDict_SetItemString(retdict, "name", PyString_FromString(info->name)); PyDict_SetItemString(retdict, "short_name", PyString_FromString(info->short_name)); PyDict_SetItemString(retdict, "author", PyString_FromString(info->author)); PyDict_SetItemString(retdict, "comment", PyString_FromString(info->comment)); return retdict; }
int fm_player_open(fm_player_t *pl, fm_player_config_t *config) { pl->config = *config; if (strcmp(config->driver, "pifm") == 0) { float f = atof(config->dev); if (f < 1) f = 102.4; printf("Player audio driver: pifm\n"); printf("Player sample rate: %d Hz\n", config->rate); printf("Player FM fequency: %f Hz\n", f); config->channels = 1; fm_setup_fm(); fm_setup_dma(f); } else { ao_sample_format ao_fmt; ao_fmt.rate = config->rate; ao_fmt.channels = config->channels; ao_fmt.bits = mpg123_encsize(config->encoding) * 8; ao_fmt.byte_format = AO_FMT_NATIVE; ao_fmt.matrix = 0; int driver = ao_driver_id(config->driver); if (driver == -1) { return -1; } ao_info *driver_info = ao_driver_info(driver); printf("Player audio driver: %s\n", driver_info->name); printf("Player sample rate: %d Hz\n", pl->config.rate); ao_option *options = NULL; if (config->dev[0] != '\0') { ao_append_option(&options, "dev", config->dev); } pl->dev = ao_open_live(driver, &ao_fmt, options); ao_free_options(options); if (pl->dev == NULL) return -1; } pl->mh = mpg123_new(NULL, NULL); mpg123_format_none(pl->mh); mpg123_format(pl->mh, config->rate, config->channels, config->encoding); pl->curl = curl_easy_init(); curl_easy_setopt(pl->curl, CURLOPT_WRITEFUNCTION, download_callback); curl_easy_setopt(pl->curl, CURLOPT_WRITEDATA, pl); pl->tid_ack = 0; pthread_mutex_init(&pl->mutex_status, NULL); pthread_cond_init(&pl->cond_play, NULL); pl->status = FM_PLAYER_STOP; return 0; }
int cAudio::PrepareClipPlay(int ch, int srate, int bits, int le) { lt_debug("%s ch %d srate %d bits %d le %d adevice %p\n", __func__, ch, srate, bits, le, adevice);; int driver; int byte_format = le ? AO_FMT_LITTLE : AO_FMT_BIG; if (sformat.bits != bits || sformat.channels != ch || sformat.rate != srate || sformat.byte_format != byte_format || adevice == NULL) { driver = ao_default_driver_id(); sformat.bits = bits; sformat.channels = ch; sformat.rate = srate; sformat.byte_format = byte_format; sformat.matrix = 0; if (adevice) ao_close(adevice); adevice = ao_open_live(driver, &sformat, NULL); ao_info *ai = ao_driver_info(driver); lt_info("%s: changed params ch %d srate %d bits %d le %d adevice %p\n", __func__, ch, srate, bits, le, adevice);; lt_info("libao driver: %d name '%s' short '%s' author '%s'\n", driver, ai->name, ai->short_name, ai->author); } return 0; };
static void usage(const char *progname) { struct params default_par = DEFAULT_PARAMS; const char *default_driver = "???"; { ao_info *info = ao_driver_info(driver_id); if (info) default_driver = info->short_name; } printf("vgmstream123 " VERSION ", built " __DATE__ "\n" "\n" "Usage: %s [options] INFILE ...\n" "Play streamed audio from video games.\n" "\n" "Options:\n" " -d DRV Use output driver DRV [%s]; available drivers:\n" " ", progname, default_driver); { ao_info **info_list; int driver_count = 0; int i; info_list = ao_driver_info_list(&driver_count); for (i = 0; i < driver_count; i++) printf("%s ", info_list[i]->short_name); } printf("\n" " -f OUTFILE Set output filename for a file driver specified with -d\n" " -o KEY:VAL Pass option KEY with value VAL to the output driver\n" " (see https://www.xiph.org/ao/doc/drivers.html)\n" " -b N Use an audio buffer of N kilobytes [%d]\n" " -@ LSTFILE Read playlist from LSTFILE\n" " -h Print this help\n" " -r Repeat playback indefinitely\n" " -v Display stream metadata and playback progress\n" " -S N Play substream with index N [%d]\n" "\n" "Options for looped streams:\n" " -L N Play loop N times [%d]\n" " -M MINTIME Loop for a playback time of at least MINTIME seconds\n" " -F FTIME End playback with a fade-out of FTIME seconds [%.1f]\n" " -D FDELAY Delay fade-out for an additional FDELAY seconds [%.1f]\n" "\n" "INFILE can be any stream file type supported by vgmstream, or an .m3u/.m3u8\n" "playlist referring to same. This program supports the \"EXT-X-VGMSTREAM\" tag\n" "in playlists, and files compressed with gzip/bzip2/xz.\n", buffer_size_kb, default_par.stream_index, default_par.loop_count, default_par.fade_time, default_par.fade_delay ); }
gchar *output_driver_name (void) { ao_info *info; if (device == NULL) { LOG ("Tried to get the driver name of a NULL device"); return NULL; } info = ao_driver_info (driver_id); return info->short_name; }
static int open_output(void) { int driver_id; ao_initialize(); if (dpm.name == NULL) { driver_id = ao_default_driver_id(); } else { ao_info *device; driver_id = ao_driver_id(dpm.name); if ((device = ao_driver_info(driver_id)) == NULL) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: driver is not supported.", dpm.name); return -1; } if (device->type == AO_TYPE_FILE) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: file output is not supported.", dpm.name); return -1; } } if (driver_id == -1) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", dpm.name, strerror(errno)); return -1; } /* They can't mean these */ dpm.encoding &= ~(PE_ULAW|PE_ALAW|PE_BYTESWAP); ao_sample_format_ctx.channels = (dpm.encoding & PE_MONO) ? 1 : 2; ao_sample_format_ctx.rate = dpm.rate; ao_sample_format_ctx.byte_format = AO_FMT_NATIVE; ao_sample_format_ctx.bits = (dpm.encoding & PE_24BIT) ? 24 : 0; ao_sample_format_ctx.bits = (dpm.encoding & PE_16BIT) ? 16 : 0; if (ao_sample_format_ctx.bits == 0) ao_sample_format_ctx.bits = 8; if ((ao_device_ctx = ao_open_live(driver_id, &ao_sample_format_ctx, NULL /* no options */)) == NULL) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", dpm.name, strerror(errno)); return -1; } return 0; }
/* Opens the audio device with the appropriate parameters */ static int set_sample_format(VGMSTREAM *vgms) { ao_sample_format format; memset(&format, 0, sizeof(format)); format.bits = 8 * sizeof(sample); format.channels = vgms->channels; format.rate = vgms->sample_rate; format.byte_format = #ifdef LITTLE_ENDIAN_OUTPUT AO_FMT_LITTLE #else AO_FMT_BIG #endif ; if (memcmp(&format, ¤t_sample_format, sizeof(format))) { /* Sample format has changed, so (re-)open audio device */ ao_info *info = ao_driver_info(driver_id); if (!info) return -1; if ((info->type == AO_TYPE_FILE) != !!out_filename) { if (out_filename) fprintf(stderr, "Live output driver \"%s\" does not take an output file\n", info->short_name); else fprintf(stderr, "File output driver \"%s\" requires an output filename\n", info->short_name); return -1; } if (device) ao_close(device); memcpy(¤t_sample_format, &format, sizeof(format)); if (out_filename) device = ao_open_file(driver_id, out_filename, 1, &format, device_options); else device = ao_open_live(driver_id, &format, device_options); if (!device) { fprintf(stderr, "Error opening \"%s\" audio device\n", info->short_name); return -1; } } return 0; }
void print_audio_devices_info(audio_device_t *d) { ao_info *info; while (d != NULL) { info = ao_driver_info(d->driver_id); status_message(2, _("\nAudio Device: %s"), info->name); status_message(3, _("Author: %s"), info->author); status_message(3, _("Comments: %s"), info->comment); status_message(2, ""); d = d->next_device; } }
static void sound_ao_print(Lisp_Object device, Lisp_Object pcfun, int ef) { sound_ao_data_t *saod = NULL; saod = get_audio_device_data(device); /* cannot use AO on incomplete or corrupt audio devices */ if (XAUDIO_DEVICE_DRIVER(device) != MYSELF || saod == NULL) { write_c_string("VOID", pcfun); /* now that we are here, mark AO device as dead */ XAUDIO_DEVICE_STATE(device) = ASTATE_DEAD; return; } /* info about the connected output plugin */ write_c_string(" :driver \"", pcfun); write_c_string(ao_driver_info(saod->driver_id)->short_name, pcfun); write_c_string("\"", pcfun); if (ef); return; }
static struct audio_output * ao_output_init(const struct config_param *param, GError **error) { struct ao_data *ad = g_new(struct ao_data, 1); if (!ao_base_init(&ad->base, &ao_output_plugin, param, error)) { g_free(ad); return NULL; } ao_info *ai; const char *value; ad->options = NULL; ad->write_size = config_get_block_unsigned(param, "write_size", 1024); if (ao_output_ref == 0) { ao_initialize(); } ao_output_ref++; value = config_get_block_string(param, "driver", "default"); if (0 == strcmp(value, "default")) ad->driver = ao_default_driver_id(); else ad->driver = ao_driver_id(value); if (ad->driver < 0) { g_set_error(error, ao_output_quark(), 0, "\"%s\" is not a valid ao driver", value); ao_base_finish(&ad->base); g_free(ad); return NULL; } if ((ai = ao_driver_info(ad->driver)) == NULL) { g_set_error(error, ao_output_quark(), 0, "problems getting driver info"); ao_base_finish(&ad->base); g_free(ad); return NULL; } g_debug("using ao driver \"%s\" for \"%s\"\n", ai->short_name, config_get_block_string(param, "name", NULL)); value = config_get_block_string(param, "options", NULL); if (value != NULL) { gchar **options = g_strsplit(value, ";", 0); for (unsigned i = 0; options[i] != NULL; ++i) { gchar **key_value = g_strsplit(options[i], "=", 2); if (key_value[0] == NULL || key_value[1] == NULL) { g_set_error(error, ao_output_quark(), 0, "problems parsing options \"%s\"", options[i]); ao_base_finish(&ad->base); g_free(ad); return NULL; } ao_append_option(&ad->options, key_value[0], key_value[1]); g_strfreev(key_value); } g_strfreev(options); } return &ad->base; }
static int open_output(void) { int driver_id, ret = 0; int driver_count; ao_info **devices; int i; ao_initialize(); opt_ao_device_id = -2; devices = ao_driver_info_list(&driver_count); if (driver_count > 0) { for(i = 0; i < driver_count; i++) { if( (devices[i]->type == AO_TYPE_LIVE) && (dpm.name != NULL) && (strcmp(dpm.name, devices[i]->short_name) == 0) ){ opt_ao_device_id = ao_driver_id(dpm.name); } } } if (opt_ao_device_id == -2){ if(dpm.name != NULL) ret = sscanf(dpm.name, "%d", &opt_ao_device_id); if ( dpm.name == NULL || ret == 0 || ret == EOF) opt_ao_device_id = -2; } if (opt_ao_device_id == -1){ ao_shutdown(); show_ao_device_info(stdout); return -1; } if (opt_ao_device_id==-2) { driver_id = ao_default_driver_id(); } else { ao_info *device; driver_id = opt_ao_device_id; if ((device = ao_driver_info(driver_id)) == NULL) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: driver is not supported.", dpm.name); return -1; } if (device->type == AO_TYPE_FILE) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: file output is not supported.", dpm.name); return -1; } } if (driver_id == -1) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", dpm.name, strerror(errno)); return -1; } /* They can't mean these */ dpm.encoding &= ~(PE_ULAW|PE_ALAW|PE_BYTESWAP); ao_sample_format_ctx.channels = (dpm.encoding & PE_MONO) ? 1 : 2; ao_sample_format_ctx.rate = dpm.rate; ao_sample_format_ctx.byte_format = AO_FMT_NATIVE; ao_sample_format_ctx.bits = (dpm.encoding & PE_24BIT) ? 24 : 0; ao_sample_format_ctx.bits = (dpm.encoding & PE_16BIT) ? 16 : 0; if (ao_sample_format_ctx.bits == 0) ao_sample_format_ctx.bits = 8; if ((ao_device_ctx = ao_open_live(driver_id, &ao_sample_format_ctx, NULL /* no options */)) == NULL) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", dpm.name, strerror(errno)); return -1; } return 0; }
void check_default_play_device() { /* check that no output devices are currently selected */ if (!(options.opt & (MPG321_USE_OSS | MPG321_USE_STDOUT | MPG321_USE_ALSA | MPG321_USE_ESD | MPG321_USE_NULL | MPG321_USE_WAV | MPG321_USE_ARTS | MPG321_USE_AU | MPG321_USE_CDR | MPG321_USE_ALSA09 | MPG321_USE_USERDEF))) { ao_info *default_info; /* set default output device & various other bits. this is here so that the device-specific inits in mad.c: open_ao_playdevice can do their dirty work all on their own */ if (strcmp(AUDIO_DEFAULT, "the libao default")==0) /* just use the libao-specified default. This is the default when compiling. */ { int unset = 1; int driver_id; /* ESD is spawned when executing the ao_default_driver_id routine. This causes a delay and is rather annoying, so we'll disable it here for now. */ #ifdef HAS_GETENV if (getenv("ESD_NO_SPAWN")) unset = 0; /* only unset it later if it's not already set */ #endif #ifdef HAS_PUTENV putenv("ESD_NO_SPAWN=1"); #else #ifdef HAS_SETENV setenv("ESD_NO_SPAWN", "1", 0); #endif #endif driver_id = ao_default_driver_id(); #ifdef HAS_PUTENV if (unset) putenv("ESD_NO_SPAWN"); #else #ifdef HAS_UNSETENV if (unset) unsetenv("ESD_NO_SPAWN"); #endif #endif if (driver_id < 0) { fprintf(stderr, "No default libao driver available.\n"); exit(1); } default_info = ao_driver_info(driver_id); set_play_device(default_info->short_name); } else { set_play_device(AUDIO_DEFAULT); } } }
int playdevice_is_live() { int driver_id=0; if(options.opt & MPG321_USE_AU) { driver_id = ao_driver_id("au"); } else if (options.opt & MPG321_USE_CDR) { driver_id = ao_driver_id("raw"); } else if(options.opt & MPG321_USE_WAV) { driver_id = ao_driver_id("wav"); } else if(options.opt & MPG321_USE_NULL) { driver_id = ao_driver_id("null"); } else if (options.opt & MPG321_USE_STDOUT) { driver_id = ao_driver_id("raw"); } else if(options.opt & MPG321_USE_ESD) { driver_id = ao_driver_id("esd"); } else if(options.opt & MPG321_USE_ARTS) { driver_id = ao_driver_id("arts"); } else if(options.opt & MPG321_USE_ALSA) { driver_id = ao_driver_id("alsa"); } else if(options.opt & MPG321_USE_OSS) { driver_id = ao_driver_id("oss"); } else if(options.opt & MPG321_USE_SUN) { driver_id = ao_driver_id("sun"); } else if (options.opt & MPG321_USE_ALSA09) { driver_id = ao_driver_id("alsa09"); } else if (options.opt & MPG321_USE_USERDEF) { driver_id = ao_driver_id(options.devicetype); } return (ao_driver_info(driver_id)->type == AO_TYPE_LIVE); }
static int play_vgmstream(const char *filename, struct params *par) { int ret = 0; STREAMFILE *sf; VGMSTREAM *vgms; FILE *save_fps[4]; int loop_count; int64_t total_samples; size_t buffer_size; int64_t buffer_samples; int64_t fade_time_samples, fade_start; int time_total_min; double time_total_sec; int64_t s; int i; sf = open_stdio_streamfile(filename); if (!sf) { fprintf(stderr, "%s: cannot open file\n", filename); return -1; } sf->stream_index = par->stream_index; vgms = init_vgmstream_from_STREAMFILE(sf); close_streamfile(sf); if (!vgms) { fprintf(stderr, "%s: error opening stream\n", filename); return -1; } printf("Playing stream: %s\n", filename); /* Print metadata in verbose mode */ if (verbose) { char description[4096] = { '\0' }; describe_vgmstream(vgms, description, sizeof(description)); puts(description); putchar('\n'); } /* If the audio device hasn't been opened yet, then describe it */ if (!device) { ao_info *info = ao_driver_info(driver_id); printf("Audio device: %s\n", info->name); printf("Comment: %s\n", info->comment); putchar('\n'); } /* Stupid hack to hang onto a few low-numbered file descriptors * so that play_compressed_file() doesn't break, due to POSIX * wackiness like https://bugs.debian.org/590920 */ for (i = 0; i < 4; i++) save_fps[i] = fopen("/dev/null", "r"); ret = set_sample_format(vgms); if (ret) goto fail; loop_count = par->loop_count; if (vgms->loop_flag && loop_count < 0) { /* * Calculate how many loops are needed to achieve a minimum * playback time. Note: This calculation is derived from the * logic in get_vgmstream_play_samples(). */ double intro = (double)vgms->loop_start_sample / vgms->sample_rate; double loop = (double)(vgms->loop_end_sample - vgms->loop_start_sample) / vgms->sample_rate; double end = par->fade_time + par->fade_delay; if (loop < 1.0) loop = 1.0; loop_count = (int)((par->min_time - intro - end) / loop + 0.99); if (loop_count < 1) loop_count = 1; } total_samples = get_vgmstream_play_samples(loop_count, par->fade_time, par->fade_delay, vgms); { double total = (double)total_samples / vgms->sample_rate; time_total_min = (int)total / 60; time_total_sec = total - 60 * time_total_min; } /* Buffer size in bytes */ buffer_size = 1024 * buffer_size_kb; if (!buffer) { if (buffer_size_kb < 1) { fprintf(stderr, "Invalid buffer size '%d'\n", buffer_size_kb); return -1; } buffer = malloc(buffer_size); if (!buffer) goto fail; } buffer_samples = buffer_size / (vgms->channels * sizeof(sample)); fade_time_samples = (int64_t)(par->fade_time * vgms->sample_rate); fade_start = total_samples - fade_time_samples; if (fade_start < 0) fade_start = total_samples; for (s = 0; s < total_samples && !interrupted; s += buffer_samples) { int64_t buffer_used_samples = MIN(buffer_samples, total_samples - s); char *suffix = ""; render_vgmstream(buffer, buffer_used_samples, vgms); #ifdef LITTLE_ENDIAN_OUTPUT swap_samples_le(buffer, vgms->channels * buffer_used_samples); #endif if (vgms->loop_flag && fade_time_samples > 0 && s >= fade_start) { /* Got to do the fade-out ourselves :p */ int64_t b; for (b = 0; b < buffer_used_samples; b++) { double factor = 1.0 - (double)(s + b - fade_start) / fade_time_samples; int c; for (c = 0; c < vgms->channels; c++) buffer[vgms->channels * b + c] *= factor; } suffix = " (fading)"; } if (verbose && !out_filename) { double played = (double)s / vgms->sample_rate; double remain = (double)(total_samples - s) / vgms->sample_rate; int time_played_min = (int)played / 60; double time_played_sec = played - 60 * time_played_min; int time_remain_min = (int)remain / 60; double time_remain_sec = remain - 60 * time_remain_min; /* Time: 01:02.34 [08:57.66] of 10:00.00 */ printf("\rTime: %02d:%05.2f [%02d:%05.2f] of %02d:%05.2f%s ", time_played_min, time_played_sec, time_remain_min, time_remain_sec, time_total_min, time_total_sec, suffix); fflush(stdout); } if (!ao_play(device, (char *)buffer, buffer_used_samples * vgms->channels * sizeof(sample))) { fputs("\nAudio playback error\n", stderr); ao_close(device); device = NULL; ret = -1; break; } } if (verbose && !ret) { /* Clear time status line */ putchar('\r'); for (i = 0; i < 64; i++) putchar(' '); putchar('\r'); fflush(stdout); } if (out_filename && !ret) printf("Wrote %02d:%05.2f of audio to %s\n\n", time_total_min, time_total_sec, out_filename); if (interrupted) { fputs("Playback terminated.\n\n", stdout); ret = record_interrupt(); if (ret) fputs("Exiting...\n", stdout); } fail: close_vgmstream(vgms); for (i = 0; i < 4; i++) fclose(save_fps[i]); return ret; }
int parse_cmdline_options (int argc, char **argv, ogg123_options_t *ogg123_opts, file_option_t *file_opts) { int option_index = 1; ao_option *temp_options = NULL; ao_option ** current_options = &temp_options; ao_info *info; int temp_driver_id = -1; audio_device_t *current; int ret; while (-1 != (ret = getopt_long(argc, argv, "b:c::d:f:hl:k:K:o:p:qvVx:y:z@:", long_options, &option_index))) { switch (ret) { case 0: if(!strcmp(long_options[option_index].name, "audio-buffer")) { ogg123_opts->buffer_size = 1024 * atoi(optarg); } else { status_error(_("Internal error parsing command line options.\n")); exit(1); } break; case 'b': ogg123_opts->input_buffer_size = atoi(optarg) * 1024; if (ogg123_opts->input_buffer_size < MIN_INPUT_BUFFER_SIZE * 1024) { status_error(_("Input buffer size smaller than minimum size of %dkB."), MIN_INPUT_BUFFER_SIZE); ogg123_opts->input_buffer_size = MIN_INPUT_BUFFER_SIZE * 1024; } break; case 'c': if (optarg) { char *tmp = strdup (optarg); parse_code_t pcode = parse_line(file_opts, tmp); if (pcode != parse_ok) status_error(_("=== Error \"%s\" while parsing config option from command line.\n" "=== Option was: %s\n"), parse_error_string(pcode), optarg); free (tmp); } else { /* not using the status interface here */ fprintf (stdout, _("Available options:\n")); file_options_describe(file_opts, stdout); exit (0); } break; case 'd': temp_driver_id = ao_driver_id(optarg); if (temp_driver_id < 0) { status_error(_("=== No such device %s.\n"), optarg); exit(1); } current = append_audio_device(ogg123_opts->devices, temp_driver_id, NULL, NULL); if(ogg123_opts->devices == NULL) ogg123_opts->devices = current; current_options = ¤t->options; break; case 'f': if (temp_driver_id >= 0) { info = ao_driver_info(temp_driver_id); if (info->type == AO_TYPE_FILE) { free(current->filename); current->filename = strdup(optarg); } else { status_error(_("=== Driver %s is not a file output driver.\n"), info->short_name); exit(1); } } else { status_error(_("=== Cannot specify output file without specifying a driver.\n")); exit (1); } break; case 'k': ogg123_opts->seekpos = strtotime(optarg); break; case 'K': ogg123_opts->endpos = strtotime(optarg); break; case 'l': ogg123_opts->delay = atoi(optarg); break; case 'o': if (optarg && !add_ao_option(current_options, optarg)) { status_error(_("=== Incorrect option format: %s.\n"), optarg); exit(1); } break; case 'h': cmdline_usage(); exit(0); break; case 'p': ogg123_opts->input_prebuffer = atof (optarg); if (ogg123_opts->input_prebuffer < 0.0f || ogg123_opts->input_prebuffer > 100.0f) { status_error (_("--- Prebuffer value invalid. Range is 0-100.\n")); ogg123_opts->input_prebuffer = ogg123_opts->input_prebuffer < 0.0f ? 0.0f : 100.0f; } break; case 'q': ogg123_opts->verbosity = 0; break; case 'v': ogg123_opts->verbosity++; break; case 'V': status_error(_("ogg123 from %s %s\n"), PACKAGE, VERSION); exit(0); break; case 'x': ogg123_opts->nth = atoi(optarg); if (ogg123_opts->nth == 0) { status_error(_("--- Cannot play every 0th chunk!\n")); ogg123_opts->nth = 1; } break; case 'y': ogg123_opts->ntimes = atoi(optarg); if (ogg123_opts->ntimes == 0) { status_error(_("--- Cannot play every chunk 0 times.\n" "--- To do a test decode, use the null output driver.\n")); ogg123_opts->ntimes = 1; } break; case 'z': ogg123_opts->shuffle = 1; break; case '@': if (playlist_append_from_file(ogg123_opts->playlist, optarg) == 0) status_error(_("--- Cannot open playlist file %s. Skipped.\n"), optarg); break; case '?': break; default: cmdline_usage(); exit(1); } } /* Sanity check bad option combinations */ if (ogg123_opts->endpos > 0.0 && ogg123_opts->seekpos > ogg123_opts->endpos) { status_error(_("=== Option conflict: End time is before start time.\n")); exit(1); } /* Add last device to device list or use the default device */ if (temp_driver_id < 0) { /* First try config file setting */ if (ogg123_opts->default_device) { temp_driver_id = ao_driver_id(ogg123_opts->default_device); if (temp_driver_id < 0) status_error(_("--- Driver %s specified in configuration file invalid.\n"), ogg123_opts->default_device); } /* Then try libao autodetect */ if (temp_driver_id < 0) temp_driver_id = ao_default_driver_id(); /* Finally, give up */ if (temp_driver_id < 0) { status_error(_("=== Could not load default driver and no driver specified in config file. Exiting.\n")); exit(1); } ogg123_opts->devices = append_audio_device(ogg123_opts->devices, temp_driver_id, temp_options, NULL); } return optind; }
void cAudio::run() { lt_info("====================== start decoder thread ================================\n"); /* libavcodec & friends */ av_register_all(); AVCodec *codec; AVFormatContext *avfc = NULL; AVInputFormat *inp; AVFrame *frame; uint8_t *inbuf = (uint8_t *)av_malloc(INBUF_SIZE); AVPacket avpkt; int ret, driver; /* libao */ ao_info *ai; // ao_device *adevice; // ao_sample_format sformat; /* resample */ SwrContext *swr = NULL; uint8_t *obuf = NULL; int obuf_sz = 0; /* in samples */ int obuf_sz_max = 0; int o_ch, o_sr; /* output channels and sample rate */ uint64_t o_layout; /* output channels layout */ char tmp[64] = "unknown"; curr_pts = 0; av_init_packet(&avpkt); inp = av_find_input_format("mpegts"); AVIOContext *pIOCtx = avio_alloc_context(inbuf, INBUF_SIZE, // internal Buffer and its size 0, // bWriteable (1=true,0=false) NULL, // user data; will be passed to our callback functions _my_read, // read callback NULL, // write callback NULL); // seek callback avfc = avformat_alloc_context(); avfc->pb = pIOCtx; avfc->iformat = inp; avfc->probesize = 188*5; thread_started = true; if (avformat_open_input(&avfc, NULL, inp, NULL) < 0) { lt_info("%s: avformat_open_input() failed.\n", __func__); goto out; } ret = avformat_find_stream_info(avfc, NULL); lt_debug("%s: avformat_find_stream_info: %d\n", __func__, ret); if (avfc->nb_streams != 1) { lt_info("%s: nb_streams: %d, should be 1!\n", __func__, avfc->nb_streams); goto out; } if (avfc->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO) lt_info("%s: stream 0 no audio codec? 0x%x\n", __func__, avfc->streams[0]->codec->codec_type); c = avfc->streams[0]->codec; codec = avcodec_find_decoder(c->codec_id); if (!codec) { lt_info("%s: Codec for %s not found\n", __func__, avcodec_get_name(c->codec_id)); goto out; } if (avcodec_open2(c, codec, NULL) < 0) { lt_info("%s: avcodec_open2() failed\n", __func__); goto out; } frame = av_frame_alloc(); if (!frame) { lt_info("%s: avcodec_alloc_frame failed\n", __func__); goto out2; } /* output sample rate, channels, layout could be set here if necessary */ o_ch = c->channels; /* 2 */ o_sr = c->sample_rate; /* 48000 */ o_layout = c->channel_layout; /* AV_CH_LAYOUT_STEREO */ if (sformat.channels != o_ch || sformat.rate != o_sr || sformat.byte_format != AO_FMT_NATIVE || sformat.bits != 16 || adevice == NULL) { driver = ao_default_driver_id(); sformat.bits = 16; sformat.channels = o_ch; sformat.rate = o_sr; sformat.byte_format = AO_FMT_NATIVE; sformat.matrix = 0; if (adevice) ao_close(adevice); adevice = ao_open_live(driver, &sformat, NULL); ai = ao_driver_info(driver); lt_info("%s: changed params ch %d srate %d bits %d adevice %p\n", __func__, o_ch, o_sr, 16, adevice);; lt_info("libao driver: %d name '%s' short '%s' author '%s'\n", driver, ai->name, ai->short_name, ai->author); } #if 0 lt_info(" driver options:"); for (int i = 0; i < ai->option_count; ++i) fprintf(stderr, " %s", ai->options[i]); fprintf(stderr, "\n"); #endif av_get_sample_fmt_string(tmp, sizeof(tmp), c->sample_fmt); lt_info("decoding %s, sample_fmt %d (%s) sample_rate %d channels %d\n", avcodec_get_name(c->codec_id), c->sample_fmt, tmp, c->sample_rate, c->channels); swr = swr_alloc_set_opts(swr, o_layout, AV_SAMPLE_FMT_S16, o_sr, /* output */ c->channel_layout, c->sample_fmt, c->sample_rate, /* input */ 0, NULL); if (! swr) { lt_info("could not alloc resample context\n"); goto out3; } swr_init(swr); while (thread_started) { int gotframe = 0; if (av_read_frame(avfc, &avpkt) < 0) break; avcodec_decode_audio4(c, frame, &gotframe, &avpkt); if (gotframe && thread_started) { int out_linesize; obuf_sz = av_rescale_rnd(swr_get_delay(swr, c->sample_rate) + frame->nb_samples, o_sr, c->sample_rate, AV_ROUND_UP); if (obuf_sz > obuf_sz_max) { lt_info("obuf_sz: %d old: %d\n", obuf_sz, obuf_sz_max); av_free(obuf); if (av_samples_alloc(&obuf, &out_linesize, o_ch, frame->nb_samples, AV_SAMPLE_FMT_S16, 1) < 0) { lt_info("av_samples_alloc failed\n"); av_free_packet(&avpkt); break; /* while (thread_started) */ } obuf_sz_max = obuf_sz; } obuf_sz = swr_convert(swr, &obuf, obuf_sz, (const uint8_t **)frame->extended_data, frame->nb_samples); curr_pts = av_frame_get_best_effort_timestamp(frame); lt_debug("%s: pts 0x%" PRIx64 " %3f\n", __func__, curr_pts, curr_pts/90000.0); int o_buf_sz = av_samples_get_buffer_size(&out_linesize, o_ch, obuf_sz, AV_SAMPLE_FMT_S16, 1); ao_play(adevice, (char *)obuf, o_buf_sz); } av_free_packet(&avpkt); } // ao_close(adevice); /* can take long :-( */ av_free(obuf); swr_free(&swr); out3: av_frame_free(&frame); out2: avcodec_close(c); c = NULL; out: avformat_close_input(&avfc); av_free(pIOCtx->buffer); av_free(pIOCtx); lt_info("======================== end decoder thread ================================\n"); }
void ags_libao_get_property(GObject *gobject, guint prop_id, GValue *value, GParamSpec *param_spec) { AgsLibao *libao; libao = AGS_LIBAO(gobject); switch(prop_id) { case PROP_DEVICE: { if((AGS_LIBAO_LIBAO & (libao->flags)) != 0) { g_value_set_string(value, ao_driver_info(libao->out.ao.driver_ao)->name); } } break; case PROP_DSP_CHANNELS: { g_value_set_uint(value, libao->dsp_channels); } break; case PROP_PCM_CHANNELS: { g_value_set_uint(value, libao->pcm_channels); } break; case PROP_BITS: { g_value_set_uint(value, libao->bits); } break; case PROP_BUFFER_SIZE: { g_value_set_uint(value, libao->buffer_size); } break; case PROP_FREQUENCY: { g_value_set_uint(value, libao->frequency); } break; case PROP_BUFFER: { g_value_set_pointer(value, libao->buffer); } break; case PROP_BPM: { g_value_set_double(value, libao->bpm); } break; case PROP_ATTACK: { g_value_set_pointer(value, libao->attack); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec); break; } }
int sound_lowlevel_init( const char *device, int *freqptr, int *stereoptr ) { ao_option *options = NULL; ao_info *driver_info = NULL; int driver_id = -1; static ao_sample_format format = { .bits = 0 }; /* To prevent recursive errors */ static int sound_lowlevel_init_in_progress = 0; int error; if( sound_lowlevel_init_in_progress ) return 0; sound_lowlevel_init_in_progress = 1; ao_initialize(); error = parse_driver_options( device, &driver_id, &options ); if( error ) { settings_current.sound = 0; sound_lowlevel_init_in_progress = 0; return error; } if( driver_id == -1 ) driver_id = ao_default_driver_id(); if( driver_id == -1 ) { ui_error( UI_ERROR_ERROR, "ao: driver '%s' unknown", device ); settings_current.sound = 0; sound_lowlevel_init_in_progress = 0; return 1; } driver_info = ao_driver_info( driver_id ); if( driver_info->type == AO_TYPE_FILE && format.bits != 0 ) { /* OK. We not want to trunc the file :-) */ ui_error( UI_ERROR_WARNING, "ao: must truncate audio file '%s'", filename ); } format.channels = *stereoptr ? 2 : 1; format.rate = *freqptr; format.bits = settings_current.sound_force_8bit ? 8 : 16; format.byte_format = AO_FMT_LITTLE; sixteenbit = settings_current.sound_force_8bit ? 0 : 1; if( driver_info->type == AO_TYPE_LIVE ) { dev_for_ao = ao_open_live( driver_id, &format, options); } else { if( !filename ) filename = (char *)default_filename; dev_for_ao = ao_open_file( driver_id, filename, 1, &format, options); } if( !dev_for_ao ) { driver_error(); settings_current.sound = 0; sound_lowlevel_init_in_progress = 0; return 1; } ao_free_options( options ); sound_lowlevel_init_in_progress = 0; first_init = 0; return 0; } void sound_lowlevel_end( void ) { if( filename != default_filename ) free( filename ); ao_close(dev_for_ao); ao_shutdown(); } void sound_lowlevel_frame( libspectrum_signed_word *data, int len ) { static signed char buf8[4096]; void *data8 = data; len <<= 1; /* now in bytes */ if( !sixteenbit ) { libspectrum_signed_word *src; signed char *dst; int f; src = data; dst = buf8; len >>= 1; for( f = 0; f < len; f++) *dst++ = ( int )( ( *src++ ) / 256 ); data8 = buf8; } ao_play( dev_for_ao, data8, len ); }