Return Values - Introduction

Return Values
Nonzero indicates success. Zero indicates failure. To get extended error information, call GetLastError.
Remarks
If part of the file is locked by another process and the write operation overlaps the locked portion, this function fails.
Accessing the output buffer while a write operation is using the buffer may lead to corruption of the data written from that buffer. Applications must not read from, write to, reallocate, or free the output buffer that a write operation is using until the write operation completes.
After understanding the basic operations to Create, Read or Write in file in Windows CE, the crude way of porting is to replace all the file operations like fopen, fread, fwrite, fclose, fseek by the CreateFile, ReadFile and WriteFile.
The following diagram shows the file operations done in the hindianalyser native code which are replaced by CreateFile, ReadFile and WriteFile operations to make it compatible with Windows CE API.
As discussed above clicking the Analyse button takes the input and invokes hindianalyser dll and return the number of tokens written in tokens file.
Each file operation is implemented using the Windows CE API now. After this stage the tokens are saved in a file Tokens.txt on disc. The file contains token in this form:
-
The token name: For example token name can be 0704 which is the name of the sound file corresponding to this token and which will be obtained in the hindiengine phase.
-
The token type: Token type specifies that whether this is a vowel or a consonant and on the basis of that the sound generation algorithm works.
Please look at the references to know the algorithms used in Shruti which are also used in the Embedded version.
Another important difference between Win32 API and Windows CE API is the memory allocation techniques. C type memory allocation (malloc) doesn’t work on Windows CE API. The following function should be used in place of that:
char *s;
s = (char *)LocalAlloc(LMEM_FIXED,cBytes);
LocalAlloc allocate memory on local heap of size cBytes and returns a pointer that is stored in s. Local heap is always there in Windows CE by default. But the developer can declare heaps on their own and write efficient memory code.
3. Generate button: On clicking the generate button first of all the Hindiengine library is loaded into the main memory. After that the exported function from the Hindiengine library is called with tokenLength as the input where tokenLength is the number of bytes in the Tokens.txt file. Generate function from the dll read the Token.txt file, retrieve the tokens and token type from the file and then concatenates the sound files according to tokens into one file.
For example if token is 0704, then it will retrieve the sound file 0704.wav from a sound library (in this model the sound library is a directory which contains all the sound files)
Thus for all tokens the sound files will be read from the directory, appropriately concatenated and the output sound file will be produced.
In this dll Windows CE counterpart for fread, fwrite and fseek were written which will be given shortly but before that the last function of the generate button click is to play the sound file generated by the dll function.
//Code to play a wav format file on Windows CE
MMRESULT PlayWave(LPCTSTR szWavFile)
{
HWAVEOUT hwo;
WAVEHDR whdr;
MMRESULT mmres;
CWaveFile waveFile;
HANDLE hDoneEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("DONE_EVENT"));
UINT devId;
DWORD dwOldVolume;
// Open wave file
if (!waveFile.Open(szWavFile)) {
TCHAR szErrMsg[MAX_ERRMSG];
_stprintf (szErrMsg, TEXT("Unable to open file: %s\n\n"),szWavFile);
MessageBox(NULL, szErrMsg, TEXT("File I/O Error"), MB_OK);
return MMSYSERR_NOERROR;
}
// Open audio device
for (devId = 0; devId < waveOutGetNumDevs(); devId++) {
mmres = waveOutOpen(&hwo, devId, waveFile.GetWaveFormat(), (DWORD) hDoneEvent,
0, CALLBACK_EVENT);
if (mmres == MMSYSERR_NOERROR) {
break;
}
}
if (mmres != MMSYSERR_NOERROR) {
return mmres;
}
// Set volume
mmres = waveOutGetVolume(hwo, &dwOldVolume);
if (mmres != MMSYSERR_NOERROR) {
return mmres;
}
waveOutSetVolume(hwo, 0xFFFFFFFF);
if (mmres != MMSYSERR_NOERROR) {
return mmres;
}
// Initialize wave header
ZeroMemory(&whdr, sizeof(WAVEHDR));
whdr.lpData = new char[waveFile.GetLength()];
whdr.dwBufferLength = waveFile.GetLength();
whdr.dwUser = 0;
whdr.dwFlags = 0;
whdr.dwLoops = 0;
whdr.dwBytesRecorded = 0;
whdr.lpNext = 0;
whdr.reserved = 0;
// Play buffer
waveFile.Read(whdr.lpData, whdr.dwBufferLength);
mmres = waveOutPrepareHeader(hwo, &whdr, sizeof(WAVEHDR));
if (mmres != MMSYSERR_NOERROR) {
return mmres;
}
mmres = waveOutWrite(hwo, &whdr, sizeof(WAVEHDR));
if (mmres != MMSYSERR_NOERROR) {
return mmres;
}
// Wait for audio to finish playing
while (!(whdr.dwFlags & WHDR_DONE)) {
WaitForSingleObject(hDoneEvent, INFINITE);
}
// Clean up
mmres = waveOutUnprepareHeader(hwo, &whdr, sizeof(WAVEHDR));
if (mmres != MMSYSERR_NOERROR) {
return mmres;
}
waveOutSetVolume(hwo, dwOldVolume);
if (mmres != MMSYSERR_NOERROR) {
return mmres;
}
mmres = waveOutClose(hwo);
if (mmres != MMSYSERR_NOERROR) {
return mmres;
}
delete [] whdr.lpData;
waveFile.Close();
return MMSYSERR_NOERROR;
}
Take a look at the source code to understand the sound producing code clearly.
Now let’s take a look at the file operations done in the hindiengine.dll in the following diagram and the respective operations to do fread, fwrite and fseek:
From the figure it is clear that hindiengine native code contained a number of file operations which are modified using Windows CE API functions to port it to Pocket-PC running Windows CE.
Mapping of fread, fwrite, fseek and fscanf to Windows CE API functions:
fread: It can be implemented using ReadFile.
fwrite: It can be implemented using WriteFile.
fseek: Read the file till the desired position.
fscanf: fscanf operation can be implemented by reading the file byte by byte and then putting the characters on a temporary array till the delimiter(say a blank) and then changing it to appropriate format like an integer or a string. The following code snippet retrieves token and token type from the tokens.txt file and save the token in a string and the token type in integer variable.
//Code to implement fscanf
do //Read tokens till the phrasal boundary
{
while(no_of_blanks!=2){
ReadFile(fin,&c,1,&bytesRead,NULL);
length+=1;
if(c==' ')
no_of_blanks+=1;
if(no_of_blanks==0){
token[tokencount]=c;
tokencount+=1;
}
if(no_of_blanks==1){
ttype1[ttypecount]=c;
ttypecount+=1;
}
if(length==tokenLength)
break;
}
token[tokencount]='\0';
ttype1[ttypecount]='\0';
tokencount=0;
ttypecount=0;
no_of_blanks=0;
ttype=atoi(ttype1);
} while(length !=tokenLength);
The variable token contains the token as a string and the variable ttype contains the type of the token. To read from the files like tokens.txt, intonation and epoch the above substitute of fscanf is used. To read the wav files fread and fseek are sufficient since the size of the wav file can be obtained by reading 4 bytes of the wav file after 40th byte. Thus using fseek and fread Windows CE implementation the wav files can be read from the sound file library (a directory in this implementation) and concatenated according to the ILPS algorithm to get the speech.
Please take a look at the reference section to get the algorithm used in NLP module and ILPS module.
|