Changeset 411


Ignore:
Timestamp:
10/31/08 00:20:05 (16 years ago)
Author:
r2d
Message:

added chapter gain / peak to libmpcdec and mpcchap as in the spec

Location:
libmpc/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • libmpc/trunk/include/mpc/mpcdec.h

    r402 r411  
    6262
    6363typedef struct mpc_frame_info_t {
    64         mpc_uint32_t samples;   /// number of samples in the frame (counting once for multiple channels)
    65         mpc_int32_t bits;       /// number of bits consumed by this frame (-1) if end of stream
     64        mpc_uint32_t samples;           /// number of samples in the frame (counting once for multiple channels)
     65        mpc_int32_t bits;                       /// number of bits consumed by this frame (-1) if end of stream
    6666        MPC_SAMPLE_FORMAT * buffer;     /// frame samples buffer (size = samples * channels * sizeof(MPC_SAMPLE_FORMAT))
    67         mpc_bool_t is_key_frame; /// 1 if this frame is a key frame (first in block) 0 else. Set by the demuxer.
     67        mpc_bool_t is_key_frame;        /// 1 if this frame is a key frame (first in block) 0 else. Set by the demuxer.
    6868} mpc_frame_info;
     69
     70typedef struct mpc_chap_info_t {
     71        mpc_uint64_t sample;    /// sample where the chapter starts
     72        mpc_uint16_t gain;              /// replaygain chapter value
     73        mpc_uint16_t peak;              /// peak chapter loudness level
     74        mpc_uint_t tag_size;    /// size of the tag element (0 if no tag is present for this chapter)
     75        char * tag;                             /// pointer to an APEv2 tag without the preamble
     76} mpc_chap_info;
    6977
    7078/// Initializes mpc decoder with the supplied stream info parameters.
     
    128136/**
    129137 * Gets datas associated to a given chapter
    130  * You can pass 0 for tag and tag_size if you don't needs the tag information
    131138 * The chapter tag is an APEv2 tag without the preamble
    132139 * @param d pointer to a musepack demuxer
    133140 * @param chap_nb chapter number you want datas (from 0 to mpc_demux_chap_nb(d) - 1)
    134  * @param tag will return a pointer to the chapter tag datas
    135  * @param tag_size will be filed with the tag data size (0 if no tag for this chapter)
    136  * @return the sample where the chapter starts
     141 * @return the chapter information structure
    137142 */
    138 MPC_API mpc_uint64_t mpc_demux_chap(mpc_demux * d, int chap_nb, char ** tag, mpc_uint_t * tag_size);
     143MPC_API mpc_chap_info * mpc_demux_chap(mpc_demux * d, int chap_nb);
    139144
    140145#ifdef __cplusplus
  • libmpc/trunk/libmpcdec/internal.h

    r402 r411  
    6060#define DEMUX_BUFFER_SIZE (65536 - MAX_FRAME_SIZE) // need some space as sand box
    6161
    62 typedef struct {
    63         mpc_uint64_t sample; /// sample where the chapter starts
    64         mpc_uint_t tag_size; /// size of the tag element (0 if no tag is present for this chapter)
    65         char * tag; /// pointer to an APEv2 tag without the preamble
    66 } mpc_chap_t;
    67 
    6862struct mpc_demux_t {
    6963        mpc_reader * r;
     
    8680        mpc_seek_t chap_pos; /// supposed position of the first chapter block
    8781        mpc_int_t chap_nb; /// number of chapters (-1 if unknown, 0 if no chapter)
    88         mpc_chap_t * chap; /// chapters position and tag
     82        mpc_chap_info * chap; /// chapters position and tag
    8983
    9084};
  • libmpc/trunk/libmpcdec/mpc_demux.c

    r407 r411  
    331331                d->chap_nb++;
    332332                chap_size += size;
    333                 size = mpc_bits_get_size(&d->bits_reader, &chap_sample);
     333                size = mpc_bits_get_size(&d->bits_reader, &chap_sample) + 4;
    334334                chap_size += size;
    335335                tag_size += b.size - size;
     
    340340        if (d->chap_nb > 0) {
    341341                char * ptag;
    342                 d->chap = malloc(sizeof(mpc_chap_t) * d->chap_nb + tag_size);
     342                d->chap = malloc(sizeof(mpc_chap_info) * d->chap_nb + tag_size);
    343343                ptag = (char*)(d->chap + d->chap_nb);
    344344
     
    347347                while (memcmp(b.key, "CT", 2) == 0) {
    348348                        mpc_demux_fill(d, 11 + (mpc_uint32_t) b.size, 0);
    349                         size = mpc_bits_get_size(&d->bits_reader, &d->chap[i].sample);
     349                        size = mpc_bits_get_size(&d->bits_reader, &d->chap[i].sample) + 4;
     350                        d->chap[i].gain = (mpc_uint16_t) mpc_bits_read(&d->bits_reader, 16);
     351                        d->chap[i].peak = (mpc_uint16_t) mpc_bits_read(&d->bits_reader, 16);
    350352                        memcpy(ptag, d->bits_reader.buff + ((8 - d->bits_reader.count) >> 3), b.size - size);
    351353                        d->bits_reader.buff += b.size - size;
     
    375377/**
    376378 * Gets datas associated to a given chapter
    377  * You can pass 0 for tag and tag_size if you don't needs the tag information
    378379 * The chapter tag is an APEv2 tag without the preamble
    379380 * @param d pointer to a musepack demuxer
    380381 * @param chap_nb chapter number you want datas (from 0 to mpc_demux_chap_nb(d) - 1)
    381  * @param tag will return a pointer to the chapter tag datas
    382  * @param tag_size will be filed with the tag data size (0 if no tag for this chapter)
    383  * @return the sample where the chapter starts
     382 * @return the chapter information structure
    384383 */
    385 mpc_uint64_t mpc_demux_chap(mpc_demux * d, int chap_nb, char ** tag, mpc_uint_t * tag_size)
     384mpc_chap_info * mpc_demux_chap(mpc_demux * d, int chap_nb)
    386385{
    387386        if (d->chap_nb == -1)
     
    389388        if (chap_nb >= d->chap_nb || chap_nb < 0)
    390389                return 0;
    391         if (tag != 0 && tag_size != 0) {
    392                 *tag = d->chap[chap_nb].tag;
    393                 *tag_size = d->chap[chap_nb].tag_size;
    394         }
    395         return d->chap[chap_nb].sample;
     390        return &d->chap[chap_nb];
    396391}
    397392
  • libmpc/trunk/mpcchap/mpcchap.c

    r408 r411  
    3030void    Init_Tags        ( void );
    3131int     FinalizeTags     ( FILE* fp, unsigned int Version, unsigned int flags );
    32 int     addtag           ( const char* key, size_t keylen, const char* value, size_t valuelen, int converttoutf8, int flags );
     32int     addtag           ( const char* key, size_t keylen, const char* value,
     33                           size_t valuelen, int converttoutf8, int flags );
    3334#define TAG_NO_HEADER 1
    3435#define TAG_NO_FOOTER 2
     
    3940#define atoll _atoi64
    4041#endif
     42
     43static const int Ptis[] = {     PTI_TITLE, PTI_PERFORMER, PTI_SONGWRITER, PTI_COMPOSER,
     44                PTI_ARRANGER, PTI_MESSAGE, PTI_GENRE};
     45static char const * const APE_keys[] = {"Title", "Artist", "Songwriter", "Composer",
     46                "Arranger", "Comment", "Genre"};
    4147
    4248static void usage(const char *exename)
     
    7783        int nchap = iniparser_getnsec(dict);
    7884        for (i = 0; i < nchap; i++) {
    79                 Init_Tags();
    80                 int j, nitem, tag_len = 0;
     85                int j, nitem, ntags = 0, tag_len = 0;
     86                mpc_uint16_t gain = 0, peak = 0;
    8187                char * chap_sec = iniparser_getsecname(dict, i);
    8288                mpc_int64_t chap_pos = atoll(chap_sec);
     89
    8390                if (chap_pos > si->samples - si->beg_silence)
    84                         fprintf(stderr, "warning : chapter %i starts @ %lli after the end of the stream (%lli)\n", i + 1, chap_pos, si->samples - si->beg_silence);
     91                        fprintf(stderr, "warning : chapter %i starts @ %lli samples after the end of the stream (%lli)\n",
     92                                i + 1, chap_pos, si->samples - si->beg_silence);
     93
     94                Init_Tags();
     95
    8596                nitem = iniparser_getnkey(dict, i);
    8697                for (j = 0; j < nitem; j++) {
     
    8899                        int key_len, item_len;
    89100                        item_key = iniparser_getkeyname(dict, i, j, & item_value);
    90                         key_len = strlen(item_key);
    91                         item_len = strlen(item_value);
    92                         addtag(item_key, key_len, item_value, item_len, 0, 0);
    93                         tag_len += key_len + item_len;
     101                        if (strcmp(item_key, "gain") == 0)
     102                                gain = atoi(item_value);
     103                        else if (strcmp(item_key, "peak") == 0)
     104                                peak = atoi(item_value);
     105                        else {
     106                                key_len = strlen(item_key);
     107                                item_len = strlen(item_value);
     108                                addtag(item_key, key_len, item_value, item_len, 0, 0);
     109                                tag_len += key_len + item_len;
     110                                ntags++;
     111                        }
    94112                }
    95                 if (nitem > 0) tag_len += 24 + nitem * 9;
     113                if (ntags > 0) tag_len += 24 + ntags * 9;
    96114                char block_header[12] = "CT";
    97115                char sample_offset[10];
    98116                int offset_size = encodeSize(chap_pos, sample_offset, MPC_FALSE);
    99                 tag_len = encodeSize(tag_len + offset_size + 2, block_header + 2, MPC_TRUE);
     117                tag_len = encodeSize(tag_len + 4 + offset_size + 2, block_header + 2, MPC_TRUE);
    100118                fwrite(block_header, 1, tag_len + 2, in_file);
    101119                fwrite(sample_offset, 1, offset_size, in_file);
     120                sample_offset[0] = gain >> 8;
     121                sample_offset[1] = gain & 0xFF;
     122                sample_offset[2] = peak >> 8;
     123                sample_offset[3] = peak & 0xFF;
     124                fwrite(sample_offset, 1, 4, in_file);
    102125                FinalizeTags(in_file, TAG_VERSION, TAG_NO_FOOTER | TAG_NO_PREAMBLE);
    103126        }
     
    115138mpc_status add_chaps_cue(char * mpc_file, char * chap_file, mpc_demux * demux, mpc_streaminfo * si)
    116139{
    117         int Ptis[7] = { PTI_TITLE, PTI_PERFORMER, PTI_SONGWRITER, PTI_COMPOSER,
    118                         PTI_ARRANGER, PTI_MESSAGE, PTI_GENRE};
    119         char * APE_keys[7] = {"Title", "Artist", "Songwriter", "Composer",
    120                         "Arranger", "Comment", "Genre"};
    121 
    122140        Cd *cd = 0;
    123141        int nchap, format = UNKNOWN;
     
    155173
    156174                if (chap_pos > si->samples - si->beg_silence)
    157                         fprintf(stderr, "warning : chapter %i starts @ %lli after the end of the stream (%lli)\n", i, chap_pos, si->samples - si->beg_silence);
     175                        fprintf(stderr, "warning : chapter %i starts @ %lli samples after the end of the stream (%lli)\n",
     176                                i, chap_pos, si->samples - si->beg_silence);
    158177
    159178                Init_Tags();
     
    168187
    169188                for (j = 0; j < (sizeof(Ptis) / sizeof(*Ptis)); j++) {
    170                         char * item_key = APE_keys[j], * item_value;
     189                        char const * item_key = APE_keys[j], * item_value;
    171190                        item_value = cdtext_get (Ptis[j], cdtext);
    172191                        if (item_value != 0) {
     
    183202                char sample_offset[10];
    184203                int offset_size = encodeSize(chap_pos, sample_offset, MPC_FALSE);
    185                 tag_len = encodeSize(tag_len + offset_size + 2, block_header + 2, MPC_TRUE);
     204                tag_len = encodeSize(tag_len + 4 + offset_size + 2, block_header + 2, MPC_TRUE);
    186205                fwrite(block_header, 1, tag_len + 2, in_file);
    187206                fwrite(sample_offset, 1, offset_size, in_file);
     207                fwrite("\0\0\0\0", 1, 4, in_file); // put unknow chapter gain / peak
    188208                FinalizeTags(in_file, TAG_VERSION, TAG_NO_FOOTER | TAG_NO_PREAMBLE);
    189209        }
     
    201221{
    202222        int i;
    203         unsigned int tag_size;
    204223        FILE * out_file;
    205         char * tag;
     224        mpc_chap_info * chap;
    206225
    207226        if (chap_nb <= 0)
     
    213232
    214233        for (i = 0; i < chap_nb; i++) {
    215                 fprintf(out_file, "[%lli]\n", mpc_demux_chap(demux, i, &tag, &tag_size));
    216                 if (tag_size > 0) {
     234                chap = mpc_demux_chap(demux, i);
     235                fprintf(out_file, "[%lli]\ngain=%i\npeak=%i\n", chap->sample, chap->gain, chap->peak);
     236                if (chap->tag_size > 0) {
    217237                        int item_count, j;
     238                        char const * tag = chap->tag;
    218239                        item_count = tag[8] | (tag[9] << 8) | (tag[10] << 16) | (tag[11] << 24);
    219240                        tag += 24;
Note: See TracChangeset for help on using the changeset viewer.