自己根据示例代码改写的可以用于Text-to-Speech的类库

 

这个类用起来很方便。直接按照方法的名字来就可以了。

类使用到的结构定义

 

代码
#ifndef __STRUCTFORSRANDTTS
#define __STRUCTFORSRANDTTS

#include 
"stdafx.h"
#include 
<vector>
#include 
<string>



typedef 
struct strMessageMap
{
    UINT m_message;
    
bool (*m_pFunc)(void*void*);
    DWORD 
* m_pParam;
    strMessageMap(UINT message, 
bool (*pFunc)(void*void*), DWORD * pParam)
        :m_message( message ),
        m_pFunc(pFunc),
        m_pParam(pParam){}
}MESSAGE_MAP, 
* PMESSAGE_MAP;

typedef 
struct strStreamFormat 
{
    
int m_index;
    
int m_khz;
    
int m_bit;
    
bool m_bMono;
    
void Generate(int index, int khz, int bit, bool bMono)
    {
        m_index 
= index;
        m_khz 
= khz;
        m_bit 
= bit;
        m_bMono 
= bMono;
    }
}STREAMFORMAT, 
*PSTREAMFORMAT;


typedef 
struct  strRecoResult
{
    
int                     m_ruleID; // ruleId
    std::vector<ULONG>     m_recoWordsIDArr; // array for recognized words id
    std::vector<std::wstring> m_recoWordsDesArr;// array for recognized words description string
    std::vector<int>     m_WordsPosition; // array for recognized words position in 
                                         
//the original spoken sentence 
    std::vector<int>     m_WordsNum;      // array for numbers of a single group recognized words.
                                         
// ie. how many words are there in the group

    
int                m_number; // number of recognized words
    
    
void Clear()
    {
        m_recoWordsDesArr.clear();
        m_recoWordsIDArr.clear();
        m_WordsNum.clear();
        m_WordsPosition.clear();
        m_number 
= 0;
    }

}RECORESULT, 
*PRECORESULT;


typedef 
struct strNewRuleInfo
{
    
int        m_ruleID;
    
int        m_propID;
    std::wstring    m_des;
    strNewRuleInfo(
int ruleID, int propID, std::wstring des)
        : m_ruleID(ruleID),
          m_propID(propID),
          m_des(des){}
}NEWRULEINFO, 
*PNUEWRULEINFO;

#endif

 

 

 

.h

 

代码
#ifndef    __TEXTTOREAD
#define __TEXTTOREAD

#pragma warning (disable: 4995)

#include 
"stdafx.h"
#include 
<windows.h>
#include 
<sapi.h>           // SAPI includes
#include <sphelper.h>
#include 
<spuihelp.h>
#include 
<vector>
#include 
"StructForSRandTTS.h"

class CTextToRead
{
public:
    CTextToRead();
    
~CTextToRead();


public:
    
void    _ReadText(WCHAR* pszwBuff);
    
void    _ReadFromFile(TCHAR* szFileName, BOOL* bIsUnicode);
    
void    _PauseRestartRead();
    
void    _StopRead();
    
bool    _ChangeVoice(ISpObjectToken* pToken);
    
bool    _ChangeVoice(WCHAR * voice);
    
// to use this method, first get the number of voices and length of each 
    
// voice description, and then allocate memory for WCHAR* VoiceDesArr[num],
    
// and reuse the method with VoiceDesArr.
    bool    _GetVoiceList(WCHAR ** ppVoiceDesArr, int* pWordsLengthArr, ULONG& numOfVoice);


    
bool    _NotifyWindowMessage(HWND hWnd, UINT Message);
    
//messages passed to the following three methods are 
    
//those that used in SAPI, beginning with SPEI_
    void    _RegisterMessageFunc(UINT message, bool (*pFunc)(void *void*), DWORD * param);
    
bool    _UnRegisterMessage(UINT message);
    
int        _DealMessage(UINT message);
    
    
bool    _PlayWave(TCHAR* szFileName);
    
bool    _SaveToWavFile(WCHAR* szFileName, WCHAR* wszTextToSave);

public:
    
void    _SetVolumn(USHORT volumn) {m_Volume = volumn; m_cpVoice->SetVolume((USHORT)m_Volume);}
    USHORT    _GetVolumn(){
return m_Volume; }
    
void    _SetRate(long rate){m_Rate = rate; m_cpVoice->SetRate(m_Rate);}
    
long    _GetRate(){return m_Rate; }
    HRESULT    _SetOutStreamFormat(SPSTREAMFORMAT format);
    
//only support Standard PCM wave formats
    HRESULT    _SetOutStreamFormat(int khz, int bit, bool bMono);


    SPSTREAMFORMAT    _GetOutStreamFormat(){
return m_CurrentStreamFormat; }
    

private:
    HRESULT _InitSapi();
    HRESULT _ReadTheFile( TCHAR
* szFileName, BOOL* bIsUnicode, WCHAR** ppszwBuff );
    
//available param is 'Mary', 'Mike', and 'Chinese'
    HRESULT _GetVoice(WCHAR * voice , ISpObjectToken ** ppGotToken);
    
void    _makeRelation();


private:
    CTextToRead(CTextToRead 
& ){}
    CTextToRead
& operator=(CTextToRead &){}

//
//  Member data
// 
private:
    CComPtr
<ISpVoice>   m_cpVoice;
    CComPtr
<ISpAudio>   m_cpOutAudio;
    BOOL                m_bPause;
    BOOL                m_bStop;
    USHORT              m_Volume;
    
long                m_Rate;
    SPSTREAMFORMAT      m_CurrentStreamFormat;
    WCHAR
*              m_pszwFileText;
    ISpObjectToken
*        m_currentVoiceToken;
    std::vector
<MESSAGE_MAP>    m_MessageMap;
    UINT                m_message;
    std::vector
<STREAMFORMAT>    m_vStreamFormat;
};



#endif

 

 

 

.cpp

 

代码
#include "stdafx.h"
#include 
"TextToRead.h"
/*******************************************************
//auxiliary string function
******************************************************
*/
int isequal(WCHAR *s, WCHAR *t);
//************************************
// Description:
// to test whether target is contained in source, the function
// returns the first index of the substring, or -1 indicating 
// no match
//************************************
int SubStringIndex(WCHAR *source, WCHAR *target) 

    
int i=0,j=0
    WCHAR 
*s2; 
    
while(source[i]!='\0'
    { 
        s2
=&source[i]; 
        
if(isequal(s2,target)) 
            
return i; 
        i
++
    } 
    
return -1


int isequal(WCHAR *s,WCHAR *t) 

    
int i=0
    
while(t[i]!='\0'
    { 
        
if(CharLower((PTSTR)s[i]) != CharLower((PTSTR)t[i])) 
            
break
        i
++
    } 
    
if(t[i]=='\0'
        
return 1
    
else 
        
return 0
}




CTextToRead::CTextToRead()
{
    
//initialize com
    CoInitialize( NULL );

    HRESULT hr 
= _InitSapi();


     
// Set the default output format
    if( SUCCEEDED( hr ) )
    {
        CComPtr
<ISpStreamFormat> cpStream;
        HRESULT hrOutputStream 
= m_cpVoice->GetOutputStream(&cpStream);
        
if (hrOutputStream == S_OK)
        {
            CSpStreamFormat Fmt;
            hr 
= Fmt.AssignFormat(cpStream);
            
if (SUCCEEDED(hr))
            {
                m_CurrentStreamFormat 
= Fmt.ComputeFormatEnum();
            }
        }
    }


    
// Set default voice data 
    if( SUCCEEDED(hr))
    {
        hr 
= m_cpVoice->GetVoice(&m_currentVoiceToken);
    }

    
// Get default rate
    if( SUCCEEDED( hr ) )
    {
        hr 
= m_cpVoice->GetRate( &m_Rate );
    }

    
// Get default volume
    if( SUCCEEDED( hr ) )
    {
        hr 
= m_cpVoice->GetVolume( &m_Volume );
    }

    
if ( SUCCEEDED( hr ) )
    {
        SpCreateDefaultObjectFromCategoryId( SPCAT_AUDIOOUT, 
&m_cpOutAudio );
    }

    m_bStop 
= m_bPause = false;

    m_pszwFileText 
= NULL;

    
// we make the relation between SPSTREAMFORMAT(only for some formats) and the index
    this->_makeRelation();


    
//If any SAPI initialization failed, shut down!
    if (!SUCCEEDED(hr))
    {
        
//TRACE(TEXT("Error in initial SAPI\n"));
        return;
    }
}

HRESULT CTextToRead::_InitSapi()
{
    HRESULT    hr 
= m_cpVoice.CoCreateInstance( CLSID_SpVoice );

    
return hr;
}



//************************************
// Method:    _ChangeVoice
// FullName:  CTextToRead::_ChangeVoice
// Access:    public 
// Returns:   bool
// param:      pToken

// Description: 
// If the new voice is different from the one that's currently 
// selected, it first stops any synthesis that is going on and
// sets the new voice on the global voice object. 
//************************************
bool CTextToRead::_ChangeVoice(ISpObjectToken* pToken)
{
    HRESULT         hr 
= S_OK;
    GUID
*           pguidAudioFormat = NULL;
    
int             iFormat = 0;

    
// Get the token associated with the selected voice

    
//Determine if it is the current voice
    CComPtr<ISpObjectToken> pOldToken;
    hr 
= m_cpVoice->GetVoice( &pOldToken );

    
if (SUCCEEDED(hr))
    {
        
if (pOldToken != pToken)
        {        
            
// Stop speaking. This is not necessary, for the next call to work,
            
// but just to show that we are changing voices.
            hr = m_cpVoice->Speak( NULL, SPF_PURGEBEFORESPEAK, 0);

            
//// Get the id of the VOICE
            //WCHAR*  pszTokenIds;
            
//hr = pToken->GetId(&pszTokenIds);
            
//CoTaskMemFree(pszTokenIds);

            
// And set the new voice on the global voice object
            if (SUCCEEDED (hr) )
            {
                hr 
= m_cpVoice->SetVoice( pToken );
            }
        }
    }

    
return SUCCEEDED(hr);
}

bool CTextToRead::_ChangeVoice(WCHAR * voice)
{
    HRESULT hr 
= S_OK;
    ISpObjectToken 
* pToken = NULL;
    
this->_GetVoice(voice, &pToken);
    
if (pToken != NULL)
    {
        hr 
= this->_ChangeVoice(pToken);
    }
    
return SUCCEEDED(hr);
}



bool CTextToRead::_NotifyWindowMessage( HWND hWnd, UINT message )
{
    
if (hWnd == NULL)
    {
        
return false;
    }

    m_message 
= message;

    HRESULT hr 
= S_OK;
    
if ( !m_cpVoice )
    {
        hr 
= E_FAIL;
    }

    
// Set the notification message for the voice
    if ( SUCCEEDED( hr ) )
    {
        
// note that the TTS's window message is the responsiblity of IspVoice
        m_cpVoice->SetNotifyWindowMessage( hWnd, message, 00 );
    }

    
// We're interested in all TTS events
    if( SUCCEEDED( hr ) )
    {
        hr 
= m_cpVoice->SetInterest( SPFEI_ALL_TTS_EVENTS, SPFEI_ALL_TTS_EVENTS );
    }

    
return SUCCEEDED(hr);
}


//************************************
// Method:    ReadTheFile
// FullName:  CTextToRead::ReadTheFile
// Access:    private 
// Returns:   HRESULT
// Qualifier:
// Parameter: TCHAR * szFileName
// Parameter: BOOL * bIsUnicode
// Parameter: WCHAR * * ppszwBuff

// Description:
// This file opens and reads the contents of a file. It
// returns a pointer to the string.
// Warning, this function allocates memory for the string on 
// the heap so the caller must free it with 'delete'.

//************************************
HRESULT CTextToRead::_ReadTheFile( TCHAR* szFileName, BOOL* bIsUnicode, WCHAR** ppszwBuff )
{
    
// Open up the file and copy it's contents into a buffer to return
    HRESULT        hr = 0;
    HANDLE        hFile;
    DWORD        dwSize 
= 0;
    DWORD        dwBytesRead 
= 0;

    
// First delete any memory previously allocated by this function
    if( m_pszwFileText )
    {
        delete [] m_pszwFileText;
    }

    hFile 
= CreateFile( szFileName, GENERIC_READ,
        FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_HIDDEN 
| FILE_ATTRIBUTE_READONLY, NULL );
    
if( hFile == INVALID_HANDLE_VALUE )
    {
        
*ppszwBuff = NULL;
        hr 
= E_FAIL;
    }

    
if( SUCCEEDED( hr ) )
    {
        dwSize 
= GetFileSize( hFile, NULL );
        
if( dwSize == 0xffffffff )
        {
            
*ppszwBuff = NULL;
            hr 
= E_FAIL;        
        }
    }

    
if( SUCCEEDED( hr ) )
    {
        
// Read the file contents into a wide buffer and then determine
        
// if it's a unicode or ascii file
        WCHAR    Signature = 0;

        ReadFile( hFile, 
&Signature, 2&dwBytesRead, NULL );

        
// Check to see if its a unicode file by looking at the signature of the first character.
        if0xFEFF == Signature )
        {
            
*ppszwBuff = new WCHAR [dwSize/2];

            
*bIsUnicode = TRUE;
            ReadFile( hFile, 
*ppszwBuff, dwSize-2&dwBytesRead, NULL );
            (
*ppszwBuff)[dwSize/2-1= NULL;

            CloseHandle( hFile );
        }            
        
else  // MBCS source
        {
            
char*    pszABuff = new char [dwSize+1];
            
*ppszwBuff = new WCHAR [dwSize+1];

            
*bIsUnicode = FALSE;
            SetFilePointer( hFile, NULL, NULL, FILE_BEGIN );
            ReadFile( hFile, pszABuff, dwSize, 
&dwBytesRead, NULL );
            pszABuff[dwSize] 
= NULL;
            ::MultiByteToWideChar( CP_ACP, 
0, pszABuff, -1*ppszwBuff, dwSize + 1 );

            delete( pszABuff );
            CloseHandle( hFile );
        }
    }

    
return hr;
}

void CTextToRead::_ReadFromFile( TCHAR* szFileName, BOOL* bIsUnicode)
{
    
this->_ReadTheFile(szFileName, bIsUnicode, &m_pszwFileText);
    
    
this->_ReadText(m_pszwFileText);

    
//we allocate it in ReadTheFile
    delete [] m_pszwFileText;

    m_pszwFileText 
= NULL;
}



void CTextToRead::_ReadText( WCHAR* pszwBuff )
{
    HRESULT hr 
= S_OK;

    m_bStop 
= FALSE;
    
    
// only get the string if we're not paused
    if!m_bPause )
    {
        hr 
= m_cpVoice->Speak( pszwBuff, SPF_ASYNC | SPF_IS_NOT_XML , NULL );
    }

    m_bPause 
= FALSE;
    
// Set state to run
    hr = m_cpVoice->Resume();            
}

void CTextToRead::_PauseRestartRead()
{
    
if!m_bStop )
    {
        
if!m_bPause )
        {
            
// Pause the voice...
            m_cpVoice->Pause();
            m_bPause 
= TRUE;
        }
        
else
        {
            
// Restart the voice...
            m_cpVoice->Resume();
            m_bPause 
= FALSE;
        }
    }
}

//************************************
// Method:    StopRead
// FullName:  CTextToRead::StopRead
// Access:    public 
// Returns:   void
// Qualifier:

// Description:
// Stop reading, and resets global audio state to stopped
//************************************
void CTextToRead::_StopRead()
{
    
// Stop current rendering with a PURGEBEFORESPEAK...
    HRESULT hr = m_cpVoice->Speak( NULL, SPF_PURGEBEFORESPEAK, 0 );

    m_bPause 
= FALSE;
    m_bStop 
= TRUE;             
}

bool CTextToRead::_PlayWave( TCHAR* szFileName )
{
    
//not checking the accuracy of the file type
    if (szFileName == NULL)
    {
        
return false;
    }

    CComPtr
<ISpStream> cpWavStream;

    
// User helper function found in sphelper.h to open the wav file and
    
// get back an IStream pointer to pass to SpeakStream
    HRESULT hr = SPBindToFile( szFileName, SPFM_OPEN_READONLY, &cpWavStream );

    
if( SUCCEEDED( hr ) )
    {
        hr 
= m_cpVoice->SpeakStream( cpWavStream, SPF_ASYNC, NULL );
    }

    
return SUCCEEDED(hr);
}

bool CTextToRead::_SaveToWavFile( WCHAR* szFileName, WCHAR* wszTextToSave )
{
    
if (szFileName == NULL)
    {
        
return false;
    }

    
//check weather the last 3 character of szFileName is 'wav'
    int length = wcslen(szFileName);
    WCHAR 
* temp = szFileName + (length - 3);
    
if (wcscmp(temp, TEXT("wav")) != 0)
    {
        
// temp is not 'wav'
        return false;
    }
    

    USES_CONVERSION;

    CComPtr
<ISpStreamFormat>    cpOldStream;
    CComPtr
<ISpStream>  cpWavStream;
    CSpStreamFormat OriginalFmt;

    HRESULT hr 
= m_cpVoice->GetOutputStream( &cpOldStream );
    
if (hr == S_OK)
    {
        hr 
= OriginalFmt.AssignFormat(cpOldStream);
    }
    
else
    {
        hr 
= E_FAIL;
    }
    
// User SAPI helper function in sphelper.h to create a wav file
    if (SUCCEEDED(hr))
    {
        hr 
= SPBindToFile( szFileName, SPFM_CREATE_ALWAYS,\
                           
&cpWavStream, &OriginalFmt.FormatId(), \
                           OriginalFmt.WaveFormatExPtr() ); 
    }
    
if( SUCCEEDED( hr ) )
    {
        
// Set the voice's output to the wav file instead of the speakers
        hr = m_cpVoice->SetOutput(cpWavStream, TRUE);
    }

    
if ( SUCCEEDED( hr ) )
    {
        
// Do the Speak, now the target is wav file rather than speakers
        this->_ReadText(wszTextToSave);
    }

    
// Set output back to original stream
    
// Wait until the speak is finished if saving to a wav file so that
    
// the smart pointer cpWavStream doesn't get released before its
    
// finished writing to the wav.
    m_cpVoice->WaitUntilDone( INFINITE );
    cpWavStream.Release();

    
// Reset output
    m_cpVoice->SetOutput( cpOldStream, FALSE );

    
if ( SUCCEEDED( hr ) )
    {
        
return true;
    }
    
else
    {
        
return false;    
    }
}

CTextToRead::
~CTextToRead()
{
    
// delete any allocated memory
    if( m_pszwFileText )
    {
        delete [] m_pszwFileText;
    }


    
// Release voice, if created
    if ( m_cpVoice )
    {
        m_cpVoice
->SetNotifySink(NULL);
        m_cpVoice.Release();
    }

    
// Release outaudio, if created
    if(m_cpOutAudio)
    {
        m_cpOutAudio.Release();
    }

    
// Unload COM
    CoUninitialize();
}

HRESULT CTextToRead::_GetVoice( WCHAR 
* voice , ISpObjectToken ** ppGotToken)
{
    
*ppGotToken = NULL;

    HRESULT hr;
    ISpObjectToken 
* pToken;        // NOTE:  Not a CComPtr!  Be Careful.
    CComPtr<IEnumSpObjectTokens> cpEnum;
    hr 
= SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
    
if (hr == S_OK)
    {
        
bool fSetDefault = false;
        
while (cpEnum->Next(1&pToken, NULL) == S_OK)
        {
            CSpDynamicString dstrDesc;
            hr 
= SpGetDescription(pToken, &dstrDesc);
            
if (SUCCEEDED(hr))
            {
                WCHAR 
* temp = dstrDesc.Copy();
                
if ( -1 != SubStringIndex(temp, voice) )
                {
                    
//the voice is what we need. Set this voice
                    *ppGotToken = pToken;

                    
break;
                }
            }
            
if (FAILED(hr))
            {
                pToken
->Release();
            }
        }
    }
    
else
    {
        hr 
= SPERR_NO_MORE_ITEMS;
    }

    
return hr;
}

HRESULT CTextToRead::_SetOutStreamFormat( SPSTREAMFORMAT format )
{
    HRESULT hr 
= E_FAIL;
    SPSTREAMFORMAT eFmt 
= format;
    
    CSpStreamFormat Fmt;
    Fmt.AssignFormat(eFmt);

    
if ( m_cpOutAudio )
    {
        hr 
= m_cpOutAudio->SetFormat( Fmt.FormatId(), Fmt.WaveFormatExPtr() );
        m_CurrentStreamFormat 
= format;
    }
    
else
    {
        hr 
= E_FAIL;
    }

    
if( SUCCEEDED( hr ) )
    {
        hr 
= m_cpVoice->SetOutput( m_cpOutAudio, FALSE );
    }

    
return hr;
}

HRESULT CTextToRead::_SetOutStreamFormat( 
int khz, int bit, bool bMono )
{
    
// combine the three parameter into a SPSTREAMFORMAT form phrase
    
//WCHAR swTempFormat[25];
    
//swprintf(swTempFormat, L"SPSF_%dkHz%dBit%s", khz, bit, bMono?L"Mono":L"Stereo");

    HRESULT hr 
= E_FAIL;

    
int length = m_vStreamFormat.size();
    
for (int i = 0;i < length;i++)
    {
        
if(     m_vStreamFormat[i].m_khz == khz
           
&&    m_vStreamFormat[i].m_bit == bit
           
&&   m_vStreamFormat[i].m_bMono == bMono)
        {
            hr 
= this->_SetOutStreamFormat((SPSTREAMFORMAT)m_vStreamFormat[i].m_index);
            
break;
        }
    }

    
return hr;
}


//************************************
// Method:    _RegisterMessageFunc
// FullName:  CTextToRead::_RegisterMessageFunc
// Access:    public 
// Returns:   void
// Qualifier:
// Parameter: UINT message        message
// Parameter: * func            callback function
// Parameter: DWORD * param        parameter passed into func

// Description:
//************************************
void CTextToRead::_RegisterMessageFunc( UINT message, bool (*pFunc)(void *void*), DWORD * pParam )
{
    MESSAGE_MAP message_map(message, pFunc, pParam);

    m_MessageMap.push_back(message_map);
}

bool CTextToRead::_UnRegisterMessage( UINT message )
{
    
bool bFind = false;
    
for (std::vector<MESSAGE_MAP>::iterator it = m_MessageMap.begin(); 
         it 
!= m_MessageMap.end(); 
         it
++)
    {
        
if (message == it->m_message)
        {
            m_MessageMap.erase(it);
            bFind 
= true;
            
break;
        }
    }
    
return bFind;
}

//************************************
// Method:    _DealMessage
// FullName:  CTextToRead::_DealMessage
// Access:    public 
// Returns:   int
// Qualifier:
// Parameter: UINT message

// Description:
// if _DealMessage returns -1, it means that we do not have the corresponding 
// message dealing function. if it returns 0 or 1, it means the dealing function
// returns it.
//************************************
int CTextToRead::_DealMessage(UINT message)
{
    
int iDeal = -1;

    
if (message == m_message)
    {
        
//it is the message that we want
        
        CSpEvent        
event;  // helper class in sphelper.h for events that releases any 
                                
// allocated memory in it's destructor - SAFER than SPEVENT

        
whileevent.GetFrom(m_cpVoice) == S_OK )
        {
            
for (std::vector<MESSAGE_MAP>::iterator it = m_MessageMap.begin(); 
                it 
!= m_MessageMap.end(); 
                it
++)
            {
                
if (event.eEventId == it->m_message)
                {
                    iDeal 
= (int) (it->m_pFunc(it->m_pParam, NULL));
                    
break;
                }
            }
        }
    }

    
return iDeal;
}

void CTextToRead::_makeRelation()
{
    STREAMFORMAT streamFormat;
    streamFormat.Generate(SPSF_8kHz8BitMono, 
88true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_8kHz16BitMono, 
816true);
    m_vStreamFormat.push_back(streamFormat);
    
    streamFormat.Generate(SPSF_8kHz16BitStereo, 
816false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_11kHz8BitMono, 
118true);
    m_vStreamFormat.push_back(streamFormat);
    
    streamFormat.Generate(SPSF_11kHz8BitStereo, 
118false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_11kHz16BitMono, 
1116true);
    m_vStreamFormat.push_back(streamFormat);
        
    streamFormat.Generate(SPSF_11kHz16BitStereo, 
1116false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_12kHz8BitMono, 
128true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_12kHz8BitStereo, 
128false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_12kHz16BitMono, 
1216true);
    m_vStreamFormat.push_back(streamFormat);
    
    streamFormat.Generate(SPSF_12kHz16BitStereo, 
1216false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_16kHz8BitMono, 
168true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_16kHz8BitStereo, 
168false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_16kHz16BitMono, 
1616true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_16kHz16BitStereo, 
1616false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_22kHz8BitMono, 
228true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_22kHz8BitStereo, 
228false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_22kHz16BitMono, 
2216true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_22kHz16BitStereo, 
2216false);
    m_vStreamFormat.push_back(streamFormat);
        
    streamFormat.Generate(SPSF_24kHz8BitMono, 
248true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_24kHz8BitStereo, 
248false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_24kHz16BitMono, 
2416true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_24kHz16BitStereo, 
2416false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_32kHz8BitMono, 
328true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_32kHz8BitStereo, 
328false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_32kHz16BitMono, 
3216true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_32kHz16BitStereo, 
3216false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_44kHz8BitMono, 
448true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_44kHz8BitStereo, 
448false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_44kHz16BitMono, 
4416true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_44kHz16BitStereo, 
4416false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_48kHz8BitMono, 
488true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_48kHz8BitStereo, 
488false);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_48kHz16BitMono, 
4816true);
    m_vStreamFormat.push_back(streamFormat);

    streamFormat.Generate(SPSF_48kHz16BitStereo, 
4816false);
    m_vStreamFormat.push_back(streamFormat);
}

bool CTextToRead::_GetVoiceList(WCHAR ** ppVoiceDesArr, int* pWordsLengthArr, ULONG& numOfVoice)
{
    HRESULT hr 
= E_FAIL;
    ISpObjectToken 
* pToken;        // NOTE:  Not a CComPtr!  Be Careful.
    CComPtr<IEnumSpObjectTokens> cpEnum;
    hr 
= SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
    
if (hr == S_OK)
    {
        cpEnum
->GetCount(&numOfVoice);
        
if (ppVoiceDesArr == NULL && pWordsLengthArr == NULL)
        {
            
// we only focus on the number of available voices
            return true;
        }
        
        
// then get descriptions and indexes
        int uIndex = 0;
        
while (cpEnum->Next(1&pToken, NULL) == S_OK)
        {
            CSpDynamicString dstrDesc;
            hr 
= SpGetDescription(pToken, &dstrDesc);
            
            
if ( SUCCEEDED(hr))
            {
                WCHAR 
* temp = dstrDesc.Copy();
                
if (pWordsLengthArr != NULL)
                {
                    pWordsLengthArr[uIndex] 
= wcslen(temp) + 1;
                }
                
if (ppVoiceDesArr != NULL)
                {
                    wcscpy(ppVoiceDesArr[uIndex], dstrDesc.Copy());
                }                
            }
            
if ( FAILED(hr) )
            {
                
if (pWordsLengthArr != NULL)
                {
                    pWordsLengthArr[uIndex] 
= 0;
                }
                
if (ppVoiceDesArr != NULL)
                {
                    ppVoiceDesArr[uIndex] 
= NULL;
                }
                pToken
->Release();
            }
            uIndex
++;
        }
    }
    
else
        
return false;

    
return true;
}

 

 

posted @ 2011-01-25 23:41  aicro  阅读(468)  评论(0编辑  收藏  举报