📄 id3tag.c
字号:
} while (c1 == c2); return c1 - c2;}intid3tag_set_genre(lame_global_flags *gfp, const char *genre){ lame_internal_flags *gfc = gfp->internal_flags; if (genre && *genre) { char *str; int num = strtol(genre, &str, 10); /* is the input a string or a valid number? */ if (*str) { int i; for (i = 0; i < GENRE_NAME_COUNT; ++i) { if (!local_strcasecmp(genre, genre_names[i])) { num = i; break; } } if (i == GENRE_NAME_COUNT) { return -1; } } else if ((num < 0) || (num >= GENRE_NAME_COUNT)) { return -1; } gfc->tag_spec.genre = num; gfc->tag_spec.flags |= CHANGED_FLAG; } return 0;}static unsigned char *set_4_byte_value(unsigned char *bytes, unsigned long value){ int index; for (index = 3; index >= 0; --index) { bytes[index] = value & 0xfful; value >>= 8; } return bytes + 4;}#define FRAME_ID(a, b, c, d) \ ( ((unsigned long)(a) << 24) \ | ((unsigned long)(b) << 16) \ | ((unsigned long)(c) << 8) \ | ((unsigned long)(d) << 0) )#define TITLE_FRAME_ID FRAME_ID('T', 'I', 'T', '2')#define ARTIST_FRAME_ID FRAME_ID('T', 'P', 'E', '1')#define ALBUM_FRAME_ID FRAME_ID('T', 'A', 'L', 'B')#define YEAR_FRAME_ID FRAME_ID('T', 'Y', 'E', 'R')#define COMMENT_FRAME_ID FRAME_ID('C', 'O', 'M', 'M')#define TRACK_FRAME_ID FRAME_ID('T', 'R', 'C', 'K')#define GENRE_FRAME_ID FRAME_ID('T', 'C', 'O', 'N')#define ENCODER_FRAME_ID FRAME_ID('T', 'S', 'S', 'E')static unsigned char *set_frame(unsigned char *frame, unsigned long id, const char *text, size_t length){ if (length) { frame = set_4_byte_value(frame, id); /* Set frame size = total size - header size. Frame header and field * bytes include 2-byte header flags, 1 encoding descriptor byte, and * for comment frames: 3-byte language descriptor and 1 content * descriptor byte */ frame = set_4_byte_value(frame, ((id == COMMENT_FRAME_ID) ? 5 : 1) + length); /* clear 2-byte header flags */ *frame++ = 0; *frame++ = 0; /* clear 1 encoding descriptor byte to indicate ISO-8859-1 format */ *frame++ = 0; if (id == COMMENT_FRAME_ID) { /* use id3lib-compatible bogus language descriptor */ *frame++ = 'X'; *frame++ = 'X'; *frame++ = 'X'; /* clear 1 byte to make content descriptor empty string */ *frame++ = 0; } while (length--) { *frame++ = *text++; } } return frame;}intid3tag_write_v2(lame_global_flags *gfp){ lame_internal_flags *gfc = gfp->internal_flags; if ((gfc->tag_spec.flags & CHANGED_FLAG) && !(gfc->tag_spec.flags & V1_ONLY_FLAG)) { /* calculate length of four fields which may not fit in verion 1 tag */ size_t title_length = gfc->tag_spec.title ? strlen(gfc->tag_spec.title) : 0; size_t artist_length = gfc->tag_spec.artist ? strlen(gfc->tag_spec.artist) : 0; size_t album_length = gfc->tag_spec.album ? strlen(gfc->tag_spec.album) : 0; size_t comment_length = gfc->tag_spec.comment ? strlen(gfc->tag_spec.comment) : 0; /* write tag if explicitly requested or if fields overflow */ if ((gfc->tag_spec.flags & (ADD_V2_FLAG | V2_ONLY_FLAG)) || (title_length > 30) || (artist_length > 30) || (album_length > 30) || (comment_length > 30) || (gfc->tag_spec.track && (comment_length > 28))) { size_t tag_size; char encoder[20]; size_t encoder_length; char year[5]; size_t year_length; char track[3]; size_t track_length; char genre[6]; size_t genre_length; unsigned char *tag; unsigned char *p; size_t adjusted_tag_size; unsigned int index; /* calulate size of tag starting with 10-byte tag header */ tag_size = 10;#if defined(__hpux) || defined(__svr4__) || defined(M_UNIX) || defined(_AIX) encoder_length = sprintf(encoder, "LAME v%s", get_lame_short_version());#else#if defined(__sun__) (void) sprintf(encoder, "LAME v%s", get_lame_short_version()); encoder_length = strlen(encoder);#else encoder_length = snprintf(encoder, sizeof(encoder), "LAME v%s", get_lame_short_version());#endif#endif tag_size += 11 + encoder_length; if (title_length) { /* add 10-byte frame header, 1 encoding descriptor byte ... */ tag_size += 11 + title_length; } if (artist_length) { tag_size += 11 + artist_length; } if (album_length) { tag_size += 11 + album_length; } if (gfc->tag_spec.year) { year_length = sprintf(year, "%d", gfc->tag_spec.year); tag_size += 11 + year_length; } else { year_length = 0; } if (comment_length) { /* add 10-byte frame header, 1 encoding descriptor byte, * 3-byte language descriptor, 1 content descriptor byte ... */ tag_size += 15 + comment_length; } if (gfc->tag_spec.track) { track_length = sprintf(track, "%d", gfc->tag_spec.track); tag_size += 11 + track_length; } else { track_length = 0; } if (gfc->tag_spec.genre != GENRE_NUM_UNKNOWN) { genre_length = sprintf(genre, "(%d)", gfc->tag_spec.genre); tag_size += 11 + genre_length; } else { genre_length = 0; } if (gfc->tag_spec.flags & PAD_V2_FLAG) { /* add 128 bytes of padding */ tag_size += 128; } tag = (unsigned char *)malloc(tag_size); if (!tag) { return -1; } p = tag; /* set tag header starting with file identifier */ *p++ = 'I'; *p++ = 'D'; *p++ = '3'; /* set version number word */ *p++ = 3; *p++ = 0; /* clear flags byte */ *p++ = 0; /* calculate and set tag size = total size - header size */ adjusted_tag_size = tag_size - 10; /* encode adjusted size into four bytes where most significant * bit is clear in each byte, for 28-bit total */ *p++ = (adjusted_tag_size >> 21) & 0x7fu; *p++ = (adjusted_tag_size >> 14) & 0x7fu; *p++ = (adjusted_tag_size >> 7) & 0x7fu; *p++ = adjusted_tag_size & 0x7fu; /* * NOTE: The remainder of the tag (frames and padding, if any) * are not "unsynchronized" to prevent false MPEG audio headers * from appearing in the bitstream. Why? Well, most players * and utilities know how to skip the ID3 version 2 tag by now * even if they don't read its contents, and it's actually * very unlikely that such a false "sync" pattern would occur * in just the simple text frames added here. */ /* set each frame in tag */ p = set_frame(p, ENCODER_FRAME_ID, encoder, encoder_length); p = set_frame(p, TITLE_FRAME_ID, gfc->tag_spec.title, title_length); p = set_frame(p, ARTIST_FRAME_ID, gfc->tag_spec.artist, artist_length); p = set_frame(p, ALBUM_FRAME_ID, gfc->tag_spec.album, album_length); p = set_frame(p, YEAR_FRAME_ID, year, year_length); p = set_frame(p, COMMENT_FRAME_ID, gfc->tag_spec.comment, comment_length); p = set_frame(p, TRACK_FRAME_ID, track, track_length); p = set_frame(p, GENRE_FRAME_ID, genre, genre_length); /* clear any padding bytes */ memset(p, 0, tag_size - (p - tag)); /* write tag directly into bitstream at current position */ for (index = 0; index < tag_size; ++index) { add_dummy_byte(gfp, tag[index]); } free(tag); return tag_size; } } return 0;}static unsigned char *set_text_field(unsigned char *field, const char *text, size_t size, int pad){ while (size--) { if (text && *text) { *field++ = *text++; } else { *field++ = pad; } } return field;}intid3tag_write_v1(lame_global_flags *gfp){ lame_internal_flags *gfc = gfp->internal_flags; if ((gfc->tag_spec.flags & CHANGED_FLAG) && !(gfc->tag_spec.flags & V2_ONLY_FLAG)) { unsigned char tag[128]; unsigned char *p = tag; int pad = (gfc->tag_spec.flags & SPACE_V1_FLAG) ? ' ' : 0; char year[5]; unsigned int index; /* set tag identifier */ *p++ = 'T'; *p++ = 'A'; *p++ = 'G'; /* set each field in tag */ p = set_text_field(p, gfc->tag_spec.title, 30, pad); p = set_text_field(p, gfc->tag_spec.artist, 30, pad); p = set_text_field(p, gfc->tag_spec.album, 30, pad); sprintf(year, "%d", gfc->tag_spec.year); p = set_text_field(p, gfc->tag_spec.year ? year : NULL, 4, pad); /* limit comment field to 28 bytes if a track is specified */ p = set_text_field(p, gfc->tag_spec.comment, gfc->tag_spec.track ? 28 : 30, pad); if (gfc->tag_spec.track) { /* clear the next byte to indicate a version 1.1 tag */ *p++ = 0; *p++ = gfc->tag_spec.track; } *p++ = gfc->tag_spec.genre; /* write tag directly into bitstream at current position */ for (index = 0; index < 128; ++index) { add_dummy_byte(gfp, tag[index]); } return 128; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -