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.77 2004/03/23 01:57:16 olcios Exp $ */
29
#include "bitstream.h"
41
/* woraround for SunOS 4.x, it has SEEK_* defined here */
47
/* #define DEBUG_VBRTAG */
51
* 4 bytes for Header Tag
52
* 4 bytes for Header Flags
53
* 100 bytes for entry (NUMTOCENTRIES)
54
* 4 bytes for FRAME SIZE
55
* 4 bytes for STREAM_SIZE
56
* 4 bytes for VBR SCALE. a VBR quality indicator: 0=best 100=worst
57
* 20 bytes for LAME tag. for example, "LAME3.12 (beta 6)"
61
#define VBRHEADERSIZE (NUMTOCENTRIES+4+4+4+4+4)
63
#define LAMEHEADERSIZE (VBRHEADERSIZE + 9 + 1 + 1 + 8 + 1 + 1 + 3 + 1 + 1 + 2 + 4 + 2 + 2)
65
/* the size of the Xing header (MPEG1 and MPEG2) in kbps */
66
#define XING_BITRATE1 128
67
#define XING_BITRATE2 64
68
#define XING_BITRATE25 32
72
const static char VBRTag[]={"Xing"};
73
const static char VBRTag2[]={"Info"};
78
/* Lookup table for fast CRC computation
79
* See 'CRC_update_lookup'
80
* Uses the polynomial x^16+x^15+x^2+1 */
82
unsigned int crc16_lookup[256] =
84
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
85
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
86
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
87
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
88
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
89
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
90
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
91
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
92
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
93
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
94
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
95
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
96
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
97
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
98
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
99
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
100
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
101
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
102
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
103
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
104
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
105
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
106
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
107
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
108
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
109
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
110
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
111
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
112
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
113
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
114
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
115
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
122
/***********************************************************************
123
* Robert Hegemann 2001-01-17
124
***********************************************************************/
126
static void addVbr(VBR_seek_info_t * v, int bitrate)
133
if (v->seen < v->want) {
137
if (v->pos < v->size) {
138
v->bag[v->pos] = v->sum;
142
if (v->pos == v->size) {
143
for (i = 1; i < v->size; i += 2) {
144
v->bag[i/2] = v->bag[i];
151
static void Xing_seek_table(VBR_seek_info_t * v, unsigned char *t)
159
for (i = 1; i < NUMTOCENTRIES; ++i) {
160
float j = i/(float)NUMTOCENTRIES, act, sum;
161
index = (int)(floor(j * v->pos));
162
if (index > v->pos-1)
166
seek_point = (int)(256. * act / sum);
167
if (seek_point > 255)
173
void print_seeking(unsigned char *t)
177
printf("seeking table ");
178
for (i = 0; i < NUMTOCENTRIES; ++i) {
179
printf(" %d ", t[i]);
186
/****************************************************************************
187
* AddVbrFrame: Add VBR entry, used to fill the VBR the TOC entries
189
* nStreamPos: how many bytes did we write to the bitstream so far
190
* (in Bytes NOT Bits)
191
****************************************************************************
193
void AddVbrFrame(lame_global_flags *gfp)
195
lame_internal_flags *gfc = gfp->internal_flags;
197
int kbps = bitrate_table[gfp->version][gfc->bitrate_index];
198
assert(gfc->VBR_seek_table.bag);
199
addVbr(&gfc->VBR_seek_table, kbps);
200
gfp->nVbrNumFrames++;
204
/*-------------------------------------------------------------*/
205
static int ExtractI4(unsigned char *buf)
208
/* big endian extract */
219
static void CreateI4(unsigned char *buf, int nValue)
221
/* big endian create */
222
buf[0]=(nValue>>24)&0xff;
223
buf[1]=(nValue>>16)&0xff;
224
buf[2]=(nValue>> 8)&0xff;
225
buf[3]=(nValue )&0xff;
230
static void CreateI2(unsigned char *buf, int nValue)
232
/* big endian create */
233
buf[0]=(nValue>> 8)&0xff;
234
buf[1]=(nValue )&0xff;
238
/*-------------------------------------------------------------*/
239
/* Same as GetVbrTag below, but only checks for the Xing tag.
240
requires buf to contain only 40 bytes */
241
/*-------------------------------------------------------------*/
242
int CheckVbrTag(unsigned char *buf)
244
int h_id, h_mode, h_sr_index;
246
/* get selected MPEG header data */
247
h_id = (buf[1] >> 3) & 1;
248
h_sr_index = (buf[2] >> 2) & 3;
249
h_mode = (buf[3] >> 6) & 3;
251
/* determine offset of header */
255
if( h_mode != 3 ) buf+=(32+4);
261
if( h_mode != 3 ) buf+=(17+4);
265
if( buf[0] != VBRTag[0] && buf[0] != VBRTag2[0] ) return 0; /* fail */
266
if( buf[1] != VBRTag[1] && buf[1] != VBRTag2[1]) return 0; /* header not found*/
267
if( buf[2] != VBRTag[2] && buf[2] != VBRTag2[2]) return 0;
268
if( buf[3] != VBRTag[3] && buf[3] != VBRTag2[3]) return 0;
272
int GetVbrTag(VBRTAGDATA *pTagData, unsigned char *buf)
275
int h_bitrate,h_id, h_mode, h_sr_index;
276
int enc_delay,enc_padding;
278
/* get Vbr header data */
281
/* get selected MPEG header data */
282
h_id = (buf[1] >> 3) & 1;
283
h_sr_index = (buf[2] >> 2) & 3;
284
h_mode = (buf[3] >> 6) & 3;
285
h_bitrate = ((buf[2]>>4)&0xf);
286
h_bitrate = bitrate_table[h_id][h_bitrate];
288
/* check for FFE syncword */
289
if ((buf[1]>>4)==0xE)
290
pTagData->samprate = samplerate_table[2][h_sr_index];
292
pTagData->samprate = samplerate_table[h_id][h_sr_index];
293
/* if( h_id == 0 ) */
294
/* pTagData->samprate >>= 1; */
298
/* determine offset of header */
302
if( h_mode != 3 ) buf+=(32+4);
308
if( h_mode != 3 ) buf+=(17+4);
312
if( buf[0] != VBRTag[0] && buf[0] != VBRTag2[0] ) return 0; /* fail */
313
if( buf[1] != VBRTag[1] && buf[1] != VBRTag2[1]) return 0; /* header not found*/
314
if( buf[2] != VBRTag[2] && buf[2] != VBRTag2[2]) return 0;
315
if( buf[3] != VBRTag[3] && buf[3] != VBRTag2[3]) return 0;
319
pTagData->h_id = h_id;
321
head_flags = pTagData->flags = ExtractI4(buf); buf+=4; /* get flags */
323
if( head_flags & FRAMES_FLAG )
325
pTagData->frames = ExtractI4(buf); buf+=4;
328
if( head_flags & BYTES_FLAG )
330
pTagData->bytes = ExtractI4(buf); buf+=4;
333
if( head_flags & TOC_FLAG )
335
if( pTagData->toc != NULL )
337
for(i=0;i<NUMTOCENTRIES;i++)
338
pTagData->toc[i] = buf[i];
343
pTagData->vbr_scale = -1;
345
if( head_flags & VBR_SCALE_FLAG )
347
pTagData->vbr_scale = ExtractI4(buf); buf+=4;
350
pTagData->headersize =
351
((h_id+1)*72000*h_bitrate) / pTagData->samprate;
354
enc_delay = buf[0] << 4;
355
enc_delay += buf[1] >> 4;
356
enc_padding= (buf[1] & 0x0F)<<8;
357
enc_padding += buf[2];
358
/* check for reasonable values (this may be an old Xing header, */
359
/* not a INFO tag) */
360
if (enc_delay<0 || enc_delay > 3000) enc_delay=-1;
361
if (enc_padding<0 || enc_padding > 3000) enc_padding=-1;
363
pTagData->enc_delay=enc_delay;
364
pTagData->enc_padding=enc_padding;
367
fprintf(stderr,"\n\n********************* VBR TAG INFO *****************\n");
368
fprintf(stderr,"tag :%s\n",VBRTag);
369
fprintf(stderr,"head_flags :%d\n",head_flags);
370
fprintf(stderr,"bytes :%d\n",pTagData->bytes);
371
fprintf(stderr,"frames :%d\n",pTagData->frames);
372
fprintf(stderr,"VBR Scale :%d\n",pTagData->vbr_scale);
373
fprintf(stderr,"enc_delay = %i \n",enc_delay);
374
fprintf(stderr,"enc_padding= %i \n",enc_padding);
375
fprintf(stderr,"toc:\n");
376
if( pTagData->toc != NULL )
378
for(i=0;i<NUMTOCENTRIES;i++)
380
if( (i%10) == 0 ) fprintf(stderr,"\n");
381
fprintf(stderr," %3d", (int)(pTagData->toc[i]));
384
fprintf(stderr,"\n***************** END OF VBR TAG INFO ***************\n");
386
return 1; /* success */
390
/****************************************************************************
391
* InitVbrTag: Initializes the header, and write empty frame to stream
393
* fpStream: pointer to output file stream
394
* nMode : Channel Mode: 0=STEREO 1=JS 2=DS 3=MONO
395
****************************************************************************
397
int InitVbrTag(lame_global_flags *gfp)
400
int i,kbps_header,tot;
401
lame_internal_flags *gfc = gfp->internal_flags;
402
#define MAXFRAMESIZE 2880 /* or 0xB40, the max freeformat 640 32kHz framesize */
403
/* uint8_t pbtStreamBuffer[MAXFRAMESIZE]; */
405
SampIndex = gfc->samplerate_index;
409
gfp->nVbrNumFrames=0;
410
/*gfp->nVbrFrameBufferSize=0;*/
413
/* Clear stream buffer */
414
/* memset(pbtStreamBuffer,0x00,sizeof(pbtStreamBuffer)); */
419
* Xing VBR pretends to be a 48kbs layer III frame. (at 44.1kHz).
420
* (at 48kHz they use 56kbs since 48kbs frame not big enough for
422
* let's always embed Xing header inside a 64kbs layer III frame.
423
* this gives us enough room for a LAME version string too.
424
* size determined by sampling frequency (MPEG1)
425
* 32kHz: 216 bytes@48kbs 288bytes@ 64kbs
426
* 44.1kHz: 156 bytes 208bytes@64kbs (+1 if padding = 1)
427
* 48kHz: 144 bytes 192
429
* MPEG 2 values are the same since the framesize and samplerate
430
* are each reduced by a factor of 2.
434
if (1==gfp->version) {
435
kbps_header = XING_BITRATE1;
437
if (gfp->out_samplerate < 16000 )
438
kbps_header = XING_BITRATE25;
440
kbps_header = XING_BITRATE2;
443
if (gfp->VBR==vbr_off)
444
kbps_header = gfp->brate;
447
((gfp->version+1)*72000*kbps_header) / gfp->out_samplerate;
449
tot = (gfc->sideinfo_len+LAMEHEADERSIZE);
451
if (gfp->TotalFrameSize < tot ||
452
gfp->TotalFrameSize > MAXFRAMESIZE ) {
453
/* disable tag, it wont fit */
454
gfp->bWriteVbrTag = 0;
458
/* write dummy VBR tag of all 0's into bitstream */
459
for (i=0; i<gfp->TotalFrameSize; ++i)
460
add_dummy_byte(gfp,0);
463
gfc->VBR_seek_table.sum = 0;
465
gfc->VBR_seek_table.seen = 0;
466
gfc->VBR_seek_table.want = 1;
467
gfc->VBR_seek_table.pos = 0;
469
if (gfc->VBR_seek_table.bag == NULL) {
470
gfc->VBR_seek_table.bag = malloc (400*sizeof(int));
471
if (gfc->VBR_seek_table.bag != NULL) {
472
gfc->VBR_seek_table.size = 400;
475
gfc->VBR_seek_table.size = 0;
476
ERRORF (gfc,"Error: can't allocate VbrFrames buffer\n");
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);
505
/****************************************************************************
506
* Jonathan Dee 2001/08/31
508
* PutLameVBR: Write LAME info: mini version + info on various switches used
510
* pbtStreamBuffer : pointer to output buffer
511
* id3v2size : size of id3v2 tag in bytes
512
* crc : computation of crc-16 of Lame Tag so far (starting at frame sync)
514
****************************************************************************
516
int PutLameVBR(lame_global_flags *gfp, FILE *fpStream, uint8_t *pbtStreamBuffer, uint32_t id3v2size, uint16_t crc)
518
lame_internal_flags *gfc = gfp->internal_flags;
519
/* FLOAT fVersion = LAME_MAJOR_VERSION + 0.01 * LAME_MINOR_VERSION; */
521
int nBytesWritten = 0;
522
int nFilesize = 0; /*size of fpStream. Will be equal to size after process finishes. */
525
int enc_delay=lame_get_encoder_delay(gfp); /* encoder delay */
526
int enc_padding=lame_get_encoder_padding(gfp); /* encoder padding */
528
/*recall: gfp->VBR_q is for example set by the switch -V */
529
/* gfp->quality by -q, -h, -f, etc */
531
int nQuality = (100 - 10 * gfp->VBR_q - gfp->quality);
534
const char *szVersion = get_lame_very_short_version();
536
uint8_t nRevision = 0x00;
538
uint8_t vbr_type_translator[] = {1,5,3,2,4,0,3}; /*numbering different in vbr_mode vs. Lame tag */
540
uint8_t nLowpass = ( ((gfp->lowpassfreq / 100.0)+.5) > 255 ? 255 : (gfp->lowpassfreq / 100.0)+.5 );
542
uint32_t nPeakSignalAmplitude = 0;
544
uint16_t nRadioReplayGain = 0;
545
uint16_t nAudiophileReplayGain = 0;
547
uint8_t nNoiseShaping = gfp->internal_flags->noise_shaping;
548
uint8_t nStereoMode = 0;
550
uint8_t nSourceFreq = 0;
552
uint32_t nMusicLength = 0;
553
int bId3v1Present = ((gfp->internal_flags->tag_spec.flags & CHANGED_FLAG)
554
&& !(gfp->internal_flags->tag_spec.flags & V2_ONLY_FLAG));
555
uint16_t nMusicCRC = 0;
557
/*psy model type: Gpsycho or NsPsytune */
558
unsigned char bExpNPsyTune = gfp->exp_nspsytune & 1;
559
unsigned char bSafeJoint = (gfp->exp_nspsytune & 2)!=0;
561
unsigned char bNoGapMore = 0;
562
unsigned char bNoGapPrevious = 0;
564
int nNoGapCount = gfp->internal_flags->nogap_total;
565
int nNoGapCurr = gfp->internal_flags->nogap_current;
568
uint8_t nAthType = gfp->ATHtype; /*4 bits. */
572
/* if ABR, {store bitrate <=255} else { store "-b"} */
576
nABRBitrate = gfp->VBR_mean_bitrate_kbps;
580
nABRBitrate = gfp->brate;
583
default:{ /*vbr modes*/
584
nABRBitrate = gfp->VBR_min_bitrate_kbps;
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;
599
if (gfp->findReplayGain) {
600
if (gfc->RadioGain > 0x1FE)
601
gfc->RadioGain = 0x1FE;
602
if (gfc->RadioGain < -0x1FE)
603
gfc->RadioGain = -0x1FE;
605
nRadioReplayGain = 0x2000; /* set name code */
606
nRadioReplayGain |= 0xC00; /* set originator code to `determined automatically' */
608
if (gfc->RadioGain >= 0)
609
nRadioReplayGain |= gfc->RadioGain; /* set gain adjustment */
611
nRadioReplayGain |= 0x200; /* set the sign bit */
612
nRadioReplayGain |= -gfc->RadioGain; /* set gain adjustment */
617
if(gfc->findPeakSample)
618
nPeakSignalAmplitude = abs((int)((((FLOAT8)gfc->PeakSample) / 32767.0 ) * pow(2,23) +.5));
621
if (nNoGapCount != -1)
626
if (nNoGapCurr < nNoGapCount-1)
632
nFlags = nAthType + (bExpNPsyTune << 4)
635
+ (bNoGapPrevious << 7);
641
/*stereo mode field... a bit ugly.*/
667
/*Intensity stereo : nStereoMode = 6. IS is not implemented */
669
if (gfp->in_samplerate <= 32000)
671
else if (gfp->in_samplerate ==48000)
673
else if (gfp->in_samplerate > 48000)
676
nSourceFreq = 0x01; /*default is 44100Hz. */
679
/*Check if the user overrided the default LAME behaviour with some nasty options */
681
if (gfp->short_blocks == short_block_forced ||
682
gfp->short_blocks == short_block_dispensed ||
683
((gfp->lowpassfreq == -1) && (gfp->highpassfreq == -1)) || /* "-k" */
684
(gfp->scale_left != gfp->scale_right) ||
685
gfp->disable_reservoir ||
689
gfp->in_samplerate <= 32000)
692
nMisc = nNoiseShaping
695
+ (nSourceFreq << 6);
700
fseek(fpStream, 0, SEEK_END);
701
nFilesize = ftell(fpStream);
704
nMusicLength = nFilesize - id3v2size; /*omit current frame */
706
nMusicLength-=128; /*id3v1 present. */
707
nMusicCRC = gfc->nMusicCRC;
710
/*Write all this information into the stream*/
711
CreateI4(&pbtStreamBuffer[nBytesWritten], nQuality);
714
strncpy(&pbtStreamBuffer[nBytesWritten], szVersion, 9);
717
pbtStreamBuffer[nBytesWritten] = nRevMethod ;
720
pbtStreamBuffer[nBytesWritten] = nLowpass;
723
CreateI4(&pbtStreamBuffer[nBytesWritten], nPeakSignalAmplitude);
726
CreateI2(&pbtStreamBuffer[nBytesWritten],nRadioReplayGain);
729
CreateI2(&pbtStreamBuffer[nBytesWritten],nAudiophileReplayGain);
732
pbtStreamBuffer[nBytesWritten] = nFlags;
735
if (nABRBitrate >= 255)
736
pbtStreamBuffer[nBytesWritten] = 0xFF;
738
pbtStreamBuffer[nBytesWritten] = nABRBitrate;
741
pbtStreamBuffer[nBytesWritten ] = enc_delay >> 4; /* works for win32, does it for unix? */
742
pbtStreamBuffer[nBytesWritten +1] = (enc_delay << 4) + (enc_padding >> 8);
743
pbtStreamBuffer[nBytesWritten +2] = enc_padding;
747
pbtStreamBuffer[nBytesWritten] = nMisc;
751
pbtStreamBuffer[nBytesWritten++] = 0; /*unused in rev0 */
753
CreateI2(&pbtStreamBuffer[nBytesWritten], gfp->preset);
756
CreateI4(&pbtStreamBuffer[nBytesWritten], nMusicLength);
759
CreateI2(&pbtStreamBuffer[nBytesWritten], nMusicCRC);
762
/*Calculate tag CRC.... must be done here, since it includes
763
*previous information*/
765
for (i = 0;i<nBytesWritten;i++)
766
crc = CRC_update_lookup(pbtStreamBuffer[i], crc);
768
CreateI2(&pbtStreamBuffer[nBytesWritten], crc);
771
return nBytesWritten;
774
/***********************************************************************
776
* PutVbrTag: Write final VBR tag to the file
778
* lpszFileName: filename of MP3 bit stream
779
* nVbrScale : encoder quality indicator (0..100)
780
****************************************************************************
782
int PutVbrTag(lame_global_flags *gfp,FILE *fpStream,int nVbrScale)
784
lame_internal_flags * gfc = gfp->internal_flags;
789
uint8_t btToc[NUMTOCENTRIES];
790
uint8_t pbtStreamBuffer[MAXFRAMESIZE];
795
unsigned char id3v2Header[10];
798
if (gfc->VBR_seek_table.pos <= 0)
802
/* Clear stream buffer */
803
memset(pbtStreamBuffer,0x00,sizeof(pbtStreamBuffer));
805
/* Seek to end of file*/
806
fseek(fpStream,0,SEEK_END);
809
lFileSize=ftell(fpStream);
811
/* Abort if file has zero length. Yes, it can happen :) */
816
* The VBR tag may NOT be located at the beginning of the stream.
817
* If an ID3 version 2 tag was added, then it must be skipped to write
821
/* seek to the beginning of the stream */
822
fseek(fpStream,0,SEEK_SET);
823
/* read 10 bytes in case there's an ID3 version 2 header here */
824
fread(id3v2Header,1,sizeof id3v2Header,fpStream);
825
/* does the stream begin with the ID3 version 2 file identifier? */
826
if (!strncmp((char *)id3v2Header,"ID3",3)) {
827
/* the tag size (minus the 10-byte header) is encoded into four
828
* bytes where the most significant bit is clear in each byte */
829
id3v2TagSize=(((id3v2Header[6] & 0x7f)<<21)
830
| ((id3v2Header[7] & 0x7f)<<14)
831
| ((id3v2Header[8] & 0x7f)<<7)
832
| (id3v2Header[9] & 0x7f))
833
+ sizeof id3v2Header;
835
/* no ID3 version 2 tag in this stream */
839
/* Seek to first real frame */
840
fseek(fpStream,id3v2TagSize+gfp->TotalFrameSize,SEEK_SET);
842
/* Read the header (first valid frame) */
843
fread(pbtStreamBuffer,4,1,fpStream);
845
/* the default VBR header. 48 kbps layer III, no padding, no crc */
846
/* but sampling freq, mode andy copyright/copy protection taken */
847
/* from first valid frame */
848
pbtStreamBuffer[0]=(uint8_t) 0xff;
849
abyte = (pbtStreamBuffer[1] & (char) 0xf1);
852
if (1==gfp->version) {
853
bitrate = XING_BITRATE1;
855
if (gfp->out_samplerate < 16000 )
856
bitrate = XING_BITRATE25;
858
bitrate = XING_BITRATE2;
861
if (gfp->VBR==vbr_off)
862
bitrate = gfp->brate;
864
if (gfp->free_format)
867
bbyte = 16*BitrateIndex(bitrate,gfp->version,gfp->out_samplerate);
870
/* Use as much of the info from the real frames in the
871
* Xing header: samplerate, channels, crc, etc...
873
if (gfp->version==1) {
875
pbtStreamBuffer[1]=abyte | (char) 0x0a; /* was 0x0b; */
876
abyte = pbtStreamBuffer[2] & (char) 0x0d; /* AF keep also private bit */
877
pbtStreamBuffer[2]=(char) bbyte | abyte; /* 64kbs MPEG1 frame */
880
pbtStreamBuffer[1]=abyte | (char) 0x02; /* was 0x03; */
881
abyte = pbtStreamBuffer[2] & (char) 0x0d; /* AF keep also private bit */
882
pbtStreamBuffer[2]=(char) bbyte | abyte; /* 64kbs MPEG2 frame */
885
/* Clear all TOC entries */
886
memset(btToc,0,sizeof(btToc));
888
if (gfp->free_format) {
890
for (i = 1; i < NUMTOCENTRIES; ++i)
891
btToc[i] = 255*i/100;
893
Xing_seek_table(&gfc->VBR_seek_table, btToc);
895
/*print_seeking (btToc);*/
897
/* Start writing the tag after the zero frame */
898
nStreamIndex=gfc->sideinfo_len;
899
/* note! Xing header specifies that Xing data goes in the
900
* ancillary data with NO ERROR PROTECTION. If error protecton
901
* in enabled, the Xing data still starts at the same offset,
902
* and now it is in sideinfo data block, and thus will not
903
* decode correctly by non-Xing tag aware players */
904
if (gfp->error_protection) nStreamIndex -= 2;
907
if (gfp->VBR == vbr_off)
909
pbtStreamBuffer[nStreamIndex++]=VBRTag2[0];
910
pbtStreamBuffer[nStreamIndex++]=VBRTag2[1];
911
pbtStreamBuffer[nStreamIndex++]=VBRTag2[2];
912
pbtStreamBuffer[nStreamIndex++]=VBRTag2[3];
917
pbtStreamBuffer[nStreamIndex++]=VBRTag[0];
918
pbtStreamBuffer[nStreamIndex++]=VBRTag[1];
919
pbtStreamBuffer[nStreamIndex++]=VBRTag[2];
920
pbtStreamBuffer[nStreamIndex++]=VBRTag[3];
923
/* Put header flags */
924
CreateI4(&pbtStreamBuffer[nStreamIndex],FRAMES_FLAG+BYTES_FLAG+TOC_FLAG+VBR_SCALE_FLAG);
927
/* Put Total Number of frames */
928
CreateI4(&pbtStreamBuffer[nStreamIndex],gfp->nVbrNumFrames);
931
/* Put Total file size */
932
CreateI4(&pbtStreamBuffer[nStreamIndex],(int)lFileSize);
936
memcpy(&pbtStreamBuffer[nStreamIndex],btToc,sizeof(btToc));
937
nStreamIndex+=sizeof(btToc);
940
if (gfp->error_protection) {
941
/* (jo) error_protection: add crc16 information to header */
942
CRC_writeheader(gfc, (char*)pbtStreamBuffer);
947
/*work out CRC so far: initially crc = 0 */
948
for (i = 0;i< nStreamIndex ;i++)
949
crc = CRC_update_lookup(pbtStreamBuffer[i], crc);
951
/*Put LAME VBR info*/
952
nStreamIndex+=PutLameVBR(gfp, fpStream, pbtStreamBuffer + nStreamIndex, id3v2TagSize,crc);
956
VBRTAGDATA TestHeader;
957
GetVbrTag(&TestHeader,pbtStreamBuffer);
961
/*Seek to the beginning of the stream */
962
fseek(fpStream,id3v2TagSize,SEEK_SET);
964
/* Put it all to disk again */
965
if (fwrite(pbtStreamBuffer,(unsigned int)gfp->TotalFrameSize,1,fpStream)!=1)
971
return 0; /* success */