📄 madplay.c
字号:
/* * madplay - MPEG audio decoder and player * Copyright (C) 2000-2004 Robert Leslie * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: madplay.c,v 1.86 2004/02/23 21:34:53 rob Exp $ */# ifdef HAVE_CONFIG_H# include "config.h"# endif# include "global.h"/* include this first to avoid conflicts with MinGW __argc et al. */# include "getopt.h"# include <locale.h># include <stdio.h># include <stdarg.h># include <stdlib.h># include <string.h># ifdef HAVE_ASSERT_H# include <assert.h># endif# ifdef HAVE_UNISTD_H# include <unistd.h># endif# ifdef HAVE_FCNTL_H# include <fcntl.h># endif# include <ctype.h># include <mad.h># include "gettext.h"# include "version.h"# include "audio.h"# include "player.h"# define FADE_DEFAULT "0:05"# if defined(EXPERIMENTAL)static int external_mix;static int experimental;# endifstaticstruct option const options[] = { { "adjust-volume", required_argument, 0, 'A' }, { "amplify", required_argument, 0, 'a' }, { "ancillary-output", required_argument, 0, -'a' }, { "attenuate", required_argument, 0, 'a' }, { "bit-depth", required_argument, 0, 'b' }, { "display-time", required_argument, 0, -'t' }, { "downsample", no_argument, 0, -'d' }, { "fade-in", optional_argument, 0, -'i' }, { "help", no_argument, 0, 'h' }, { "ignore-crc", no_argument, 0, 'i' }, { "left", no_argument, 0, '1' }, { "license", no_argument, 0, -'l' }, { "mono", no_argument, 0, 'm' }, { "no-dither", no_argument, 0, 'd' }, { "output", required_argument, 0, 'o' }, { "pre-amp", required_argument, 0, 'a' }, { "quiet", no_argument, 0, 'q' }, { "repeat", optional_argument, 0, 'r' }, { "replay-gain", optional_argument, 0, 'G' }, { "right", no_argument, 0, '2' }, { "sample-rate", required_argument, 0, 'R' }, { "show-tags-only", no_argument, 0, 'T' }, { "shuffle", no_argument, 0, 'z' }, { "start", required_argument, 0, 's' }, { "stereo", no_argument, 0, 'S' }, { "time", required_argument, 0, 't' }, { "verbose", no_argument, 0, 'v' }, { "version", no_argument, 0, 'V' }, { "very-quiet", no_argument, 0, 'Q' },# if defined(USE_TTY) { "tty-control", no_argument, 0, -'c' }, { "no-tty-control", no_argument, 0, -'C' },# endif# if 0 { "cross-fade", no_argument, 0, 'x' }, { "fade-out", optional_argument, 0, -'o' }, { "gap", required_argument, 0, 'g' },# endif# if defined(EXPERIMENTAL) { "external-mix", no_argument, &external_mix, 1 }, { "experimental", no_argument, &experimental, 1 },# endif { 0 }};char const *argv0;# define EPUTS(str) fputs(str, stream)/* * NAME: show_usage() * DESCRIPTION: display usage message */staticvoid show_usage(int verbose){ FILE *stream = verbose ? stdout : stderr; fprintf(stream, _("Usage: %s [OPTIONS] FILE [...]\n"), argv0); if (!verbose) { fprintf(stream, _("Try `%s --help' for more information.\n"), argv0); return; } EPUTS(_("Decode and play MPEG audio FILE(s).\n")); /* the following usage text should agree with the option names */ EPUTS(_("\nVerbosity:\n")); EPUTS(_(" -v, --verbose show status while decoding\n")); EPUTS(_(" -q, --quiet be quiet but show warnings\n")); EPUTS(_(" -Q, --very-quiet " "be quiet and do not show warnings\n")); EPUTS(_(" --display-time=MODE " "use default verbose time display MODE\n" " (remaining, current, overall)\n")); EPUTS(_("\nDecoding:\n")); EPUTS(_(" --downsample reduce sample rate 2:1\n")); EPUTS(_(" -i, --ignore-crc ignore CRC errors\n")); EPUTS(_(" --ancillary-output=PATH write ancillary data to PATH\n")); EPUTS(_("\nAudio output:\n")); EPUTS(_(" -o, --output=[TYPE:]PATH " "write output to PATH with format TYPE (below)\n")); EPUTS(_(" -b, --bit-depth=DEPTH request DEPTH bits per sample\n")); EPUTS(_(" -R, --sample-rate=HERTZ " "request HERTZ samples per second\n")); EPUTS(_(" -d, --no-dither " "do not dither output PCM samples\n")); fprintf(stream, _(" --fade-in[=DURATION] " "fade-in songs over DURATION (default %s)\n"), FADE_DEFAULT);# if 0 fprintf(stream, _(" --fade-out[=DURATION] " "fade-out songs over DURATION (default %s)\n"), FADE_DEFAULT); EPUTS(_(" -g, --gap=DURATION set inter-song gap to DURATION\n")); EPUTS(_(" -x, --cross-fade " "cross-fade songs (use with negative gap)\n"));# endif EPUTS(_(" -a, --attenuate=DECIBELS " "attenuate signal by DECIBELS (-)\n")); EPUTS(_(" -a, --amplify=DECIBELS amplify signal by DECIBELS (+)\n")); EPUTS(_(" -A, --adjust-volume=DECIBELS " "override per-file volume adjustments\n")); EPUTS(_(" -G, --replay-gain[=PROFILE] " "enable Replay Gain volume adjustments using\n" " PROFILE (radio, audiophile)\n")); EPUTS(_("\nChannel selection:\n")); EPUTS(_(" -1, --left " "output first (left) channel only\n")); EPUTS(_(" -2, --right " "output second (right) channel only\n")); EPUTS(_(" -m, --mono " "mix left and right channels for monaural output\n")); EPUTS(_(" -S, --stereo force stereo output\n"));# if defined(EXPERIMENTAL) EPUTS(_("\nExperimental:\n")); EPUTS(_(" --external-mix " "output pre-synthesis samples for external mixer\n")); EPUTS(_(" --experimental enable experimental filter\n"));# endif EPUTS(_("\nPlayback:\n")); EPUTS(_(" -s, --start=TIME " "skip to begin at TIME (HH:MM:SS.DDD)\n")); EPUTS(_(" -t, --time=DURATION " "play only for DURATION (HH:MM:SS.DDD)\n")); EPUTS(_(" -z, --shuffle randomize file list\n")); EPUTS(_(" -r, --repeat[=MAX] " "play files MAX times, or indefinitely\n"));# if defined(USE_TTY) EPUTS(_(" --tty-control enable keyboard controls\n")); EPUTS(_(" --no-tty-control disable keyboard controls\n"));# endif EPUTS(_("\nMiscellaneous:\n")); EPUTS(_(" -T, --show-tags-only " "show ID3/encoder tags only (do not decode)\n")); EPUTS(_(" -V, --version display version number and exit\n")); EPUTS(_(" --license " "show copyright/license message and exit\n")); EPUTS(_(" -h, --help display this help and exit\n")); EPUTS(_("\nSupported output formats:\n")); EPUTS(_(" cdda " "CD audio, 16-bit big-endian 44100 Hz stereo PCM (*.cdr, *.cda)\n")); EPUTS(_(" aiff Audio IFF, [16-bit] PCM (*.aif, *.aiff)\n")); EPUTS(_(" wave Microsoft RIFF/WAVE, [16-bit] PCM (*.wav)\n")); fprintf(stream, _(" snd Sun/NeXT audio, 8-bit ISDN %s (*.au, *.snd)\n"), _("mu-law")); EPUTS(_(" raw binary [16-bit] host-endian linear PCM\n")); EPUTS(_(" hex ASCII hexadecimal [24-bit] linear PCM\n"));# if defined(HAVE_LIBESD) EPUTS(_(" esd " "Enlightened Sound Daemon [16-bit] (give speaker host as PATH)\n"));# endif# if defined(HAVE_LIBAUDIO) EPUTS(_(" nas " "Network Audio System [16-bit] (give server name as PATH)\n"));# endif EPUTS(_(" null no output (decode only)\n"));}# undef EPUTS/* * NAME: verror() * DESCRIPTION: print error message with program title prefix */staticvoid verror(char const *message, va_list args){ fprintf(stderr, "%s: ", argv0); vfprintf(stderr, message, args); fputc('\n', stderr);}/* * NAME: warn() * DESCRIPTION: print warning message */staticvoid warn(char const *message, ...){ va_list args; va_start(args, message); verror(message, args); va_end(args);}/* * NAME: die() * DESCRIPTION: exit with failure status after printing message */staticvoid die(char const *message, ...){ va_list args; va_start(args, message); verror(message, args); va_end(args); exit(1);}/* * NAME: parse_time() * DESCRIPTION: parse a time specification string */staticint parse_time(mad_timer_t *timer, char const *str){ mad_timer_t time, accum = mad_timer_zero; signed long decimal; unsigned long seconds, fraction, fracpart; int minus; while (isspace((unsigned char) *str)) ++str; do { seconds = fraction = fracpart = 0; switch (*str) { case '-': ++str; minus = 1; break; case '+': ++str; default: minus = 0; } do { decimal = strtol(str, (char **) &str, 10); if (decimal < 0) return -1; seconds += decimal; if (*str == ':') { seconds *= 60; ++str; } } while (*str >= '0' && *str <= '9'); if (*str == '.'# if defined(HAVE_LOCALECONV) || *str == *localeconv()->decimal_point# endif ) { char const *ptr; decimal = strtol(++str, (char **) &ptr, 10); if (decimal < 0) return -1; fraction = decimal; for (fracpart = 1; str != ptr; ++str) fracpart *= 10; } else if (*str == '/') { ++str; decimal = strtol(str, (char **) &str, 10); if (decimal < 0) return -1; fraction = seconds; fracpart = decimal; seconds = 0; } mad_timer_set(&time, seconds, fraction, fracpart); if (minus) mad_timer_negate(&time); mad_timer_add(&accum, time); } while (*str == '-' || *str == '+'); while (isspace((unsigned char) *str)) ++str; if (*str != 0) return -1; *timer = accum; return 0;}/* * NAME: get_time() * DESCRIPTION: parse a time value or die */staticmad_timer_t get_time(char const *str, int positive, char const *name){ mad_timer_t time; if (parse_time(&time, str) == -1) die(_("invalid %s specification \"%s\""), name, str); if (positive && mad_timer_sign(time) <= 0) die(_("%s must be positive"), name); return time;}/* * NAME: parse_decibels() * DESCRIPTION: parse a decibel value specification string */staticint parse_decibels(double *db, char const *str){ *db = strtod(str, (char **) &str); while (isspace((unsigned char) *str)) ++str; if (strncasecmp(str, "dB", 2) == 0) { str += 2; while (isspace((unsigned char) *str)) ++str; } if (*str != 0) return -1; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -