⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 formatbitstream.c

📁 mp3 source code decoder & encoder
💻 C
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************
  Copyright (c) 1995 ISO/IEC JTC1 SC29 WG1, All Rights Reserved
  formatBitstream.c
**********************************************************************/
/* 
 * $Header: /MP3Stego/MP3Stego Encoder/formatBitstream.c 4     30/11/00 15:57 Fabienpe $
 */

/*
  Revision History:

  Date        Programmer                Comment
  ==========  ========================= ===============================
  1995/09/06  mc@fivebats.com           created
  1995/09/18  mc@fivebats.com           bugfix: WriteMainDataBits
  1995/09/20  mc@fivebats.com           bugfix: store_side_info
*/

#include "formatBitstream.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif

/* globals */
static int BitCount       = 0;
static int ThisFrameSize  = 0;
static int BitsRemaining  = 0;
static BitsFcnPtr PutBits = NULL;

/* forward declarations */
static int store_side_info( BF_FrameData *frameInfo );
static int main_data( BF_FrameData *frameInfo, BF_FrameResults *results );
static int side_queue_elements( int *forwardFrameLength, int *forwardSILength );
static void free_side_queues();
static void WriteMainDataBits( unsigned val,
                               unsigned nbits,
			       BF_FrameResults *results );
/*
  BitStreamFrame is the public interface to the bitstream
  formatting package. It writes one frame of main data per call.

  Assumptions:
  - The back pointer is zero on the first call
  - An integral number of bytes is written each frame

  You should be able to change the frame length, side info
  length, #channels, #granules on a frame-by-frame basis.

  See formatBitstream.h for more information about the data
  structures and the bitstream syntax.
*/
void
BF_BitstreamFrame( BF_FrameData *frameInfo, BF_FrameResults *results )
{
    int elements, forwardFrameLength, forwardSILength;

    assert( frameInfo->nGranules <= MAX_GRANULES );
    assert( frameInfo->nChannels <= MAX_CHANNELS );

    /* get ptr to bit writing function */
    PutBits = frameInfo->putbits;
    assert( PutBits );
    /* save SI and compute its length */
    results->SILength = store_side_info( frameInfo );

    /* write the main data, inserting SI to maintain framing */
    results->mainDataLength = main_data( frameInfo, results );

    /*
      Caller must ensure that back SI and main data are
      an integral number of bytes, since the back pointer
      can only point to a byte boundary and this code
      does not add stuffing bits
    */
    assert( (BitsRemaining % 8) == 0 );

    /* calculate nextBackPointer */
    elements = side_queue_elements( &forwardFrameLength, &forwardSILength );
    results->nextBackPtr = (BitsRemaining / 8) + (forwardFrameLength / 8) - (forwardSILength / 8);
}

/*
  FlushBitstream writes zeros into main data
  until all queued headers are written. The
  queue data buffers are also freed.
*/
void
BF_FlushBitstream( BF_FrameData *frameInfo, BF_FrameResults *results )
{
    int elements, forwardFrameLength, forwardSILength;

    /* get ptr to bit writing function */
    PutBits = frameInfo->putbits;
    assert( PutBits );

    elements = side_queue_elements( &forwardFrameLength, &forwardSILength );

    if ( elements )
    {
	int bitsRemaining = forwardFrameLength - forwardSILength;
	int wordsRemaining = bitsRemaining / 32;
	while ( wordsRemaining-- )
	    WriteMainDataBits( 0, 32, results );
	WriteMainDataBits( 0, (bitsRemaining % 32), results );	
    }

    results->mainDataLength = forwardFrameLength - forwardSILength;
    results->SILength       = forwardSILength;
    results->nextBackPtr    = 0;

    /* reclaim queue space */
    free_side_queues();

    /* reinitialize globals */
    BitCount       = 0;
    ThisFrameSize  = 0;
    BitsRemaining  = 0;    
    PutBits        = NULL;
    return;
}

int
BF_PartLength( BF_BitstreamPart *part )
{
    BF_BitstreamElement *ep = part->element;
    int i, bits;

    bits = 0;
    for ( i = 0; i < part->nrEntries; i++, ep++ )
	bits += ep->length;
    return bits;
}


/*
  The following is all private to this file
*/

typedef struct
{
    int frameLength;
    int SILength;
    int nGranules;
    int nChannels;
    BF_PartHolder *headerPH;
    BF_PartHolder *frameSIPH;
    BF_PartHolder *channelSIPH[MAX_CHANNELS];
    BF_PartHolder *spectrumSIPH[MAX_GRANULES][MAX_CHANNELS];
} MYSideInfo;

static MYSideInfo *get_side_info();
static int write_side_info();
typedef int (*PartWriteFcnPtr)( BF_BitstreamPart *part, BF_FrameResults *results );


static int
writePartMainData( BF_BitstreamPart *part, BF_FrameResults *results )
{
    BF_BitstreamElement *ep;
    int i, bits;

    assert( results );
    assert( part );

    bits = 0;
    ep = part->element;
    for ( i = 0; i < part->nrEntries; i++, ep++ )
    {
	WriteMainDataBits( ep->value, ep->length, results );
	bits += ep->length;
    }
    return bits;
}

static int
writePartSideInfo( BF_BitstreamPart *part, BF_FrameResults *results )
{
    BF_BitstreamElement *ep;
    int i, bits;

    assert( part );

    bits = 0;
    ep = part->element;
    for ( i = 0; i < part->nrEntries; i++, ep++ )
    {
	(*PutBits)( ep->value, ep->length );
	bits += ep->length;
    }
    return bits;
}

static int
main_data( BF_FrameData *fi, BF_FrameResults *results )
{
    int gr, ch, bits;
    PartWriteFcnPtr wp = writePartMainData;
    bits = 0;
    results->mainDataLength = 0;

    for ( gr = 0; gr < fi->nGranules; gr++ )
	for ( ch = 0; ch < fi->nChannels; ch++ )
	{
	    bits += (*wp)( fi->scaleFactors[gr][ch], results );
	    bits += (*wp)( fi->codedData[gr][ch],    results );
	    bits += (*wp)( fi->userSpectrum[gr][ch], results );
	}
    bits += (*wp)( fi->userFrameData, results );
    return bits;
}

/*
  This is a wrapper around PutBits() that makes sure that the
  framing header and side info are inserted at the proper
  locations
*/

static void
WriteMainDataBits( unsigned val,
		   unsigned nbits,
		   BF_FrameResults *results )
{
    assert( nbits <= 32 );
    if ( BitCount == ThisFrameSize )
    {
	BitCount = write_side_info();
	BitsRemaining = ThisFrameSize - BitCount;
    }
    if ( nbits == 0 )
	return;
    if ( nbits > BitsRemaining )
    {
	unsigned extra = val >> (nbits - BitsRemaining);
	nbits -= BitsRemaining;
	(*PutBits)( extra, BitsRemaining );
	BitCount = write_side_info();
	BitsRemaining = ThisFrameSize - BitCount;
	(*PutBits)( val, nbits );
    }
    else
	(*PutBits)( val, nbits );
    BitCount += nbits;
    BitsRemaining -= nbits;
    assert( BitCount <= ThisFrameSize );
    assert( BitsRemaining >= 0 );
    assert( (BitCount + BitsRemaining) == ThisFrameSize );
}


static int
write_side_info()
{
    MYSideInfo *si;
    int bits, ch, gr;
    PartWriteFcnPtr wp = writePartSideInfo;

    bits = 0;
    si = get_side_info();
    ThisFrameSize = si->frameLength;
    bits += (*wp)( si->headerPH->part,  NULL );
    bits += (*wp)( si->frameSIPH->part, NULL );

    for ( ch = 0; ch < si->nChannels; ch++ )
	bits += (*wp)( si->channelSIPH[ch]->part, NULL );

    for ( gr = 0; gr < si->nGranules; gr++ )
	for ( ch = 0; ch < si->nChannels; ch++ )
	    bits += (*wp)( si->spectrumSIPH[gr][ch]->part, NULL );
    return bits;
}

typedef struct side_info_link
{

⌨️ 快捷键说明

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