"Fossies" - the Fresh Open Source Software Archive

Member "faac-1_30/common/Cfaac/Cfaac.cpp" (16 Oct 2019, 19383 Bytes) of package /linux/misc/faac-1_30.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Cfaac.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2 CFAAC - set of classes to import/export .aac/.mp4 files
    3 Copyright (C) 2004 Antonio Foranna
    4 
    5 This program is free software; you can redistribute it and/or modify
    6 it under the terms of the GNU General Public License as published by
    7 the Free Software Foundation.
    8     
    9 This program is distributed in the hope that it will be useful,
   10 but WITHOUT ANY WARRANTY; without even the implied warranty of
   11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12 GNU General Public License for more details.
   13         
   14 You should have received a copy of the GNU General Public License
   15 along with this program; if not, write to the Free Software
   16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   17             
   18 The author can be contacted at:
   19 ntnfrn_email-temp@yahoo.it
   20 */
   21 
   22 #include "Cfaac.h"
   23 
   24 
   25 
   26 // *********************************************************************************************
   27 //                                      CMyEncCfg
   28 // *********************************************************************************************
   29 
   30 void CMyEncCfg::getCfg(CMyEncCfg *cfg)
   31 { 
   32 CRegistry reg;
   33 
   34     if(reg.OpenCreate(HKEY_CURRENT_USER, REGISTRY_PROGRAM_NAME "\\FAAC"))
   35     {
   36         cfg->AutoCfg=reg.GetSetBool(REG_AUTO,DEF_AUTO);
   37         cfg->SaveMP4=reg.GetSetByte(REG_WRITEMP4,DEF_WRITEMP4);
   38         cfg->EncCfg.mpegVersion=reg.GetSetDword(REG_MPEGVER,DEF_MPEGVER); 
   39         cfg->EncCfg.aacObjectType=reg.GetSetDword(REG_PROFILE,DEF_PROFILE); 
   40         cfg->EncCfg.allowMidside=reg.GetSetDword(REG_MIDSIDE,DEF_MIDSIDE); 
   41         cfg->EncCfg.useTns=reg.GetSetDword(REG_TNS,DEF_TNS); 
   42         cfg->EncCfg.useLfe=reg.GetSetDword(REG_LFE,DEF_LFE);
   43         cfg->UseQuality=reg.GetSetBool(REG_USEQUALTY,DEF_USEQUALTY);
   44         cfg->EncCfg.quantqual=reg.GetSetDword(REG_QUALITY,DEF_QUALITY); 
   45         cfg->EncCfg.bitRate=reg.GetSetDword(REG_BITRATE,DEF_BITRATE); 
   46         cfg->EncCfg.bandWidth=reg.GetSetDword(REG_BANDWIDTH,DEF_BANDWIDTH); 
   47         cfg->EncCfg.outputFormat=reg.GetSetDword(REG_HEADER,DEF_HEADER); 
   48 
   49         FREE_ARRAY(cfg->OutDir);
   50         cfg->OutDir=reg.GetSetStr(REG_OutFolder,"");
   51 
   52         cfg->TagOn=reg.GetSetByte(REG_TAGON,0);
   53 #ifdef USE_IMPORT_TAG
   54         cfg->TagImport=reg.GetSetByte(REG_TAGIMPORT,0);
   55     #ifdef USE_PATHEXT
   56         FREE_ARRAY(cfg->TagSrcPath);
   57         FREE_ARRAY(cfg->TagSrcExt);
   58         cfg->TagSrcPath=reg.GetSetStr(REG_InFolder,"");
   59         cfg->TagSrcExt=reg.GetSetStr(REG_SrcExt,"");
   60     #endif
   61 #endif
   62         cfg->Tag.artist=reg.GetSetStr(REG_ARTIST,"");
   63         cfg->Tag.title=reg.GetSetStr(REG_TITLE,"");
   64         cfg->Tag.album=reg.GetSetStr(REG_ALBUM,"");
   65         cfg->Tag.year=reg.GetSetStr(REG_YEAR,"");
   66         cfg->Tag.genre=reg.GetSetStr(REG_GENRE,"");
   67         cfg->Tag.writer=reg.GetSetStr(REG_WRITER,"");
   68         cfg->Tag.comment=reg.GetSetStr(REG_COMMENT,"");
   69         cfg->Tag.trackno=reg.GetSetWord(REG_TRACK,0);
   70         cfg->Tag.ntracks=reg.GetSetWord(REG_NTRACKS,0);
   71         cfg->Tag.discno=reg.GetSetWord(REG_DISK,0);
   72         cfg->Tag.ndiscs=reg.GetSetWord(REG_NDISKS,0);
   73         cfg->Tag.compilation=reg.GetSetByte(REG_COMPILATION,0);
   74         cfg->Tag.artFilename=reg.GetSetStr(REG_ARTFILE,"");
   75     }
   76     else
   77         MessageBox(0,"Can't open registry!",0,MB_OK|MB_ICONSTOP);
   78 }
   79 // -----------------------------------------------------------------------------------------------
   80 
   81 void CMyEncCfg::setCfg(CMyEncCfg *cfg)
   82 { 
   83 CRegistry reg;
   84 
   85     if(reg.OpenCreate(HKEY_CURRENT_USER, REGISTRY_PROGRAM_NAME "\\FAAC"))
   86     {
   87         reg.SetBool(REG_AUTO,cfg->AutoCfg);
   88         reg.SetByte(REG_WRITEMP4,cfg->SaveMP4);
   89         reg.SetDword(REG_MPEGVER,cfg->EncCfg.mpegVersion);
   90         reg.SetDword(REG_PROFILE,cfg->EncCfg.aacObjectType);
   91         reg.SetDword(REG_MIDSIDE,cfg->EncCfg.allowMidside);
   92         reg.SetDword(REG_TNS,cfg->EncCfg.useTns);
   93         reg.SetDword(REG_LFE,cfg->EncCfg.useLfe);
   94         reg.SetBool(REG_USEQUALTY,cfg->UseQuality);
   95         reg.SetDword(REG_QUALITY,cfg->EncCfg.quantqual);
   96         reg.SetDword(REG_BITRATE,cfg->EncCfg.bitRate);
   97         reg.SetDword(REG_BANDWIDTH,cfg->EncCfg.bandWidth);
   98         reg.SetDword(REG_HEADER,cfg->EncCfg.outputFormat);
   99 
  100         reg.SetStr(REG_OutFolder,cfg->OutDir);
  101 
  102         reg.SetByte(REG_TAGON,cfg->TagOn);
  103 #ifdef USE_IMPORT_TAG
  104         reg.SetByte(REG_TAGIMPORT,cfg->TagImport);
  105     #ifdef USE_PATHEXT
  106         reg.SetStr(REG_InFolder,cfg->TagSrcPath);
  107         reg.SetStr(REG_SrcExt,cfg->TagSrcExt);
  108     #endif
  109 #endif
  110         reg.SetStr(REG_ARTIST,cfg->Tag.artist);
  111         reg.SetStr(REG_TITLE,cfg->Tag.title);
  112         reg.SetStr(REG_ALBUM,cfg->Tag.album);
  113         reg.SetStr(REG_YEAR,cfg->Tag.year);
  114         reg.SetStr(REG_GENRE,cfg->Tag.genre);
  115         reg.SetStr(REG_WRITER,cfg->Tag.writer);
  116         reg.SetStr(REG_COMMENT,cfg->Tag.comment);
  117         reg.SetWord(REG_TRACK,cfg->Tag.trackno);
  118         reg.SetWord(REG_NTRACKS,cfg->Tag.ntracks);
  119         reg.SetWord(REG_DISK,cfg->Tag.discno);
  120         reg.SetWord(REG_NDISKS,cfg->Tag.ndiscs);
  121         reg.SetByte(REG_COMPILATION,cfg->Tag.compilation);
  122         reg.SetStr(REG_ARTFILE,cfg->Tag.artFilename);
  123     }
  124     else
  125         MessageBox(0,"Can't open registry!",0,MB_OK|MB_ICONSTOP);
  126 }
  127 
  128 // *********************************************************************************************
  129 //                                          Cfaac
  130 // *********************************************************************************************
  131 
  132 
  133 
  134 Cfaac::Cfaac(HANDLE hOut)
  135 {
  136     if(hOut)
  137     {
  138         hOutput=hOut;
  139         return;
  140     }
  141 
  142     if(!(hOutput=GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE|GMEM_ZEROINIT,sizeof(MYOUTPUT))))
  143     {
  144         MessageBox(0, "Memory allocation error: hOutput", APP_NAME " plugin", MB_OK|MB_ICONSTOP); \
  145         return;
  146     }
  147 //  dontAskGetFilename=false;
  148 }
  149 // -----------------------------------------------------------------------------------------------
  150 
  151 Cfaac::~Cfaac()
  152 {
  153     if(!hOutput)
  154         return;
  155 
  156 MYOUTPUT *mo;
  157 
  158     GLOBALLOCK(mo,hOutput,MYOUTPUT,return);
  159     
  160     if(mo->WrittenSamples)
  161     {
  162     int BytesWritten;
  163         if(mo->bytes_into_buffer>0)
  164             memset(mo->bufIn+mo->bytes_into_buffer, 0, (mo->samplesInput*(mo->BitsPerSample>>3))-mo->bytes_into_buffer);
  165         do
  166         {
  167             if((BytesWritten=processData(hOutput,mo->bufIn,mo->bytes_into_buffer))<0)
  168                 MessageBox(0, "~Cfaac: processData", APP_NAME " plugin", MB_OK|MB_ICONSTOP);
  169             mo->bytes_into_buffer=0;
  170         }while(BytesWritten>0);
  171     }
  172 
  173     if(mo->aacFile)
  174     {
  175         fclose(mo->aacFile);
  176         mo->aacFile=0;
  177 
  178     CMyEncCfg cfg(false);
  179         if(cfg.TagOn && mo->OutFilename)
  180         {
  181         int error=0;
  182 #ifdef USE_IMPORT_TAG
  183             if(cfg.TagImport && mo->InFilename)
  184             {
  185             int l=strlen(mo->InFilename);
  186                 if( !strcmpi(mo->InFilename+l-4,".mp4") ||
  187                     !strcmpi(mo->InFilename+l-4,".m4a") ||
  188                     !strcmpi(mo->InFilename+l-4,".m4b"))
  189                     error=cfg.Tag.ReadMp4Tag(mo->InFilename);
  190                 else
  191                     error=cfg.Tag.ReadAacTag(mo->InFilename);
  192             }
  193 #endif
  194             if(!error)
  195                 cfg.Tag.WriteAacTag(mo->OutFilename);
  196         }
  197     }
  198     else
  199     {
  200         MP4Close(mo->MP4File);
  201         mo->MP4File=0;
  202     }
  203     
  204     if(mo->hEncoder)
  205         faacEncClose(mo->hEncoder);
  206     
  207     FREE_ARRAY(mo->bitbuf)
  208     FREE_ARRAY(mo->buf32bit)
  209     FREE_ARRAY(mo->bufIn)
  210 
  211     FREE_ARRAY(mo->OutFilename)
  212     FREE_ARRAY(mo->InFilename)
  213 
  214     GlobalUnlock(hOutput);
  215     GlobalFree(hOutput);
  216 }
  217 
  218 // *********************************************************************************************
  219 //                                  Utilities
  220 // *********************************************************************************************
  221 
  222 char *Cfaac::getSourceFilename(char *path, char *src, char *ext)
  223 {
  224 char    *dst, chExt,
  225         *pname, *pext;
  226 
  227 
  228     if(!src)
  229         return NULL;
  230     if(!path)
  231         path="";
  232     if(!ext)
  233         ext="";
  234     pname=pext=src+strlen(src);
  235 
  236     while(pname!=src && *pname!='\\' && *pname!='/')
  237         pname--;
  238     if(*pname=='\\' || *pname=='/')
  239         pname++;
  240     while(pext!=src && *pext!='.')
  241         pext--;
  242     chExt=*pext;
  243     if(chExt=='.')
  244         *pext='\0';
  245 
  246     if(*path)
  247     {
  248     int l;
  249         if(!(dst=(char *)malloc(strlen(path)+strlen(pname)+strlen(ext)+3))) // '\0','\\','.'
  250             return dst;
  251         l=strlen(path);
  252         if(l>0 && path[l-1]=='\\')
  253             sprintf(dst,"%s%s.%s",path,pname,ext);
  254         else
  255             sprintf(dst,"%s\\%s.%s",path,pname,ext);
  256     }
  257     else
  258     {
  259         if(!(dst=(char *)malloc(strlen(pname)+strlen(ext)+2)))
  260             return dst;
  261         sprintf(dst,"%s.%s",pname,ext);
  262     }
  263     *pext=chExt;
  264 
  265     if(!strcmpi(src,dst))
  266     {
  267 //      if(!dontAskGetFilename)
  268         {
  269         char buf[MAX_PATH+100];
  270             sprintf(buf,"%s\nSource file=Destination file...aborting!\n\n\tSuppress this warning?",dst);
  271 //          if(MessageBox(NULL,buf,NULL,MB_YESNO)==IDYES)
  272 //              dontAskGetFilename=true;
  273         }
  274         FREE_ARRAY(dst);
  275         return NULL;
  276     }
  277 
  278     return dst;
  279 }
  280 // *********************************************************************************************
  281 
  282 #define SWAP32(x) (((x & 0xff) << 24) | ((x & 0xff00) << 8) \
  283     | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24))
  284 #define SWAP16(x) (((x & 0xff) << 8) | ((x & 0xff00) >> 8))
  285 
  286 void Cfaac::To32bit(int32_t *buf, BYTE *bufi, int size, BYTE samplebytes, BYTE bigendian)
  287 {
  288 int i;
  289 
  290     switch(samplebytes)
  291     {
  292     case 1:
  293         // this is endian clean
  294         for (i = 0; i < size; i++)
  295             buf[i] = (bufi[i] - 128) * 65536;
  296         break;
  297         
  298     case 2:
  299 #ifdef WORDS_BIGENDIAN
  300         if (!bigendian)
  301 #else
  302             if (bigendian)
  303 #endif
  304             {
  305                 // swap bytes
  306                 for (i = 0; i < size; i++)
  307                 {
  308                     int16_t s = ((int16_t *)bufi)[i];
  309                     
  310                     s = SWAP16(s);
  311                     
  312                     buf[i] = ((uint32_t)s) << 8;
  313                 }
  314             }
  315             else
  316             {
  317                 // no swap
  318                 for (i = 0; i < size; i++)
  319                 {
  320                     int s = ((int16_t *)bufi)[i];
  321                     
  322                     buf[i] = s << 8;
  323                 }
  324             }
  325             break;
  326             
  327     case 3:
  328         if (!bigendian)
  329         {
  330             for (i = 0; i < size; i++)
  331             {
  332                 int s = bufi[3 * i] | (bufi[3 * i + 1] << 8) | (bufi[3 * i + 2] << 16);
  333                 
  334                 // fix sign
  335                 if (s & 0x800000)
  336                     s |= 0xff000000;
  337                 
  338                 buf[i] = s;
  339             }
  340         }
  341         else // big endian input
  342         {
  343             for (i = 0; i < size; i++)
  344             {
  345                 int s = (bufi[3 * i] << 16) | (bufi[3 * i + 1] << 8) | bufi[3 * i + 2];
  346                 
  347                 // fix sign
  348                 if (s & 0x800000)
  349                     s |= 0xff000000;
  350                 
  351                 buf[i] = s;
  352             }
  353         }
  354         break;
  355         
  356     case 4:     
  357 #ifdef WORDS_BIGENDIAN
  358         if (!bigendian)
  359 #else
  360             if (bigendian)
  361 #endif
  362             {
  363                 // swap bytes
  364                 for (i = 0; i < size; i++)
  365                 {
  366                     int s = bufi[i];
  367                     
  368                     buf[i] = SWAP32(s);
  369                 }
  370             }
  371             else
  372                 memcpy(buf,bufi,size*sizeof(uint32_t));
  373         /*
  374         int exponent, mantissa;
  375         float *bufo=(float *)buf;
  376             
  377             for (i = 0; i < size; i++)
  378             {
  379                 exponent=bufi[(i<<2)+3]<<1;
  380                 if(bufi[i*4+2] & 0x80)
  381                     exponent|=0x01;
  382                 exponent-=126;
  383                 mantissa=(DWORD)bufi[(i<<2)+2]<<16;
  384                 mantissa|=(DWORD)bufi[(i<<2)+1]<<8;
  385                 mantissa|=bufi[(i<<2)];
  386                 bufo[i]=(float)ldexp(mantissa,exponent);
  387             }*/
  388             break;
  389     }
  390 }
  391 
  392 // *********************************************************************************************
  393 //                                  Main functions
  394 // *********************************************************************************************
  395 
  396 void Cfaac::DisplayError(char *ProcName, char *str)
  397 {
  398 char buf[100]="";
  399 
  400     if(str && *str)
  401     {
  402         if(ProcName && *ProcName)
  403             sprintf(buf,"%s: ", ProcName);
  404         strcat(buf,str);
  405         MessageBox(0, buf, APP_NAME " plugin", MB_OK|MB_ICONSTOP);
  406     }
  407 
  408 MYOUTPUT *mo;
  409     GLOBALLOCK(mo,hOutput,MYOUTPUT,return);
  410     mo->bytes_into_buffer=-1;
  411     GlobalUnlock(hOutput);
  412     GlobalUnlock(hOutput);
  413 }
  414 // *********************************************************************************************
  415 
  416 HANDLE Cfaac::Init(LPSTR InFileName, LPSTR OutFileName,long lSamprate,WORD wBitsPerSample,WORD wChannels,long FileSize)
  417 {
  418 MYOUTPUT    *mo;
  419 CMyEncCfg   cfg(false);
  420 DWORD       samplesInput,
  421             maxBytesOutput;
  422 
  423 //  if(wBitsPerSample!=8 && wBitsPerSample!=16) // 32 bit audio from cooledit is in unsupported format
  424 //      return 0;
  425     if(wChannels>48)    // FAAC supports max 48 tracks!
  426         return NULL;
  427 
  428     GLOBALLOCK(mo,hOutput,MYOUTPUT,return NULL);
  429 
  430     // open the encoder library
  431     if(!(mo->hEncoder=faacEncOpen(lSamprate, wChannels, &samplesInput, &maxBytesOutput)))
  432         return ERROR_Init("Can't open library");
  433 
  434     if(!(mo->bitbuf=(unsigned char *)malloc(maxBytesOutput*sizeof(unsigned char))))
  435         return ERROR_Init("Memory allocation error: output buffer");
  436 
  437     if(!(mo->bufIn=(BYTE *)malloc(samplesInput*sizeof(int32_t))))
  438         return ERROR_Init("Memory allocation error: input buffer");
  439 
  440     if(!(mo->buf32bit=(int32_t *)malloc(samplesInput*sizeof(int32_t))))
  441         return ERROR_Init("Memory allocation error: 32 bit buffer");
  442 
  443     if(cfg.SaveMP4)// || cfg.Tag.On)
  444     {
  445     int ExtPos=0, // append new ext
  446         fnLen=lstrlen(OutFileName);
  447 //      if(OutFileName[lstrlen(OutFileName)-4]=='.')
  448         if( fnLen>=4 &&
  449             (!strcmpi(OutFileName+fnLen-4,".aac") ||
  450             !strcmpi(OutFileName+fnLen-4,".mp4") ||
  451             !strcmpi(OutFileName+fnLen-4,".m4a") ||
  452             !strcmpi(OutFileName+fnLen-4,".m4b"))) // no aac/mp4 ext => append new ext
  453             if( (cfg.SaveMP4==1 && strcmpi(OutFileName+fnLen-4,".mp4")) ||
  454                 (cfg.SaveMP4==2 && strcmpi(OutFileName+fnLen-4,".m4a")) ||
  455                 (cfg.SaveMP4==3 && strcmpi(OutFileName+fnLen-4,".m4b")))
  456                 ExtPos=4; // wrong ext => replace it
  457             else
  458                 ExtPos=-1; // correct ext => no action
  459         if(ExtPos!=-1)
  460         {
  461             switch(cfg.SaveMP4)
  462             {
  463             case 1: strcpy(OutFileName+fnLen-ExtPos,".mp4"); break;
  464             case 2: strcpy(OutFileName+fnLen-ExtPos,".m4a"); break;
  465             case 3: strcpy(OutFileName+fnLen-ExtPos,".m4b"); break;
  466             }
  467         FILE *f=fopen(OutFileName,"rb");
  468             if(f)
  469             {
  470             char buf[MAX_PATH+20];
  471                 sprintf(buf,"Overwrite \"%s\" ?",OutFileName);
  472                 fclose(f);
  473                 if(MessageBox(NULL,buf,"File already exists!",MB_YESNO|MB_ICONQUESTION)==IDNO)
  474                     return ERROR_Init(0);//"User abort");
  475             }
  476         }
  477     }
  478     mo->WriteMP4=   !strcmpi(OutFileName+lstrlen(OutFileName)-4,".mp4") ||
  479                     !strcmpi(OutFileName+lstrlen(OutFileName)-4,".m4a") ||
  480                     !strcmpi(OutFileName+lstrlen(OutFileName)-4,".m4b");
  481 
  482 faacEncConfigurationPtr CurFormat=faacEncGetCurrentConfiguration(mo->hEncoder);
  483     CurFormat->inputFormat=FAAC_INPUT_32BIT;
  484 /*  switch(wBitsPerSample)
  485     {
  486     case 16:
  487         CurFormat->inputFormat=FAAC_INPUT_16BIT;
  488         break;
  489     case 24:
  490         CurFormat->inputFormat=FAAC_INPUT_24BIT;
  491         break;
  492     case 32:
  493         CurFormat->inputFormat=FAAC_INPUT_32BIT;
  494         break;
  495     default:
  496         CurFormat->inputFormat=FAAC_INPUT_NULL;
  497         break;
  498     }*/
  499     if(!cfg.AutoCfg)
  500     {
  501     faacEncConfigurationPtr myFormat=&cfg.EncCfg;
  502 
  503         if(cfg.UseQuality)
  504         {
  505             CurFormat->quantqual=myFormat->quantqual;
  506             CurFormat->bitRate=0;//myFormat->bitRate;
  507         }
  508         else
  509         {
  510             CurFormat->bitRate=(myFormat->bitRate*1000)/wChannels;
  511             CurFormat->quantqual=100;
  512         }
  513 
  514         switch(CurFormat->bandWidth)
  515         {
  516         case 0: // Auto
  517             break;
  518         case 0xffffffff: // Full
  519             CurFormat->bandWidth=lSamprate/2;
  520             break;
  521         default:
  522             CurFormat->bandWidth=myFormat->bandWidth;
  523             break;
  524         }
  525         CurFormat->mpegVersion=myFormat->mpegVersion;
  526         CurFormat->outputFormat=myFormat->outputFormat;
  527         CurFormat->mpegVersion=myFormat->mpegVersion;
  528         CurFormat->aacObjectType=myFormat->aacObjectType;
  529         CurFormat->allowMidside=myFormat->allowMidside;
  530 //      CurFormat->useTns=myFormat->useTns;
  531         CurFormat->useTns=false;
  532     }
  533     else
  534     {
  535         CurFormat->mpegVersion=DEF_MPEGVER;
  536         CurFormat->aacObjectType=DEF_PROFILE;
  537         CurFormat->allowMidside=DEF_MIDSIDE;
  538 //      CurFormat->useTns=DEF_TNS;
  539         CurFormat->useTns=false;
  540         CurFormat->useLfe=DEF_LFE;
  541         CurFormat->quantqual=DEF_QUALITY;
  542         CurFormat->bitRate=DEF_BITRATE;
  543         CurFormat->bandWidth=DEF_BANDWIDTH;
  544         CurFormat->outputFormat=DEF_HEADER;
  545     }
  546     if(mo->WriteMP4)
  547         CurFormat->outputFormat=RAW;
  548     CurFormat->useLfe=wChannels>=6 ? 1 : 0;
  549     if(!faacEncSetConfiguration(mo->hEncoder, CurFormat))
  550         return ERROR_Init("Unsupported parameters!");
  551 
  552 //  mo->src_size=lSize;
  553 //  mi->dst_name=strdup(OutFileName);
  554     mo->Samprate=lSamprate;
  555     mo->BitsPerSample=wBitsPerSample;
  556     mo->Channels=wChannels;
  557     mo->samplesInput=samplesInput;
  558     mo->samplesInputSize=samplesInput*(mo->BitsPerSample>>3);
  559 
  560     mo->maxBytesOutput=maxBytesOutput;
  561 
  562     if(mo->WriteMP4) // Create MP4 file --------------------------------------------------------------------------
  563     {
  564     BYTE *ASC=0;
  565     DWORD ASCLength=0;
  566 
  567         if((mo->MP4File=MP4Create(OutFileName, 0, 0))==MP4_INVALID_FILE_HANDLE)
  568             return ERROR_Init("Can't create file");
  569         MP4SetTimeScale(mo->MP4File, 90000);
  570         mo->MP4track=MP4AddAudioTrack(mo->MP4File, lSamprate, MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
  571         MP4SetAudioProfileLevel(mo->MP4File, 0x0F);
  572         faacEncGetDecoderSpecificInfo(mo->hEncoder, &ASC, &ASCLength);
  573         MP4SetTrackESConfiguration(mo->MP4File, mo->MP4track, (unsigned __int8 *)ASC, ASCLength);
  574         mo->frameSize=samplesInput/wChannels;
  575         mo->ofs=mo->frameSize;
  576 
  577         if(cfg.TagOn)
  578         {
  579         int error=0;
  580 #ifdef USE_IMPORT_TAG
  581             if(cfg.TagImport && InFileName)
  582             {
  583             int l=strlen(InFileName);
  584                 if( !strcmpi(InFileName+l-4,".mp4") ||
  585                     !strcmpi(InFileName+l-4,".m4a") ||
  586                     !strcmpi(InFileName+l-4,".m4b"))
  587                     error=cfg.Tag.ReadMp4Tag(InFileName);
  588                 else
  589                     error=cfg.Tag.ReadAacTag(InFileName);
  590             }
  591 #endif
  592             if(!error)
  593                 cfg.Tag.WriteMP4Tag(mo->MP4File);
  594         }
  595     }
  596     else // Create AAC file -----------------------------------------------------------------------------
  597     {
  598         // open the aac output file 
  599         if(!(mo->aacFile=fopen(OutFileName, "wb")))
  600             return ERROR_Init("Can't create file");
  601 
  602         // use bufferized stream
  603         setvbuf(mo->aacFile,NULL,_IOFBF,32767);
  604 
  605         mo->InFilename=strdup(InFileName);
  606         mo->OutFilename=strdup(OutFileName);
  607     }
  608 
  609     showInfo(mo);
  610 
  611     GlobalUnlock(hOutput);
  612     return hOutput;
  613 }
  614 // *********************************************************************************************
  615 
  616 int Cfaac::processData(HANDLE hOutput, BYTE *bufIn, DWORD len)
  617 {
  618     if(!hOutput)
  619         return -1;
  620 
  621 int bytesWritten=0;
  622 int bytesEncoded;
  623 MYOUTPUT far *mo;
  624 
  625     GLOBALLOCK(mo,hOutput,MYOUTPUT,return 0);
  626 
  627 int32_t *buf=mo->buf32bit;
  628 
  629     if((int)len<mo->samplesInputSize)
  630     {
  631         mo->samplesInput=(len<<3)/mo->BitsPerSample;
  632         mo->samplesInputSize=mo->samplesInput*(mo->BitsPerSample>>3);
  633     }
  634 //  if(mo->BitsPerSample==8 || mo->BitsPerSample==32)
  635         To32bit(buf,bufIn,mo->samplesInput,mo->BitsPerSample>>3,false);
  636 
  637     // call the actual encoding routine
  638     if((bytesEncoded=faacEncEncode(mo->hEncoder, (int32_t *)buf, mo->samplesInput, mo->bitbuf, mo->maxBytesOutput))<0)
  639         return ERROR_processData("faacEncEncode()");
  640 
  641     // write bitstream to aac file 
  642     if(mo->aacFile)
  643     {
  644         if(bytesEncoded>0)
  645         {
  646             if((bytesWritten=fwrite(mo->bitbuf, 1, bytesEncoded, mo->aacFile))!=bytesEncoded)
  647                 return ERROR_processData("Write failed!");
  648             mo->WrittenSamples=1; // needed into destructor
  649         }
  650     }
  651     else
  652     // write bitstream to mp4 file
  653     {
  654     MP4Duration dur,
  655                 SamplesLeft;
  656         if(len>0)
  657         {
  658             mo->srcSize+=len;
  659             dur=mo->frameSize;
  660         }
  661         else
  662         {
  663             mo->TotalSamples=(mo->srcSize<<3)/(mo->BitsPerSample*mo->Channels);
  664             SamplesLeft=(mo->TotalSamples-mo->WrittenSamples)+mo->frameSize;
  665             dur=SamplesLeft>mo->frameSize ? mo->frameSize : SamplesLeft;
  666         }
  667         if(bytesEncoded>0)
  668         {
  669             if(!(bytesWritten=MP4WriteSample(mo->MP4File, mo->MP4track, (unsigned __int8 *)mo->bitbuf, (DWORD)bytesEncoded, dur, mo->ofs, true) ? bytesEncoded : -1))
  670                 return ERROR_processData("MP4WriteSample()");
  671             mo->ofs=0;
  672             mo->WrittenSamples+=dur;
  673         }
  674     }
  675 
  676     showProgress(mo);
  677 
  678     GlobalUnlock(hOutput);
  679     return bytesWritten;
  680 }
  681 // -----------------------------------------------------------------------------------------------
  682 
  683 int Cfaac::processDataBufferized(HANDLE hOutput, BYTE *bufIn, long lBytes)
  684 {
  685     if(!hOutput)
  686         return -1;
  687 
  688 int bytesWritten=0, tot=0;
  689 MYOUTPUT far *mo;
  690 
  691     GLOBALLOCK(mo,hOutput,MYOUTPUT,return 0);
  692 
  693     if(mo->bytes_into_buffer>=0)
  694         do
  695         {
  696             if(mo->bytes_into_buffer+lBytes<mo->samplesInputSize)
  697             {
  698                 memmove(mo->bufIn+mo->bytes_into_buffer, bufIn, lBytes);
  699                 mo->bytes_into_buffer+=lBytes;
  700                 lBytes=0;
  701             }
  702             else
  703             {
  704             int shift=mo->samplesInputSize-mo->bytes_into_buffer;
  705                 memmove(mo->bufIn+mo->bytes_into_buffer, bufIn, shift);
  706                 mo->bytes_into_buffer+=shift;
  707                 bufIn+=shift;
  708                 lBytes-=shift;
  709 
  710                 tot+=bytesWritten=processData(hOutput,mo->bufIn,mo->bytes_into_buffer);
  711                 if(bytesWritten<0)
  712                     return ERROR_processData(0);
  713                 mo->bytes_into_buffer=0;
  714             }
  715         }while(lBytes);
  716 
  717     GlobalUnlock(hOutput);
  718     return tot;
  719 }