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

📄 player.c

📁 mp3 plyer linux version
💻 C
📖 第 1 页 / 共 5 页
字号:
      if (fputc((ancillary->buffer << balance) | mad_bit_read(&ptr, balance),		ancillary->file) == EOF) {	error("ancillary", ":fputc");	return -1;      }      ancillary->length = 0;      length -= balance;    }  }  while (length >= 8) {    int byte;    byte = mad_bit_read(&ptr, 8);    if (putc(byte, ancillary->file) == EOF) {      error("ancillary", ":putc");      return -1;    }    length -= 8;  }  if (length) {    ancillary->buffer = mad_bit_read(&ptr, length);    ancillary->length = length;  }  if (fflush(ancillary->file) == EOF) {    error("ancillary", ":fflush");    return -1;  }  return 0;}/* * NAME:	show_id3() * DESCRIPTION:	display ID3 tag information */staticvoid show_id3(struct id3_tag const *tag){  unsigned int i;  struct id3_frame const *frame;  id3_ucs4_t const *ucs4;  id3_latin1_t *latin1;  static struct {    char const *id;    char const *label;  } const info[] = {    { ID3_FRAME_TITLE,  N_("Title")     },    { "TIT3",           0               },  /* Subtitle */    { "TCOP",           0               },  /* Copyright */    { "TPRO",           0               },  /* Produced */    { "TCOM",           N_("Composer")  },    { ID3_FRAME_ARTIST, N_("Artist")    },    { "TPE2",           N_("Orchestra") },    { "TPE3",           N_("Conductor") },    { "TEXT",           N_("Lyricist")  },    { ID3_FRAME_ALBUM,  N_("Album")     },    { ID3_FRAME_TRACK,  N_("Track")     },    { ID3_FRAME_YEAR,   N_("Year")      },    { "TPUB",           N_("Publisher") },    { ID3_FRAME_GENRE,  N_("Genre")     },    { "TRSN",           N_("Station")   },    { "TENC",           N_("Encoder")   }  };  /* text information */  for (i = 0; i < sizeof(info) / sizeof(info[0]); ++i) {    union id3_field const *field;    unsigned int nstrings, j;    frame = id3_tag_findframe(tag, info[i].id, 0);    if (frame == 0)      continue;    field    = id3_frame_field(frame, 1);    nstrings = id3_field_getnstrings(field);    for (j = 0; j < nstrings; ++j) {      ucs4 = id3_field_getstrings(field, j);      assert(ucs4);      if (strcmp(info[i].id, ID3_FRAME_GENRE) == 0)	ucs4 = id3_genre_name(ucs4);      latin1 = id3_ucs4_latin1duplicate(ucs4);      if (latin1 == 0)	goto fail;      if (j == 0 && info[i].label)	detail(gettext(info[i].label), 0, latin1);      else {	if (strcmp(info[i].id, "TCOP") == 0 ||	    strcmp(info[i].id, "TPRO") == 0) {	  detail(0, "%s %s", (info[i].id[1] == 'C') ?		 _("Copyright (C)") : _("Produced (P)"), latin1);	}	else	  detail(0, 0, latin1);      }      free(latin1);    }  }  /* comments */  i = 0;  while ((frame = id3_tag_findframe(tag, ID3_FRAME_COMMENT, i++))) {    ucs4 = id3_field_getstring(id3_frame_field(frame, 2));    assert(ucs4);    if (*ucs4)      continue;    ucs4 = id3_field_getfullstring(id3_frame_field(frame, 3));    assert(ucs4);    latin1 = id3_ucs4_latin1duplicate(ucs4);    if (latin1 == 0)      goto fail;    detail(_("Comment"), 0, latin1);    free(latin1);    break;  }  if (0) {  fail:    error("id3", _("not enough memory to display tag"));  }}/* * NAME:	show_rgain() * DESCRIPTION:	display Replay Gain information */staticvoid show_rgain(struct rgain const *rgain){  char const *label, *source;  if (!RGAIN_VALID(rgain))    return;  label = 0;  switch (rgain->name) {  case RGAIN_NAME_NOT_SET:    break;  case RGAIN_NAME_RADIO:    label = _("Radio Gain");    break;  case RGAIN_NAME_AUDIOPHILE:    label = _("Audiophile Gain");    break;  }  source = rgain_originator(rgain);  assert(label && source);  detail(label, "%+.1f dB => %d dB SPL (%s)",	 RGAIN_DB(rgain), (int) RGAIN_REFERENCE, source);}/* * NAME:	show_tag() * DESCRIPTION:	display Xing/LAME tag information */staticvoid show_tag(struct tag const *tag){  char ident[22];  int i;  memcpy(ident, tag->encoder, 21);  /* separate version number from encoder name */  for (i = 0; i < 20; ++i) {    if (ident[i] == 0)      break;    if (ident[i] >= '0' && ident[i] <= '9') {      if (i > 0 && ident[i - 1] != ' ' && ident[i - 1] != 'v') {	memmove(&ident[i + 1], &ident[i], 21 - i);	ident[i] = ' ';      }      break;    }  }  if (ident[0])    detail(_("Encoder Version"), "%s", ident);  if (tag->flags & TAG_LAME) {    char const *text;# if 0    detail(_("Tag Revision"), "%u", tag->lame.revision);# endif    text = 0;    switch (tag->lame.vbr_method) {    case TAG_LAME_VBR_CONSTANT:      text = _("constant");      break;    case TAG_LAME_VBR_ABR:      text = _("ABR");	break;    case TAG_LAME_VBR_METHOD1:      text = _("1 (old/rh)");      break;    case TAG_LAME_VBR_METHOD2:      text = _("2 (mtrh)");      break;    case TAG_LAME_VBR_METHOD3:      text = _("3 (mt)");      break;    case TAG_LAME_VBR_METHOD4:      text = _("4");      break;    case TAG_LAME_VBR_CONSTANT2PASS:      text = _("constant (two-pass)");      break;    case TAG_LAME_VBR_ABR2PASS:      text = _("ABR (two-pass)");      break;    }    detail(_("VBR Method"), "%s", text ? text : _("unknown"));    text = 0;    switch (tag->lame.vbr_method) {    case TAG_LAME_VBR_CONSTANT:    case TAG_LAME_VBR_CONSTANT2PASS:      text = _("Bitrate");      break;    case TAG_LAME_VBR_ABR:    case TAG_LAME_VBR_ABR2PASS:      text = _("Target Bitrate");      break;    case TAG_LAME_VBR_METHOD1:    case TAG_LAME_VBR_METHOD2:    case TAG_LAME_VBR_METHOD3:    case TAG_LAME_VBR_METHOD4:      text = _("Minimum Bitrate");      break;    }    if (text) {      detail(text, _("%u%s kbps"), tag->lame.bitrate,	     tag->lame.bitrate == 255 ? "+" : "");    }    text = 0;    switch (tag->lame.stereo_mode) {    case TAG_LAME_MODE_MONO:      text = _("mono");      break;    case TAG_LAME_MODE_STEREO:      text = _("normal");      break;    case TAG_LAME_MODE_DUAL:      text = _("dual channel");      break;    case TAG_LAME_MODE_JOINT:      text = _("joint");      break;    case TAG_LAME_MODE_FORCE:      text = _("force");      break;    case TAG_LAME_MODE_AUTO:      text = _("auto");      break;    case TAG_LAME_MODE_INTENSITY:      text = _("intensity");      break;    case TAG_LAME_MODE_UNDEFINED:      text = _("undefined");      break;    }    if (text)      detail(_("Stereo Mode"), "%s", text);    if (tag->lame.preset >= 8 && tag->lame.preset <= 320)      detail(_("Preset"), _("ABR %u"), tag->lame.preset);    else {      text = 0;      switch (tag->lame.preset) {      case TAG_LAME_PRESET_NONE:	text = _("none");	break;      case TAG_LAME_PRESET_V9:	text = _("V9");	break;      case TAG_LAME_PRESET_V8:	text = _("V8");	break;      case TAG_LAME_PRESET_V7:	text = _("V7");	break;      case TAG_LAME_PRESET_V6:	text = _("V6");	break;      case TAG_LAME_PRESET_V5:	text = _("V5");	break;      case TAG_LAME_PRESET_V4:	text = _("V4");	break;      case TAG_LAME_PRESET_V3:	text = _("V3");	break;      case TAG_LAME_PRESET_V2:	text = _("V2");	break;      case TAG_LAME_PRESET_V1:	text = _("V1");	break;      case TAG_LAME_PRESET_V0:	text = _("V0");	break;      case TAG_LAME_PRESET_R3MIX:	text = _("r3mix");	break;      case TAG_LAME_PRESET_STANDARD:	text = _("standard");	break;      case TAG_LAME_PRESET_EXTREME:	text = _("extreme");	break;      case TAG_LAME_PRESET_INSANE:	text = _("insane");	break;      case TAG_LAME_PRESET_STANDARD_FAST:	text = _("standard/fast");	break;      case TAG_LAME_PRESET_EXTREME_FAST:	text = _("extreme/fast");	break;      case TAG_LAME_PRESET_MEDIUM:	text = _("medium");	break;      case TAG_LAME_PRESET_MEDIUM_FAST:	text = _("medium/fast");	break;      }      detail(_("Preset"), "%s", text ? text : _("unknown"));    }    detail(_("Unwise Settings"), "%s",	   (tag->lame.flags & TAG_LAME_UNWISE) ? _("yes") : _("no"));    detail(_("Encoding Flags"), "%s%s%s",	   (tag->lame.flags & TAG_LAME_NSPSYTUNE)   ? "--nspsytune "   : "",	   (tag->lame.flags & TAG_LAME_NSSAFEJOINT) ? "--nssafejoint " : "",	   (tag->lame.flags & (TAG_LAME_NOGAP_NEXT | TAG_LAME_NOGAP_PREV)) ?	   "--nogap" : "");    text = 0;    switch (tag->lame.flags & (TAG_LAME_NOGAP_NEXT | TAG_LAME_NOGAP_PREV)) {    case TAG_LAME_NOGAP_NEXT:      text = _("following");      break;    case TAG_LAME_NOGAP_PREV:      text = _("preceding");      break;    case TAG_LAME_NOGAP_NEXT | TAG_LAME_NOGAP_PREV:      text = _("following or preceding");      break;    }    if (text)      detail(_("No Gap"), "%s", text);    text = _("Lowpass Filter");    if (tag->lame.lowpass_filter == 0)      detail(text, "%s", _("unknown"));    else      detail(text, _("%u Hz"), tag->lame.lowpass_filter);    detail(_("ATH Type"), "%u", tag->lame.ath_type);    detail(_("Noise Shaping"), "%u", tag->lame.noise_shaping);    switch (tag->lame.surround) {    case TAG_LAME_SURROUND_NONE:      text = _("none");      break;    case TAG_LAME_SURROUND_DPL:      text = _("DPL");      break;    case TAG_LAME_SURROUND_DPL2:      text = _("DPL2");      break;    case TAG_LAME_SURROUND_AMBISONIC:      text = _("Ambisonic");      break;    default:      text = _("unknown");    }    detail(_("Surround"), "%s", text);    detail(_("Start Delay"), _("%u samples"), tag->lame.start_delay);    detail(_("End Padding"), _("%u samples"), tag->lame.end_padding);    text = 0;    switch (tag->lame.source_samplerate) {    case TAG_LAME_SOURCE_32LOWER:      text = _("32 kHz or lower");      break;    case TAG_LAME_SOURCE_44_1:      text = _("44.1 kHz");      break;    case TAG_LAME_SOURCE_48:      text = _("48 kHz");      break;    case TAG_LAME_SOURCE_HIGHER48:      text = _("higher than 48 kHz");      break;    }    if (text)      detail(_("Source Rate"), "%s", text);    if (tag->lame.gain != 0)      detail(_("Gain"), _("%+.1f dB"), tag->lame.gain * 1.5);    /* Replay Gain */    if (tag->lame.peak > 0) {      double peak = mad_f_todouble(tag->lame.peak);      detail(_("Peak Amplitude"), _("%.8f (%+.1f dB)"),	     peak, 20 * log10(peak));    }    if (tag->lame.replay_gain[0].name == RGAIN_NAME_RADIO)      show_rgain(&tag->lame.replay_gain[0]);    if (tag->lame.replay_gain[1].name == RGAIN_NAME_AUDIOPHILE)      show_rgain(&tag->lame.replay_gain[1]);    detail(_("Music Length"), _("%lu bytes"), tag->lame.music_length);# if 0    detail(_("Music CRC"), "0x%04x", tag->lame.music_crc);# endif  }  if (tag->flags & TAG_XING) {    if (tag->xing.flags & TAG_XING_FRAMES)      detail(_("Audio Frames"), "%lu", tag->xing.frames);    if ((tag->xing.flags & TAG_XING_BYTES) &&	(!(tag->flags & TAG_LAME) ||	 tag->lame.music_length != tag->xing.bytes))      detail(_("Data Bytes"), "%lu", tag->xing.bytes);    if ((tag->flags & TAG_VBR) && (tag->xing.flags & TAG_XING_SCALE))      detail(_("VBR Scale"), _("%ld/100"), 100 - tag->xing.scale);  }}enum {  GAIN_VOLADJ   = 0x0001,  GAIN_ATTAMP   = 0x0002,  GAIN_RELATIVE = 0x0010};/* * NAME:	set_gain() * DESCRIPTION:	modify player gain information */staticdouble set_gain(struct player *player, int how, double db){  double *gain_db = 0;  if (how & GAIN_ATTAMP)    gain_db = &player->output.attamp_db;  else if (how & GAIN_VOLADJ)    gain_db = &player->output.voladj_db;  if (gain_db) {    if (how & GAIN_RELATIVE)      *gain_db += db;    else      *gain_db  = db;  }  db = player->output.voladj_db + player->output.attamp_db;  if (db > DB_MAX || db < DB_MIN) {    db = (db > DB_MAX) ? DB_MAX : DB_MIN;    player->output.attamp_db = db - player->output.voladj_db;  }  player->output.gain = db ? mad_f_tofixed(pow(10, db / 20)) : MAD_F_ONE;  return db;}/* * NAME:	use_rgain() * DESCRIPTION:	select and employ a Replay Gain volume adjustment */staticvoid use_rgain(struct player *player, struct rgain *list){  struct rgain *rgain = &list[0];  if ((player->output.replay_gain & PLAYER_RGAIN_AUDIOPHILE) &&      list[1].name == RGAIN_NAME_AUDIOPHILE &&      list[1].originator != RGAIN_ORIGINATOR_UNSPECIFIED)    rgain = &list[1];  if (RGAIN_VALID(rgain)) {    double gain = RGAIN_DB(rgain);    set_gain(player, GAIN_VOLADJ, gain);    if (player->verbosity >= 0 ||	(player->options & PLAYER_OPTION_SHOWTAGSONLY)) {      char const *source;      source = rgain_originator(rgain);      assert(source);      detail(_("Replay Gain"), _("%+.1f dB %s adjustment (%s)"),	     gain, (rgain->name == RGAIN_NAME_RADIO) ?	     _("radio") : _("audiophile"), source);    }    player->output.replay_gain |= PLAYER_RGAIN_SET;  }}/* * NAME:	decode->filter() * DESCRIPTION:	perform filtering on decoded frame */staticenum mad_flow decode_filter(void *data, struct mad_stream const *stream,			    struct mad_frame *frame){  struct player *player = data;  /* output ancillary data */  if (player->ancillary.file && stream->anc_bitlen &&      write_ancillary(&player->ancillary,		      stream->anc_ptr, stream->anc_bitlen) == -1)    return MAD_FLOW_BREAK;  /* first frame accounting */  if (player->stats.absolute_framecount == 0) {    if (player->input.tag.flags == 0 &&	tag_parse(&player->input.tag, stream) == 0) {      struct tag *tag = &player->input.tag;      unsigned int frame_size;

⌨️ 快捷键说明

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