windows-nt/Source/XPSP1/NT/enduser/speech/tts/common/vapiio/vapiio.cpp
2020-09-26 16:20:57 +08:00

1512 lines
38 KiB
C++

/******************************************************************************
* vapiIo.cpp *
*------------*
* I/O library functions for extended speech files (vapi format)
*------------------------------------------------------------------------------
* Copyright (C) 2000 Microsoft Corporation Date: 03/02/00
* All Rights Reserved
*
********************************************************************* PACOG ***/
#include "vapiIoInt.h"
#include <mmsystem.h>
#include <mmreg.h>
#include <assert.h>
#include <stdio.h>
typedef struct {
int code;
char* message;
} ErrorMsg;
class VapiFile : VapiIO
{
public:
VapiFile();
~VapiFile();
int OpenFile ( const char* pszFileName, int iMode );
int OpenFile ( const WCHAR* wcsFileName, int iMode );
void CloseFile ( );
int CreateChunk ( const char* pszName );
int CloseChunk ( );
int WriteToChunk (const char* pszData, int iSize);
int GetDataSize (long* lDataSize);
int Format (int* piSampFreq, int* piFormat, WAVEFORMATEX* pWaveFormatEx = NULL);
int WriteFormat (int iSampFreq, int iFormat);
int ReadSamples (double dFrom, double dTo, void** ppvSamples, int* piNumSamples, bool bClosedInterval);
int WriteSamples (void* pvSamples, int iNumSamples);
int ReadF0SampFreq (int* piSampFreq);
int WriteF0SampFreq (int iSampFreq);
int ReadFeature (char* pszName, float** ppfSamples, int* piNumSamples);
int WriteFeature (char* pszName, float* pfSamples, int iNumSamples);
int ReadEpochs (Epoch** ppEpochs, int* iNumEpochs);
int WriteEpochs (Epoch* pEpochs, int iNumEpochs);
int ReadLabels (char* pszName, Label** ppLabels, int* piNumLabels);
int WriteLabels (char* pszName, Label* pLabels, int iNumLabels);
char* ErrMessage (int iErrCode);
private:
HMMIO m_HWav;
MMCKINFO m_ParentInfo;
MMCKINFO m_SubchunkInfo;
int m_iSampFormat;
int m_iSampFreq;
static ErrorMsg m_ErrorMsg[];
static int m_iNumErrorMsg;
};
ErrorMsg VapiFile::m_ErrorMsg[] = {
{VAPI_IOERR_NOERROR, 0},
{VAPI_IOERR_MODE, "Wrong opening mode."},
{VAPI_IOERR_MEMORY, "Memory error."},
{VAPI_IOERR_CANTOPEN, "Error opening file."},
{VAPI_IOERR_NOWAV, "Not RIFF-WAVE format."},
{VAPI_IOERR_NOFORMAT, "Can't find data format."},
{VAPI_IOERR_STEREO, "File is stereo\n"},
{VAPI_IOERR_FORMAT, "Unknown data format."},
{VAPI_IOERR_NOCHUNK, "Error accessing data chunk."},
{VAPI_IOERR_DATAACCESS, "Error accessing input data."},
{VAPI_IOERR_WRITEWAV, "Error creating RIFF-WAVE chunk."},
{VAPI_IOERR_CREATECHUNK, "Error creating new subchunk."},
{VAPI_IOERR_WRITECHUNK, "Error writing data in new subchunk."}
};
int VapiFile::m_iNumErrorMsg = sizeof (VapiFile::m_ErrorMsg) / sizeof (VapiFile::m_ErrorMsg[0]);
/*****************************************************************************
* VapiIO::ClassFactory *
*----------------------*
* Description:
* Class Factory, creates an object of the VapiIO implementation class.
******************************************************************* PACOG ***/
VapiIO* VapiIO::ClassFactory ()
{
return new VapiFile();
}
/*****************************************************************************
* VapiIO::SizeOf *
*----------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiIO::SizeOf (int iType)
{
switch (iType)
{
case VAPI_PCM8:
case VAPI_ALAW:
case VAPI_ULAW:
return 1;
case VAPI_PCM16:
return 2;
default:
return 0;
}
return 0;
}
/*****************************************************************************
* VapiIO::TypeOf *
*----------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiIO::TypeOf (WAVEFORMATEX *pWavFormat)
{
int iSampFormat;
if (pWavFormat->wFormatTag == WAVE_FORMAT_PCM)
{
switch (pWavFormat->nBlockAlign/pWavFormat->nChannels)
{
case 1:
iSampFormat = VAPI_PCM8;
break;
case 2:
iSampFormat = VAPI_PCM16;
break;
default:
iSampFormat = -1;
break;
}
}
else if (pWavFormat->wFormatTag == WAVE_FORMAT_ALAW)
{
iSampFormat = VAPI_ALAW;
}
else if (pWavFormat->wFormatTag == WAVE_FORMAT_MULAW)
{
iSampFormat = VAPI_ULAW;
}
else
{
iSampFormat = -1;
}
return iSampFormat;
}
/*****************************************************************************
* VapiIO::DataFormatConversion *
*------------------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiIO::DataFormatConversion (char* pcInput, int iInType,
char* pcOutput, int iOutType, int iNumSamples)
{
int i;
assert (pcInput);
assert (pcOutput);
assert (iNumSamples>0);
// Check that these are valid types
if (!SizeOf(iInType) || !SizeOf(iOutType))
{
return 0;
}
// If same type, just copy samples
if (iInType == iOutType)
{
memcpy( pcOutput, pcInput, iNumSamples * SizeOf(iInType));
return 1;
}
// Ok, need to convert
switch (iInType)
{
case VAPI_PCM16:
switch (iOutType)
{
case VAPI_PCM8:
for (i=0; i<iNumSamples; i++)
{
pcOutput[i] = ((int)((short*)pcInput)[i] + 32768) >> 8;
}
break;
case VAPI_ALAW:
for (i=0; i<iNumSamples; i++)
{
pcOutput[i] = Linear2Alaw (((short*)pcInput)[i]);
}
break;
case VAPI_ULAW:
for (i=0; i<iNumSamples; i++)
{
pcOutput[i] = Linear2Ulaw (((short*)pcInput)[i]);
}
break;
}
break;
case VAPI_PCM8:
switch (iOutType)
{
case VAPI_PCM16:
for (i=0; i<iNumSamples; i++)
{
((short*)pcOutput)[i] = (((int)((char*)pcInput)[i])<<8) - 32768;
}
break;
case VAPI_ALAW:
for (i=0; i<iNumSamples; i++)
{
pcOutput[i] = Linear2Alaw ((short)((((int)((char*)pcInput)[i])<<8) - 32768));
}
break;
case VAPI_ULAW:
for (i=0; i<iNumSamples; i++)
{
pcOutput[i] = Linear2Ulaw ((short)((((int)((char*)pcInput)[i])<<8) - 32768));
}
break;
}
break;
case VAPI_ALAW:
switch (iOutType)
{
case VAPI_PCM16:
for (i=0; i<iNumSamples; i++)
{
((short*)pcOutput)[i] = (short) Alaw2Linear(((char*)pcInput)[i]);
}
break;
case VAPI_PCM8:
for (i=0; i<iNumSamples; i++)
{
pcOutput[i] = ((int)Alaw2Linear(((char*)pcInput)[i]) + 32768) >> 8;
}
break;
case VAPI_ULAW:
for (i=0; i<iNumSamples; i++)
{
pcOutput[i] = Alaw2Ulaw(((char*)pcInput)[i]);
}
break;
}
break;
case VAPI_ULAW:
switch (iOutType)
{
case VAPI_PCM16:
for (i=0; i<iNumSamples; i++)
{
((short*)pcOutput)[i] = (short) Ulaw2Linear(((char*)pcInput)[i]);
}
break;
case VAPI_PCM8:
for (i=0; i<iNumSamples; i++)
{
pcOutput[i] = ((int)Ulaw2Linear(((char*)pcInput)[i]) + 32768)>>8;
}
break;
case VAPI_ALAW:
for (i=0; i<iNumSamples; i++)
{
pcOutput[i] = Ulaw2Alaw(((char*)pcInput)[i]);
}
break;
}
break;
}
return 1;
}
/*****************************************************************************
* VapiFile::ErrMessage *
*----------------------*
* Description:
*
******************************************************************* PACOG ***/
char* VapiFile::ErrMessage (int errCode)
{
for (int i=0; i< m_iNumErrorMsg; i++)
{
if (errCode == m_ErrorMsg[i].code)
{
return m_ErrorMsg[i].message;
}
}
return 0;
}
/*****************************************************************************
* VapiFile::VapiFile *
*--------------------*
* Description:
*
******************************************************************* PACOG ***/
VapiFile::VapiFile()
{
m_HWav = 0;
memset (&m_ParentInfo, 0, sizeof(m_ParentInfo));
memset (&m_SubchunkInfo, 0, sizeof(m_SubchunkInfo));
m_iSampFormat = 0;
m_iSampFreq = 0;
}
/*****************************************************************************
* VapiFile::~VapiFile *
*---------------------*
* Description:
*
******************************************************************* PACOG ***/
VapiFile::~VapiFile()
{
CloseFile();
}
/*****************************************************************************
* VapiFile::OpenFile *
*--------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::OpenFile (const char* pszFileName, int iMode)
{
int iErrCode = VAPI_IOERR_NOERROR;
assert (pszFileName);
switch (iMode)
{
case VAPI_IO_READ:
iMode = MMIO_READ;
break;
case VAPI_IO_WRITE:
iMode = MMIO_WRITE|MMIO_CREATE;
break;
case VAPI_IO_READWRITE:
iMode = MMIO_READWRITE;
break;
default:
return VAPI_IOERR_MODE;
}
if ((m_HWav = mmioOpen ((char *)pszFileName, NULL, iMode)) == NULL)
{
iErrCode = VAPI_IOERR_CANTOPEN;
goto error;
}
if (iMode == MMIO_READ)
{
m_ParentInfo.fccType = mmioFOURCC ('W', 'A', 'V', 'E');
if (mmioDescend (m_HWav, &m_ParentInfo, 0, MMIO_FINDRIFF))
{
iErrCode = VAPI_IOERR_NOWAV;
goto error;
}
}
else
{
m_ParentInfo.fccType = mmioFOURCC ('W', 'A', 'V', 'E');
if (mmioCreateChunk (m_HWav, &m_ParentInfo, MMIO_CREATERIFF))
{
iErrCode = VAPI_IOERR_WRITEWAV;
goto error;
}
}
return VAPI_IOERR_NOERROR;
error:
CloseFile ();
return iErrCode;
}
/*****************************************************************************
* VapiFile::OpenFile *
*--------------------*
* Description: Same as previous OpenFile, but takes WCHAR* as arg
*
******************************************************************* JOEM ****/
int VapiFile::OpenFile (const WCHAR* wcsFileName, int iMode)
{
int iErrCode = VAPI_IOERR_NOERROR;
assert (wcsFileName);
switch (iMode)
{
case VAPI_IO_READ:
iMode = MMIO_READ;
break;
case VAPI_IO_WRITE:
iMode = MMIO_WRITE|MMIO_CREATE;
break;
case VAPI_IO_READWRITE:
iMode = MMIO_READWRITE;
break;
default:
return VAPI_IOERR_MODE;
}
if ((m_HWav = mmioOpenW ((WCHAR *)wcsFileName, NULL, iMode)) == NULL)
{
iErrCode = VAPI_IOERR_CANTOPEN;
goto error;
}
if (iMode == MMIO_READ)
{
m_ParentInfo.fccType = mmioFOURCC ('W', 'A', 'V', 'E');
if (mmioDescend (m_HWav, &m_ParentInfo, 0, MMIO_FINDRIFF))
{
iErrCode = VAPI_IOERR_NOWAV;
goto error;
}
}
else
{
m_ParentInfo.fccType = mmioFOURCC ('W', 'A', 'V', 'E');
if (mmioCreateChunk (m_HWav, &m_ParentInfo, MMIO_CREATERIFF))
{
iErrCode = VAPI_IOERR_WRITEWAV;
goto error;
}
}
return VAPI_IOERR_NOERROR;
error:
CloseFile ();
return iErrCode;
}
/*****************************************************************************
* VapiFile::CloseFile *
*---------------------*
* Description:
*
******************************************************************* PACOG ***/
void VapiFile::CloseFile ()
{
if (m_HWav)
{
mmioAscend (m_HWav, &m_ParentInfo, 0);
mmioClose (m_HWav, 0);
memset (&m_ParentInfo, 0, sizeof(m_ParentInfo));
m_HWav = 0;
}
}
/*****************************************************************************
* VapiFile::Format *
*------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::Format (int* piSampFreq, int* piFormat, WAVEFORMATEX* pWaveFormatEx)
{
WAVEFORMATEX* WavFormat = NULL;
WAVEFORMATEX LocalWaveFormat;
MMCKINFO SubchunkInfo;
int iErrCode = VAPI_IOERR_NOERROR;
assert (m_HWav);
memset((void*)&LocalWaveFormat, 0, sizeof(WAVEFORMATEX));
if ( pWaveFormatEx )
{
memset((void*)pWaveFormatEx, 0, sizeof(WAVEFORMATEX));
WavFormat = pWaveFormatEx;
}
else
{
WavFormat = &LocalWaveFormat;
}
mmioSeek (m_HWav, m_ParentInfo.dwDataOffset+4, SEEK_SET);
SubchunkInfo.ckid = mmioFOURCC ('f', 'm', 't', ' ');
if (mmioDescend (m_HWav, &SubchunkInfo, &m_ParentInfo, MMIO_FINDCHUNK) )
{
iErrCode = VAPI_IOERR_NOFORMAT;
goto error;
}
if (mmioRead (m_HWav, (char *)WavFormat, SubchunkInfo.cksize)!= (int)SubchunkInfo.cksize)
{
iErrCode = VAPI_IOERR_NOFORMAT;
goto error;
}
mmioAscend (m_HWav, &SubchunkInfo, 0);
/*
* Process header info.
* Files must be mono, and in one of these formats
*/
if (WavFormat->nChannels >1 )
{
iErrCode = VAPI_IOERR_STEREO;
goto error;
}
m_iSampFormat = TypeOf (WavFormat);
if (m_iSampFormat < 0)
{
iErrCode = VAPI_IOERR_FORMAT;
goto error;
}
m_iSampFreq = WavFormat->nSamplesPerSec;
if (piFormat)
{
*piFormat = m_iSampFormat;
}
if (piSampFreq)
{
*piSampFreq = m_iSampFreq;
}
error:
return iErrCode;
}
/*****************************************************************************
* VapiFile::GetDataSize *
*------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::GetDataSize (long* lDataSize)
{
MMCKINFO SubchunkInfo;
int iErrCode = VAPI_IOERR_NOERROR;
/*
* Go for the data
*/
mmioSeek (m_HWav, m_ParentInfo.dwDataOffset+4, SEEK_SET);
SubchunkInfo.ckid = mmioFOURCC ('d', 'a', 't', 'a');
if (mmioDescend (m_HWav, &SubchunkInfo, &m_ParentInfo, MMIO_FINDCHUNK))
{
iErrCode = VAPI_IOERR_NOCHUNK;
goto error;
}
*lDataSize = SubchunkInfo.cksize;
mmioAscend (m_HWav, &SubchunkInfo, 0);
error:
return iErrCode;
}
/*****************************************************************************
* VapiFile::WriteFormat *
*-----------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::WriteFormat (int iSampFreq, int iFormat)
{
WAVEFORMATEX WavFormat;
MMCKINFO SubchunkInfo;
int iErrCode = VAPI_IOERR_NOERROR;
assert (m_HWav);
assert (iSampFreq>0);
switch (iFormat)
{
case VAPI_PCM8:
WavFormat.wFormatTag = WAVE_FORMAT_PCM;
WavFormat.wBitsPerSample = 8;
break;
case VAPI_ALAW:
WavFormat.wFormatTag = WAVE_FORMAT_ALAW;
WavFormat.wBitsPerSample = 8;
break;
case VAPI_ULAW:
WavFormat.wFormatTag = WAVE_FORMAT_MULAW;
WavFormat.wBitsPerSample = 8;
break;
case VAPI_PCM16:
WavFormat.wFormatTag = WAVE_FORMAT_PCM;
WavFormat.wBitsPerSample = 16;
break;
default:
iErrCode = VAPI_IOERR_FORMAT;
goto error;
}
WavFormat.nChannels = 1;
WavFormat.nSamplesPerSec = iSampFreq;
WavFormat.nBlockAlign = (WavFormat.wBitsPerSample / 8) ;
WavFormat.nAvgBytesPerSec = WavFormat.nBlockAlign * WavFormat.nSamplesPerSec;
WavFormat.cbSize = 0;
SubchunkInfo.ckid = mmioFOURCC ('f', 'm', 't', ' ');
if (mmioCreateChunk (m_HWav, &SubchunkInfo, 0) )
{
iErrCode = VAPI_IOERR_CREATECHUNK;
goto error;
}
if (mmioWrite(m_HWav, (char *)&WavFormat, sizeof(WavFormat)) != (int)sizeof(WavFormat))
{
iErrCode = VAPI_IOERR_WRITECHUNK;
goto error;
}
mmioAscend (m_HWav, &SubchunkInfo, 0);
m_iSampFreq = iSampFreq;
m_iSampFormat = iFormat;
error:
return iErrCode;
}
/*****************************************************************************
* VapiFile::CreateChunk *
*-----------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::CreateChunk (const char* pszName)
{
assert (pszName);
m_SubchunkInfo.ckid = mmioStringToFOURCC (pszName, 0);
if (mmioCreateChunk (m_HWav, &m_SubchunkInfo, 0))
{
return VAPI_IOERR_CREATECHUNK;
}
return VAPI_IOERR_NOERROR;
}
/*****************************************************************************
* VapiFile::WriteToChunk *
*------------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::WriteToChunk (const char* pcData, int iSize)
{
assert (pcData);
assert (iSize>0);
if ( mmioWrite (m_HWav, pcData, iSize) != iSize )
{
return VAPI_IOERR_WRITECHUNK;
}
return VAPI_IOERR_NOERROR;
}
/*****************************************************************************
* VapiFile::CloseChunk *
*----------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::CloseChunk ( )
{
assert (m_HWav);
mmioAscend (m_HWav, &m_SubchunkInfo, 0);
return VAPI_IOERR_NOERROR;
}
/*****************************************************************************
* VapiFile::ReadSamples *
*-----------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::ReadSamples (double dFrom, double dTo,
void** ppvSamples, int* piNumSamples, bool bClosedInterval)
{
MMCKINFO SubchunkInfo;
int iErrCode = VAPI_IOERR_NOERROR;
void* pvBuffer = NULL;
int iBuffLen;
int iBuffLenInFile;
int iSkipBytes;
long lRead;
double dEndOfData;
assert (m_HWav);
assert (ppvSamples);
assert (piNumSamples);
assert (dFrom>=0.0);
assert (dTo == -1.0 || dTo>=dFrom);
/*
* Go for the data
*/
mmioSeek (m_HWav, m_ParentInfo.dwDataOffset+4, SEEK_SET);
SubchunkInfo.ckid = mmioFOURCC ('d', 'a', 't', 'a');
if (mmioDescend (m_HWav, &SubchunkInfo, &m_ParentInfo, MMIO_FINDCHUNK))
{
iErrCode = VAPI_IOERR_NOCHUNK;
goto error;
}
iBuffLenInFile = SubchunkInfo.cksize;
dEndOfData = ((double)iBuffLenInFile) / SizeOf(m_iSampFormat) / m_iSampFreq;
if ( dFrom > dEndOfData )
{
// nothing to read
iErrCode = VAPI_IOERR_NOCHUNK;
goto error;
}
if ( dTo != -1.0 && dFrom >= dTo )
{
// nothing to read
iErrCode = VAPI_IOERR_NOCHUNK;
goto error;
}
/*
* Read only the desired region
*/
if (dFrom < 0.0)
{
dFrom = 0.0;
}
iSkipBytes = (int)(dFrom * m_iSampFreq + 0.5) * SizeOf(m_iSampFormat);
if (dTo == -1.0)
{
iBuffLen = iBuffLenInFile;
}
else
{
iBuffLen = (int)(dTo * m_iSampFreq + 0.5) * SizeOf(m_iSampFormat);
if (iBuffLen>=iBuffLenInFile)
{
dTo = -1.0;
iBuffLen = iBuffLenInFile;
}
}
iBuffLen -= iSkipBytes;
if (bClosedInterval && dTo != -1.0)
{
iBuffLen += SizeOf (m_iSampFormat);
}
if (iSkipBytes>0 && mmioSeek (m_HWav, iSkipBytes, SEEK_CUR) == -1)
{
iErrCode = VAPI_IOERR_DATAACCESS;
goto error;
}
if ((pvBuffer = new char[iBuffLen]) == NULL)
{
iErrCode = VAPI_IOERR_MEMORY;
goto error;
}
lRead = mmioRead (m_HWav, (char *)pvBuffer, iBuffLen);
if ( lRead != (int)iBuffLen)
{
iErrCode = VAPI_IOERR_DATAACCESS;
goto error;
}
mmioAscend (m_HWav, &SubchunkInfo, 0);
*ppvSamples = pvBuffer;
*piNumSamples = iBuffLen/SizeOf(m_iSampFormat);
return VAPI_IOERR_NOERROR;
error:
if (pvBuffer)
{
delete[] pvBuffer;
}
return iErrCode;
}
/*****************************************************************************
* VapiFile::WriteSamples *
*------------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::WriteSamples (void* pvSamples, int iNumSamples)
{
MMCKINFO subchunkInfo;
int iErrCode = VAPI_IOERR_NOERROR;
int iBuffLen;
assert (m_HWav);
assert (pvSamples);
assert (iNumSamples>0);
subchunkInfo.ckid = mmioFOURCC ('d', 'a', 't', 'a');
if (mmioCreateChunk (m_HWav, &subchunkInfo, 0) )
{
iErrCode = VAPI_IOERR_CREATECHUNK;
goto error;
}
iBuffLen = iNumSamples * SizeOf (m_iSampFormat);
if (mmioWrite(m_HWav, (char *)pvSamples, iBuffLen) != iBuffLen)
{
iErrCode = VAPI_IOERR_WRITECHUNK;
goto error;
}
mmioAscend (m_HWav, &subchunkInfo, 0);
error:
return iErrCode;
}
/*****************************************************************************
* VapiFile::ReadF0SampFreq *
*--------------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::ReadF0SampFreq (int* piSampFreq)
{
MMCKINFO SubchunkInfo;
int iErrCode = VAPI_IOERR_NOERROR;
assert (m_HWav);
assert (piSampFreq);
mmioSeek (m_HWav, m_ParentInfo.dwDataOffset+4, SEEK_SET);
SubchunkInfo.ckid = mmioFOURCC ('f', '0', 's', 'f') ;
if (mmioDescend (m_HWav, &SubchunkInfo, &m_ParentInfo, MMIO_FINDCHUNK) == MMIOERR_CHUNKNOTFOUND)
{
iErrCode = VAPI_IOERR_NOCHUNK;
}
else
{
if (mmioRead (m_HWav, (char *)piSampFreq, SubchunkInfo.cksize) != (int)SubchunkInfo.cksize)
{
iErrCode = VAPI_IOERR_F0SFACCESS;
goto error;
}
mmioAscend (m_HWav, &SubchunkInfo, 0);
}
error:
return iErrCode;
}
/*****************************************************************************
* VapiFile::WriteF0SampFreq *
*---------------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::WriteF0SampFreq (int iSampFreq)
{
MMCKINFO SubchunkInfo;
int iErrCode = VAPI_IOERR_NOERROR;
assert (m_HWav);
assert (iSampFreq>0);
SubchunkInfo.ckid = mmioFOURCC ('f', '0', 's', 'f') ;
if (mmioCreateChunk (m_HWav, &SubchunkInfo, 0) )
{
iErrCode = VAPI_IOERR_CREATECHUNK;
goto error;
}
if (mmioWrite(m_HWav, (char *)&iSampFreq, sizeof(iSampFreq)) != sizeof(iSampFreq))
{
iErrCode = VAPI_IOERR_WRITECHUNK;
goto error;
}
mmioAscend (m_HWav, &SubchunkInfo, 0);
error:
return iErrCode;
}
/*****************************************************************************
* VapiFile::ReadFeature *
*-----------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::ReadFeature (char* pszName, float** ppfSamples, int* piNumSamples)
{
MMCKINFO SubchunkInfo;
int iErrCode = VAPI_IOERR_NOERROR;
assert (m_HWav);
assert (pszName);
assert (ppfSamples);
assert (piNumSamples);
mmioSeek (m_HWav, m_ParentInfo.dwDataOffset+4, SEEK_SET);
SubchunkInfo.ckid = mmioStringToFOURCC (pszName, 0);
if (mmioDescend (m_HWav, &SubchunkInfo, &m_ParentInfo, MMIO_FINDCHUNK) == MMIOERR_CHUNKNOTFOUND)
{
iErrCode = VAPI_IOERR_NOCHUNK;
}
else
{
*piNumSamples = SubchunkInfo.cksize/ sizeof(**ppfSamples);
if ((*ppfSamples = new float[SubchunkInfo.cksize/sizeof(float)]) == NULL )
{
iErrCode = VAPI_IOERR_MEMORY;
goto error;
}
if (mmioRead (m_HWav, (char *)*ppfSamples, SubchunkInfo.cksize) != (int)SubchunkInfo.cksize)
{
iErrCode = VAPI_IOERR_FEATACCESS;
goto error;
}
mmioAscend (m_HWav, &SubchunkInfo, 0);
}
error:
return iErrCode;
}
/*****************************************************************************
* VapiFile::WriteFeature *
*------------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::WriteFeature (char* pszName, float* pfSamples, int iNumSamples)
{
MMCKINFO SubchunkInfo;
int iErrCode = VAPI_IOERR_NOERROR;
int iBuffLen;
assert (m_HWav);
assert (pszName);
assert (pfSamples);
assert (iNumSamples>0);
SubchunkInfo.ckid = mmioStringToFOURCC (pszName, 0);
if (mmioCreateChunk (m_HWav, &SubchunkInfo, 0) )
{
iErrCode = VAPI_IOERR_CREATECHUNK;
goto error;
}
iBuffLen = iNumSamples * sizeof(*pfSamples);
if (mmioWrite(m_HWav, (char *)pfSamples, iBuffLen) != iBuffLen)
{
iErrCode = VAPI_IOERR_WRITECHUNK;
goto error;
}
mmioAscend (m_HWav, &SubchunkInfo, 0);
error:
return iErrCode;
}
/*****************************************************************************
* VapiFile::ReadEpochs *
*----------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::ReadEpochs (Epoch** ppEpochs, int* piNumEpochs)
{
MMCKINFO SubchunkInfo;
int iErrCode = VAPI_IOERR_NOERROR;
assert (m_HWav);
assert (ppEpochs);
assert (piNumEpochs);
mmioSeek (m_HWav, m_ParentInfo.dwDataOffset+4, SEEK_SET);
SubchunkInfo.ckid = mmioFOURCC ('e', 'p', 'o', 'c');
if (mmioDescend (m_HWav, &SubchunkInfo, &m_ParentInfo, MMIO_FINDCHUNK) == MMIOERR_CHUNKNOTFOUND)
{
iErrCode = VAPI_IOERR_NOCHUNK;
goto error;
}
else
{
*piNumEpochs = SubchunkInfo.cksize / sizeof(**ppEpochs);
if ((*ppEpochs = new Epoch[SubchunkInfo.cksize/sizeof(Epoch)]) == NULL )
{
iErrCode = VAPI_IOERR_MEMORY;
goto error;
}
if (mmioRead (m_HWav, (char *)*ppEpochs, SubchunkInfo.cksize) != (int)SubchunkInfo.cksize)
{
iErrCode = VAPI_IOERR_EPOCHACCESS;
goto error;
}
mmioAscend (m_HWav, &SubchunkInfo, 0);
}
error:
return iErrCode;
}
/*****************************************************************************
* VapiFile::WriteEpochs *
*-----------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::WriteEpochs (Epoch* pEpochs, int iNumEpochs)
{
MMCKINFO SubchunkInfo;
int iErrCode = VAPI_IOERR_NOERROR;
int iBuffLen;
assert (m_HWav);
assert (pEpochs);
assert (iNumEpochs>0);
SubchunkInfo.ckid = mmioFOURCC ('e', 'p', 'o', 'c');
if (mmioCreateChunk (m_HWav, &SubchunkInfo, 0) )
{
iErrCode = VAPI_IOERR_CREATECHUNK;
goto error;
}
iBuffLen = iNumEpochs * sizeof(*pEpochs);
if (mmioWrite(m_HWav, (char *)pEpochs, iBuffLen) != iBuffLen)
{
iErrCode = VAPI_IOERR_WRITECHUNK;
goto error;
}
mmioAscend (m_HWav, &SubchunkInfo, 0);
error:
return iErrCode;
}
/*****************************************************************************
* VapiFile::ReadLabels *
*----------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::ReadLabels (char* pszName, Label** ppLabels, int* piNumLabels)
{
MMCKINFO SubchunkInfo;
int iErrCode = VAPI_IOERR_NOERROR;
assert (m_HWav);
assert (pszName);
assert (ppLabels);
assert (piNumLabels);
mmioSeek (m_HWav, m_ParentInfo.dwDataOffset+4, SEEK_SET);
SubchunkInfo.ckid = mmioStringToFOURCC (pszName, 0);
if (mmioDescend (m_HWav, &SubchunkInfo, &m_ParentInfo, MMIO_FINDCHUNK) == MMIOERR_CHUNKNOTFOUND)
{
iErrCode = VAPI_IOERR_NOCHUNK;
}
else
{
*piNumLabels = SubchunkInfo.cksize/ sizeof(**ppLabels);
if ((*ppLabels = new Label[SubchunkInfo.cksize/sizeof(Label)]) == NULL )
{
iErrCode = VAPI_IOERR_MEMORY;
goto error;
}
if (mmioRead (m_HWav, (char *)*ppLabels, SubchunkInfo.cksize) != (int)SubchunkInfo.cksize)
{
iErrCode = VAPI_IOERR_LABELACCESS;
goto error;
}
mmioAscend (m_HWav, &SubchunkInfo, 0);
}
error:
return iErrCode;
}
/*****************************************************************************
* VapiFile::WriteLabels *
*-----------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiFile::WriteLabels (char* pszName, Label* pLabels, int iNumLabels)
{
MMCKINFO SubchunkInfo;
int iErrCode = VAPI_IOERR_NOERROR;
int iBuffLen;
assert (m_HWav);
assert (pszName);
assert (pLabels);
assert (iNumLabels>0);
SubchunkInfo.ckid = mmioStringToFOURCC (pszName, 0);
if (mmioCreateChunk (m_HWav, &SubchunkInfo, 0) )
{
iErrCode = VAPI_IOERR_CREATECHUNK;
goto error;
}
iBuffLen = iNumLabels * sizeof(*pLabels);
if (mmioWrite(m_HWav, (char *)pLabels, iBuffLen) != iBuffLen)
{
iErrCode = VAPI_IOERR_WRITECHUNK;
goto error;
}
mmioAscend (m_HWav, &SubchunkInfo, 0);
error:
return iErrCode;
}
/*****************************************************************************
* VapiIO::ReadVapiFile *
*----------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiIO::ReadVapiFile (const char* pszFileName, short** ppnSamples, int* piNumSamples,
int* piSampFreq, int* piSampFormat, int* piF0SampFreq,
float** ppfF0, int* piNumF0, float** ppfRms, int* piNumRms,
Epoch** ppEpochs, int* piNumEpochs,
Label** ppPhones, int* piNumPhones, Label** ppWords, int* piNumWords)
{
VapiIO* pViof = 0;
void* pvBuffer = NULL;
int iErrCode = VAPI_IOERR_NOERROR;
int iRetVal;
assert (pszFileName);
if (( pViof = VapiIO::ClassFactory()) == 0)
{
iErrCode = VAPI_IOERR_MEMORY;
goto error;
}
if ( (iRetVal = pViof->OpenFile (pszFileName, VAPI_IO_READ)) != VAPI_IOERR_NOERROR)
{
iErrCode = iRetVal;
goto error;
}
if (ppnSamples && piNumSamples)
{
int sFreq;
int sType;
iRetVal = pViof->Format (&sFreq, &sType);
switch (iRetVal)
{
case VAPI_IOERR_NOERROR:
break;
case VAPI_IOERR_NOCHUNK:
sFreq = 0;
break;
default:
iErrCode = iRetVal;
goto error;
}
if (piSampFreq)
{
*piSampFreq = sFreq;
}
if (piSampFormat)
{
*piSampFormat = sType;
}
/*
* Read samples
*/
iRetVal = pViof->ReadSamples (0.0, -1.0, &pvBuffer, piNumSamples, 0);
switch (iRetVal)
{
case VAPI_IOERR_NOERROR:
break;
case VAPI_IOERR_NOCHUNK:
*ppnSamples = NULL;
*piNumSamples = 0;
break;
default:
iErrCode = iRetVal;
goto error;
}
/*
* Convert samples to PCM16
*/
if ( (*ppnSamples = new short[*piNumSamples]) == 0)
{
iErrCode = VAPI_IOERR_MEMORY;
goto error;
}
DataFormatConversion ((char *)pvBuffer, sType, (char*)*ppnSamples, VAPI_PCM16, *piNumSamples);
delete[] pvBuffer;
}
if (piF0SampFreq)
{
iRetVal = pViof->ReadF0SampFreq (piF0SampFreq);
switch (iRetVal)
{
case VAPI_IOERR_NOERROR:
break;
case VAPI_IOERR_NOCHUNK:
*piF0SampFreq = 0;
break;
default:
iErrCode = iRetVal;
goto error;
}
}
if (ppEpochs && piNumEpochs)
{
iRetVal = pViof->ReadEpochs(ppEpochs, piNumEpochs);
switch (iRetVal)
{
case VAPI_IOERR_NOERROR:
break;
case VAPI_IOERR_NOCHUNK:
*ppEpochs = NULL;
*piNumEpochs = 0;
break;
default:
iErrCode = iRetVal;
goto error;
}
}
if (ppfF0 && piNumF0)
{
iRetVal = pViof->ReadFeature ("f0", ppfF0, piNumF0);
switch (iRetVal)
{
case VAPI_IOERR_NOERROR:
break;
case VAPI_IOERR_NOCHUNK:
*ppfF0 = NULL;
*piNumF0 = 0;
break;
default:
iErrCode = iRetVal;
goto error;
}
}
if (ppfRms && piNumRms)
{
iRetVal = pViof->ReadFeature ("rms", ppfRms, piNumRms);
switch (iRetVal)
{
case VAPI_IOERR_NOERROR:
break;
case VAPI_IOERR_NOCHUNK:
*ppfRms = NULL;
*piNumRms = 0;
break;
default:
iErrCode = iRetVal;
goto error;
}
}
if (ppPhones && piNumPhones)
{
iRetVal = pViof->ReadLabels ("phon", ppPhones, piNumPhones);
switch (iRetVal)
{
case VAPI_IOERR_NOERROR:
break;
case VAPI_IOERR_NOCHUNK:
*ppPhones = NULL;
*piNumPhones = 0;
break;
default:
iErrCode = iRetVal;
goto error;
}
}
if (ppWords && piNumWords)
{
iRetVal = pViof->ReadLabels ("word", ppWords, piNumWords);
switch (iRetVal)
{
case VAPI_IOERR_NOERROR:
break;
case VAPI_IOERR_NOCHUNK:
*ppWords = NULL;
*piNumWords = 0;
break;
default:
iErrCode = iRetVal;
goto error;
}
}
error:
if (pViof)
{
pViof->CloseFile();
delete pViof;
}
return iErrCode;
}
/*****************************************************************************
* VapiIO::WriteVapiFile *
*-----------------------*
* Description:
*
******************************************************************* PACOG ***/
int VapiIO::WriteVapiFile (const char* pszFileName, short* pnSamples, int iNumSamples, int iFormat,
int iSampFreq, int iF0SampFreq, float* pfF0, int iNumF0,
float* pfRms, int iNumRms, Epoch* pEpochs, int iNumEpochs,
Label* pPhones, int iNumPhones, Label* pWords, int iNumWords)
{
VapiIO* pViof = 0;
void* pvBuffer = 0;
int iErrCode = VAPI_IOERR_NOERROR;
int iRetVal;
assert (pszFileName);
if (( pViof = VapiIO::ClassFactory()) == 0)
{
iErrCode = VAPI_IOERR_MEMORY;
goto error;
}
if ( (iRetVal = pViof->OpenFile (pszFileName, VAPI_IO_WRITE)) != VAPI_IOERR_NOERROR)
{
iErrCode = iRetVal;
goto error;
}
if (pnSamples && iNumSamples)
{
if ((iRetVal = pViof->WriteFormat (iSampFreq, iFormat)) != VAPI_IOERR_NOERROR)
{
iErrCode = iRetVal;
goto error;
}
/*
* Convert samples to output format
*/
if ( (pvBuffer = new char[iNumSamples * SizeOf(iFormat)]) == NULL)
{
iErrCode = VAPI_IOERR_MEMORY;
goto error;
}
DataFormatConversion ((char*)pnSamples, VAPI_PCM16, (char *)pvBuffer, iFormat, iNumSamples);
/*
* Write samples
*/
if ((iRetVal = pViof->WriteSamples (pvBuffer, iNumSamples)) != VAPI_IOERR_NOERROR)
{
iErrCode = iRetVal;
goto error;
}
delete[] pvBuffer;
}
if (iF0SampFreq)
{
if ((iRetVal = pViof->WriteF0SampFreq (iF0SampFreq)) != VAPI_IOERR_NOERROR)
{
iErrCode = iRetVal;
goto error;
}
}
if (pEpochs && iNumEpochs)
{
if ((iRetVal = pViof->WriteEpochs (pEpochs, iNumEpochs)) != VAPI_IOERR_NOERROR)
{
iErrCode = iRetVal;
goto error;
}
}
if (pfF0 && iNumF0)
{
if ((iRetVal = pViof->WriteFeature ("f0", pfF0, iNumF0)) != VAPI_IOERR_NOERROR)
{
iErrCode = iRetVal;
goto error;
}
}
if (pfRms && iNumRms)
{
if ((iRetVal = pViof->WriteFeature ("rms", pfRms, iNumRms)) != VAPI_IOERR_NOERROR)
{
iErrCode = iRetVal;
goto error;
}
}
if (pPhones && iNumPhones)
{
if ((iRetVal = pViof->WriteLabels ("phon", pPhones, iNumPhones))!= VAPI_IOERR_NOERROR)
{
iErrCode = iRetVal;
goto error;
}
}
if (pWords && iNumWords)
{
if ((iRetVal = pViof->WriteLabels ("word", pWords, iNumWords)) != VAPI_IOERR_NOERROR)
{
iErrCode = iRetVal;
goto error;
}
}
error:
if (pViof)
{
pViof->CloseFile ();
delete pViof;
}
return iErrCode;
}