www.pudn.com > mediator15src.zip > AudioCompressor.cpp


/* 
 * AudioCompressor.cpp 
 * Copyright (C) 2002 Arno Hornberger  
 * Original Version Copyright (C) Alberto Vigata - January 2000 - ultraflask@yahoo.com 
 * Class 'AudioL3Corrector' Copyright (C) 1998-2001 Avery Lee 
 * 
 * This file is part of MPEG Mediator, a free MPEG stream converter. 
 * 
 * MPEG Mediator is free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 2 of the License, or 
 * (at your option) any later version. 
 * 
 * MPEG Mediator is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */ 
 
#include "stdafx.h" 
#include "opendmlavioutput.h" 
#include "AudioCompressor.h" 
#include "error.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
/////////////////////////////////////////////////////////////////////////// 
// 
//	Corrects the nAvgBytesPerFrame for that stupid Fraunhofer-IIS 
//	codec. 
 
AudioL3Corrector::AudioL3Corrector() 
{ 
	samples = frame_bytes = 0; 
	read_left = 4; 
	header_mode = true; 
} 
 
long AudioL3Corrector::ComputeByterate(long sample_rate) 
{ 
	return MulDiv(frame_bytes, sample_rate, samples); 
} 
 
void AudioL3Corrector::Process(void *buffer, long bytes) 
{ 
	static const int bitrates[2][16]={ 
		{0, 8,16,24,32,40,48,56, 64, 80, 96,112,128,144,160,0}, 
		{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0} 
	}; 
	static const long samp_freq[4] = {44100, 48000, 32000, 0}; 
 
	int cnt=0; 
	int tc; 
 
	while(cnt < bytes) { 
		tc = bytes - cnt; 
		if (tc > read_left) 
			tc = read_left; 
 
		if (header_mode) 
			memcpy(&hdr_buffer[4-read_left], buffer, tc); 
 
		buffer = (char *)buffer + tc; 
		cnt += tc; 
		read_left -= tc; 
 
		if (read_left <= 0) 
			if (header_mode) { 
				// We've got a header!  Process it... 
 
				long hdr = *(long *)hdr_buffer; 
				long samp_rate, framelen; 
 
				if ((hdr & 0xE0FF) != 0xE0FF) 
					throw MyError("AudioL3Corrector::Process - MPEG audio sync error"); 
 
				samp_rate = samp_freq[(hdr>>18)&3]; 
 
				if (!((hdr>>11)&1)) { 
					samp_rate /= 2; 
					samples += 576; 
				} else 
					samples += 1152; 
 
				if (!(hdr & 0x1000)) 
					samp_rate /= 2; 
 
				framelen = (bitrates[(hdr>>11)&1][(hdr>>20)&15] * (((hdr>>11)&1) ? 144000 : 72000)) / samp_rate; 
 
				if (hdr&0x20000) ++framelen; 
 
				// update statistics 
 
				frame_bytes += framelen; 
 
				// start skipping the remainder 
 
				read_left = framelen - 4; 
				header_mode = false; 
 
			} else { 
 
				// Done skipping frame data; collect the next header 
 
				read_left = 4; 
				header_mode = true; 
			} 
	} 
} 
 
CAudioCompressor::CAudioCompressor(HACMDRIVERID hadid, WAVEFORMATEX *wfxIn, WAVEFORMATEX *wfxOut, bool hq) 
{ 
  pInAudio = new BYTE[AUDIO_BUFFER_SIZE]; 
  pOutAudio = new BYTE[AUDIO_BUFFER_SIZE]; 
 
  if (acmDriverOpen(&m_hHad, hadid, 0)) 
    throw MyError("CAudioCompressor::CAudioCompressor - error opening acm driver"); 
 
  if (acmStreamOpen(&m_hHas, m_hHad, wfxIn, wfxOut, NULL, NULL, 0, hq ? ACM_STREAMOPENF_NONREALTIME : 0)) 
	{ 
		acmDriverClose(m_hHad, 0); 
    throw MyError("CAudioCompressor::CAudioCompressor - error opening acm stream"); 
	} 
 
  memset(&m_sStreamHdr, 0, sizeof(ACMSTREAMHEADER)); 
  m_sStreamHdr.cbStruct = sizeof(ACMSTREAMHEADER); 
  m_sStreamHdr.pbSrc       = pInAudio; 
  m_sStreamHdr.cbSrcLength = AUDIO_BUFFER_SIZE; 
  m_sStreamHdr.pbDst       = pOutAudio; 
  m_sStreamHdr.cbDstLength = AUDIO_BUFFER_SIZE; 
 
  if (acmStreamPrepareHeader(m_hHas, &m_sStreamHdr, 0)) 
  { 
    acmStreamClose(m_hHas, 0); 
		acmDriverClose(m_hHad, 0); 
    throw MyError("CAudioCompressor::CAudioCompressor - error preparing stream header"); 
  } 
 
  m_nBufferPtr = 0; 
} 
 
CAudioCompressor::~CAudioCompressor() 
{ 
  acmStreamUnprepareHeader(m_hHas, &m_sStreamHdr, 0); 
  acmStreamClose(m_hHas, 0); 
  acmDriverClose(m_hHad, 0); 
 
	delete []pInAudio; 
	delete []pOutAudio; 
} 
 
/* 
bool CAudioCompressor::DeInitAudioCompressor() 
{ 
  acmStreamUnprepareHeader(m_hHas, &m_sStreamHdr, 0); 
  acmStreamClose(m_hHas, 0); 
  acmDriverClose(m_hHad, 0); 
 
  return true; 
} 
*/ 
 
/* 
bool CAudioCompressor::InitAudioCompressor(HACMDRIVERID hadid, WAVEFORMATEX *wfxIn, WAVEFORMATEX *wfxOut, bool hq) 
{ 
  if (acmDriverOpen(&m_hHad, hadid, 0)) 
    return false; 
 
  if (acmStreamOpen(&m_hHas, m_hHad, wfxIn, wfxOut, NULL, NULL, 0, hq ? ACM_STREAMOPENF_NONREALTIME : 0)) 
	{ 
		acmDriverClose(m_hHad, 0); 
    return false; 
	} 
 
  memset(&m_sStreamHdr, 0, sizeof(ACMSTREAMHEADER)); 
  m_sStreamHdr.cbStruct = sizeof(ACMSTREAMHEADER); 
  m_sStreamHdr.pbSrc       = pInAudio; 
  m_sStreamHdr.cbSrcLength = AUDIO_BUFFER_SIZE; 
  m_sStreamHdr.pbDst       = pOutAudio; 
  m_sStreamHdr.cbDstLength = AUDIO_BUFFER_SIZE; 
 
  if (acmStreamPrepareHeader(m_hHas, &m_sStreamHdr, 0)) 
  { 
    acmStreamClose(m_hHas, 0); 
		acmDriverClose(m_hHad, 0); 
    return false; 
  } 
 
  m_nBufferPtr = 0; 
  return true; 
} 
*/ 
 
bool CAudioCompressor::Compress(PBYTE inAudio, long inSize, PBYTE &outAudio, long &outSize) 
{ 
  outAudio = NULL; 
  outSize  = 0; 
 
  // copy source data to our stream header 
  if ((m_nBufferPtr + inSize) > MIN_AUDIO_BUFFER) 
  { 
    // check that inSize is not too much 
    if ((m_nBufferPtr + inSize) > AUDIO_BUFFER_SIZE) 
      return false; 
    // we have enough data to be compressed 
    // copy the data 
 
    memcpy(m_sStreamHdr.pbSrc + m_nBufferPtr, inAudio, inSize); 
    m_nBufferPtr += inSize; 
  } 
  else 
  { 
    // copy data and exit 
    memcpy(m_sStreamHdr.pbSrc + m_nBufferPtr, inAudio, inSize); 
    m_nBufferPtr += inSize; 
    return false; 
  } 
 
  m_sStreamHdr.cbSrcLength     = m_nBufferPtr; 
  m_sStreamHdr.cbSrcLengthUsed = 0; 
  m_sStreamHdr.cbDstLengthUsed = 0; 
 
  // try to compress this buffer 
  if (acmStreamConvert(m_hHas, &m_sStreamHdr, ACM_STREAMCONVERTF_BLOCKALIGN)) 
    return false; 
 
  if (!(m_sStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_DONE)) 
    return false; 
 
  // conversion was successful 
  // copy remaining data after conversion in source buffer 
  int newBufSize = 0; 
  for (int j = 0, i = m_sStreamHdr.cbSrcLengthUsed; i < m_nBufferPtr; i++, j++) 
  { 
    pInAudio[j] = pInAudio[i]; 
    newBufSize++; 
  } 
  m_nBufferPtr = newBufSize; 
 
  // output the compressed data 
  outAudio = m_sStreamHdr.pbDst; 
  outSize  = m_sStreamHdr.cbDstLengthUsed; 
  return true; 
}