|
|
/******************************************************************************
* Backend.cpp * *-------------* * *------------------------------------------------------------------------------ * Copyright (C) 1998 Entropic, Inc * Copyright (C) 2000 Microsoft Corporation Date: 03/02/00 * All Rights Reserved * ********************************************************************* PACOG ***/
#include "backend.h"
#include "tips.h"
#include "SynthUnit.h"
#include "SpeakerData.h"
#include "vapiIo.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
static const int DEFAULT_F0_SAMPFREQ = 200; static const double SYNTH_PROPORTION = .1;
class CBEndImp : public CBackEnd { public: CBEndImp();
~CBEndImp();
int LoadTable (const char* pszFilePath, int iDebug = 0); int GetSampFreq (); void SetGain (double dGain); void GetSpeakerInfo (int* piBaseLine, int* piRefLine, int* piTopLine); void SetF0SampFreq (int iF0SampFreq = DEFAULT_F0_SAMPFREQ); int NewPhoneString (Phone* phList, int nPh, float* newF0, int nNewF0); int OutputPending (); int GenerateOutput (short** ppnSamples, int* piNumSamples); int GetChunk (ChkDescript** ppChunk); bool GetPhoneSetFlag (); void SetFrontEndFlag () { m_pSlm->SetFrontEndFlag(); }
private: static const int m_iDefSampFreq; CSlm* m_pSlm; CTips* m_pTips; int m_iNumUnits; int m_iCurrUnit; int m_iF0SampFreq; float* m_pflF0; short* m_pnSynthBuff; int m_iSynthBuffSamples; short* m_pnOverflow; int m_iOverflowCurSamples; int m_iOverflowMaxSamples; int m_iPrevSamples; };
const int CBEndImp::m_iDefSampFreq = 8000;
/*****************************************************************************
* CBackEnd::ClassFactory * *------------------------* * Description: * ******************************************************************* PACOG ***/ CBackEnd* CBackEnd::ClassFactory() { return new CBEndImp; }
/*****************************************************************************
* CBEndImp::CBEndImp * *--------------------* * Description: * ******************************************************************* PACOG ***/
CBEndImp::CBEndImp() { int iSlmOptions = CSlm::UseGain | CSlm::Blend | CSlm::DynSearch | CSlm::UseTargetF0; int iTipsOptions = 0;
if ( (m_pSlm = CSlm::ClassFactory(iSlmOptions)) == NULL) { goto error; } if ((m_pTips = new CTips(iTipsOptions)) == NULL) { goto error; }
m_iPrevSamples = 0; m_iSynthBuffSamples = 0; m_pnSynthBuff = NULL; m_pnOverflow = NULL; m_iOverflowCurSamples = 0; m_iOverflowMaxSamples = 0;
m_pTips->Init(VAPI_PCM16, m_iDefSampFreq);
m_iNumUnits = 0; m_iCurrUnit = 0; m_iF0SampFreq = DEFAULT_F0_SAMPFREQ; m_pflF0 = NULL; return;
error: if ( m_pTips ) { delete m_pTips; m_pTips = NULL; }
return; }
/*****************************************************************************
* CBEndImp::~CBEndImp * *---------------------* * Description: * ******************************************************************* PACOG ***/
CBEndImp::~CBEndImp () { if (m_pSlm) { delete m_pSlm; }
if (m_pTips) { delete m_pTips; }
if ( m_pflF0 ) { delete[] m_pflF0; m_pflF0 = NULL; }
if ( m_pnSynthBuff ) { delete [] m_pnSynthBuff; m_pnSynthBuff = NULL; }
if ( m_pnOverflow ) { delete [] m_pnOverflow; m_pnOverflow = NULL; } }
/*****************************************************************************
* CBEndImp::LoadTable * *---------------------* * Description: * ******************************************************************* PACOG ***/
int CBEndImp::LoadTable (const char* pszFilePath, int iDebug) { assert (pszFilePath);
if (!m_pSlm->Load (pszFilePath, true)) { if (iDebug) { fprintf (stderr, "BackEnd: can't load table file %s\n", pszFilePath); } return 0; }
m_pTips->Init(m_pSlm->GetSampFormat(), m_pSlm->GetSampFreq());
m_iSynthBuffSamples = SYNTH_PROPORTION * m_pSlm->GetSampFreq(); if ((m_pnSynthBuff = new short[m_iSynthBuffSamples]) == NULL) { return 0; }
return 1; }
/*****************************************************************************
* CBEndImp::SetGain * *-------------------* * Description: * ******************************************************************* PACOG ***/ void CBEndImp::SetGain (double dGain) { m_pTips->SetGain(dGain); }
/*****************************************************************************
* CBEndImp::GetSampFreq * *-----------------------* * Description: * ******************************************************************* PACOG ***/ int CBEndImp::GetSampFreq () { return m_pSlm->GetSampFreq(); }
/*****************************************************************************
* CBEndImp::GetSpeakerInfo * *--------------------------* * Description: * ******************************************************************* PACOG ***/
void CBEndImp::GetSpeakerInfo (int* piBaseLine, int* piRefLine, int* piTopLine) { m_pSlm->GetTtpParam (piBaseLine, piRefLine, piTopLine); }
/*****************************************************************************
* CBEndImp::GetPhoneSetFlag * *--------------------------* * Description: * ******************************************************************* mplumpe ***/
bool CBEndImp::GetPhoneSetFlag () { return m_pSlm->GetPhoneSetFlag (); }
/*****************************************************************************
* CBEndImp::SetF0SampFreq * *-------------------------* * Description: * ******************************************************************* PACOG ***/ void CBEndImp::SetF0SampFreq(int iF0SampFreq) { assert (iF0SampFreq>0); m_iF0SampFreq = iF0SampFreq; }
/*****************************************************************************
* CBEndImp::NewPhoneString * *--------------------------* * Description: * ******************************************************************* PACOG ***/
int CBEndImp::NewPhoneString (Phone* phList, int nPh, float* newF0, int nNewF0) { assert (nPh==0 || phList!=NULL); assert (nNewF0==0 || newF0!=NULL); int nF0 = 0;
m_iCurrUnit = 0;
if (( m_iNumUnits = m_pSlm->Process (phList, nPh, 0.0)) == 0) { return 0; }
if ( m_pSlm->GetSynthMethod() ) { m_pSlm->GetNewF0 ( &m_pflF0, &nF0, m_iF0SampFreq); m_pTips->NewSentence (m_pflF0, nF0, m_iF0SampFreq); } else { m_pTips->NewSentence (newF0, nNewF0, m_iF0SampFreq); }
return 1; }
/*****************************************************************************
* CBEndImp::OutputPending * *-------------------------* * Description: * ******************************************************************* PACOG ***/
int CBEndImp::OutputPending () { return (m_iNumUnits - m_iCurrUnit) || m_pTips->Pending() || m_iOverflowCurSamples; }
/*****************************************************************************
* CBEndImp::GenerateOutput * *--------------------------* * Description: * ******************************************************************* PACOG ***/
int CBEndImp::GenerateOutput (short** ppnSamples, int* piNumSamples) { bool fDone = false; short* pnCurSamples = NULL; int iNumCurSamples = 0; assert (ppnSamples && piNumSamples && m_pnSynthBuff); if ( m_iOverflowCurSamples ) { assert( m_pnOverflow ); memcpy(m_pnSynthBuff, m_pnOverflow, m_iOverflowCurSamples * sizeof(short)); m_iPrevSamples = m_iOverflowCurSamples; m_iOverflowCurSamples = 0; } do { while ( m_pTips->Pending() ) { if (m_pTips->NextPeriod( &pnCurSamples, &iNumCurSamples)) { if ( m_iPrevSamples + iNumCurSamples <= m_iSynthBuffSamples ) { memcpy(&m_pnSynthBuff[m_iPrevSamples], pnCurSamples, iNumCurSamples * sizeof(short)); m_iPrevSamples += iNumCurSamples; } else { // something's wrong if a single period exceeds the buffer.
assert (iNumCurSamples <= m_iSynthBuffSamples); // is the overflow buffer too small?
if ( m_iOverflowMaxSamples < iNumCurSamples ) { if ( m_pnOverflow ) { delete [] m_pnOverflow; m_pnOverflow = NULL; } if ( (m_pnOverflow = new short[iNumCurSamples]) == NULL ) { return 0; } m_iOverflowMaxSamples = iNumCurSamples; } // save the extra in the overflow buffer
memcpy(m_pnOverflow, pnCurSamples, iNumCurSamples * sizeof(short)); m_iOverflowCurSamples = iNumCurSamples; fDone = true; break; } } }
if (!fDone) { if (m_iCurrUnit < m_iNumUnits) { if (! m_pTips->NewUnit (m_pSlm->GetUnit (m_iCurrUnit))) { return 0; } m_iCurrUnit ++; } else { *ppnSamples = 0; *piNumSamples = 0; fDone = true; } } } while (! fDone);
if ( m_iPrevSamples ) { *ppnSamples = m_pnSynthBuff; *piNumSamples = m_iPrevSamples; m_iPrevSamples = 0; } else { *ppnSamples = 0; *piNumSamples = 0; } return 1; }
/*****************************************************************************
* CBEndImp::GetChunk * *--------------------* * Description: * ******************************************************************* PACOG ***/
int CBEndImp::GetChunk(ChkDescript** ppChunk) { assert (ppChunk);
if (!ppChunk) { return 0; }
if (m_iNumUnits > 0) { if (m_iCurrUnit < m_iNumUnits) { *ppChunk = m_pSlm->GetChunk (m_iCurrUnit++); } }
return 1; }
|