cfaac.cpp

来自「faac-1.25.rar音频编解码器demo」· C++ 代码 · 共 720 行 · 第 1/2 页

CPP
720
字号
#endif
			{
				// swap bytes
				for (i = 0; i < size; i++)
				{
					int s = bufi[i];
					
					buf[i] = SWAP32(s);
				}
			}
			else
				memcpy(buf,bufi,size*sizeof(u_int32_t));
		/*
		int exponent, mantissa;
		float *bufo=(float *)buf;
			
			for (i = 0; i < size; i++)
			{
				exponent=bufi[(i<<2)+3]<<1;
				if(bufi[i*4+2] & 0x80)
					exponent|=0x01;
				exponent-=126;
				mantissa=(DWORD)bufi[(i<<2)+2]<<16;
				mantissa|=(DWORD)bufi[(i<<2)+1]<<8;
				mantissa|=bufi[(i<<2)];
				bufo[i]=(float)ldexp(mantissa,exponent);
			}*/
			break;
	}
}

// *********************************************************************************************
//									Main functions
// *********************************************************************************************

void Cfaac::DisplayError(char *ProcName, char *str)
{
char buf[100]="";

	if(str && *str)
	{
		if(ProcName && *ProcName)
			sprintf(buf,"%s: ", ProcName);
		strcat(buf,str);
		MessageBox(0, buf, APP_NAME " plugin", MB_OK|MB_ICONSTOP);
	}

MYOUTPUT *mo;
	GLOBALLOCK(mo,hOutput,MYOUTPUT,return);
	mo->bytes_into_buffer=-1;
	GlobalUnlock(hOutput);
	GlobalUnlock(hOutput);
}
// *********************************************************************************************

HANDLE Cfaac::Init(LPSTR InFileName, LPSTR OutFileName,long lSamprate,WORD wBitsPerSample,WORD wChannels,long FileSize)
{
MYOUTPUT	*mo;
CMyEncCfg	cfg(false);
DWORD		samplesInput,
			maxBytesOutput;

//	if(wBitsPerSample!=8 && wBitsPerSample!=16) // 32 bit audio from cooledit is in unsupported format
//		return 0;
	if(wChannels>48)	// FAAC supports max 48 tracks!
		return NULL;

	GLOBALLOCK(mo,hOutput,MYOUTPUT,return NULL);

	// open the encoder library
	if(!(mo->hEncoder=faacEncOpen(lSamprate, wChannels, &samplesInput, &maxBytesOutput)))
		return ERROR_Init("Can't open library");

	if(!(mo->bitbuf=(unsigned char *)malloc(maxBytesOutput*sizeof(unsigned char))))
		return ERROR_Init("Memory allocation error: output buffer");

	if(!(mo->bufIn=(BYTE *)malloc(samplesInput*sizeof(int32_t))))
		return ERROR_Init("Memory allocation error: input buffer");

	if(!(mo->buf32bit=(int32_t *)malloc(samplesInput*sizeof(int32_t))))
		return ERROR_Init("Memory allocation error: 32 bit buffer");

	if(cfg.SaveMP4)// || cfg.Tag.On)
	{
	int ExtPos=0, // append new ext
		fnLen=lstrlen(OutFileName);
//		if(OutFileName[lstrlen(OutFileName)-4]=='.')
		if(	fnLen>=4 &&
			(!strcmpi(OutFileName+fnLen-4,".aac") ||
			!strcmpi(OutFileName+fnLen-4,".mp4") ||
			!strcmpi(OutFileName+fnLen-4,".m4a") ||
			!strcmpi(OutFileName+fnLen-4,".m4b"))) // no aac/mp4 ext => append new ext
			if(	(cfg.SaveMP4==1 && strcmpi(OutFileName+fnLen-4,".mp4")) ||
				(cfg.SaveMP4==2 && strcmpi(OutFileName+fnLen-4,".m4a")) ||
				(cfg.SaveMP4==3 && strcmpi(OutFileName+fnLen-4,".m4b")))
				ExtPos=4; // wrong ext => replace it
			else
				ExtPos=-1; // correct ext => no action
		if(ExtPos!=-1)
		{
			switch(cfg.SaveMP4)
			{
			case 1:	strcpy(OutFileName+fnLen-ExtPos,".mp4"); break;
			case 2: strcpy(OutFileName+fnLen-ExtPos,".m4a"); break;
			case 3: strcpy(OutFileName+fnLen-ExtPos,".m4b"); break;
			}
		FILE *f=fopen(OutFileName,"rb");
			if(f)
			{
			char buf[MAX_PATH+20];
				sprintf(buf,"Overwrite \"%s\" ?",OutFileName);
				fclose(f);
				if(MessageBox(NULL,buf,"File already exists!",MB_YESNO|MB_ICONQUESTION)==IDNO)
					return ERROR_Init(0);//"User abort");
			}
		}
	}
	mo->WriteMP4=	!strcmpi(OutFileName+lstrlen(OutFileName)-4,".mp4") ||
					!strcmpi(OutFileName+lstrlen(OutFileName)-4,".m4a") ||
					!strcmpi(OutFileName+lstrlen(OutFileName)-4,".m4b");

faacEncConfigurationPtr CurFormat=faacEncGetCurrentConfiguration(mo->hEncoder);
	CurFormat->inputFormat=FAAC_INPUT_32BIT;
/*	switch(wBitsPerSample)
	{
	case 16:
		CurFormat->inputFormat=FAAC_INPUT_16BIT;
		break;
	case 24:
		CurFormat->inputFormat=FAAC_INPUT_24BIT;
		break;
	case 32:
		CurFormat->inputFormat=FAAC_INPUT_32BIT;
		break;
	default:
		CurFormat->inputFormat=FAAC_INPUT_NULL;
		break;
	}*/
	if(!cfg.AutoCfg)
	{
	faacEncConfigurationPtr myFormat=&cfg.EncCfg;

		if(cfg.UseQuality)
		{
			CurFormat->quantqual=myFormat->quantqual;
			CurFormat->bitRate=0;//myFormat->bitRate;
		}
		else
		{
			CurFormat->bitRate=(myFormat->bitRate*1000)/wChannels;
			CurFormat->quantqual=100;
		}

		switch(CurFormat->bandWidth)
		{
		case 0: // Auto
			break;
		case 0xffffffff: // Full
			CurFormat->bandWidth=lSamprate/2;
			break;
		default:
			CurFormat->bandWidth=myFormat->bandWidth;
			break;
		}
		CurFormat->mpegVersion=myFormat->mpegVersion;
		CurFormat->outputFormat=myFormat->outputFormat;
		CurFormat->mpegVersion=myFormat->mpegVersion;
		CurFormat->aacObjectType=myFormat->aacObjectType;
		CurFormat->allowMidside=myFormat->allowMidside;
//		CurFormat->useTns=myFormat->useTns;
		CurFormat->useTns=false;
	}
	else
	{
		CurFormat->mpegVersion=DEF_MPEGVER;
		CurFormat->aacObjectType=DEF_PROFILE;
		CurFormat->allowMidside=DEF_MIDSIDE;
//		CurFormat->useTns=DEF_TNS;
		CurFormat->useTns=false;
		CurFormat->useLfe=DEF_LFE;
		CurFormat->quantqual=DEF_QUALITY;
		CurFormat->bitRate=DEF_BITRATE;
		CurFormat->bandWidth=DEF_BANDWIDTH;
		CurFormat->outputFormat=DEF_HEADER;
	}
	if(mo->WriteMP4)
		CurFormat->outputFormat=RAW;
	CurFormat->useLfe=wChannels>=6 ? 1 : 0;
	if(!faacEncSetConfiguration(mo->hEncoder, CurFormat))
		return ERROR_Init("Unsupported parameters!");

//	mo->src_size=lSize;
//	mi->dst_name=strdup(OutFileName);
	mo->Samprate=lSamprate;
	mo->BitsPerSample=wBitsPerSample;
	mo->Channels=wChannels;
	mo->samplesInput=samplesInput;
	mo->samplesInputSize=samplesInput*(mo->BitsPerSample>>3);

	mo->maxBytesOutput=maxBytesOutput;

    if(mo->WriteMP4) // Create MP4 file --------------------------------------------------------------------------
	{
    BYTE *ASC=0;
    DWORD ASCLength=0;

        if((mo->MP4File=MP4Create(OutFileName, 0, 0))==MP4_INVALID_FILE_HANDLE)
			return ERROR_Init("Can't create file");
        MP4SetTimeScale(mo->MP4File, 90000);
        mo->MP4track=MP4AddAudioTrack(mo->MP4File, lSamprate, MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
        MP4SetAudioProfileLevel(mo->MP4File, 0x0F);
        faacEncGetDecoderSpecificInfo(mo->hEncoder, &ASC, &ASCLength);
        MP4SetTrackESConfiguration(mo->MP4File, mo->MP4track, (unsigned __int8 *)ASC, ASCLength);
		mo->frameSize=samplesInput/wChannels;
		mo->ofs=mo->frameSize;

		if(cfg.TagOn)
		{
		int error=0;
#ifdef USE_IMPORT_TAG
			if(cfg.TagImport && InFileName)
			{
			int l=strlen(InFileName);
				if(	!strcmpi(InFileName+l-4,".mp4") ||
					!strcmpi(InFileName+l-4,".m4a") ||
					!strcmpi(InFileName+l-4,".m4b"))
					error=cfg.Tag.ReadMp4Tag(InFileName);
				else
					error=cfg.Tag.ReadAacTag(InFileName);
			}
#endif
			if(!error)
				cfg.Tag.WriteMP4Tag(mo->MP4File);
		}
	}
	else // Create AAC file -----------------------------------------------------------------------------
	{
		// open the aac output file 
		if(!(mo->aacFile=fopen(OutFileName, "wb")))
			return ERROR_Init("Can't create file");

		// use bufferized stream
		setvbuf(mo->aacFile,NULL,_IOFBF,32767);

		mo->InFilename=strdup(InFileName);
		mo->OutFilename=strdup(OutFileName);
	}

	showInfo(mo);

	GlobalUnlock(hOutput);
    return hOutput;
}
// *********************************************************************************************

int Cfaac::processData(HANDLE hOutput, BYTE *bufIn, DWORD len)
{
	if(!hOutput)
		return -1;

int bytesWritten=0;
int bytesEncoded;
MYOUTPUT far *mo;

	GLOBALLOCK(mo,hOutput,MYOUTPUT,return 0);

int32_t *buf=mo->buf32bit;

	if((int)len<mo->samplesInputSize)
	{
		mo->samplesInput=(len<<3)/mo->BitsPerSample;
		mo->samplesInputSize=mo->samplesInput*(mo->BitsPerSample>>3);
	}
//	if(mo->BitsPerSample==8 || mo->BitsPerSample==32)
		To32bit(buf,bufIn,mo->samplesInput,mo->BitsPerSample>>3,false);

	// call the actual encoding routine
	if((bytesEncoded=faacEncEncode(mo->hEncoder, (int32_t *)buf, mo->samplesInput, mo->bitbuf, mo->maxBytesOutput))<0)
		return ERROR_processData("faacEncEncode()");

	// write bitstream to aac file 
	if(mo->aacFile)
	{
		if(bytesEncoded>0)
		{
			if((bytesWritten=fwrite(mo->bitbuf, 1, bytesEncoded, mo->aacFile))!=bytesEncoded)
				return ERROR_processData("Write failed!");
			mo->WrittenSamples=1; // needed into destructor
		}
	}
	else
	// write bitstream to mp4 file
	{
	MP4Duration dur,
				SamplesLeft;
		if(len>0)
		{
			mo->srcSize+=len;
			dur=mo->frameSize;
		}
		else
		{
			mo->TotalSamples=(mo->srcSize<<3)/(mo->BitsPerSample*mo->Channels);
			SamplesLeft=(mo->TotalSamples-mo->WrittenSamples)+mo->frameSize;
			dur=SamplesLeft>mo->frameSize ? mo->frameSize : SamplesLeft;
		}
		if(bytesEncoded>0)
		{
			if(!(bytesWritten=MP4WriteSample(mo->MP4File, mo->MP4track, (unsigned __int8 *)mo->bitbuf, (DWORD)bytesEncoded, dur, mo->ofs, true) ? bytesEncoded : -1))
				return ERROR_processData("MP4WriteSample()");
			mo->ofs=0;
			mo->WrittenSamples+=dur;
		}
	}

	showProgress(mo);

	GlobalUnlock(hOutput);
	return bytesWritten;
}
// -----------------------------------------------------------------------------------------------

int Cfaac::processDataBufferized(HANDLE hOutput, BYTE *bufIn, long lBytes)
{
	if(!hOutput)
		return -1;

int	bytesWritten=0, tot=0;
MYOUTPUT far *mo;

	GLOBALLOCK(mo,hOutput,MYOUTPUT,return 0);

	if(mo->bytes_into_buffer>=0)
		do
		{
			if(mo->bytes_into_buffer+lBytes<mo->samplesInputSize)
			{
				memmove(mo->bufIn+mo->bytes_into_buffer, bufIn, lBytes);
				mo->bytes_into_buffer+=lBytes;
				lBytes=0;
			}
			else
			{
			int	shift=mo->samplesInputSize-mo->bytes_into_buffer;
				memmove(mo->bufIn+mo->bytes_into_buffer, bufIn, shift);
				mo->bytes_into_buffer+=shift;
				bufIn+=shift;
				lBytes-=shift;

				tot+=bytesWritten=processData(hOutput,mo->bufIn,mo->bytes_into_buffer);
				if(bytesWritten<0)
					return ERROR_processData(0);
				mo->bytes_into_buffer=0;
			}
		}while(lBytes);

	GlobalUnlock(hOutput);
	return tot;
}

⌨️ 快捷键说明

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