examples/SFExamples/oggvorbiscodec94/src/VorbisEncoder/VorbisEncoder.cpp

00001 // VorbisEncoder.cpp
00002 //
00003 // Copyright (c) Symbian Software Ltd 2005-2007.  All rights reserved.
00004 //
00005 
00006 #include <e32base.h>
00007 #include <e32debug.h>
00008 #include <e32math.h>
00009 #include "vorbisencoder.h"
00010 
00011 const TInt KDefaultBitRate = 64000;
00012 const TInt KDefaultQuality = 0.0;
00013 
00014 //--------------------------------------------------------------------
00015 //----------------------------- Encoder ------------------------------
00016 //--------------------------------------------------------------------
00017 
00018  CVorbisEncoder* CVorbisEncoder::NewL()
00019     {
00020     CVorbisEncoder* self = new(ELeave)CVorbisEncoder;
00021     CleanupStack::PushL(self);
00022     self->ConstructL();
00023     CleanupStack::Pop(self);
00024     return self;
00025     }
00026     
00027 CVorbisEncoder::CVorbisEncoder(): iState(ENotReady), iBitRate(KDefaultBitRate), iQuality(KDefaultQuality)
00028     {
00029     }
00030 
00031 void CVorbisEncoder::ConstructL()
00032     {
00033     vorbis_info_init(&iInfo);
00034     ogg_stream_init(&iStream,10);
00035     }
00036 
00037 CVorbisEncoder::~CVorbisEncoder()
00038     {
00039         if (iState != ENotReady)
00040         {
00041         vorbis_block_clear(&iBlock);
00042         vorbis_dsp_clear(&iDspState);
00043         }
00044     ogg_stream_clear(&iStream);
00045     vorbis_comment_clear(&iComment);
00046     vorbis_info_clear(&iInfo);
00047     }
00048 
00056 void CVorbisEncoder::PcmInL(const CMMFDataBuffer& aBuf)
00057     {
00058     TPtrC8 data = aBuf.Data();
00059     TInt bytes = data.Length();
00060     TInt ret = KErrNone;
00061     if (iState == ENotReady)
00062         {
00063         User::Leave(KErrNotReady);
00064         }
00065     if(bytes==0)
00066         {
00067         ret = vorbis_analysis_wrote(&iDspState,0);
00068         DEBUG1("Called vorbis_analysis_wrote zero bytes = %d",bytes);
00069         if (ret != KErrNone)
00070                 {
00071                 User::Leave(TranslateOggVorbisError(ret));
00072                 }
00073         }
00074     else
00075         {
00076         TReal32** buffer;
00077         TInt bytesPerSample = 2*iInfo.channels; // 16-bit assumed (most likely 2 channels)
00078         TInt bufSamples = bytes/bytesPerSample;
00079         buffer = vorbis_analysis_buffer(&iDspState,bufSamples);
00080         TInt i = 0;
00081         if(iInfo.channels == 1)
00082                 {
00083                 for(i = 0 ; i < bufSamples ; i++)
00084                         {
00085                         buffer[0][i]=((static_cast<TInt8>(data[i*2+1])<<8)|(0x00ff&static_cast<TInt16>(data[i*2])))/32768.f;
00086                         }
00087                 }
00088         else
00089                 {
00090                 for(i=0;i<bufSamples;i++)
00091                         {
00092                         //16 bits either side of the | 
00093                         buffer[0][i]=((static_cast<TInt8>(data[i*4+1])<<8)|(0x00ff&static_cast<TInt16>(data[i*4])))/32768.f;
00094                                 buffer[1][i]=((static_cast<TInt8>(data[i*4+3])<<8)|(0x00ff&static_cast<TInt16>(data[i*4+2])))/32768.f;
00095                         }       
00096         }
00097 
00098         ret = vorbis_analysis_wrote(&iDspState,i);
00099         if (ret != KErrNone)
00100                 {
00101                 User::Leave(TranslateOggVorbisError(ret));
00102                 }
00103         DEBUG1("Called vorbis_analysis_wrote with vals = %d",i);
00104         }
00105      }
00106 
00117 TInt CVorbisEncoder::PageOutL(CMMFDataBuffer& aDst)
00118     {
00119     TDes8* dst = &aDst.Data();
00120     dst->SetLength(0);
00121     ogg_packet  op; // one raw packet of data to output 
00122     ogg_page og;
00123     TInt pageCount = 0;
00124     if(iState == EInitialized)
00125         {
00126         while(ogg_stream_flush(&iStream,&og))
00127                         {
00128                         dst->Append(og.header, og.header_len);
00129                         dst->Append(og.body, og.body_len);
00130                         DEBUG1("HeaderPageLength %d",og.header_len + og.body_len);
00131                         iState = EReady;
00132                         }
00133         }
00134     DEBUG("about to call vorbis_analysis_blockout");
00135         while (vorbis_analysis_blockout(&iDspState,&iBlock) == 1)
00136                 {
00137                 // got a block of vorbis data, analyse it
00138                 DEBUG("called vorbis_analysis_blockout with return of 1");
00139                 vorbis_analysis(&iBlock,NULL);
00140                 vorbis_bitrate_addblock(&iBlock);
00141             DEBUG1("called  packet vorbis_bitrate_flushpacket",(*dst).Length());
00142             while (vorbis_bitrate_flushpacket(&iDspState,&op))
00143                 {
00144                 ogg_stream_packetin(&iStream,&op);
00145                 DEBUG1("CVorbisEncoder::PacketOut packet of length %d added to cache",op.bytes);
00146                         while(ogg_stream_pageout(&iStream, &og))
00147                                 {
00148                                 dst->Append(og.header, og.header_len);
00149                                 dst->Append(og.body, og.body_len);
00150                                 
00151                                 DEBUG1("PageLength %d",og.header_len + og.body_len);
00152                                 DEBUG1("PageCount %d",++iPageCount);
00153                                 pageCount++;
00154                                 if(ogg_page_eos(&og))
00155                                         {
00156                                         aDst.SetLastBuffer(ETrue);
00157                                         DEBUG1("LastPageLength %d",og.header_len + og.body_len);
00158                                         return dst->Length();
00159                                         }
00160                                 }
00161                 }
00162              }
00163         return dst->Length();
00164     }
00165 
00169 void CVorbisEncoder::PrepareHeadersL()
00170         {
00171         ogg_packet op1,op2,op3;
00172         TInt ret = KErrNone;
00173         ret = vorbis_analysis_headerout(&iDspState,&iComment,&op1,&op2,&op3);
00174         if (ret != KErrNone)
00175                 {
00176                 User::Leave(TranslateOggVorbisError(ret));      
00177                 }
00178         ogg_stream_packetin(&iStream,&op1);
00179         ogg_stream_packetin(&iStream,&op2);     
00180         ogg_stream_packetin(&iStream,&op3);
00181         }
00182 
00183 void CVorbisEncoder::Reset()
00184     {
00185     if (iState==EReady)
00186         {
00187         vorbis_block_clear(&iBlock);
00188         vorbis_dsp_clear(&iDspState);
00189         }
00190     vorbis_comment_clear(&iComment);
00191     vorbis_info_clear(&iInfo);
00192     vorbis_info_init(&iInfo);
00193     vorbis_comment_init(&iComment);
00194     iState = ENotReady;
00195     }
00196 
00197 TInt CVorbisEncoder::BitRateL()
00198         {
00199         return iBitRate;
00200         }
00201         
00202 void CVorbisEncoder::SetBitRateL(TInt aBitRate)
00203         {
00204         if (aBitRate < KOggVorbisMinBitrate)
00205                 {
00206                 aBitRate = KOggVorbisMinBitrate;
00207                 }
00208         iBitRate = aBitRate;
00209         ConvertBitRateToQuality(iBitRate, iQuality);
00210         }
00217 void CVorbisEncoder::InitializeVorbisStreamL()
00218         {
00219         TInt ret = KErrNone;
00220         ret = vorbis_encode_init_vbr(&iInfo,iChannels,iSampleRate,iQuality);
00221         if(ret == KErrNone)
00222                 {
00223                 vorbis_comment_init(&iComment);
00224                 //Custom interface could allow user to set up iComments in future
00225         vorbis_comment_add_tag(&iComment,"ENCODER","Reference Vorbis Encoder");
00226                 vorbis_analysis_init(&iDspState,&iInfo);        
00227                 vorbis_block_init(&iDspState,&iBlock);
00228                 PrepareHeadersL();
00229                 iState = EInitialized;  
00230                 }
00231         if(ret)
00232                 {
00233                 User::Leave(TranslateOggVorbisError(ret));      
00234                 }
00235         }
00241 void CVorbisEncoder::ConfigureL(TInt aSampleRate, TInt aChannels)
00242         {
00243         iSampleRate = aSampleRate;
00244         iChannels = aChannels;
00245         InitializeVorbisStreamL();
00246         }
00247         
00248 TInt CVorbisEncoder::TranslateOggVorbisError(TInt aError)
00249         {
00250         //reference libvorbis\doc\vorbis-errors.txt
00251         switch (aError)
00252                 {
00253                 case OV_EIMPL:
00254                         return KErrNotSupported;
00255                 case OV_EINVAL:
00256                         return KErrArgument;
00257                 default:
00258                 return KErrUnknown;
00259                 }       
00260         }
00261 
00270 void CVorbisEncoder::ConvertBitRateToQuality(TInt aBitRate, TReal32& aQuality)
00271         {
00272         switch (aBitRate)
00273                 {
00274                 case KVorbisQuality0:
00275                         aQuality = 0.0;
00276                         break;
00277                 case KVorbisQuality1:
00278                         aQuality = 0.1;
00279                         break;
00280                 case KVorbisQuality2:
00281                         aQuality = 0.2;
00282                         break;
00283                 case KVorbisQuality3:
00284                         aQuality = 0.3;
00285                         break;
00286                 case KVorbisQuality4:
00287                         aQuality = 0.4;
00288                         break;
00289                 case KVorbisQuality5:
00290                         aQuality = 0.5;
00291                         break;
00292                 case KVorbisQuality6:
00293                         aQuality = 0.6;
00294                         break;
00295                 case KVorbisQuality7:
00296                         aQuality = 0.7;
00297                         break;
00298                 case KVorbisQuality8:
00299                         aQuality = 0.8;
00300                         break;
00301                 case KVorbisQuality9:
00302                         aQuality = 0.9;
00303                         break;
00304                 case KVorbisQuality10:
00305                         aQuality = 1.0;
00306                         break;  
00307                 default:
00308                 aQuality = -0.1;
00309                 break;
00310                 }       
00311         }
00312 //--------------------------------------------------------------------
00313 //---------------------------- Processor -----------------------------
00314 //--------------------------------------------------------------------
00315 
00316 CVorbisProcessor* CVorbisProcessor::NewL()
00317     {
00318     CVorbisProcessor* self = new(ELeave)CVorbisProcessor;
00319     CleanupStack::PushL(self);
00320     self->ConstructL();
00321     CleanupStack::Pop(self);
00322     return self;
00323     }
00324 
00325 CVorbisProcessor::CVorbisProcessor()
00326     {
00327     }
00328 
00329 void CVorbisProcessor::ConstructL()
00330     {
00331 #ifdef SYMBIAN_SEP_HEAP    
00332     User::LeaveIfError(iVorbisChunk.CreateLocal(KInitialChunkSize, KMaxChunkSize, EOwnerThread));
00333     iVorbisHeap = User::ChunkHeap(iVorbisChunk, KMinHeapLength);
00334     iDefaultHeap = &User::Heap();
00335 #endif
00336     VORBIS_TRAPD(leaveErr, iEncoder = CVorbisEncoder::NewL());
00337     User::LeaveIfError(leaveErr);
00338     }
00339     
00340 CVorbisProcessor::~CVorbisProcessor()
00341     {
00342 #ifdef SYMBIAN_SEP_HEAP
00343         if(iVorbisHeap)
00344                 {
00345                 User::SwitchHeap(iVorbisHeap);
00346                 }
00347 #endif
00348     delete iEncoder;
00349 #ifdef SYMBIAN_SEP_HEAP
00350     if(iVorbisHeap)
00351         {
00352         iVorbisChunk.Close();
00353         User::SwitchHeap(iDefaultHeap);
00354         }
00355 #endif
00356     }
00357 
00358 void CVorbisProcessor::ProcessL(const CMMFBuffer& aSource,
00359                                 CMMFBuffer& aDst,
00360                                 TProcessResult& aRes,
00361                                 TUint& aSourceUsed,
00362                                 TUint& aDestWritten)
00363     {
00364     // check that buffers are instances of CMMFDataBuffer
00365     if (!CMMFBuffer::IsSupportedDataBuffer(aSource.Type())) 
00366         {
00367         User::Leave(KErrNotSupported);
00368         }
00369     if (!CMMFBuffer::IsSupportedDataBuffer(aDst.Type())) 
00370         {
00371         User::Leave(KErrNotSupported);
00372         }
00373         const CMMFDataBuffer& src = static_cast<const CMMFDataBuffer&>(aSource);
00374     CMMFDataBuffer& dstBuf = static_cast<CMMFDataBuffer&>(aDst);
00375     VORBIS_TRAPD(leaveErr, iEncoder->PcmInL(src));
00376     User::LeaveIfError(leaveErr);
00377     VORBIS_TRAP(leaveErr, iEncoder->PageOutL(dstBuf));
00378     User::LeaveIfError(leaveErr);
00379     aDestWritten = dstBuf.Data().Length();
00380     aSourceUsed = src.Data().Length();
00381     aRes = ( aDestWritten > 0 ? EComplete : EDestNotFilled);
00382     }
00383     
00384 TInt CVorbisProcessor::BitRateL()
00385         {
00386         return iEncoder->BitRateL();
00387         }
00388         
00389 void CVorbisProcessor::SetBitRateL(TInt aBitRate)
00390         {
00391         iEncoder->SetBitRateL(aBitRate);
00392         }
00393 
00394 void CVorbisProcessor::ConfigureL(TInt aSampleRate, TInt aChannels)
00395         {
00396         VORBIS_TRAPD(leaveErr, iEncoder->ConfigureL(aSampleRate, aChannels));
00397         User::LeaveIfError(leaveErr);
00398         }

Generated by  doxygen 1.6.2