videoeditorengine/mp3aacManipLib/AACGain/src/sbr_bitmux.cpp
changeset 0 951a5db380a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/mp3aacManipLib/AACGain/src/sbr_bitmux.cpp	Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,749 @@
+/*
+* Copyright (c) 2010 Ixonos Plc.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - Initial contribution
+*
+* Contributors:
+* Ixonos Plc
+*
+* Description:
+*
+*/
+
+
+/*
+  \file
+  \brief SBR bitstream multiplexer implementation $Revision: 1.1.1.1 $
+*/
+
+/**************************************************************************
+  sbr_bitmux.cpp - Bitstream implementations for SBR encoder.
+ 
+  Author(s): Juha Ojanpera
+  Copyright (c) 2004 by Nokia Research Center, Multimedia Technologies.
+  *************************************************************************/
+
+/*-- Project Headers. --*/
+#include "sbr_rom.h"
+#include "sbr_bitmux.h"
+
+#define CODE_BOOK_SCF_LAV10         (60)
+#define CODE_BOOK_SCF_LAV11         (31)
+#define CODE_BOOK_SCF_LAV_BALANCE11 (12)
+#define CODE_BOOK_SCF_LAV_BALANCE10 (24)
+
+/**
+ * Writes SBR header data.
+ */
+int16
+SBR_WriteHeaderData(SbrHeaderData *h_sbr_header, TBitStream *bs, uint8 writeFlag)
+{
+  int16 bitsWritten;
+  uint8 headerExtra1, headerExtra2;
+
+  bitsWritten = 1 + 4 + 4 + 3 + 2 + 2;
+
+  if(writeFlag)
+  {
+    BsPutBits(bs, 1, h_sbr_header->ampResolution);
+    BsPutBits(bs, 4, h_sbr_header->startFreq);
+    BsPutBits(bs, 4, h_sbr_header->stopFreq); 
+    BsPutBits(bs, 3, h_sbr_header->xover_band);
+    BsPutBits(bs, 2, 0);
+  }
+
+  headerExtra1 = 0;
+  if(h_sbr_header->freqScale   != SBR_FREQ_SCALE_DEF ||
+     h_sbr_header->alterScale  != SBR_ALTER_SCALE_DEF ||
+     h_sbr_header->noise_bands != SBR_NOISE_BANDS_DEF)
+   headerExtra1 = 1;
+
+  headerExtra2 = 0;
+  if(h_sbr_header->limiterBands    != SBR_LIMITER_BANDS_DEF ||
+     h_sbr_header->limiterGains    != SBR_LIMITER_GAINS_DEF ||
+     h_sbr_header->interpolFreq    != SBR_INTERPOL_FREQ_DEF ||
+     h_sbr_header->smoothingLength != SBR_SMOOTHING_LENGTH_DEF)
+   headerExtra2 = 1;
+
+  if(writeFlag)
+  {
+    BsPutBits(bs, 1, headerExtra1);
+    BsPutBits(bs, 1, headerExtra2);
+  }
+
+  if(headerExtra1)
+  {
+    bitsWritten += 5;
+
+    if(writeFlag)
+    {
+      BsPutBits(bs, 2, h_sbr_header->freqScale);
+      BsPutBits(bs, 1, h_sbr_header->alterScale);
+      BsPutBits(bs, 2, h_sbr_header->noise_bands);
+    }
+  }
+
+  if(headerExtra2)
+  {
+    bitsWritten += 6;
+
+    if(writeFlag)
+    {
+      BsPutBits(bs, 2, h_sbr_header->limiterBands);
+      BsPutBits(bs, 2, h_sbr_header->limiterGains);
+      BsPutBits(bs, 1, h_sbr_header->interpolFreq);
+      BsPutBits(bs, 1, h_sbr_header->smoothingLength);
+    }
+  }
+
+  return (bitsWritten);
+}
+
+/**
+ * Writes additional sinusoidal data for SBR.
+ */
+int16
+SBR_WriteSinusoidalData(SbrFrameData *hFrameData, TBitStream *bs, int16 nSfb, uint8 writeFlag)
+{
+  int16 bitsWritten;
+
+  bitsWritten = 1;
+  if(writeFlag)
+  {
+    if(hFrameData->isSinesPresent)
+      BsPutBits(bs, 1, 1);
+    else
+      BsPutBits(bs, 1, 0);
+  }
+
+  if(hFrameData->isSinesPresent)
+  {
+    bitsWritten += nSfb;
+
+    if(writeFlag)
+    {
+      int16 wSfb;
+
+      wSfb = (nSfb > 32) ? 32 : nSfb;
+
+      BsPutBits(bs, wSfb, hFrameData->addHarmonics[0]);
+      if(nSfb > 32)
+      {
+        wSfb = nSfb - 32;
+        BsPutBits(bs, wSfb, hFrameData->addHarmonics[1]);
+      }
+    }
+  }
+
+
+  return (bitsWritten);
+}
+
+/**
+ * Writes envelope direction coding data.
+ */
+int16
+SBR_WriteDTDFData(SbrFrameData *frameData, TBitStream *bs, uint8 writeFlag)
+{
+  int16 bitsWritten;
+
+  bitsWritten = frameData->frameInfo.nEnvelopes + frameData->frameInfo.nNoiseEnvelopes;
+
+  if(writeFlag)
+  {
+    BsPutBits(bs, frameData->frameInfo.nEnvelopes, frameData->domain_vec);
+    BsPutBits(bs, frameData->frameInfo.nNoiseEnvelopes, frameData->domain_vec_noise);
+  }
+
+  return (bitsWritten);
+}
+
+/**
+ * Writes envelope data for SBR.
+ */
+int16
+SBR_WriteEnvelopeData(SbrHeaderData *hHeaderData, SbrFrameData *frameData,
+                      TBitStream *bs, uint8 writeFlag)
+{
+  const uint8 *hCbBits_f, *hCbBits_t;
+  const int32 *hCb_f = 0, *hCb_t = 0;
+  const uint16 *hCb_f0 = 0, *hCb_t0 = 0;
+  uint8 no_band[MAX_ENVELOPES], hCbIndexOffset;
+  int16 i, j, k, offset, start_bits, bitsWritten, start_bits_balance, ampRes;
+
+  ampRes = hHeaderData->ampResolution;
+  if(frameData->frameInfo.frameClass == FIXFIX && frameData->frameInfo.nEnvelopes == 1)
+    ampRes = SBR_AMP_RES_1_5;
+
+  if(ampRes == SBR_AMP_RES_3_0)
+  {
+    start_bits = 6;
+    start_bits_balance = 5;
+  }
+  else
+  {
+    start_bits = 7;
+    start_bits_balance = 6;
+  }
+
+  k = SBR_BIT_ARRAY_SIZE - frameData->frameInfo.nEnvelopes;
+  for(i = 0; i < frameData->frameInfo.nEnvelopes; i++, k++)
+  {
+    uint8 resValue = (frameData->frameInfo.freqRes & bitArray[k]) ? 1 : 0;
+
+    no_band[i] = hHeaderData->hFreqBandData->nSfb[resValue];
+  }
+
+  /*
+   * Indexing of the codebooks needs some effort in order to same ROM memory...
+   */
+  if(frameData->coupling == COUPLING_BAL) 
+  {
+    if(ampRes == SBR_AMP_RES_1_5) 
+    {
+      hCb_f = bookSbrEnvBalanceC10F;
+      hCbBits_f = bookSbrEnvBalanceL10F;
+
+      hCb_t = bookSbrEnvBalanceC10T;
+      hCbBits_t = bookSbrEnvBalanceL10T;
+
+      hCbIndexOffset = CODE_BOOK_SCF_LAV_BALANCE10; 
+    }
+    else 
+    {
+      hCb_f0 = bookSbrEnvBalanceC11F;
+      hCbBits_f = bookSbrEnvBalanceL11F;
+
+      hCb_t0 = bookSbrEnvBalanceC11T;
+      hCbBits_t = bookSbrEnvBalanceL11T;
+
+      hCbIndexOffset = CODE_BOOK_SCF_LAV_BALANCE11;
+    }
+  }
+  else 
+  {
+    if(ampRes == SBR_AMP_RES_1_5) 
+    {
+      hCb_f = v_Huff_envelopeLevelC10F;
+      hCbBits_f = v_Huff_envelopeLevelL10F;
+
+      hCb_t = v_Huff_envelopeLevelC10T;
+      hCbBits_t = v_Huff_envelopeLevelL10T;
+
+      hCbIndexOffset = CODE_BOOK_SCF_LAV10;
+    }
+    else 
+    {
+      hCb_f = v_Huff_envelopeLevelC11F;
+      hCbBits_f = v_Huff_envelopeLevelL11F;
+
+      hCb_t = v_Huff_envelopeLevelC11T;
+      hCbBits_t = v_Huff_envelopeLevelL11T;
+
+      hCbIndexOffset = CODE_BOOK_SCF_LAV11;
+    }
+  }
+
+  k = SBR_BIT_ARRAY_SIZE - frameData->frameInfo.nEnvelopes;
+  for(j = 0, offset = 0, bitsWritten = 0; j < frameData->frameInfo.nEnvelopes; j++, k++) 
+  {
+    int16 index;
+    uint8 codValue;
+
+    codValue = frameData->domain_vec & bitArray[k];
+
+    if(!codValue) 
+    {
+      index = frameData->iEnvelope[offset];
+      index = MAX(0, index);
+
+      if(frameData->coupling == COUPLING_BAL) 
+      {
+        index = MIN(index, (1 << start_bits_balance) - 1);
+
+        bitsWritten += start_bits_balance;
+        if(writeFlag) BsPutBits(bs, start_bits_balance, index);
+      }
+      else 
+      {
+        index = MIN(index, (1 << start_bits) - 1);
+
+        bitsWritten += start_bits;
+        if(writeFlag) BsPutBits(bs, start_bits, index);
+      }
+    }
+
+    for(i = (1 - ((codValue) ? 1 : 0)); i < no_band[j]; i++)
+    {
+      uint32 codeWord;
+
+      index  = frameData->iEnvelope[offset + i];
+      index  = (index < 0) ? MAX(index, -hCbIndexOffset) : MIN(index, hCbIndexOffset);
+      index += hCbIndexOffset;
+
+      if(!codValue)
+      {
+        bitsWritten += hCbBits_f[index];
+        if(writeFlag) 
+        {
+          if(frameData->coupling == COUPLING_BAL && ampRes != SBR_AMP_RES_1_5)
+            codeWord = hCb_f0[index];
+          else
+            codeWord = hCb_f[index];
+
+          BsPutBits(bs, hCbBits_f[index], codeWord);
+        }
+      }
+      else
+      {
+        bitsWritten += hCbBits_t[index];
+        if(writeFlag) 
+        {
+          if(frameData->coupling == COUPLING_BAL && ampRes != SBR_AMP_RES_1_5)
+            codeWord = hCb_t0[index];
+          else
+            codeWord = hCb_t[index];
+
+          BsPutBits(bs, hCbBits_t[index], codeWord);
+        }
+      }
+    }
+
+    offset += no_band[j];
+  }
+
+  return (bitsWritten);
+}
+
+/**
+ * Writes noise data for SBR.
+ */
+int16
+SBR_WriteNoiseData(SbrHeaderData *hHeaderData, SbrFrameData *frameData,
+                   TBitStream *bs, uint8 writeFlag)
+{
+  uint8 hCbIndexOffset;
+  const int32 *hCb_f = 0;
+  const uint16 *hCb_f0 = 0, *hCb_t = 0;
+  const uint8 *hCbBits_f, *hCbBits_t;
+  int16 i, k, noNoiseBands, bitsWritten;
+
+  noNoiseBands = hHeaderData->hFreqBandData->nNfb;
+
+  if(frameData->coupling == COUPLING_BAL) 
+  {
+    hCb_f0 = bookSbrEnvBalanceC11F;
+    hCbBits_f = bookSbrEnvBalanceL11F;
+
+    hCb_t = bookSbrNoiseBalanceC11T;
+    hCbBits_t = bookSbrNoiseBalanceL11T;
+
+    hCbIndexOffset = CODE_BOOK_SCF_LAV_BALANCE11;
+  }
+  else 
+  {
+    hCb_f = v_Huff_envelopeLevelC11F;
+    hCbBits_f = v_Huff_envelopeLevelL11F;
+
+    hCb_t = v_Huff_NoiseLevelC11T;
+    hCbBits_t = v_Huff_NoiseLevelL11T;
+
+    hCbIndexOffset = CODE_BOOK_SCF_LAV11;
+  }
+
+  k = SBR_BIT_ARRAY_SIZE - frameData->frameInfo.nNoiseEnvelopes;
+  for(i = 0, bitsWritten = 0; i < frameData->frameInfo.nNoiseEnvelopes; i++, k++) 
+  {
+    int16 j, index;
+    uint8 codValue;
+
+    codValue = frameData->domain_vec_noise & bitArray[k];
+
+    if(!codValue) 
+    {      
+      bitsWritten += 5;
+      if(writeFlag) 
+        BsPutBits(bs, 5, frameData->sbrNoiseFloorLevel[i * noNoiseBands]);
+
+      for(j = 1; j < noNoiseBands; j++) 
+      {
+        index  = frameData->sbrNoiseFloorLevel[i * noNoiseBands + j];
+        index  = (index < 0) ? MAX(index, -hCbIndexOffset) : MIN(index, hCbIndexOffset);
+        index += hCbIndexOffset;
+
+        bitsWritten += hCbBits_f[index];
+        if(writeFlag) 
+        {
+          uint32 codeWord = (frameData->coupling == COUPLING_BAL) ? hCb_f0[index] : hCb_f[index];
+          BsPutBits(bs, hCbBits_f[index], codeWord);
+        }
+      }
+    }
+    else 
+    {
+      for(j = 0; j < noNoiseBands; j++) 
+      {
+        index  = frameData->sbrNoiseFloorLevel[i * noNoiseBands + j];
+        index  = (index < 0) ? MAX(index, -hCbIndexOffset) : MIN(index, hCbIndexOffset);
+        index += hCbIndexOffset;
+
+        bitsWritten += hCbBits_t[index];
+        if(writeFlag) BsPutBits(bs, hCbBits_t[index], hCb_t[index]);
+      }
+    }
+  }
+
+  return (bitsWritten);
+}
+
+/**
+ * Writes dummy (=silence) data for parametric stereo part of SBR.
+ */
+int16
+SBR_WriteParametricStereoData(TBitStream *bs, uint8 writeFlag)
+{
+  int16 bitsWritten = 0;
+
+  /*-- Write header flag. --*/
+  bitsWritten += 1;
+  if(writeFlag) BsPutBits(bs, 1, 1);
+
+  /*-- Write 'enable_iid' element. --*/
+  bitsWritten += 1;
+  if(writeFlag) BsPutBits(bs, 1, 0);
+
+  /*-- Write 'enable_icc' element. --*/
+  bitsWritten += 1;
+  if(writeFlag) BsPutBits(bs, 1, 0);
+
+  /*-- Write 'enable_ext' element. --*/
+  bitsWritten += 1;
+  if(writeFlag) BsPutBits(bs, 1, 0);
+
+  /*-- Write frame class. --*/
+  bitsWritten += 1;
+  if(writeFlag) BsPutBits(bs, 1, 0);
+
+  /*-- Write envelope index. --*/
+  bitsWritten += 2;
+  if(writeFlag) BsPutBits(bs, 2, 0);
+
+  return (bitsWritten);
+}
+
+/**
+ * Writes extension data for SBR.
+ */
+int16 
+SBR_WritetExtendedData(TBitStream *bs, SbrExtensionData *extData, uint8 writeFlag)
+{
+  uint8 writeExt;
+  int16 bitsWritten = 0;
+
+  writeExt = (extData->writePsData || extData->extensionDataPresent) ? 1 : 0;
+
+  bitsWritten += 1;
+  if(writeFlag) BsPutBits(bs, 1, writeExt);
+
+  if(writeExt) 
+  {
+    int16 i, nBitsLeft, cnt, byteCount;
+
+    byteCount = (extData->writePsData) ? 2 : extData->byteCount;
+    cnt = (byteCount >= 15) ? 15 : byteCount;
+
+    bitsWritten += 4;
+    if(writeFlag) BsPutBits(bs, 4, cnt);
+
+    if(cnt == 15)
+    {
+      int16 diff;
+
+      diff = byteCount - 15;
+
+      bitsWritten += 8;
+      if(writeFlag) BsPutBits(bs, 8, diff);
+    }
+
+    nBitsLeft = byteCount << 3;
+
+    while(nBitsLeft > 7) 
+    {
+      nBitsLeft -= 2;
+      bitsWritten += 2;
+      if(writeFlag) BsPutBits(bs, 2, (extData->writePsData) ? 2 : extData->extension_id);
+
+      cnt = nBitsLeft >> 3;
+      bitsWritten += cnt << 3;
+      if(writeFlag)
+      {
+        if(extData->writePsData)
+        {
+          SBR_WriteParametricStereoData(bs, writeFlag);
+          BsPutBits(bs, 1, 0); /*-- This will byte align the data. --*/
+        }
+        else
+          for(i = 0; i < cnt; i++)
+            BsPutBits(bs, 8, extData->extensioData[i]);
+      }
+
+      nBitsLeft -= cnt << 3;
+    }
+
+    bitsWritten += nBitsLeft;
+    if(writeFlag) BsPutBits(bs, nBitsLeft, 0);
+  }
+
+  return (bitsWritten);
+}
+
+/**
+ * Writes envelope coding grid for SBR.
+ */
+int16
+SBR_WriteGridInfo(TBitStream *bs, SbrFrameData *frameData, uint8 writeFlag)
+{
+  FRAME_INFO *frameInfo;
+  SbrGridInfo *sbrGridInfo;
+  int16 pointer_bits, nEnv, bitsWritten, k;
+
+  nEnv = 0;
+  bitsWritten = 0;
+  frameInfo = &frameData->frameInfo;
+  sbrGridInfo = &frameData->sbrGridInfo;
+
+  bitsWritten += 2;
+  if(writeFlag) BsPutBits(bs, 2, frameInfo->frameClass);
+
+  switch(frameInfo->frameClass) 
+  {
+    case FIXFIX:
+      bitsWritten += 2;
+      if(writeFlag) BsPutBits(bs, 2, sbrGridInfo->bs_num_env);
+
+      bitsWritten += 1;
+      if(writeFlag) 
+        BsPutBits(bs, 1, frameInfo->freqRes & 0x1);
+      break;
+      
+    case FIXVAR:
+    case VARFIX:
+      bitsWritten += 2;
+      if(writeFlag) BsPutBits(bs, 2, sbrGridInfo->bs_var_board[0]);
+
+      bitsWritten += 2;
+      if(writeFlag) BsPutBits(bs, 2, sbrGridInfo->bs_num_env);
+
+      bitsWritten += sbrGridInfo->bs_num_env << 1;
+      if(writeFlag)
+        for(k = 0; k < sbrGridInfo->bs_num_env; k++) 
+          BsPutBits(bs, 2, sbrGridInfo->bs_rel_board_0[k]);
+
+      pointer_bits = (int16) (FloatFR_logDualis(sbrGridInfo->bs_num_env + 2) + 0.992188f);
+
+      bitsWritten += pointer_bits;
+      if(writeFlag) BsPutBits(bs, pointer_bits, sbrGridInfo->bs_pointer);
+
+      bitsWritten += sbrGridInfo->bs_num_env + 1;
+      break;
+  }
+
+  switch(frameInfo->frameClass) 
+  {
+    case FIXVAR:
+      if(writeFlag)
+      {
+        uint8 tmp = 0, tmp2 = frameInfo->freqRes;
+        for(k = sbrGridInfo->bs_num_env; k >= 0; k--)
+        {
+          tmp <<= 1;
+          tmp  |= tmp2 & 0x1;
+          tmp2 >>= 1;
+        }
+        BsPutBits(bs, sbrGridInfo->bs_num_env + 1, tmp);
+      }
+      break;
+
+    case VARFIX:
+      if(writeFlag)
+        BsPutBits(bs, sbrGridInfo->bs_num_env + 1, frameInfo->freqRes);
+      break;
+
+    case VARVAR:
+      bitsWritten += 8;
+      if(writeFlag)
+      {
+        BsPutBits(bs, 2, sbrGridInfo->bs_var_board[0]);
+        BsPutBits(bs, 2, sbrGridInfo->bs_var_board[1]);
+        BsPutBits(bs, 2, sbrGridInfo->bs_num_rel[0]);
+        BsPutBits(bs, 2, sbrGridInfo->bs_num_rel[1]);
+      }
+      
+      nEnv = sbrGridInfo->bs_num_rel[0] + sbrGridInfo->bs_num_rel[1] + 1;
+
+      bitsWritten += sbrGridInfo->bs_num_rel[0] << 1;
+      if(writeFlag)
+        for(k = 0; k < sbrGridInfo->bs_num_rel[0]; k++)
+          BsPutBits(bs, 2, sbrGridInfo->bs_rel_board_0[k]);
+
+      bitsWritten += sbrGridInfo->bs_num_rel[1] << 1;
+      if(writeFlag)
+        for(k = 0; k < sbrGridInfo->bs_num_rel[1]; k++) 
+          BsPutBits(bs, 2, sbrGridInfo->bs_rel_board_1[k]);
+
+      pointer_bits = (int16) (FloatFR_logDualis(nEnv + 1) + 0.992188f);
+
+      bitsWritten += pointer_bits;
+      if(writeFlag) BsPutBits(bs, pointer_bits, sbrGridInfo->bs_pointer);
+
+      bitsWritten += nEnv;
+      if(writeFlag)
+        BsPutBits(bs, nEnv, frameInfo->freqRes);
+      break;
+  }
+
+  return (bitsWritten);
+}
+
+int16
+SBR_WriteSCE(SbrHeaderData *hHeaderData, SbrFrameData  *hFrameData,
+             SbrExtensionData *sbrExtData, TBitStream *bs,
+             uint8 isMono, uint8 writeFlag)
+{
+  int16 bitsWritten;
+
+  /*-- No reserved bits. --*/
+  bitsWritten = 1;
+  if(writeFlag) BsPutBits(bs, 1, hFrameData->dataPresent);
+
+  bitsWritten += (hFrameData->dataPresent) ? 4 : 0;
+  if(hFrameData->dataPresent)
+    if(writeFlag) BsPutBits(bs, 4, 0);
+
+  /*-- Write grid info. --*/
+  bitsWritten += SBR_WriteGridInfo(bs, hFrameData, writeFlag);
+
+  /*-- Write direction info for the envelope coding. --*/
+  bitsWritten += SBR_WriteDTDFData(hFrameData, bs, writeFlag);
+
+  /*-- Write inverse filtering modes. --*/
+  bitsWritten += hHeaderData->hFreqBandData->nInvfBands << 1;
+  if(writeFlag)
+    BsPutBits(bs, hHeaderData->hFreqBandData->nInvfBands << 1, hFrameData->sbr_invf_mode);
+
+  /*-- Write envelope values. --*/
+  bitsWritten += SBR_WriteEnvelopeData(hHeaderData, hFrameData, bs, writeFlag);
+
+  /*-- Write noise floor values. --*/
+  bitsWritten += SBR_WriteNoiseData(hHeaderData, hFrameData, bs, writeFlag);
+
+  /*-- Write additional sinusoidals, if any. --*/
+  bitsWritten += SBR_WriteSinusoidalData(hFrameData, bs, hHeaderData->hFreqBandData->nSfb[1], writeFlag);
+
+  /*
+   * Write extended data info, this is only in case of mono since parameters
+   * for parametric stereo are decoded via the data extension. In case of stereo
+   * do nothing.
+   */
+  if(!isMono)
+  {
+    bitsWritten += 1;
+    if(writeFlag) BsPutBits(bs, 1, 0);
+  }
+  else
+    bitsWritten += SBR_WritetExtendedData(bs, sbrExtData, writeFlag);
+
+  return (bitsWritten);
+}
+
+int16
+SBR_WriteCPE(SbrHeaderData *hHeaderData, SbrFrameData *hFrameDataLeft,
+             SbrFrameData *hFrameDataRight, SbrExtensionData *sbrExtData,
+             TBitStream *bs, uint8 writeFlag)
+{
+  int16 bitsWritten;
+
+  /*-- No reserved bits. --*/
+  bitsWritten = 1;
+  if(writeFlag) BsPutBits(bs, 1, 0);
+  bitsWritten += (hFrameDataLeft->dataPresent) ? 8 : 0;
+  if(hFrameDataLeft->dataPresent)
+    if(writeFlag) BsPutBits(bs, 8, 0);
+
+  bitsWritten += 1;
+  if(writeFlag)
+  {
+    if(hFrameDataLeft->coupling) 
+      BsPutBits(bs, 1, 1);
+    else
+      BsPutBits(bs, 1, 0);
+  }
+
+  /*-- Write grid info (left channel). --*/
+  bitsWritten += SBR_WriteGridInfo(bs, hFrameDataLeft, writeFlag);
+
+  /*-- Write grid info (right channel). --*/
+  if(!hFrameDataLeft->coupling)
+    bitsWritten += SBR_WriteGridInfo(bs, hFrameDataRight, writeFlag);
+
+  /*-- Write direction info for the envelope coding (left channel). --*/
+  bitsWritten += SBR_WriteDTDFData(hFrameDataLeft, bs, writeFlag);
+
+  /*-- Write direction info for the envelope coding (right channel). --*/
+  bitsWritten += SBR_WriteDTDFData(hFrameDataRight, bs, writeFlag);
+
+  /*-- Write inverse filtering modes. --*/
+  bitsWritten += hHeaderData->hFreqBandData->nInvfBands << 1;
+  if(writeFlag)
+    BsPutBits(bs, hHeaderData->hFreqBandData->nInvfBands << 1, hFrameDataLeft->sbr_invf_mode);
+
+  if(hFrameDataLeft->coupling) 
+  {
+    /*-- Write envelope values. --*/
+    bitsWritten += SBR_WriteEnvelopeData(hHeaderData, hFrameDataLeft, bs, writeFlag);
+
+    /*-- Write noise floor values. --*/
+    bitsWritten += SBR_WriteNoiseData(hHeaderData, hFrameDataLeft, bs, writeFlag);
+
+    /*-- Write envelope values. --*/
+    bitsWritten += SBR_WriteEnvelopeData(hHeaderData, hFrameDataRight, bs, writeFlag);
+  }
+  else 
+  {
+    bitsWritten += hHeaderData->hFreqBandData->nInvfBands << 1;
+    if(writeFlag)
+      BsPutBits(bs, hHeaderData->hFreqBandData->nInvfBands << 1, hFrameDataRight->sbr_invf_mode);
+
+    /*-- Write envelope values. --*/
+    bitsWritten += SBR_WriteEnvelopeData(hHeaderData, hFrameDataLeft, bs, writeFlag);
+
+    /*-- Write envelope values. --*/
+    bitsWritten += SBR_WriteEnvelopeData(hHeaderData, hFrameDataRight, bs, writeFlag);
+
+    /*-- Write noise floor values. --*/
+    bitsWritten += SBR_WriteNoiseData(hHeaderData, hFrameDataLeft, bs, writeFlag);
+  }
+
+  /*-- Write noise floor values. --*/
+  bitsWritten += SBR_WriteNoiseData(hHeaderData, hFrameDataRight, bs, writeFlag);
+
+  /*-- Write additional sinusoidals, if any. --*/
+  bitsWritten += SBR_WriteSinusoidalData(hFrameDataLeft, bs, hHeaderData->hFreqBandData->nSfb[1], writeFlag);
+  bitsWritten += SBR_WriteSinusoidalData(hFrameDataRight, bs, hHeaderData->hFreqBandData->nSfb[1], writeFlag);
+
+  /*-- No extended data. --*/
+#if 0
+  bitsWritten += 1;
+  if(writeFlag) BsPutBits(bs, 1, 0);
+#else
+  bitsWritten += SBR_WritetExtendedData(bs, sbrExtData, writeFlag);
+#endif /*-- 0 --*/
+
+  return (bitsWritten);
+}