2 * Xing VBR tagging for LAME.
4 * Copyright (c) 1999 A.L. Faber
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 /* $Id: VbrTag.c,v 1.1 2002/04/28 17:30:17 kramm Exp $ */
24 #include "config_static.h"
27 #if defined(__riscos__) && defined(FPA10)
34 #include "bitstream.h"
48 /* #define DEBUG_VBRTAG */
52 // 4 bytes for Header Tag
53 // 4 bytes for Header Flags
54 // 100 bytes for entry (NUMTOCENTRIES)
55 // 4 bytes for FRAME SIZE
56 // 4 bytes for STREAM_SIZE
57 // 4 bytes for VBR SCALE. a VBR quality indicator: 0=best 100=worst
58 // 20 bytes for LAME tag. for example, "LAME3.12 (beta 6)"
62 #define VBRHEADERSIZE (NUMTOCENTRIES+4+4+4+4+4)
64 #define LAMEHEADERSIZE (VBRHEADERSIZE + 9 + 1 + 1 + 8 + 1 + 1 + 3 + 1 + 1 + 2 + 4 + 2 + 2)
66 /* the size of the Xing header (MPEG1 and MPEG2) in kbps */
67 #define XING_BITRATE1 128
68 #define XING_BITRATE2 64
69 #define XING_BITRATE25 32
73 const static char VBRTag
[]={"Xing"};
74 const static char VBRTag2
[]={"Info"};
79 /* Lookup table for fast CRC computation
80 * See 'CRC_update_lookup'
81 * Uses the polynomial x^16+x^15+x^2+1 */
83 unsigned int crc16_lookup
[256] =
85 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
86 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
87 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
88 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
89 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
90 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
91 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
92 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
93 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
94 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
95 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
96 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
97 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
98 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
99 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
100 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
101 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
102 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
103 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
104 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
105 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
106 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
107 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
108 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
109 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
110 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
111 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
112 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
113 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
114 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
115 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
116 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
123 /***********************************************************************
124 * Robert Hegemann 2001-01-17
125 ***********************************************************************/
127 static void addVbr(VBR_seek_info_t
* v
, int bitrate
)
134 if (v
->seen
< v
->want
) {
138 if (v
->pos
< v
->size
) {
139 v
->bag
[v
->pos
] = v
->sum
;
143 if (v
->pos
== v
->size
) {
144 for (i
= 1; i
< v
->size
; i
+= 2) {
145 v
->bag
[i
/2] = v
->bag
[i
];
152 static void Xing_seek_table(VBR_seek_info_t
* v
, unsigned char *t
)
160 for (i
= 1; i
< NUMTOCENTRIES
; ++i
) {
161 float j
= i
/(float)NUMTOCENTRIES
, act
, sum
;
162 index
= (int)(floor(j
* v
->pos
));
163 if (index
> v
->pos
-1)
167 seek_point
= (int)(256. * act
/ sum
);
168 if (seek_point
> 255)
175 void print_seeking(unsigned char *t
)
179 printf("seeking table ");
180 for (i
= 0; i
< NUMTOCENTRIES
; ++i
) {
181 printf(" %d ", t
[i
]);
189 /****************************************************************************
190 * AddVbrFrame: Add VBR entry, used to fill the VBR the TOC entries
192 * nStreamPos: how many bytes did we write to the bitstream so far
193 * (in Bytes NOT Bits)
194 ****************************************************************************
196 void AddVbrFrame(lame_global_flags
*gfp
)
198 lame_internal_flags
*gfc
= gfp
->internal_flags
;
200 int kbps
= bitrate_table
[gfp
->version
][gfc
->bitrate_index
];
202 if (gfc
->VBR_seek_table
.bag
== NULL
) {
203 gfc
->VBR_seek_table
.sum
= 0;
204 gfc
->VBR_seek_table
.seen
= 0;
205 gfc
->VBR_seek_table
.want
= 1;
206 gfc
->VBR_seek_table
.pos
= 0;
207 gfc
->VBR_seek_table
.bag
= malloc (400*sizeof(int));
208 if (gfc
->VBR_seek_table
.bag
!= NULL
) {
209 gfc
->VBR_seek_table
.size
= 400;
212 gfc
->VBR_seek_table
.size
= 0;
213 ERRORF (gfc
,"Error: can't allocate VbrFrames buffer\n");
217 addVbr(&gfc
->VBR_seek_table
, kbps
);
218 gfp
->nVbrNumFrames
++;
222 /*-------------------------------------------------------------*/
223 static int ExtractI4(unsigned char *buf
)
226 /* big endian extract */
237 static void CreateI4(unsigned char *buf
, int nValue
)
239 /* big endian create */
240 buf
[0]=(nValue
>>24)&0xff;
241 buf
[1]=(nValue
>>16)&0xff;
242 buf
[2]=(nValue
>> 8)&0xff;
243 buf
[3]=(nValue
)&0xff;
248 static void CreateI2(unsigned char *buf
, int nValue
)
250 /* big endian create */
251 buf
[0]=(nValue
>> 8)&0xff;
252 buf
[1]=(nValue
)&0xff;
256 /*-------------------------------------------------------------*/
257 /* Same as GetVbrTag below, but only checks for the Xing tag.
258 requires buf to contain only 40 bytes */
259 /*-------------------------------------------------------------*/
260 int CheckVbrTag(unsigned char *buf
)
262 int h_id
, h_mode
, h_sr_index
;
264 /* get selected MPEG header data */
265 h_id
= (buf
[1] >> 3) & 1;
266 h_sr_index
= (buf
[2] >> 2) & 3;
267 h_mode
= (buf
[3] >> 6) & 3;
269 /* determine offset of header */
273 if( h_mode
!= 3 ) buf
+=(32+4);
279 if( h_mode
!= 3 ) buf
+=(17+4);
283 if( buf
[0] != VBRTag
[0] && buf
[0] != VBRTag2
[0] ) return 0; /* fail */
284 if( buf
[1] != VBRTag
[1] && buf
[1] != VBRTag2
[1]) return 0; /* header not found*/
285 if( buf
[2] != VBRTag
[2] && buf
[2] != VBRTag2
[2]) return 0;
286 if( buf
[3] != VBRTag
[3] && buf
[3] != VBRTag2
[3]) return 0;
290 int GetVbrTag(VBRTAGDATA
*pTagData
, unsigned char *buf
)
293 int h_bitrate
,h_id
, h_mode
, h_sr_index
;
294 int enc_delay
,enc_padding
;
296 /* get Vbr header data */
299 /* get selected MPEG header data */
300 h_id
= (buf
[1] >> 3) & 1;
301 h_sr_index
= (buf
[2] >> 2) & 3;
302 h_mode
= (buf
[3] >> 6) & 3;
303 h_bitrate
= ((buf
[2]>>4)&0xf);
304 h_bitrate
= bitrate_table
[h_id
][h_bitrate
];
306 /* check for FFE syncword */
307 if ((buf
[1]>>4)==0xE)
308 pTagData
->samprate
= samplerate_table
[2][h_sr_index
];
310 pTagData
->samprate
= samplerate_table
[h_id
][h_sr_index
];
312 // pTagData->samprate >>= 1;
316 /* determine offset of header */
320 if( h_mode
!= 3 ) buf
+=(32+4);
326 if( h_mode
!= 3 ) buf
+=(17+4);
330 if( buf
[0] != VBRTag
[0] && buf
[0] != VBRTag2
[0] ) return 0; /* fail */
331 if( buf
[1] != VBRTag
[1] && buf
[1] != VBRTag2
[1]) return 0; /* header not found*/
332 if( buf
[2] != VBRTag
[2] && buf
[2] != VBRTag2
[2]) return 0;
333 if( buf
[3] != VBRTag
[3] && buf
[3] != VBRTag2
[3]) return 0;
337 pTagData
->h_id
= h_id
;
339 head_flags
= pTagData
->flags
= ExtractI4(buf
); buf
+=4; /* get flags */
341 if( head_flags
& FRAMES_FLAG
)
343 pTagData
->frames
= ExtractI4(buf
); buf
+=4;
346 if( head_flags
& BYTES_FLAG
)
348 pTagData
->bytes
= ExtractI4(buf
); buf
+=4;
351 if( head_flags
& TOC_FLAG
)
353 if( pTagData
->toc
!= NULL
)
355 for(i
=0;i
<NUMTOCENTRIES
;i
++)
356 pTagData
->toc
[i
] = buf
[i
];
361 pTagData
->vbr_scale
= -1;
363 if( head_flags
& VBR_SCALE_FLAG
)
365 pTagData
->vbr_scale
= ExtractI4(buf
); buf
+=4;
368 pTagData
->headersize
=
369 ((h_id
+1)*72000*h_bitrate
) / pTagData
->samprate
;
372 enc_delay
= buf
[0] << 4;
373 enc_delay
+= buf
[1] >> 4;
374 enc_padding
= (buf
[1] & 0x0F)<<8;
375 enc_padding
+= buf
[2];
376 // check for reasonable values (this may be an old Xing header,
378 if (enc_delay
<0 || enc_delay
> 3000) enc_delay
=-1;
379 if (enc_padding
<0 || enc_padding
> 3000) enc_padding
=-1;
381 pTagData
->enc_delay
=enc_delay
;
382 pTagData
->enc_padding
=enc_padding
;
385 fprintf(stderr
,"\n\n********************* VBR TAG INFO *****************\n");
386 fprintf(stderr
,"tag :%s\n",VBRTag
);
387 fprintf(stderr
,"head_flags :%d\n",head_flags
);
388 fprintf(stderr
,"bytes :%d\n",pTagData
->bytes
);
389 fprintf(stderr
,"frames :%d\n",pTagData
->frames
);
390 fprintf(stderr
,"VBR Scale :%d\n",pTagData
->vbr_scale
);
391 fprintf(stderr
,"enc_delay = %i \n",enc_delay
);
392 fprintf(stderr
,"enc_padding= %i \n",enc_padding
);
393 fprintf(stderr
,"toc:\n");
394 if( pTagData
->toc
!= NULL
)
396 for(i
=0;i
<NUMTOCENTRIES
;i
++)
398 if( (i
%10) == 0 ) fprintf(stderr
,"\n");
399 fprintf(stderr
," %3d", (int)(pTagData
->toc
[i
]));
402 fprintf(stderr
,"\n***************** END OF VBR TAG INFO ***************\n");
404 return 1; /* success */
408 /****************************************************************************
409 * InitVbrTag: Initializes the header, and write empty frame to stream
411 * fpStream: pointer to output file stream
412 * nMode : Channel Mode: 0=STEREO 1=JS 2=DS 3=MONO
413 ****************************************************************************
415 int InitVbrTag(lame_global_flags
*gfp
)
418 lame_internal_flags
*gfc
= gfp
->internal_flags
;
419 #define MAXFRAMESIZE 2880 // or 0xB40, the max freeformat 640 32kHz framesize
420 // uint8_t pbtStreamBuffer[MAXFRAMESIZE];
422 SampIndex
= gfc
->samplerate_index
;
425 /* Clear Frame position array variables */
426 //gfp->pVbrFrames=NULL;
427 gfp
->nVbrNumFrames
=0;
428 gfp
->nVbrFrameBufferSize
=0;
431 /* Clear stream buffer */
432 // memset(pbtStreamBuffer,0x00,sizeof(pbtStreamBuffer));
437 // Xing VBR pretends to be a 48kbs layer III frame. (at 44.1kHz).
438 // (at 48kHz they use 56kbs since 48kbs frame not big enough for
439 // table of contents)
440 // let's always embed Xing header inside a 64kbs layer III frame.
441 // this gives us enough room for a LAME version string too.
442 // size determined by sampling frequency (MPEG1)
443 // 32kHz: 216 bytes@48kbs 288bytes@ 64kbs
444 // 44.1kHz: 156 bytes 208bytes@64kbs (+1 if padding = 1)
445 // 48kHz: 144 bytes 192
447 // MPEG 2 values are the same since the framesize and samplerate
448 // are each reduced by a factor of 2.
452 if (1==gfp
->version
) {
453 bitrate
= XING_BITRATE1
;
455 if (gfp
->out_samplerate
< 16000 )
456 bitrate
= XING_BITRATE25
;
458 bitrate
= XING_BITRATE2
;
461 if (gfp
->VBR
==vbr_off
)
462 bitrate
= gfp
->brate
;
465 ((gfp
->version
+1)*72000*bitrate
) / gfp
->out_samplerate
;
467 tot
= (gfc
->sideinfo_len
+LAMEHEADERSIZE
);
469 if (gfp
->TotalFrameSize
< tot
||
470 gfp
->TotalFrameSize
> MAXFRAMESIZE
) {
471 // disable tag, it wont fit
472 gfp
->bWriteVbrTag
= 0;
476 for (i
=0; i
<gfp
->TotalFrameSize
; ++i
)
477 add_dummy_byte(gfp
,0);
486 /* fast CRC-16 computation - uses table crc16_lookup 8*/
487 int CRC_update_lookup(int value
, int crc
)
491 crc
=(crc
>>8)^crc16_lookup
[tmp
& 0xff];
495 void UpdateMusicCRC(uint16_t *crc
,unsigned char *buffer
, int size
){
497 for (i
=0; i
<size
; ++i
)
498 *crc
= CRC_update_lookup(buffer
[i
],*crc
);
504 void ReportLameTagProgress(lame_global_flags
*gfp
,int nStart
)
506 if (!gfp
->bWriteVbrTag
)
510 MSGF( gfp
->internal_flags
, "Writing LAME Tag...");
512 MSGF( gfp
->internal_flags
, "done\n");
517 /****************************************************************************
518 * Jonathan Dee 2001/08/31
520 * PutLameVBR: Write LAME info: mini version + info on various switches used
522 * pbtStreamBuffer : pointer to output buffer
523 * id3v2size : size of id3v2 tag in bytes
524 * crc : computation of crc-16 of Lame Tag so far (starting at frame sync)
526 ****************************************************************************
528 int PutLameVBR(lame_global_flags
*gfp
, FILE *fpStream
, uint8_t *pbtStreamBuffer
, uint32_t id3v2size
, uint16_t crc
)
530 lame_internal_flags
*gfc
= gfp
->internal_flags
;
531 // FLOAT fVersion = LAME_MAJOR_VERSION + 0.01 * LAME_MINOR_VERSION;
533 int nBytesWritten
= 0;
534 int nFilesize
= 0; //size of fpStream. Will be equal to size after process finishes.
537 int enc_delay
=lame_get_encoder_delay(gfp
); // encoder delay
538 int enc_padding
=lame_get_encoder_padding(gfp
); // encoder padding
540 //recall: gfp->VBR_q is for example set by the switch -V
541 // gfp->quality by -q, -h, -f, etc
543 int nQuality
= (100 - 10 * gfp
->VBR_q
- gfp
->quality
);
546 const char *szVersion
= get_lame_very_short_version();
548 uint8_t nRevision
= 0x00;
550 uint8_t vbr_type_translator
[] = {1,5,3,2,4,0,3}; //numbering different in vbr_mode vs. Lame tag
552 uint8_t nLowpass
= ( ((gfp
->lowpassfreq
/ 100.0)+.5) > 255 ? 255 : (gfp
->lowpassfreq
/ 100.0)+.5 );
554 ieee754_float32_t fPeakSignalAmplitude
= 0; //TODO...
555 uint16_t nRadioReplayGain
= 0; //TODO...
556 uint16_t nAudioPhileReplayGain
= 0; //TODO...
561 uint8_t nNoiseShaping
= gfp
->internal_flags
->noise_shaping
;
562 uint8_t nStereoMode
= 0;
564 uint8_t nSourceFreq
= 0;
566 uint32_t nMusicLength
= 0;
567 int bId3v1Present
= ((gfp
->internal_flags
->tag_spec
.flags
& CHANGED_FLAG
)
568 && !(gfp
->internal_flags
->tag_spec
.flags
& V2_ONLY_FLAG
));
569 uint16_t nMusicCRC
= 0;
571 //psy model type: Gpsycho or NsPsytune
572 unsigned char bExpNPsyTune
= gfp
->exp_nspsytune
& 1;
573 unsigned char bSafeJoint
= (gfp
->exp_nspsytune
& 2)!=0;
575 unsigned char bNoGapMore
= 0;
576 unsigned char bNoGapPrevious
= 0;
578 int nNoGapCount
= gfp
->internal_flags
->nogap_total
;
579 int nNoGapCurr
= gfp
->internal_flags
->nogap_current
;
582 uint8_t nAthType
= gfp
->ATHtype
; //4 bits.
586 // if ABR, {store bitrate <=255} else { store "-b"}
587 int nABRBitrate
= (gfp
->VBR
==vbr_abr
)?gfp
->VBR_mean_bitrate_kbps
:gfp
->brate
;
589 //revision and vbr method
590 if (gfp
->VBR
>=0 && gfp
->VBR
< sizeof(vbr_type_translator
))
591 nVBR
= vbr_type_translator
[gfp
->VBR
];
593 nVBR
= 0x00; //unknown.
595 nRevMethod
= 0x10 * nRevision
+ nVBR
;
598 if (nNoGapCount
!= -1)
603 if (nNoGapCurr
< nNoGapCount
-1)
609 nFlags
= nAthType
+ (bExpNPsyTune
<< 4)
612 + (bNoGapPrevious
<< 7);
618 /*stereo mode field... a bit ugly.*/
644 if (gfp
->mode_automs
)
647 /*Intensity stereo : nStereoMode = 6. IS is not implemented */
649 if (gfp
->in_samplerate
<= 32000)
651 else if (gfp
->in_samplerate
==48000)
653 else if (gfp
->in_samplerate
> 48000)
656 nSourceFreq
= 0x01; //default is 44100Hz.
659 //Check if the user overrided the default LAME behaviour with some nasty options
661 if (gfp
->short_blocks
== short_block_forced
||
662 gfp
->short_blocks
== short_block_dispensed
||
663 ((gfp
->lowpassfreq
== -1) && (gfp
->highpassfreq
== -1)) || // "-k"
664 (gfp
->scale_left
!= gfp
->scale_right
) ||
665 gfp
->disable_reservoir
||
669 gfp
->in_samplerate
<= 32000)
672 nMisc
= nNoiseShaping
675 + (nSourceFreq
<< 6);
680 fseek(fpStream
, 0, SEEK_END
);
681 nFilesize
= ftell(fpStream
);
684 nMusicLength
= nFilesize
- id3v2size
; //omit current frame
686 nMusicLength
-=128; //id3v1 present.
687 nMusicCRC
= gfc
->nMusicCRC
;
690 /*Write all this information into the stream*/
691 CreateI4(&pbtStreamBuffer
[nBytesWritten
], nQuality
);
694 strncpy(&pbtStreamBuffer
[nBytesWritten
], szVersion
, 9);
697 pbtStreamBuffer
[nBytesWritten
] = nRevMethod
;
700 pbtStreamBuffer
[nBytesWritten
] = nLowpass
;
703 memmove(&pbtStreamBuffer
[nBytesWritten
], &fPeakSignalAmplitude
, 4);
706 CreateI2(&pbtStreamBuffer
[nBytesWritten
],nRadioReplayGain
);
709 CreateI2(&pbtStreamBuffer
[nBytesWritten
],nAudioPhileReplayGain
);
712 pbtStreamBuffer
[nBytesWritten
] = nFlags
;
715 if (nABRBitrate
>= 255)
716 pbtStreamBuffer
[nBytesWritten
] = 0xFF;
718 pbtStreamBuffer
[nBytesWritten
] = nABRBitrate
;
721 pbtStreamBuffer
[nBytesWritten
] = enc_delay
>> 4; // works for win32, does it for unix?
722 pbtStreamBuffer
[nBytesWritten
+1] = (enc_delay
<< 4) + (enc_padding
>> 8);
723 pbtStreamBuffer
[nBytesWritten
+2] = enc_padding
;
727 pbtStreamBuffer
[nBytesWritten
] = nMisc
;
731 memset(pbtStreamBuffer
+nBytesWritten
,0, 3); //unused in rev0
734 CreateI4(&pbtStreamBuffer
[nBytesWritten
], nMusicLength
);
737 CreateI2(&pbtStreamBuffer
[nBytesWritten
], nMusicCRC
);
740 /*Calculate tag CRC.... must be done here, since it includes
741 *previous information*/
743 for (i
= 0;i
<nBytesWritten
;i
++)
744 crc
= CRC_update_lookup(pbtStreamBuffer
[i
], crc
);
746 CreateI2(&pbtStreamBuffer
[nBytesWritten
], crc
);
749 return nBytesWritten
;
752 /***********************************************************************
754 * PutVbrTag: Write final VBR tag to the file
756 * lpszFileName: filename of MP3 bit stream
757 * nVbrScale : encoder quality indicator (0..100)
758 ****************************************************************************
760 int PutVbrTag(lame_global_flags
*gfp
,FILE *fpStream
,int nVbrScale
)
762 lame_internal_flags
* gfc
= gfp
->internal_flags
;
767 uint8_t btToc
[NUMTOCENTRIES
];
768 uint8_t pbtStreamBuffer
[MAXFRAMESIZE
];
773 unsigned char id3v2Header
[10];
776 if (gfc
->VBR_seek_table
.pos
<= 0)
780 /* Clear stream buffer */
781 memset(pbtStreamBuffer
,0x00,sizeof(pbtStreamBuffer
));
783 /* Seek to end of file*/
784 fseek(fpStream
,0,SEEK_END
);
787 lFileSize
=ftell(fpStream
);
789 /* Abort if file has zero length. Yes, it can happen :) */
794 * The VBR tag may NOT be located at the beginning of the stream.
795 * If an ID3 version 2 tag was added, then it must be skipped to write
799 /* seek to the beginning of the stream */
800 fseek(fpStream
,0,SEEK_SET
);
801 /* read 10 bytes in case there's an ID3 version 2 header here */
802 fread(id3v2Header
,1,sizeof id3v2Header
,fpStream
);
803 /* does the stream begin with the ID3 version 2 file identifier? */
804 if (!strncmp((char *)id3v2Header
,"ID3",3)) {
805 /* the tag size (minus the 10-byte header) is encoded into four
806 * bytes where the most significant bit is clear in each byte */
807 id3v2TagSize
=(((id3v2Header
[6] & 0x7f)<<21)
808 | ((id3v2Header
[7] & 0x7f)<<14)
809 | ((id3v2Header
[8] & 0x7f)<<7)
810 | (id3v2Header
[9] & 0x7f))
811 + sizeof id3v2Header
;
813 /* no ID3 version 2 tag in this stream */
817 /* Seek to first real frame */
818 fseek(fpStream
,id3v2TagSize
+gfp
->TotalFrameSize
,SEEK_SET
);
820 /* Read the header (first valid frame) */
821 fread(pbtStreamBuffer
,4,1,fpStream
);
823 /* the default VBR header. 48 kbps layer III, no padding, no crc */
824 /* but sampling freq, mode andy copyright/copy protection taken */
825 /* from first valid frame */
826 pbtStreamBuffer
[0]=(uint8_t) 0xff;
827 abyte
= (pbtStreamBuffer
[1] & (char) 0xf1);
830 if (1==gfp
->version
) {
831 bitrate
= XING_BITRATE1
;
833 if (gfp
->out_samplerate
< 16000 )
834 bitrate
= XING_BITRATE25
;
836 bitrate
= XING_BITRATE2
;
839 if (gfp
->VBR
==vbr_off
)
840 bitrate
= gfp
->brate
;
842 bbyte
= 16*BitrateIndex(bitrate
,gfp
->version
,gfp
->out_samplerate
);
845 /* Use as much of the info from the real frames in the
846 * Xing header: samplerate, channels, crc, etc...
848 if (gfp
->version
==1) {
850 pbtStreamBuffer
[1]=abyte
| (char) 0x0a; /* was 0x0b; */
851 abyte
= pbtStreamBuffer
[2] & (char) 0x0d; /* AF keep also private bit */
852 pbtStreamBuffer
[2]=(char) bbyte
| abyte
; /* 64kbs MPEG1 frame */
855 pbtStreamBuffer
[1]=abyte
| (char) 0x02; /* was 0x03; */
856 abyte
= pbtStreamBuffer
[2] & (char) 0x0d; /* AF keep also private bit */
857 pbtStreamBuffer
[2]=(char) bbyte
| abyte
; /* 64kbs MPEG2 frame */
860 /* Clear all TOC entries */
861 memset(btToc
,0,sizeof(btToc
));
863 Xing_seek_table (&gfc
->VBR_seek_table
, btToc
);
864 /* print_seeking (btToc); */
866 /* Start writing the tag after the zero frame */
867 nStreamIndex
=gfc
->sideinfo_len
;
868 /* note! Xing header specifies that Xing data goes in the
869 * ancillary data with NO ERROR PROTECTION. If error protecton
870 * in enabled, the Xing data still starts at the same offset,
871 * and now it is in sideinfo data block, and thus will not
872 * decode correctly by non-Xing tag aware players */
873 if (gfp
->error_protection
) nStreamIndex
-= 2;
876 if (gfp
->VBR
== vbr_off
)
878 pbtStreamBuffer
[nStreamIndex
++]=VBRTag2
[0];
879 pbtStreamBuffer
[nStreamIndex
++]=VBRTag2
[1];
880 pbtStreamBuffer
[nStreamIndex
++]=VBRTag2
[2];
881 pbtStreamBuffer
[nStreamIndex
++]=VBRTag2
[3];
886 pbtStreamBuffer
[nStreamIndex
++]=VBRTag
[0];
887 pbtStreamBuffer
[nStreamIndex
++]=VBRTag
[1];
888 pbtStreamBuffer
[nStreamIndex
++]=VBRTag
[2];
889 pbtStreamBuffer
[nStreamIndex
++]=VBRTag
[3];
892 /* Put header flags */
893 CreateI4(&pbtStreamBuffer
[nStreamIndex
],FRAMES_FLAG
+BYTES_FLAG
+TOC_FLAG
+VBR_SCALE_FLAG
);
896 /* Put Total Number of frames */
897 CreateI4(&pbtStreamBuffer
[nStreamIndex
],gfp
->nVbrNumFrames
);
900 /* Put Total file size */
901 CreateI4(&pbtStreamBuffer
[nStreamIndex
],(int)lFileSize
);
905 memcpy(&pbtStreamBuffer
[nStreamIndex
],btToc
,sizeof(btToc
));
906 nStreamIndex
+=sizeof(btToc
);
909 if (gfp
->error_protection
) {
910 /* (jo) error_protection: add crc16 information to header */
911 CRC_writeheader(gfc
, pbtStreamBuffer
);
916 //work out CRC so far: initially crc = 0
917 for (i
= 0;i
< nStreamIndex
;i
++)
918 crc
= CRC_update_lookup(pbtStreamBuffer
[i
], crc
);
920 /*Put LAME VBR info*/
921 nStreamIndex
+=PutLameVBR(gfp
, fpStream
, pbtStreamBuffer
+ nStreamIndex
, id3v2TagSize
,crc
);
925 VBRTAGDATA TestHeader
;
926 GetVbrTag(&TestHeader
,pbtStreamBuffer
);
930 /*Seek to the beginning of the stream */
931 fseek(fpStream
,id3v2TagSize
,SEEK_SET
);
933 /* Put it all to disk again */
934 if (fwrite(pbtStreamBuffer
,(unsigned int)gfp
->TotalFrameSize
,1,fpStream
)!=1)
938 /* Save to delete the frame buffer */
939 //free(gfp->pVbrFrames); see HACKING for instructions on how
940 //gfp->pVbrFrames=NULL; memory in 'gfp' is allocated/free'd
942 return 0; /* success */