⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 madmix.c

📁 一个嵌入式Linux上的mp3播放器
💻 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: madmix.c,v 1.24 2004/01/23 09:41:31 rob Exp $ */# ifdef HAVE_CONFIG_H#  include "config.h"# endif# include "global.h"# include <stdio.h># include <stdarg.h># include <stdlib.h># include <string.h># include <unistd.h># ifdef HAVE_ERRNO_H#  include <errno.h># endif# include <mad.h># include "getopt.h"# include "gettext.h"# include "audio.h"struct audio {  char const *fname;  FILE *file;  int active;  mad_fixed_t scale;  struct mad_frame frame;};char const *argv0;/* * NAME:	error() * DESCRIPTION:	show a labeled error message */staticvoid error(char const *id, char const *format, ...){  int err;  va_list args;  err = errno;  if (id)    fprintf(stderr, "%s: ", id);  va_start(args, format);  if (*format == ':') {    if (format[1] == 0) {      format = va_arg(args, char const *);      errno = err;      perror(format);    }    else {      errno = err;      perror(format + 1);    }  }  else {    vfprintf(stderr, format, args);    fputc('\n', stderr);  }  va_end(args);}/* * NAME:	do_output() * DESCRIPTION:	play mixed output */staticint do_output(int (*audio)(union audio_control *),	      struct mad_frame *frame, struct mad_synth *synth){  union audio_control control;  static unsigned int channels;  static unsigned long speed;  if (channels != synth->pcm.channels ||      speed    != synth->pcm.samplerate) {    audio_control_init(&control, AUDIO_COMMAND_CONFIG);    control.config.channels = synth->pcm.channels;    control.config.speed    = synth->pcm.samplerate;    if (audio(&control) == -1) {      error("output", audio_error);      return -1;    }    channels = synth->pcm.channels;    speed    = synth->pcm.samplerate;  }  audio_control_init(&control, AUDIO_COMMAND_PLAY);  control.play.nsamples   = synth->pcm.length;  control.play.samples[0] = synth->pcm.samples[0];  control.play.samples[1] = synth->pcm.samples[1];  control.play.mode       = AUDIO_MODE_DITHER;  if (audio(&control) == -1) {    error("output", audio_error);    return -1;  }  return 0;}/* * NAME:	do_mix() * DESCRIPTION:	perform mixing and audio output */staticint do_mix(struct audio *mix, int ninputs, int (*audio)(union audio_control *)){  struct mad_frame frame;  struct mad_synth synth;  int i, count;  mad_frame_init(&frame);  mad_synth_init(&synth);  count = ninputs;  while (1) {    int ch, s, sb;    mad_frame_mute(&frame);    for (i = 0; i < ninputs; ++i) {      if (!mix[i].active)	continue;      if (fread(&mix[i].frame, sizeof(mix[i].frame), 1, mix[i].file) != 1) {	if (ferror(mix[i].file))	  error("fread", ":", mix[i].fname);	mix[i].active = 0;	--count;	continue;      }      mix[i].frame.overlap = 0;      if (frame.header.layer == 0) {	frame.header.layer	    = mix[i].frame.header.layer;	frame.header.mode	    = mix[i].frame.header.mode;	frame.header.mode_extension = mix[i].frame.header.mode_extension;	frame.header.emphasis	    = mix[i].frame.header.emphasis;	frame.header.bitrate	    = mix[i].frame.header.bitrate;	frame.header.samplerate	    = mix[i].frame.header.samplerate;	frame.header.flags	    = mix[i].frame.header.flags;	frame.header.private_bits   = mix[i].frame.header.private_bits;	frame.header.duration	    = mix[i].frame.header.duration;      }      for (ch = 0; ch < 2; ++ch) {	for (s = 0; s < 36; ++s) {	  for (sb = 0; sb < 32; ++sb) {	    frame.sbsample[ch][s][sb] +=	      mad_f_mul(mix[i].frame.sbsample[ch][s][sb], mix[i].scale);	  }	}      }    }    if (count == 0)      break;    mad_synth_frame(&synth, &frame);    do_output(audio, &frame, &synth);  }  mad_synth_finish(&synth);  mad_frame_finish(&frame);  return 0;}/* * NAME:	audio->init() * DESCRIPTION:	initialize the audio output module */staticint audio_init(int (*audio)(union audio_control *), char const *path){  union audio_control control;  audio_control_init(&control, AUDIO_COMMAND_INIT);  control.init.path = path;  if (audio(&control) == -1) {    error("audio", audio_error, control.init.path);    return -1;  }  return 0;}/* * NAME:	audio->finish() * DESCRIPTION:	terminate the audio output module */staticint audio_finish(int (*audio)(union audio_control *)){  union audio_control control;  audio_control_init(&control, AUDIO_COMMAND_FINISH);  if (audio(&control) == -1) {    error("audio", audio_error);    return -1;  }  return 0;}/* * NAME:	usage() * DESCRIPTION:	display usage message and exit */staticvoid usage(char const *argv0){  fprintf(stderr, _("Usage: %s input1 [input2 ...]\n"), argv0);}/* * NAME:	main() * DESCRIPTION:	program entry point */int main(int argc, char *argv[]){  int opt, ninputs, i, result = 0;  int (*output)(union audio_control *) = 0;  char const *fname, *opath = 0;  FILE *file;  struct audio *mix;  argv0 = argv[0];  if (argc > 1) {    if (strcmp(argv[1], "--version") == 0) {      printf("%s - %s\n", mad_version, mad_copyright);      printf(_("Build options: %s\n"), mad_build);      return 0;    }    if (strcmp(argv[1], "--help") == 0) {      usage(argv[0]);      return 0;    }  }  while ((opt = getopt(argc, argv, "o:")) != -1) {    switch (opt) {    case 'o':      opath = optarg;      output = audio_output(&opath);      if (output == 0) {	error(0, _("%s: unknown output format type"), opath);	return 2;      }      break;    default:      usage(argv[0]);      return 1;    }  }  if (optind == argc) {    usage(argv[0]);    return 1;  }  if (output == 0)    output = audio_output(0);  if (audio_init(output, opath) == -1)    return 2;  ninputs = argc - optind;  mix = malloc(ninputs * sizeof(*mix));  if (mix == 0) {    error(0, _("not enough memory to allocate mixing buffers"));    return 3;  }  printf(_("mixing %d streams\n"), ninputs);  for (i = 0; i < ninputs; ++i) {    if (strcmp(argv[optind + i], "-") == 0) {      fname = "stdin";      file  = stdin;    }    else {      fname = argv[optind + i];      file = fopen(fname, "rb");      if (file == 0) {	error(0, ":", fname);	return 4;      }    }    mix[i].fname  = fname;    mix[i].file   = file;    mix[i].active = 1;    mix[i].scale  = mad_f_tofixed(1.0);  /* / ninputs); */  }  if (do_mix(mix, ninputs, output) == -1)    result = 5;  for (i = 0; i < ninputs; ++i) {    file = mix[i].file;    if (file != stdin) {      if (fclose(file) == EOF) {	error(0, ":", mix[i].fname);	result = 6;      }    }  }  free(mix);  if (audio_finish(output) == -1)    result = 7;  return result;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -