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

📄 vbrtag.c

📁 音频编码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* fast CRC-16 computation - uses table crc16_lookup 8*/int CRC_update_lookup(int value, int crc){	int tmp;	tmp=crc^value;	crc=(crc>>8)^crc16_lookup[tmp & 0xff];	return crc;}void UpdateMusicCRC(uint16_t *crc,unsigned char *buffer, int size){    int i;    for (i=0; i<size; ++i)         *crc = CRC_update_lookup(buffer[i],*crc);}/**************************************************************************** * Jonathan Dee 2001/08/31 * * PutLameVBR: Write LAME info: mini version + info on various switches used * Paramters: *				pbtStreamBuffer	: pointer to output buffer   *				id3v2size		: size of id3v2 tag in bytes *				crc				: computation of crc-16 of Lame Tag so far (starting at frame sync) *				 *****************************************************************************/int PutLameVBR(lame_global_flags *gfp, FILE *fpStream, uint8_t *pbtStreamBuffer, uint32_t id3v2size,  uint16_t crc){    lame_internal_flags *gfc = gfp->internal_flags;/*	FLOAT fVersion = LAME_MAJOR_VERSION + 0.01 * LAME_MINOR_VERSION; */	int nBytesWritten = 0;	int nFilesize	  = 0;		/*size of fpStream. Will be equal to size after process finishes. */	int i;    int enc_delay=lame_get_encoder_delay(gfp);       /* encoder delay */    int enc_padding=lame_get_encoder_padding(gfp);   /* encoder padding  */	/*recall:	gfp->VBR_q is for example set by the switch -V  */	/*			gfp->quality by -q, -h, -f, etc */		int nQuality		= (100 - 10 * gfp->VBR_q - gfp->quality);		const char *szVersion	= get_lame_very_short_version();	uint8_t nVBR;	uint8_t nRevision = 0x00;	uint8_t nRevMethod;	uint8_t vbr_type_translator[] = {1,5,3,2,4,0,3};		/*numbering different in vbr_mode vs. Lame tag */	uint8_t nLowpass		= ( ((gfp->lowpassfreq / 100.0)+.5) > 255 ? 255 : (gfp->lowpassfreq / 100.0)+.5 );        uint32_t nPeakSignalAmplitude = 0;  	uint16_t nRadioReplayGain		= 0; 	uint16_t nAudiophileReplayGain		= 0;	uint8_t nNoiseShaping			= gfp->internal_flags->noise_shaping;	uint8_t nStereoMode				= 0;	int		bNonOptimal				= 0;	uint8_t nSourceFreq				= 0;	uint8_t nMisc					= 0;	uint32_t nMusicLength			= 0;	int		bId3v1Present			= ((gfp->internal_flags->tag_spec.flags & CHANGED_FLAG)		&& !(gfp->internal_flags->tag_spec.flags & V2_ONLY_FLAG));	uint16_t nMusicCRC				= 0;	/*psy model type: Gpsycho or NsPsytune */	unsigned char    bExpNPsyTune	= gfp->exp_nspsytune & 1;	unsigned char	 bSafeJoint		= (gfp->exp_nspsytune & 2)!=0;	unsigned char	 bNoGapMore		= 0;	unsigned char	 bNoGapPrevious	= 0;	int		 nNoGapCount	= gfp->internal_flags->nogap_total;	int		 nNoGapCurr		= gfp->internal_flags->nogap_current;	uint8_t  nAthType		= gfp->ATHtype;	/*4 bits. */		uint8_t  nFlags			= 0;	/* if ABR, {store bitrate <=255} else { store "-b"} */	int nABRBitrate;    switch (gfp->VBR) {        case vbr_abr:{            nABRBitrate = gfp->VBR_mean_bitrate_kbps;            break;        }        case vbr_off:{            nABRBitrate = gfp->brate;            break;        }        default:{ /*vbr modes*/            nABRBitrate = gfp->VBR_min_bitrate_kbps;        }    }        	/*revision and vbr method */	if (gfp->VBR>=0 && gfp->VBR < sizeof(vbr_type_translator))		nVBR = vbr_type_translator[gfp->VBR];	else		nVBR = 0x00;		/*unknown. */	nRevMethod = 0x10 * nRevision + nVBR; 	/* ReplayGain */	if (gfc->findReplayGain) { 	  if (gfc->RadioGain > 0x1FE)	    gfc->RadioGain = 0x1FE;	  if (gfc->RadioGain < -0x1FE)	    gfc->RadioGain = -0x1FE;	  nRadioReplayGain = 0x2000; /* set name code */	  nRadioReplayGain |= 0xC00; /* set originator code to `determined automatically' */	  if (gfc->RadioGain >= 0) 	    nRadioReplayGain |= gfc->RadioGain; /* set gain adjustment */	  else {            nRadioReplayGain |= 0x200; /* set the sign bit */	    nRadioReplayGain |= -gfc->RadioGain; /* set gain adjustment */	  }	}        /* peak sample */	        if(gfc->findPeakSample)          nPeakSignalAmplitude = abs((int)((((FLOAT)gfc->PeakSample) / 32767.0 ) * pow(2,23) +.5));	/*nogap */	if (nNoGapCount != -1)	{		if (nNoGapCurr > 0)			bNoGapPrevious = 1;		if (nNoGapCurr < nNoGapCount-1)			bNoGapMore = 1;	}	/*flags */	nFlags	= nAthType	+ (bExpNPsyTune		<< 4)						+ (bSafeJoint		<< 5)						+ (bNoGapMore		<< 6)						+ (bNoGapPrevious	<< 7);	if (nQuality < 0)		nQuality = 0;	/*stereo mode field... a bit ugly.*/	switch(gfp->mode)	{	case MONO:		nStereoMode = 0;		break;	case STEREO:		nStereoMode = 1;		break;	case DUAL_CHANNEL:		nStereoMode = 2;		break;	case JOINT_STEREO:		if (gfp->force_ms)			nStereoMode = 4;		else			nStereoMode = 3;		break;	case NOT_SET:	    /* FALLTHROUGH */	default:		nStereoMode = 7;		break;	}	/*Intensity stereo : nStereoMode = 6. IS is not implemented */	if (gfp->in_samplerate <= 32000)		nSourceFreq = 0x00;	else if (gfp->in_samplerate ==48000)		nSourceFreq = 0x02;	else if (gfp->in_samplerate > 48000)		nSourceFreq = 0x03;	else		nSourceFreq = 0x01;  /*default is 44100Hz. */	/*Check if the user overrided the default LAME behaviour with some nasty options */	if (gfp->short_blocks == short_block_forced 			||		gfp->short_blocks == short_block_dispensed 		||		((gfp->lowpassfreq == -1) && (gfp->highpassfreq == -1))	|| /* "-k" */		(gfp->scale_left != gfp->scale_right)			||		(gfp->disable_reservoir	 && gfp->brate < 320)	||		gfp->noATH			||		gfp->ATHonly			||		(nAthType == 0)    ||		gfp->in_samplerate <= 32000)			bNonOptimal = 1;		nMisc =		nNoiseShaping			+	(nStereoMode << 2)			+	(bNonOptimal << 5)			+	(nSourceFreq << 6);		/*get filesize */	fseek(fpStream, 0, SEEK_END);	nFilesize = ftell(fpStream);		nMusicLength = nFilesize - id3v2size;		/*omit current frame */	if (bId3v1Present)		nMusicLength-=128;                     /*id3v1 present. */        nMusicCRC = gfc->nMusicCRC;	/*Write all this information into the stream*/	CreateI4(&pbtStreamBuffer[nBytesWritten], nQuality);	nBytesWritten+=4;	strncpy(&pbtStreamBuffer[nBytesWritten], szVersion, 9);	nBytesWritten+=9;	pbtStreamBuffer[nBytesWritten] = nRevMethod ;	nBytesWritten++;	pbtStreamBuffer[nBytesWritten] = nLowpass;	nBytesWritten++;	CreateI4(&pbtStreamBuffer[nBytesWritten], nPeakSignalAmplitude);	nBytesWritten+=4;	CreateI2(&pbtStreamBuffer[nBytesWritten],nRadioReplayGain);	nBytesWritten+=2;	CreateI2(&pbtStreamBuffer[nBytesWritten],nAudiophileReplayGain);	nBytesWritten+=2;	pbtStreamBuffer[nBytesWritten] = nFlags;	nBytesWritten++;	if (nABRBitrate >= 255)		pbtStreamBuffer[nBytesWritten] = 0xFF;	else		pbtStreamBuffer[nBytesWritten] = nABRBitrate;	nBytesWritten++;        pbtStreamBuffer[nBytesWritten   ] = enc_delay >> 4; /* works for win32, does it for unix? */        pbtStreamBuffer[nBytesWritten +1] = (enc_delay << 4) + (enc_padding >> 8);        pbtStreamBuffer[nBytesWritten +2] = enc_padding;	nBytesWritten+=3;	pbtStreamBuffer[nBytesWritten] = nMisc;	nBytesWritten++;	pbtStreamBuffer[nBytesWritten++] = 0;	/*unused in rev0 */	CreateI2(&pbtStreamBuffer[nBytesWritten], gfp->preset);	nBytesWritten+=2;	CreateI4(&pbtStreamBuffer[nBytesWritten], nMusicLength);	nBytesWritten+=4;	CreateI2(&pbtStreamBuffer[nBytesWritten], nMusicCRC);	nBytesWritten+=2;	/*Calculate tag CRC.... must be done here, since it includes	 *previous information*/		for (i = 0;i<nBytesWritten;i++)		crc = CRC_update_lookup(pbtStreamBuffer[i], crc);		CreateI2(&pbtStreamBuffer[nBytesWritten], crc);	nBytesWritten+=2;	return nBytesWritten;}/*********************************************************************** *  * PutVbrTag: Write final VBR tag to the file * Paramters: *				lpszFileName: filename of MP3 bit stream *				nVbrScale	: encoder quality indicator (0..100) *****************************************************************************/int PutVbrTag(lame_global_flags *gfp,FILE *fpStream,int nVbrScale){    lame_internal_flags * gfc = gfp->internal_flags;	long lFileSize;	int nStreamIndex;	char abyte,bbyte;	uint8_t		btToc[NUMTOCENTRIES];	uint8_t pbtStreamBuffer[MAXFRAMESIZE];		int i;	uint16_t crc = 0x00;	    unsigned char id3v2Header[10];    size_t id3v2TagSize;    if (gfc->VBR_seek_table.pos <= 0)	return -1;	/* Clear stream buffer */	memset(pbtStreamBuffer,0x00,sizeof(pbtStreamBuffer));	/* Seek to end of file*/	fseek(fpStream,0,SEEK_END);	/* Get file size */	lFileSize=ftell(fpStream);	/* Abort if file has zero length. Yes, it can happen :) */	if (lFileSize==0)		return -1;        /*         * The VBR tag may NOT be located at the beginning of the stream.         * If an ID3 version 2 tag was added, then it must be skipped to write         * the VBR tag data.         */        /* seek to the beginning of the stream */	fseek(fpStream,0,SEEK_SET);        /* read 10 bytes in case there's an ID3 version 2 header here */        fread(id3v2Header,1,sizeof id3v2Header,fpStream);        /* does the stream begin with the ID3 version 2 file identifier? */        if (!strncmp((char *)id3v2Header,"ID3",3)) {          /* the tag size (minus the 10-byte header) is encoded into four           * bytes where the most significant bit is clear in each byte */          id3v2TagSize=(((id3v2Header[6] & 0x7f)<<21)            | ((id3v2Header[7] & 0x7f)<<14)            | ((id3v2Header[8] & 0x7f)<<7)            | (id3v2Header[9] & 0x7f))            + sizeof id3v2Header;        } else {          /* no ID3 version 2 tag in this stream */          id3v2TagSize=0;        }	/* Seek to first real frame */	fseek(fpStream,id3v2TagSize+gfp->TotalFrameSize,SEEK_SET);	/* Read the header (first valid frame) */	fread(pbtStreamBuffer,4,1,fpStream);	/* the default VBR header. 48 kbps layer III, no padding, no crc */	/* but sampling freq, mode andy copyright/copy protection taken */	/* from first valid frame */	pbtStreamBuffer[0]=(uint8_t) 0xff;	abyte = (pbtStreamBuffer[1] & (char) 0xf1);	{			int bitrate;		if (1==gfp->version) {		  bitrate = XING_BITRATE1;		} else {		  if (gfp->out_samplerate < 16000 )			bitrate = XING_BITRATE25;		  else			bitrate = XING_BITRATE2;		}				if (gfp->VBR==vbr_off)			bitrate = gfp->brate;                if (gfp->free_format)            bbyte = 0x00;        else		    bbyte = 16*BitrateIndex(bitrate,gfp->version,gfp->out_samplerate);	}	/* Use as much of the info from the real frames in the	 * Xing header:  samplerate, channels, crc, etc...	 */ 	if (gfp->version==1) {	  /* MPEG1 */	  pbtStreamBuffer[1]=abyte | (char) 0x0a;     /* was 0x0b; */	  abyte = pbtStreamBuffer[2] & (char) 0x0d;   /* AF keep also private bit */	  pbtStreamBuffer[2]=(char) bbyte | abyte;     /* 64kbs MPEG1 frame */	}else{	  /* MPEG2 */	  pbtStreamBuffer[1]=abyte | (char) 0x02;     /* was 0x03; */	  abyte = pbtStreamBuffer[2] & (char) 0x0d;   /* AF keep also private bit */	  pbtStreamBuffer[2]=(char) bbyte | abyte;     /* 64kbs MPEG2 frame */	}	/* Clear all TOC entries */	memset(btToc,0,sizeof(btToc));    if (gfp->free_format) {        int i;        for (i = 1; i < NUMTOCENTRIES; ++i)            btToc[i] = 255*i/100;    } else {        Xing_seek_table(&gfc->VBR_seek_table, btToc);    }    /*print_seeking (btToc);*/	/* Start writing the tag after the zero frame */	nStreamIndex=gfc->sideinfo_len;	/* note! Xing header specifies that Xing data goes in the	 * ancillary data with NO ERROR PROTECTION.  If error protecton	 * in enabled, the Xing data still starts at the same offset,	 * and now it is in sideinfo data block, and thus will not	 * decode correctly by non-Xing tag aware players */	if (gfp->error_protection) nStreamIndex -= 2;	/* Put Vbr tag */	if (gfp->VBR == vbr_off)	{		pbtStreamBuffer[nStreamIndex++]=VBRTag1[0];		pbtStreamBuffer[nStreamIndex++]=VBRTag1[1];		pbtStreamBuffer[nStreamIndex++]=VBRTag1[2];		pbtStreamBuffer[nStreamIndex++]=VBRTag1[3];	}	else	{		pbtStreamBuffer[nStreamIndex++]=VBRTag0[0];		pbtStreamBuffer[nStreamIndex++]=VBRTag0[1];		pbtStreamBuffer[nStreamIndex++]=VBRTag0[2];		pbtStreamBuffer[nStreamIndex++]=VBRTag0[3];	}		/* Put header flags */	CreateI4(&pbtStreamBuffer[nStreamIndex],FRAMES_FLAG+BYTES_FLAG+TOC_FLAG+VBR_SCALE_FLAG);	nStreamIndex+=4;	/* Put Total Number of frames */	CreateI4(&pbtStreamBuffer[nStreamIndex],gfp->nVbrNumFrames);	nStreamIndex+=4;	/* Put Total file size */	CreateI4(&pbtStreamBuffer[nStreamIndex],(int)lFileSize);	nStreamIndex+=4;	/* Put TOC */	memcpy(&pbtStreamBuffer[nStreamIndex],btToc,sizeof(btToc));	nStreamIndex+=sizeof(btToc);	if (gfp->error_protection) {	  /* (jo) error_protection: add crc16 information to header */	  CRC_writeheader(gfc, (char*)pbtStreamBuffer);	}	/*work out CRC so far: initially crc = 0 */	for (i = 0;i< nStreamIndex ;i++)		crc = CRC_update_lookup(pbtStreamBuffer[i], crc);	/*Put LAME VBR info*/	nStreamIndex+=PutLameVBR(gfp, fpStream, pbtStreamBuffer + nStreamIndex, id3v2TagSize,crc);#ifdef DEBUG_VBRTAG	{	  VBRTAGDATA TestHeader;	  GetVbrTag(&TestHeader,pbtStreamBuffer);	}#endif	/*Seek to the beginning of the stream */	fseek(fpStream,id3v2TagSize,SEEK_SET);        /* Put it all to disk again */	if (fwrite(pbtStreamBuffer,(unsigned int)gfp->TotalFrameSize,1,fpStream)!=1)	{		return -1;	}	return 0;       /* success */}

⌨️ 快捷键说明

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