ref: 5cea228a755a35b79ebc20b211dc4ee236c19fd9
dir: /plugins/cooledit/faad.c/
#include <windows.h>
#include <stdio.h> // FILE *
#include "filters.h" //CoolEdit
#include "faad.h"
#include "faac.h"
#include "aacinfo.h"
#define MAX_CHANNELS 2
#define QWORD __int32
typedef struct input_tag // any special vars associated with input file
{
FILE *fFile;
DWORD lSize;
QWORD len_ms;
WORD wChannels;
DWORD dwSamprate;
WORD wBitsPerSample;
char szName[256];
faacDecHandle hDecoder;
faadAACInfo file_info;
unsigned char *buffer;
DWORD full_size; // size of decoded file needed to set the length of progress bar
DWORD tagsize;
DWORD bytes_read; // from file
DWORD bytes_consumed; // by faadDecDecode
long bytes_into_buffer;
} MYINPUT;
int id3v2_tag(unsigned char *buffer)
{
if(StringComp(buffer, "ID3", 3) == 0)
{
unsigned long tagsize;
// high bit is not used
tagsize=(buffer[6] << 21) | (buffer[7] << 14) |
(buffer[8] << 7) | (buffer[9] << 0);
tagsize += 10;
return tagsize;
}
else
return 0;
}
__declspec(dllexport) BOOL FAR PASCAL FilterUnderstandsFormat(LPSTR filename)
{
WORD len;
if((len=lstrlen(filename))>4 &&
(!strcmpi(filename+len-4,".aac") ||
!strcmpi(filename+len-4,".mp4")))
return TRUE;
return FALSE;
}
__declspec(dllexport) long FAR PASCAL FilterGetFileSize(HANDLE hInput)
{
DWORD full_size;
if(hInput)
{
MYINPUT *mi;
mi=(MYINPUT *)GlobalLock(hInput);
full_size=mi->full_size;
GlobalUnlock(hInput);
}
return full_size;
}
__declspec(dllexport) DWORD FAR PASCAL FilterOptionsString(HANDLE hInput, LPSTR szString)
{
char buf[20];
if(hInput)
{
MYINPUT *mi;
mi=(MYINPUT *)GlobalLock(hInput);
lstrcpy(szString,"");
if(mi->file_info.version == 2)
lstrcat(szString,"MPEG2 - ");
else
lstrcat(szString,"MPEG4 - ");
sprintf(buf,"%lu bps\n",mi->file_info.bitrate);
lstrcat(szString,buf);
switch(mi->file_info.headertype)
{
case 0:
lstrcat(szString,"RAW\n");
return 0L;
case 1:
lstrcat(szString,"ADIF\n");
break;
case 2:
lstrcat(szString,"ADTS\n");
break;
}
switch(mi->file_info.object_type)
{
case MAIN:
lstrcat(szString,"Main");
break;
case LOW:
lstrcat(szString,"Low Complexity");
break;
case SSR:
lstrcat(szString,"SSR (unsupported)");
break;
case LTP:
lstrcat(szString,"Main LTP");
break;
}
GlobalUnlock(hInput);
}
return 1;
}
__declspec(dllexport) DWORD FAR PASCAL FilterGetFirstSpecialData(HANDLE hInput,
SPECIALDATA * psp)
{
return 0L;
}
__declspec(dllexport) DWORD FAR PASCAL FilterGetNextSpecialData(HANDLE hInput, SPECIALDATA * psp)
{ return 0; // only has 1 special data! Otherwise we would use psp->hSpecialData
// as either a counter to know which item to retrieve next, or as a
// structure with other state information in it.
}
__declspec(dllexport) void FAR PASCAL CloseFilterInput(HANDLE hInput)
{
if(hInput)
{
MYINPUT far *mi;
mi=(MYINPUT far *)GlobalLock(hInput);
if(mi->fFile)
fclose(mi->fFile);
if(mi->buffer)
free(mi->buffer);
if(mi->hDecoder)
faacDecClose(mi->hDecoder);
GlobalUnlock(hInput);
GlobalFree(hInput);
}
}
// return handle that will be passed in to close, and write routines
__declspec(dllexport) HANDLE FAR PASCAL OpenFilterInput( LPSTR lpstrFilename,
long far *lSamprate,
WORD far *wBitsPerSample,
WORD far *wChannels,
HWND hWnd,
long far *lChunkSize)
{
HANDLE hInput;
faacDecHandle hDecoder;
DWORD tmp;
//int shift;
FILE *infile;
DWORD samplerate, channels;
DWORD pos; // into the file. Needed to obtain length of file
DWORD read;
int *seek_table;
//faadAACInfo file_info;
unsigned char *buffer;
long tagsize;
faacDecConfigurationPtr config;
if(!(infile=fopen(lpstrFilename,"rb")))
return 0;
hInput=GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE|GMEM_ZEROINIT,sizeof(MYINPUT));
if(!hInput)
{
fclose(infile);
return 0;
}
else
{
MYINPUT *mi;
mi=(MYINPUT *)GlobalLock(hInput);
mi->fFile=infile;
pos=ftell(infile);
fseek(infile, 0, SEEK_END);
mi->lSize=ftell(infile);
fseek(infile, pos, SEEK_SET);
if(!(buffer=(BYTE *)malloc(768*MAX_CHANNELS)))
{
MessageBox(0, "Memory allocation error: buffer", "FAAD interface", MB_OK);
fclose(infile);
GlobalUnlock(hInput);
return 0;
}
mi->buffer=buffer;
memset(buffer, 0, 768*MAX_CHANNELS);
if(mi->lSize<768*MAX_CHANNELS)
tmp=mi->lSize;
else
tmp=768*MAX_CHANNELS;
read=fread(buffer, 1, tmp, infile);
if(read==tmp)
{
mi->bytes_read=read;
mi->bytes_into_buffer=read;
}
else
{
MessageBox(0, "fread", "FAAD interface", MB_OK);
fclose(mi->fFile);
free(mi->buffer);
GlobalUnlock(hInput);
return 0;
}
tagsize=id3v2_tag(buffer);
if(tagsize)
{
memcpy(buffer,buffer+tagsize,768*MAX_CHANNELS - tagsize);
if(mi->bytes_read+tagsize<mi->lSize)
tmp=tagsize;
else
tmp=mi->lSize-mi->bytes_read;
read=fread(buffer+mi->bytes_into_buffer, 1, tmp, mi->fFile);
if(read==tmp)
{
mi->bytes_read+=read;
mi->bytes_into_buffer+=read;
}
else
{
MessageBox(0, "fread", "FAAD interface", MB_OK);
fclose(mi->fFile);
free(mi->buffer);
GlobalUnlock(hInput);
return 0;
}
}
mi->tagsize=tagsize;
hDecoder = faacDecOpen();
if(!hDecoder)
{
MessageBox(0, "Can't init library", "FAAD interface", MB_OK);
fclose(mi->fFile);
free(mi->buffer);
GlobalUnlock(hInput);
return 0;
}
mi->hDecoder=hDecoder;
config = faacDecGetCurrentConfiguration(hDecoder);
// config->defObjectType = MAIN;
config->defSampleRate = 44100;
faacDecSetConfiguration(hDecoder, config);
if((mi->bytes_consumed=faacDecInit(hDecoder, buffer, &samplerate, &channels)) < 0)
{
MessageBox(hWnd, "Error retrieving information form input file", "FAAD interface", MB_OK);
fclose(mi->fFile);
free(mi->buffer);
faacDecClose(mi->hDecoder);
GlobalUnlock(hInput);
return 0;
}
mi->bytes_into_buffer-=mi->bytes_consumed;
// if(mi->bytes_consumed>0)
// faacDecInit reports there is an header to skip
// this operation will be done in ReadFilterInput
*lSamprate=samplerate;
*wBitsPerSample=16;
*wChannels=(WORD)channels;
*lChunkSize=sizeof(short)*1024*channels;
mi->wChannels=(WORD)channels;
mi->dwSamprate=samplerate;
mi->wBitsPerSample=*wBitsPerSample;
strcpy(mi->szName,lpstrFilename);
if(seek_table=(int *)malloc(sizeof(int)*10800))
{
get_AAC_format(mi->szName, &(mi->file_info), seek_table);
free(seek_table);
}
else
if(!mi->file_info.version)
{
fclose(mi->fFile);
free(mi->buffer);
faacDecClose(hDecoder);
GlobalUnlock(hInput);
return 0;
}
mi->len_ms=1000*((mi->lSize*8)/mi->file_info.bitrate);
if(mi->len_ms)
mi->full_size=(DWORD)(mi->len_ms*((float)mi->dwSamprate/1000)*mi->wChannels*(16/8));
else
mi->full_size=mi->lSize; // corrupted stream?
/* {
fclose(mi->fFile);
free(mi->buffer);
faacDecClose(hDecoder);
GlobalUnlock(hInput);
return 0;
}*/
GlobalUnlock(hInput);
}
return hInput;
}
#define ERROR_ReadFilterInput(msg) \
{ \
if(msg) \
MessageBox(0, msg, "FAAD interface", MB_OK); \
GlobalUnlock(hInput); \
return 0; \
} \
__declspec(dllexport) DWORD FAR PASCAL ReadFilterInput(HANDLE hInput, unsigned char far *bufout, long lBytes)
{
DWORD read,
tmp,
shorts_decoded=0;
long result=0;
unsigned char *buffer;
if(hInput)
{
MYINPUT *mi;
mi=(MYINPUT *)GlobalLock(hInput);
buffer=mi->buffer;
do
{
if(mi->bytes_consumed>0 && mi->bytes_into_buffer>=0)
{
if(mi->bytes_into_buffer)
memcpy(buffer,buffer+mi->bytes_consumed,mi->bytes_into_buffer);
if(mi->bytes_read<mi->lSize)
{
if(mi->bytes_read+mi->bytes_consumed<mi->lSize)
tmp=mi->bytes_consumed;
else
tmp=mi->lSize-mi->bytes_read;
read=fread(buffer+mi->bytes_into_buffer, 1, tmp, mi->fFile);
if(read==tmp)
{
mi->bytes_read+=read;
mi->bytes_into_buffer+=read;
}
}
else
if(mi->bytes_into_buffer)
memset(buffer+mi->bytes_into_buffer, 0, mi->bytes_consumed);
}
if(mi->bytes_into_buffer<1)
if(mi->bytes_read<mi->lSize)
ERROR_ReadFilterInput("ReadFilterInput: buffer empty!")
else
return 0;
result=faacDecDecode(mi->hDecoder, buffer, &(mi->bytes_consumed), (short*)bufout, &shorts_decoded);
mi->bytes_into_buffer-=mi->bytes_consumed;
}while(!shorts_decoded || result==FAAD_OK_CHUPDATE);
GlobalUnlock(hInput);
}
if(result==FAAD_FATAL_ERROR || result==FAAD_ERROR)
ERROR_ReadFilterInput("ReadFilterInput: FAAD_FATAL_ERROR or FAAD_ERROR");
/* if(shorts_decoded>1024*MAX_CHANNELS)
return 0;*/
return shorts_decoded*sizeof(short);
}