int fm_player_open(fm_player_t *pl, fm_player_config_t *config) { pl->config = *config; pl->mh = mpg123_new(NULL, NULL); mpg123_format_none(pl->mh); mpg123_format(pl->mh, config->rate, config->channels, config->encoding); 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); ao_info *driver_info = ao_driver_info(driver); printf("Audio Driver: %s\n", driver_info->name); printf("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->curl = curl_easy_init(); curl_easy_setopt(pl->curl, CURLOPT_WRITEFUNCTION, download_callback); curl_easy_setopt(pl->curl, CURLOPT_WRITEDATA, pl); pl->tid_ack = -1; pthread_mutex_init(&pl->mutex_status, NULL); pthread_cond_init(&pl->cond_play, NULL); pl->status = FM_PLAYER_STOP; return 0; }
static PyObject * py_ao_driver_id(PyObject *self, PyObject *args) { int driver_id; char *str = NULL; if (self != NULL) { ao_Object *ao_self = (ao_Object *) self; driver_id = ao_self->driver_id; } else { if (!PyArg_ParseTuple(args, "s", &str)) return NULL; driver_id = ao_driver_id(str); } if (driver_id == -1) { PyErr_SetString(Py_aoError, "No such driver"); return NULL; } return PyInt_FromLong(driver_id); }
static ao_device * audio_open_device(shairplay_options_t *opt, int bits, int channels, int samplerate) { ao_device *device = NULL; ao_option *ao_options = NULL; ao_sample_format format; int driver_id; /* Get the libao driver ID */ if (strlen(opt->ao_driver)) { driver_id = ao_driver_id(opt->ao_driver); } else { driver_id = ao_default_driver_id(); } /* Add all available libao options */ ao_append_option(&ao_options, "client_name", opt->apname); if (strlen(opt->ao_devicename)) { ao_append_option(&ao_options, "dev", opt->ao_devicename); } if (strlen(opt->ao_deviceid)) { ao_append_option(&ao_options, "id", opt->ao_deviceid); } /* Set audio format */ memset(&format, 0, sizeof(format)); format.bits = bits; format.channels = channels; format.rate = samplerate; format.byte_format = AO_FMT_NATIVE; /* Try opening the actual device */ device = ao_open_live(driver_id, &format, ao_options); ao_free_options(ao_options); return device; }
void audio_init() { // Initialize audio device // Set the framerate based on the region. For PAL: (60 / 6) * 5 = 50 framerate = nst_pal ? (conf.timing_speed / 6) * 5 : conf.timing_speed; channels = conf.audio_stereo ? 2 : 1; memset(audiobuf, 0, sizeof(audiobuf)); #ifdef _MINGW conf.audio_api = 0; // Set SDL audio for MinGW #endif #if SDL_VERSION_ATLEAST(2,0,4) #else // Force libao if SDL lib is not modern enough if (conf.audio_api == 0) { conf.audio_api = 1; fprintf(stderr, "Audio: Forcing libao\n"); } #endif if (conf.audio_api == 0) { // SDL spec.freq = conf.audio_sample_rate; spec.format = AUDIO_S16SYS; spec.channels = channels; spec.silence = 0; spec.samples = 512; spec.userdata = 0; spec.callback = NULL; // Use SDL_QueueAudio instead dev = SDL_OpenAudioDevice(NULL, 0, &spec, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE); if (!dev) { fprintf(stderr, "Error opening audio device.\n"); } else { fprintf(stderr, "Audio: SDL - %dHz %d-bit, %d channel(s)\n", spec.freq, 16, spec.channels); } SDL_PauseAudioDevice(dev, 1); // Setting to 0 unpauses } #ifndef _MINGW else if (conf.audio_api == 1) { // libao ao_initialize(); int default_driver = ao_default_driver_id(); memset(&format, 0, sizeof(format)); format.bits = 16; format.channels = channels; format.rate = conf.audio_sample_rate; format.byte_format = AO_FMT_NATIVE; aodevice = ao_open_live(default_driver, &format, NULL); if (aodevice == NULL) { fprintf(stderr, "Error opening audio device.\n"); aodevice = ao_open_live(ao_driver_id("null"), &format, NULL); } else { fprintf(stderr, "Audio: libao - %dHz, %d-bit, %d channel(s)\n", format.rate, format.bits, format.channels); } } #endif paused = false; }
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; }
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; }
int main(int argc, char* argv[]) { long size; char *filedata; term_size terminal; ModPlugFile *f2; int mlen; struct timeval tvstart; struct timeval tv; struct timeval tvpause, tvunpause; struct timeval tvptotal; char status[161]; char songname[41]; char notpaus[4]; int loop=0; // kontest int songsplayed = 0; int nFiles = 0, fnOffset[100]; int i; ModPlug_Settings settings; ModPlug_GetSettings(&settings); ao_device *device; ao_sample_format format = {0}; int default_driver; ao_initialize(); default_driver = ao_default_driver_id(); for (i=1; i<argc; i++) { /* check if arguments need to be parsed */ if (argv[i][0] == '-') { if (strstr(argv[i],"-h")) { printf("\n"); help(argv[0],0); } else if (strstr(argv[i],"-v")) { versioninfo(); exit(0); } else if (strstr(argv[i],"-l")) { loop=1; continue; } else if (strstr(argv[i],"-ao")) { default_driver = ao_driver_id(argv[++i]); continue; } if (argv[i][1] == '-') { // not a song if (strstr(argv[i],"--help")) { help(argv[0],0); } else if (strstr(argv[i],"--version")) { versioninfo(); exit(0); } continue; } } /* "valid" filename - store it */ fnOffset[nFiles++] = i; } format.bits = 16; format.channels = 2; format.rate = 44100; format.byte_format = AO_FMT_LITTLE; // printf("Default driver = %i\n", default_driver); char buffer[128]; int result, nread; struct pollfd pollfds; int timeout = 1; /* Timeout in msec. */ int pause=0; int mono=0; int bits=0; int song; // [rev--dly--] [sur--dly--] [bas--rng--] int rev=0; // a int revdly=0; // s int sur=0; // d int surdly=0; // y int bas=0; // x int basrng=0; // c /* Initialize pollfds; we're looking at input, stdin */ pollfds.fd = 0; /* stdin */ pollfds.events = POLLIN; /* Wait for input */ if (argc==1) { help(argv[0],1); } if (!get_term_size(STDIN_FILENO,&terminal)) { fprintf(stderr,"warning: failed to get terminal size\n"); } srand(time(NULL)); for (song=0; song<nFiles; song++) { char *filename = argv[fnOffset[song]]; /* -- Open driver -- */ if (default_driver == ao_driver_id("wav")) { device = ao_open_file(default_driver, "output.wav", 1, &format, NULL /*no options*/); } else { device = ao_open_live(default_driver, &format, NULL /* no options */); } if (device == NULL) { fprintf(stderr, "Error opening device. (%s)\n", filename); fprintf(stderr, "ERROR: %i\n", errno); return 1; } printf("%s ",filename); printf("[%d/%d]",song+1,nFiles); filedata = getFileData(filename, &size); if (filedata == NULL) continue; printf(" [%ld]\n",size); // Note: All "Basic Settings" must be set before ModPlug_Load. settings.mResamplingMode = MODPLUG_RESAMPLE_FIR; /* RESAMP */ settings.mChannels = 2; settings.mBits = 16; settings.mFrequency = 44100; settings.mStereoSeparation = 128; settings.mMaxMixChannels = 256; /* insert more setting changes here */ ModPlug_SetSettings(&settings); f2 = ModPlug_Load(filedata, size); if (!f2) { printf("could not load %s\n", filename); close(audio_fd); free(filedata); /* ? */ } else { songsplayed++; /* settings.mFlags=MODPLUG_ENABLE_OVERSAMPLING | \ MODPLUG_ENABLE_NOISE_REDUCTION | \ MODPLUG_ENABLE_REVERB | \ MODPLUG_ENABLE_MEGABASS | \ MODPLUG_ENABLE_SURROUND;*/ // settings.mReverbDepth = 100; /* 0 - 100 */ * [REV--DLY--] // settings.mReverbDelay = 200; /* 40 - 200 ms 00-FF */ // settings.mSurroundDepth = 100; /* 0 - 100 */ [SUR--DLY--] // settings.mSurroundDelay = 40; /* 5 - 40 ms */ // settings.mBassAmount = 100; /* 0 - 100 */ [BAS--RNG--] // settings.mBassRange = 100; /* 10 - 100 hz */ // [REV--DLY--] [SUR--DLY--] [BAS--RNG--] // [rev--dly--] [sur--dly--] [bas--rng--] set_keypress(); strcpy(songname, ModPlug_GetName(f2)); /* if no modplug "name" - use last 41 characters of filename */ if (strlen(songname)==0) { int l = strlen(filename); char *st = filename; if (l >= 41) st = filename + l - 41; strncpy(songname,st,41); songname[40] = 0; } sprintf(status,"[1Gplaying %s (%%d.%%d/%d\") (%%d/%%d/%%d) \b\b\b\b",songname,ModPlug_GetLength(f2)/1000); if (loop) sprintf(status,"[1Glooping %s (%%d.%%d/%d\") (%%d/%%d/%%d) \b\b\b\b",songname,ModPlug_GetLength(f2)/1000); gettimeofday(&tvstart,NULL); tvptotal.tv_sec=tvptotal.tv_usec=0; mlen=1; while(mlen!=0) { if (mlen==0) { break; } if (!pause) { gettimeofday(&tv,NULL); mlen = ModPlug_Read(f2,audio_buffer,BUF_SIZE); if (mlen > 0 && ao_play(device, audio_buffer, mlen) == 0) { perror("audio write"); exit(1); } } printf(status,tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec,tv.tv_usec/100000,format.rate,format.channels,settings.mBits/*,rev,revdly,sur,surdly,bas,basrng*/); fflush(stdout); if ((mlen==0) && (loop==1)) { /*printf("LOOPING NOW\n");*/ ModPlug_Seek(f2,0); gettimeofday(&tvstart,NULL); mlen=ModPlug_Read(f2,audio_buffer,BUF_SIZE); tvptotal.tv_sec=tvptotal.tv_usec=0; } result = poll(&pollfds, 1, timeout); switch (result) { case 0: /*printf(".");*/ break; case -1: perror("select"); exit(1); default: if (pollfds.revents && POLLIN) { nread = read(0, buffer, 1); /* s/nread/1/2 */ if (nread == 0) { printf("keyboard done\n"); exit(0); } else { buffer[nread] = 0; /* printf("%s", buffer); */ if (buffer[0]=='q') { mlen=0; song=nFiles; } /* quit */ if (buffer[0]=='f') { if ((tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec+10) < (ModPlug_GetLength(f2)/1000)) { ModPlug_Seek(f2,(tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec)*1000+10000); tvstart.tv_sec-=10; } } /* forward 10" */ if (buffer[0]=='b') { if ((tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec-10) > 0) { ModPlug_Seek(f2,(tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec)*1000-10000); tvstart.tv_sec+=10; } } /* backward 10" */ /* if (buffer[0]=='i') { printf("\n"); } */ /* if (buffer[0]=='a') { rev++; settings.mReverbDepth=rev; ModPlug_SetSettings(&settings); } if (buffer[0]=='A') { rev--; settings.mReverbDepth=rev; ModPlug_SetSettings(&settings); } if (buffer[0]=='s') { revdly++; settings.mReverbDelay=revdly; ModPlug_SetSettings(&settings); } if (buffer[0]=='S') { revdly--; settings.mReverbDelay=revdly; ModPlug_SetSettings(&settings); } if (buffer[0]=='d') { sur++; settings.mSurroundDepth=sur; ModPlug_SetSettings(&settings); } if (buffer[0]=='D') { sur--; settings.mSurroundDepth=sur; ModPlug_SetSettings(&settings); } if (buffer[0]=='y') { surdly++; settings.mSurroundDelay=surdly; ModPlug_SetSettings(&settings); } if (buffer[0]=='Y') { surdly--; settings.mSurroundDelay=surdly; ModPlug_SetSettings(&settings); } if (buffer[0]=='x') { bas++; settings.mBassAmount=bas; ModPlug_SetSettings(&settings); } if (buffer[0]=='X') { bas--; settings.mBassAmount=bas; ModPlug_SetSettings(&settings); } if (buffer[0]=='c') { basrng++; settings.mBassRange=basrng; ModPlug_SetSettings(&settings); } if (buffer[0]=='C') { basrng--; settings.mBassRange=basrng; ModPlug_SetSettings(&settings); } */ if (buffer[0]=='n') { if (song<argc) { mlen=0; pause=0; } } if (buffer[0]=='N') { if (song>1) { song-=2; mlen=0; pause=0; } } if (buffer[0]=='r') { song=(int) ((float)(argc-1)*rand()/(RAND_MAX+1.0)); mlen=0; pause=0; // ioctl(audio_fd,SNDCTL_DSP_RESET,0); /* printf("\n[%d?]\n",song+1); */ } /*if (buffer[0]=='R') { song=(int) ((float)(argc-1)*rand()/(RAND_MAX+1.0)); mlen=0; pause=0; }*/ /* if (buffer[0]=='m') { // mono/stereo mono^=1; if (mono) format.channels=1; else format.channels=2; ioctl(audio_fd,SNDCTL_DSP_RESET,0); if (ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels) == -1) { perror("SNDCTL_DSP_CHANNELS"); exit(1); } if (mono) settings.mChannels=1; else settings.mChannels=2; ModPlug_SetSettings(&settings); f2=ModPlug_Load(d,size); ModPlug_Seek(f2,(tv.tv_sec-tvstart.tv_sec-tvptotal.tv_sec)*1000+10000); } */ if (buffer[0]=='l') { loop^=1; if (loop) { memcpy(status+4,"loop",4); } else { memcpy(status+4,"play",4); } } /* loop */ if (buffer[0]=='p') { pause^=1; if (pause) { gettimeofday(&tvpause,NULL); memcpy(notpaus,status+4,4); memcpy(status+4,"paus",4); } else { gettimeofday(&tvunpause,NULL); memcpy(status+4,notpaus,4); tvptotal.tv_sec+=tvunpause.tv_sec-tvpause.tv_sec; tvptotal.tv_usec+=tvunpause.tv_usec-tvpause.tv_usec; /* printf(status,tv.tv_sec-tvstart.tv_sec,tv.tv_usec/100000); */ } } /* pause */ } } } } printf("\n"); reset_keypress(); ModPlug_Unload(f2); ao_close(device); fprintf(stderr, "Closing audio device.\n"); free(filedata); } /* valid module */ } /* for */ ao_shutdown(); return 0; }
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; }
ao_device *open_ao_playdevice_buffer(struct mad_header const *header) { ao_sample_format format; ao_device *pldev = NULL; /* Because these can sometimes block, we stop our custom signal handler, and restore it afterwards */ signal(SIGINT, SIG_DFL); format.bits = 16; format.rate = header->samplerate; format.channels = (options.opt & MPG321_FORCE_STEREO) ? 2 : MAD_NCHANNELS(header); /* Add this element as an option to mpg321 */ format.matrix = "L,R"; /* mad gives us little-endian data; we swap it on big-endian targets, to big-endian format, because that's what most drivers expect. */ format.byte_format = AO_FMT_NATIVE; if(options.opt & MPG321_USE_AU) { int driver_id = ao_driver_id("au"); ao_option *ao_options = NULL; /* Don't have to check options.device here: we only define MPG321_USE_AU when --au <aufile> is defined, and <aufile> is pointd to by options.device */ if((pldev=ao_open_file(driver_id, options.device, 1 /*overwrite*/, &format, ao_options))==NULL) { fprintf(stderr, "Error opening libao file output driver to write AU data.\n"); return NULL; } } else if (options.opt & MPG321_USE_CDR) { ao_option * ao_options = NULL; int driver_id = ao_driver_id("raw"); /* because CDR is a special format, i.e. headerless PCM, big endian, this is a special case. */ ao_append_option(&ao_options, "byteorder", "big"); if((pldev=ao_open_file(driver_id, options.device, 1 /*overwrite*/, &format, ao_options))==NULL) { fprintf(stderr, "Error opening libao file output driver to write CDR data.\n"); return NULL; } } /* if the user specifies both au and wave, wav will be prefered, so testing * later */ else if(options.opt & MPG321_USE_WAV) { int driver_id = ao_driver_id("wav"); ao_option *ao_options = NULL; /* Don't have to check options.device here: we only define MPG321_USE_WAV when -w <wavfile> is defined, and <wavfile> is pointd to by options.device */ if((pldev=ao_open_file(driver_id, options.device, 1 /*overwrite*/, &format, ao_options))==NULL) { fprintf(stderr, "Error opening libao wav file driver. (Do you have write permissions?)\n"); return NULL; } } else if(options.opt & MPG321_USE_NULL) { int driver_id = ao_driver_id("null"); /* null is dirty, create a proper options struct later */ if((pldev = ao_open_live(driver_id, &format, NULL)) == NULL) { fprintf(stderr, "Error opening libao null driver. (This shouldn't have happened.)\n"); return NULL; } } else if (options.opt & MPG321_USE_STDOUT) { ao_option * ao_options = NULL; int driver_id = ao_driver_id("raw"); /* stdout output is expected to be little-endian generally */ ao_append_option(&ao_options, "byteorder", "little"); if((pldev=ao_open_file(driver_id, "-", 1 /*overwrite*/, &format, ao_options))==NULL) { fprintf(stderr, "Error opening libao raw output driver.\n"); return NULL; } } else if (options.opt & MPG321_USE_USERDEF) { ao_option *ao_options = NULL; int driver_id = ao_driver_id(options.devicetype); if (driver_id < 0) { fprintf(stderr, "Can't open unknown ao driver %s\n", options.devicetype); exit(1); } if (playdevice_is_live()) { if (options.device) { fprintf(stderr, "Can't set output device to %s for unknown ao plugin %s", options.device, options.devicetype); } if((pldev=ao_open_live(driver_id, &format, ao_options))==NULL) { fprintf(stderr, "Error opening unknown libao %s driver. (Is device in use?)\n", options.devicetype); return NULL; } } else { if (options.device) { /* Just assume that options.device is a filename. The user can shoot themselves in the foot all they like... */ if((pldev=ao_open_file(driver_id, options.device, 1 /*overwrite*/, &format, ao_options))==NULL) { fprintf(stderr, "Error opening unknown libao %s file driver for file %s. (Do you have write permissions?)\n", options.devicetype, options.device); return NULL; } } else { fprintf(stderr, "Filename must be specified (with -a filename) for unknown ao driver %s\n", options.devicetype); } } } else { /* Hack-tacular. This code tries to the device as specified; if it can't, it'll fall through to the other devices, trying each in turn. If the user specified a device to use, though, it won't fall through: principle of least surprise */ int opened = 0; if(!opened && options.opt & MPG321_USE_ALSA) { ao_option *ao_options = NULL; int driver_id = ao_driver_id("alsa"); char *c; char *card=(char *)malloc((int)16); memset(card,0,16); strncat(card,"alsa:\0",6); if (options.device) { strcat(card,options.device); //if ((c = strchr(options.device, ':')) == NULL || strlen(c+1) < 1) if ((c = strchr(card, ':')) == NULL || strlen(c+1) < 1) { fprintf(stderr, "Poorly formed ALSA card:device specification %s", options.device); exit(1); } *(c++) = '\0'; /* change the : to a null to create two separate strings */ //ao_append_option(&ao_options, "card", options.device); ao_append_option(&ao_options, "card", card); ao_append_option(&ao_options, "dev", c); } if((pldev=ao_open_live(driver_id, &format, ao_options))==NULL) { if (options.device) { fprintf(stderr, "Can't open libao driver with device %s (is device in use?)\n", options.device); return NULL; } else options.opt |= MPG321_USE_ALSA09; } else opened++; } if(!opened && options.opt & MPG321_USE_ALSA09) { ao_option *ao_options = NULL; int driver_id = ao_driver_id("alsa09"); if(options.device) ao_append_option(&ao_options, "dev", options.device); if((pldev=ao_open_live(driver_id, &format, ao_options))==NULL) { if (options.device) { fprintf(stderr, "Can't open libao driver with device %s (is device in use?)\n", options.device); return NULL; } else options.opt |= MPG321_USE_OSS; } else opened++; } if(!opened && options.opt & MPG321_USE_OSS) { ao_option *ao_options = NULL; int driver_id = ao_driver_id("oss"); if(options.device) ao_append_option(&ao_options, "dsp", options.device); if((pldev=ao_open_live(driver_id, &format, ao_options))==NULL) { if (options.device) { fprintf(stderr, "Can't open libao driver with device %s (is device in use?)\n", options.device); return NULL; } else options.opt |= MPG321_USE_SUN; } else opened++; } if(!opened && options.opt & MPG321_USE_SUN) { ao_option *ao_options = NULL; int driver_id = ao_driver_id("sun"); if(options.device) ao_append_option(&ao_options, "dev", options.device); if((pldev=ao_open_live(driver_id, &format, ao_options))==NULL) { if (options.device) { fprintf(stderr, "Can't open libao driver with device %s (is device in use?)\n", options.device); return NULL; } else options.opt |= MPG321_USE_ESD; } } if(!opened && options.opt & MPG321_USE_ESD) { ao_option *ao_options = NULL; int driver_id = ao_driver_id("esd"); if(options.device) ao_append_option(&ao_options, "host", options.device); if((pldev=ao_open_live(driver_id, &format, ao_options))==NULL) { if (options.device) { fprintf(stderr, "Can't open libao driver with device %s (is device in use?)\n", options.device); return NULL; } else options.opt |= MPG321_USE_ARTS; } else opened++; } if(!opened && options.opt & MPG321_USE_ARTS) { ao_option *ao_options = NULL; int driver_id = ao_driver_id("arts"); if((pldev=ao_open_live(driver_id, &format, ao_options))==NULL) { fprintf(stderr, "Can't find a suitable libao driver. (Is device in use?)\n"); return NULL; } } } /* Restore signal handler */ signal(SIGINT, handle_signals); return pldev; }
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 init(int argc, char **argv) { const char *str; int value; ao_initialize(); int driver = ao_default_driver_id(); ao_option *ao_opts = NULL; config.audio_backend_buffer_desired_length = 44100; // one second. config.audio_backend_latency_offset = 0; // get settings from settings file first, allow them to be overridden by command line options if (config.cfg != NULL) { /* Get the desired buffer size setting. */ if (config_lookup_int(config.cfg, "ao.audio_backend_buffer_desired_length", &value)) { if ((value < 0) || (value > 66150)) die("Invalid a0 audio backend buffer desired length \"%d\". It should be between 0 and " "66150, default is 44100", value); else { config.audio_backend_buffer_desired_length = value; } } /* Get the latency offset. */ if (config_lookup_int(config.cfg, "ao.audio_backend_latency_offset", &value)) { if ((value < -66150) || (value > 66150)) die("Invalid ao audio backend buffer latency offset \"%d\". It should be between -66150 and +66150, default is 0", value); else config.audio_backend_latency_offset = value; } } optind = 1; // optind=0 is equivalent to optind=1 plus special behaviour argv--; // so we shift the arguments to satisfy getopt() argc++; // some platforms apparently require optreset = 1; - which? int opt; char *mid; while ((opt = getopt(argc, argv, "d:i:n:o:")) > 0) { switch (opt) { case 'd': driver = ao_driver_id(optarg); if (driver < 0) die("could not find ao driver %s", optarg); break; case 'i': ao_append_option(&ao_opts, "id", optarg); break; case 'n': ao_append_option(&ao_opts, "dev", optarg); // Old libao versions (for example, 0.8.8) only support // "dsp" instead of "dev". ao_append_option(&ao_opts, "dsp", optarg); break; case 'o': mid = strchr(optarg, '='); if (!mid) die("Expected an = in audio option %s", optarg); *mid = 0; ao_append_option(&ao_opts, optarg, mid + 1); break; default: help(); die("Invalid audio option -%c specified", opt); } } if (optind < argc) die("Invalid audio argument: %s", argv[optind]); ao_sample_format fmt; memset(&fmt, 0, sizeof(fmt)); fmt.bits = 16; fmt.rate = 44100; fmt.channels = 2; fmt.byte_format = AO_FMT_NATIVE; dev = ao_open_live(driver, &fmt, ao_opts); return dev ? 0 : 1; }
// Initialize the libPOLY global state. Return 0 on success, 1 on error. int poly_init(int bitdepth, int channels, int bitrate, int max_generators, const char *filename) { // Make sure arguments are valid: if(!((bitdepth == 8) || (bitdepth == 16) || (bitdepth == 24))) { DEBUG_MSG("bitdepth not one of 8, 16, 26"); errno = EINVAL; return 1; } if(!((channels == 1) || (channels == 2))) { DEBUG_MSG("channels not one of 1, 2"); errno = EINVAL; return 1; } if(!((bitrate == 44100) || (bitrate == 48000) || (bitrate == 96000))) { DEBUG_MSG("bitrate not one of 44100, 48000, 96000"); errno = EINVAL; return 1; } if(max_generators <= 0) { DEBUG_MSG("max_generators <= 0"); errno = EINVAL; return 1; } // Initialize libao: ao_initialize(); poly_ao_init = 1; poly_playback = 0; poly_max_generators = max_generators; poly_time = 0; int driver; // Populate the format struct: poly_format = calloc(1, sizeof(*poly_format)); if(poly_format == NULL) { DEBUG_MSG("calloc for *poly_format failed"); errno = ENOMEM; return 1; } poly_format->bits = bitdepth; poly_format->channels = channels; poly_format->rate = bitrate; poly_format->byte_format = AO_FMT_NATIVE; // Are we using a sound card? if(filename == NULL) { #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) || defined(WIN64) || defined(_WIN64) || defined(__WIN64) || defined(__WIN32__) || defined(__WIN64__) || defined(__WINDOWS__) driver = ao_default_driver_id(); if(driver == -1) { DEBUG_MSG("ao_default_driver_id() failed"); errno = ENODEV; free(poly_format); return 1; } #else driver = ao_driver_id("alsa"); if(driver == -1) { DEBUG_MSG("ao_driver_id() failed"); errno = ENODEV; free(poly_format); return 1; } #endif poly_card = ao_open_live(driver, poly_format, NULL); if(poly_card == NULL) { switch(errno) { case AO_ENODRIVER: DEBUG_MSG("invalid driver"); break; case AO_ENOTLIVE: DEBUG_MSG("file driver passed, live driver expected"); break; case AO_EBADOPTION: DEBUG_MSG("invalid libao option, check local libao config"); break; case AO_EOPENDEVICE: DEBUG_MSG("can't open device"); break; default: DEBUG_MSG("unknown libao error"); break; } free(poly_format); return 1; } } // We're using an output file: else { driver = ao_driver_id("wav"); if(driver == -1) { DEBUG_MSG("libao error, can't open WAV driver"); errno = ENODEV; free(poly_format); return 1; } poly_card = ao_open_file(driver, filename, 1, poly_format, NULL); if(poly_card == NULL) { switch(errno) { case AO_ENODRIVER: DEBUG_MSG("invalid driver"); break; case AO_ENOTFILE: DEBUG_MSG("non-file driver passed"); break; case AO_EBADOPTION: DEBUG_MSG("invalid libao option, check local libao config"); break; case AO_EOPENFILE: DEBUG_MSG("can't open file"); break; default: DEBUG_MSG("unknown libao error"); break; } free(poly_format); return 1; } } poly_generators = calloc(poly_max_generators, sizeof(*poly_generators)); return 0; }
int main(int argc, char **argv) { int status = 0; struct params par; int opt; signal(SIGHUP, interrupt_handler); signal(SIGINT, interrupt_handler); signal(SIGQUIT, interrupt_handler); ao_initialize(); driver_id = ao_default_driver_id(); memset(¤t_sample_format, 0, sizeof(current_sample_format)); if (argc == 1) { /* We were invoked with no arguments */ usage(argv[0]); goto done; } again: { struct params default_par = DEFAULT_PARAMS; memcpy(&par, &default_par, sizeof(par)); } while ((opt = getopt(argc, argv, "-D:F:L:M:S:b:d:f:o:@:hrv")) != -1) { switch (opt) { case '@': if (play_playlist(optarg, &par)) { status = 1; goto done; } break; case 'D': par.fade_delay = atof(optarg); break; case 'F': par.fade_time = atof(optarg); break; case 'L': par.loop_count = atoi(optarg); break; case 'M': par.min_time = atof(optarg); par.loop_count = -1; break; case 'S': par.stream_index = atoi(optarg); break; case 'b': if (!buffer) buffer_size_kb = atoi(optarg); break; case 'd': driver_id = ao_driver_id(optarg); if (driver_id < 0) { fprintf(stderr, "Invalid output driver \"%s\"\n", optarg); status = 1; goto done; } break; case 'f': out_filename = optarg; break; case 'h': usage(argv[0]); goto done; case 'o': add_driver_option(optarg); break; case 'r': repeat = 1; break; case 'v': verbose = 1; break; default: goto done; } } argc -= optind; argv += optind; for (opt = 0; opt < argc; ++opt) { if (play_file(argv[opt], &par)) { status = 1; goto done; } } if (repeat) { optind = 0; goto again; } done: if (device) ao_close(device); if (buffer) free(buffer); ao_free_options(device_options); ao_shutdown(); return status; }
/* SNDDMA_Init: initialises cycling through a DMA bufffer and returns * information on it */ qboolean SNDDMA_Init(struct sndinfo * s){ int driver_id; ao_sample_format format; ao_option * options = NULL; if(snd_inited) return 1; snd_inited = 0; si = s; ao_initialize(); if((driver_id = ao_driver_id(si->device->string)) == -1){ si->Com_Printf("ao: no driver %s found, trying default\n", si->device->string); if((driver_id = ao_default_driver_id()) == -1){ Com_Printf("ao: no default driver found\n"); return 0; } } format.bits = si->dma->samplebits = si->bits->value; format.rate = si->dma->speed = 44100; format.channels = si->dma->channels = si->channels->value; format.byte_format = AO_FMT_NATIVE; switch(si->dma->speed){ case 44100: si->dma->samples = 2048 * si->dma->channels; break; case 22050: si->dma->samples = 1024 * si->dma->channels; break; default: si->dma->samples = 512 * si->dma->channels; break; } if((device = ao_open_live(driver_id, &format, options)) == NULL){ switch(errno){ case AO_ENODRIVER: Com_Printf("ao: no driver for %d\n", driver_id); break; case AO_ENOTLIVE: Com_Printf("ao: not a valid live output device\n"); break; case AO_EBADOPTION: Com_Printf("ao: valid option has invalid key\n"); break; case AO_EOPENDEVICE: Com_Printf("ao: cannot open device\n"); break; case AO_EFAIL: Com_Printf("ao: something broke during ao_open_live\n"); break; case AO_ENOTFILE: Com_Printf("ao: not a file\n"); break; case AO_EOPENFILE: Com_Printf("ao: can't open file\n"); break; case AO_EFILEEXISTS: Com_Printf("ao: file exists already\n"); break; default: Com_Printf("ao: whoa, bad trip dude\n"); break; } return 0; } samplesize = si->dma->samplebits >> 3; si->dma->buffer = malloc(si->dma->samples * samplesize); memset(si->dma->buffer, 0, si->dma->samples * samplesize); si->dma->samplepos = 0; si->dma->submission_chunk = 1; si->Com_Printf("ao: buffer size is %d, %d samples\n", si->dma->samples * samplesize, si->dma->samples); snd_inited = 1; return 1; }
void output_ao::setup(libconfig::Setting& setting) { int channels; int rate; int bps; std::string driver; if (setting.lookupValue("channels", channels)) { setting.remove("channels"); format.channels = channels; } else { format.channels = DEFAULT_GLOBAL_CHANNELS; } if (setting.lookupValue("rate", rate)) { setting.remove("rate"); format.rate = rate; } else { format.rate = 44100; } if (setting.lookupValue("bps", bps)) { setting.remove("bps"); format.bits = bps; } else { format.bits = 16; } format.byte_format = AO_FMT_LITTLE; if (setting.lookupValue("driver", driver)) { setting.remove("driver"); driver = ao_driver_id(driver.c_str()); } else { driver = ao_default_driver_id(); } int length = setting.getLength(); ao_option *current = NULL; for (int i = 0; i < length; i++) { libconfig::Setting& s = setting[i]; if (current == NULL) { current = new ao_option; options = current; } else { current->next = new ao_option; } std::string key = s.getName(); std::string value = s; current->key = new char[key.size() + 1]; current->value = new char[value.size() + 1]; ::strncpy(current->key, key.c_str(), key.size()); ::strncpy(current->value, value.c_str(), value.size()); } }
int main(int argc, char **argv) { int r, tmp, fi, random=0; char Buffer[1024]; char length_str[256], fade_str[256], volume[256], title_str[256]; char tmp_str[256]; char *tag; soundLowPass = 0; soundEcho = 0; soundQuality = 0; DetectSilence=1; silencelength=5; IgnoreTrackLength=0; DefaultLength=150000; TrailingSilence=1000; playforever=0; while((r=getopt(argc, argv, "hlsrieWL:t:"))>=0) { char *e; switch(r) { case 'h': printf("playgsf version %s (based on Highly Advanced version %s)\n\n", VERSION_STR, HA_VERSION_STR); printf("Usage: ./playgsf [options] files...\n\n"); printf(" -l Enable low pass filer\n"); printf(" -s Detect silence\n"); printf(" -L Set silence length in seconds (for detection). Default 5\n"); printf(" -t Set default track length in milliseconds. Default 150000 ms\n"); printf(" -i Ignore track length (use default length)\n"); printf(" -e Endless play\n"); printf(" -r Play files in random order\n"); printf(" -W output to 'output.wav' rather than soundcard\n"); printf(" -h Displays what you are reading right now\n"); return 0; break; case 'i': IgnoreTrackLength = 1; break; case 'l': soundLowPass = 1; break; case 's': DetectSilence = 1; break; case 'L': silencelength = strtol(optarg, &e, 0); if (e==optarg) { fprintf(stderr, "Bad value\n"); return 1; } break; case 'e': playforever = 1; break; case 't': DefaultLength = strtol(optarg, &e, 0); if (e==optarg) { fprintf(stderr, "Bad value\n"); return 1; } break; case 'r': random = 1; break; case 'W': fileoutput = 1; break; case '?': fprintf(stderr, "Unknown argument. try -h\n"); return 1; break; } } if (argc-optind<=0) { printf("No files specified! For help, try -h\n"); return 1; } if (random) { shuffle_list(&argv[optind], argc-optind); } printf("playgsf version %s (based on Highly Advanced version %s)\n\n", VERSION_STR, HA_VERSION_STR); signal(SIGINT, signal_handler); tag = (char*)malloc(50001); fi = optind; while (!g_must_exit && fi < argc) { decode_pos_ms = 0; seek_needed = -1; TrailingSilence=1000; r = GSFRun(argv[fi]); if (!r) { fi++; continue; } g_playing = 1; psftag_readfromfile((void*)tag, argv[fi]); BOLD(); printf("Filename: "); NORMAL(); printf("%s\n", basename(argv[fi])); BOLD(); printf("Channels: "); NORMAL(); printf("%d\n", sndNumChannels); BOLD(); printf("Sample rate: "); NORMAL(); printf("%d\n", sndSamplesPerSec); if (!psftag_getvar(tag, "title", title_str, sizeof(title_str)-1)) { BOLD(); printf("Title: "); NORMAL(); printf("%s\n", title_str); } if (!psftag_getvar(tag, "artist", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("Artist: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "game", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("Game: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "year", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("Year: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "copyright", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("Copyright: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "gsfby", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("GSF By: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "tagger", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("Tagger: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "comment", tmp_str, sizeof(tmp_str)-1)) { BOLD(); printf("Comment: "); NORMAL(); printf("%s\n", tmp_str); } if (!psftag_getvar(tag, "fade", fade_str, sizeof(fade_str)-1)) { FadeLength = LengthFromString(fade_str); BOLD(); printf("Fade: "); NORMAL(); printf("%s (%d ms)\n", fade_str, FadeLength); } if (!psftag_raw_getvar(tag, "length", length_str, sizeof(length_str)-1)) { TrackLength = LengthFromString(length_str) + FadeLength; BOLD(); printf("Length: "); NORMAL(); printf("%s (%d ms) ", length_str, TrackLength); if (IgnoreTrackLength) { printf("(ignored)"); TrackLength = DefaultLength; } printf("\n"); } else { TrackLength = DefaultLength; } /* Must be done after GSFrun so sndNumchannels and * sndSamplesPerSec are set to valid values */ ao_initialize(); ao_sample_format format_ao = { 16, sndSamplesPerSec, sndNumChannels, AO_FMT_LITTLE }; if(fileoutput) { snd_ao = ao_open_file(ao_driver_id("wav"), "output.wav", 1, &format_ao, NULL); } else { snd_ao = ao_open_live(ao_default_driver_id(), &format_ao, NULL); } while(g_playing) { int remaining = TrackLength - (int)decode_pos_ms; if (remaining<0) { // this happens during silence period remaining = 0; } EmulationLoop(); BOLD(); printf("Time: "); NORMAL(); printf("%02d:%02d.%02d ", (int)(decode_pos_ms/1000.0)/60, (int)(decode_pos_ms/1000.0)%60, (int)(decode_pos_ms/10.0)%100); if (!playforever) { /*BOLD();*/ printf("["); /*NORMAL();*/ printf("%02d:%02d.%02d", remaining/1000/60, (remaining/1000)%60, (remaining/10%100) ); /*BOLD();*/ printf("] of "); /*NORMAL();*/ printf("%02d:%02d.%02d ", TrackLength/1000/60, (TrackLength/1000)%60, (TrackLength/10%100)); } BOLD(); printf(" GBA Cpu: "); NORMAL(); printf("%02d%% ", cpupercent); printf(" \r"); fflush(stdout); } printf("\n--\n"); ao_close(snd_ao); fi++; } ao_shutdown(); return 0; }