How to initialize argv[i]? - c++

I am trying to initialize argv[i] to the value of "C:\Games\World_of_Tanks\res\packages\gui.pkg" with a const char* pointer. Can I get some help doing this as I am new to programming.
#include <windows.h>
#include <cstdio>
void pf(const char* name)
{
HANDLE file = CreateFile(name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if(file == INVALID_HANDLE_VALUE) { printf("couldn't open %s\n", name); return; };
unsigned int len = GetFileSize(file, 0);
HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, 0, 0);
if(mapping == 0) { printf("couldn't map %s\n", name); return; }
const char* data = (const char*) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
if(data)
{
printf("prefetching %s... ", name);
// need volatile or need to use result - compiler will otherwise optimize out whole loop
volatile unsigned int touch = 0;
for(unsigned int i = 0; i < len; i += 4096)
touch += data[i];
}
else
printf("couldn't create view of %s\n", name);
UnmapViewOfFile(data);
CloseHandle(mapping);
CloseHandle(file);
}
int main(int argc, const char** argv)
{
if(argc >= 2) for(int i = 1; argv[i]; ++i) pf(argv[i]);
return 0;
}

The value of a const charcan not be changed. What is it you want to do?
If you want a value of the argv array in the main function to be set you need to execute the program with a command line argument like:
program argument argument etc
Edit from comment info:
If you want to run the pffunction on program start you could add
pf("C:\Games\World_of_Tanks\res\packages\gui.pkg"); // this might need to be escaped...
in the main function.

You can just use another array
const char *myargv[] = { "pgmname",
"my_first_filename.dat",
"my_second_filename.dat",
NULL };
argv = myargv;
argc = 3;
If this is just to be able to run the program from an IDE note however that there is for sure a GUI option for setting the command line arguments for the program.

Related

Why does multi threading mess up my file watcher?

I am trying to make a file watcher that watches multiple directories simultaneously and i found a function that watches one directory and it works well. So I tried to create multiple threads with the same function and just give them the different paths of the directories as parameters. And it still works, but not perfectly. It does provide me with the first change in one directory, but then it gets stuck for that one and in the other directories the changes i make are printed as if they wore made in the first directory. I think the threads are getting messed up and I don`t know why. Here is the function
void watch_directory(LPCSTR path, int i)
{
char buf[2048];
DWORD nRet;
BOOL result = TRUE;
char filename[MAX_PATH];
DirInfo[0].hDir = CreateFile(path, GENERIC_READ | FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
NULL);
if (DirInfo[0].hDir == INVALID_HANDLE_VALUE)
{
return; //cannot open folder
}
lstrcpy(DirInfo[0].lpszDirName, path);
OVERLAPPED PollingOverlap;
FILE_NOTIFY_INFORMATION* pNotify;
int offset;
PollingOverlap.OffsetHigh = 0;
PollingOverlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
while (result)
{
result = ReadDirectoryChangesW(
DirInfo[0].hDir,// handle to the directory to be watched
&buf,// pointer to the buffer to receive the read results
sizeof(buf),// length of lpBuffer
TRUE,// flag for monitoring directory or directory tree
FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_SIZE,
&nRet,// number of bytes returned
&PollingOverlap,// pointer to structure needed for overlapped I/O
NULL);
WaitForSingleObject(PollingOverlap.hEvent, INFINITE);
offset = 0;
int rename = 0;
char oldName[260];
char newName[260];
do
{
pNotify = (FILE_NOTIFY_INFORMATION*)((char*)buf + offset);
strcpy(filename, "");
int filenamelen = WideCharToMultiByte(CP_ACP, 0, pNotify->FileName, pNotify->FileNameLength / 2, filename, sizeof(filename), NULL, NULL);
filename[pNotify->FileNameLength / 2] = '\0';
cout << pNotify->Action << i << filename << endl;
offset += pNotify->NextEntryOffset;
} while (pNotify->NextEntryOffset); //(offset != 0);
}
/*label:*/ CloseHandle(DirInfo[0].hDir);
}
And here is the way I create the threads:
vector <string> dirs;
vector <thread> threads;
dirs.push_back("F:\\Arhitecturi\\test0");
dirs.push_back("F:\\Arhitecturi\\test1");
for (int i = 0; i < dirs.size(); i++)
{
threads.push_back(thread(watch_directory, dirs[i].c_str(), i));
}
for (int i = 0; i < threads.size(); i++)
{
threads[i].join();
}

With MODULEENTRY32 and MODULEINFO, what are the steps to scan for a specific INT value in a separate process?

I have enumerated a processes modules and have a MODULEINFO. From that I have a base address, size of the module, and the entrypoint. If I have a separate process with an integer int x = 4 defined in main(), can I scan for that integer's address using what I have with MODULEINFO? Wouldn't x exist on the stack, which is separate from the module exe?
I tried making a loop with the base address and SizeOfImage member, casting the base address to a byte*, and then adding 1 byte and then casting it to a int* to search for a specific value, however every value I got back was a "0". I believe my method was (grossly) incorrect.
If it is possible to scan an int value can anyone point me in the general direction to do so?
Yes--local variables (non-static ones, anyway) are allocated on the stack. To see their values, you'll need to write something on the order of a debugger, such as pausing the program while it's running (and the function containing the variable of interest is active), and walk the stack to find the value.
Since you're apparently using Windows, functions you'll probably want to look at include:
WaitForDebugEvent (or WaitForDebugEventEx)
ContinueDebugEvent
Stackwalk64
You'll probably also want to look at the dbghlp API, probably starting with these:
SymInitialize
SymFromName
SymCleanup
There's a lot more there to consider, but that's probably enough to at least get a bit of a start. I previously posted an answer that demonstrates StackWalk64, and some of the Sym* stuff.
Here's some code with the bare skeleton of a debugger that will spawn a child process, and then log the debug events it produces:
#include <windows.h>
#include <stdio.h>
#include "child_process.h"
void dispatch_child_event(DEBUG_EVENT const &event, child_process const &child) {
char *file_name;
char buffer[512];
switch ( event.dwDebugEventCode ) {
case LOAD_DLL_DEBUG_EVENT:
file_name = child.get_string(event.u.LoadDll.lpImageName);
if ( event.u.LoadDll.fUnicode)
printf("Loading %S\n", (wchar_t *)file_name);
else
printf("Loading %s\n", file_name);
break;
case EXCEPTION_DEBUG_EVENT:
switch (event.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
{
if ( event.u.Exception.dwFirstChance)
break;
EXCEPTION_RECORD const &r = event.u.Exception.ExceptionRecord;
printf("Access Violation %x at %0#p\n",
r.ExceptionCode,
r.ExceptionAddress);
break;
}
case EXCEPTION_BREAKPOINT:
printf("Breakpoint reached\n");
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
if ( !event.u.Exception.dwFirstChance)
printf("Misaligned data exception.\n");
break;
case EXCEPTION_SINGLE_STEP:
printf("Single Step...\n");
break;
case DBG_CONTROL_C:
if ( !event.u.Exception.dwFirstChance)
printf("Control+C pressed\n");
break;
break;
}
case CREATE_THREAD_DEBUG_EVENT:
printf("Client created a thread\n");
break;
case CREATE_PROCESS_DEBUG_EVENT:
printf("Create-Process\n");
break;
case EXIT_THREAD_DEBUG_EVENT:
printf("Thread exited.\n");
break;
case UNLOAD_DLL_DEBUG_EVENT:
printf("DLL being unloaded\n");
break;
case OUTPUT_DEBUG_STRING_EVENT: {
OUTPUT_DEBUG_STRING_INFO const &d = event.u.DebugString;
char *string = child.get_debug_string(d.lpDebugStringData,
d.nDebugStringLength);
if ( d.fUnicode)
printf("Debug string: %S\n", string);
else
printf("Debug string: %s\n", string);
break;
}
}
}
int main(int argc, char **argv) {
DEBUG_EVENT event;
if ( argc < 2 ) {
fprintf(stderr, "Usage: Trace [executable|PID]");
return EXIT_FAILURE;
}
child_process child(argv[1]);
do {
WaitForDebugEvent(&event, INFINITE);
dispatch_child_event(event, child);
ContinueDebugEvent( event.dwProcessId,
event.dwThreadId,
DBG_CONTINUE );
} while ( event.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT);
return 0;
}
That uses the following child_process header:
#ifndef CHILD_PROCESS_H_INC_
#define CHILD_PROCESS_H_INC_
#include <windows.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <io.h>
#include "syserror.h"
struct no_spawn {
no_spawn() { system_error("Spawning Program"); }
};
class child_process {
HANDLE process_;
HANDLE thread_;
mutable char buffer[FILENAME_MAX];
public:
child_process(char const *filename);
char *get_string(void *string_name, DWORD num = 0) const;
char *get_debug_string(void *string, DWORD num) const;
HANDLE process() { return process_; }
HANDLE thread() { return thread_; }
~child_process() { CloseHandle(process()); }
};
#endif
The implementation of that class is as follows:
#include "child_process.h"
static BOOL find_image(char const *name, char *buffer) {
// Try to find an image file named by the user.
// First search for the exact file name in the current
// directory. If that's not found, look for same base name
// with ".com", ".exe" and ".bat" appended, in that order.
// If we can't find it in the current directory, repeat
// the entire process on directories specified in the
// PATH environment variable.
//
#define elements(array) (sizeof(array)/sizeof(array[0]))
static char *extensions[] = {".com", ".exe", ".bat", ".cmd"};
int i;
char temp[FILENAME_MAX];
if (-1 != _access(name, 0)) {
strcpy(buffer, name);
return TRUE;
}
for (i=0; i<elements(extensions); i++) {
strcpy(temp, name);
strcat(temp, extensions[i]);
if ( -1 != _access(temp, 0)) {
strcpy(buffer, temp);
return TRUE;
}
}
_searchenv(name, "PATH", buffer);
if ( buffer[0] != '\0')
return TRUE;
for ( i=0; i<elements(extensions); i++) {
strcpy(temp, name);
strcat(temp, extensions[i]);
_searchenv(temp, "PATH", buffer);
if ( buffer[0] != '\0')
return TRUE;
}
return FALSE;
}
child_process::child_process(char const *filename) {
if (isdigit(filename[0])) {
DWORD id = atoi(filename);
process_ = OpenProcess(PROCESS_ALL_ACCESS, false, atoi(filename));
DebugActiveProcess(id);
}
else {
char buf[FILENAME_MAX];
PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
si.cb = sizeof(si);
if (!find_image(filename, buf))
throw no_spawn();
BOOL new_process_ = CreateProcess(buf, NULL, NULL, NULL, FALSE,
DEBUG_ONLY_THIS_PROCESS,
NULL, NULL,
&si, &pi);
if (!new_process_)
throw no_spawn();
CloseHandle(pi.hThread);
process_ = pi.hProcess;
thread_ = pi.hThread;
}
}
char *child_process::get_string(void *string_name, DWORD num) const {
// string_name is a pointer to a pointer to a string, with the pointer and the
// string itself located in another process_. We use Readprocess_Memory to read
// the first pointer, then the string itself into our process_ address space.
// We then return a pointer (in our address space) to the string we read in.
//
char *ptr;
SIZE_T bytes_read;
if ( 0 == num )
num = sizeof(buffer);
if ( string_name == NULL )
return NULL;
ReadProcessMemory(process_,
string_name,
&ptr,
sizeof(ptr),
&bytes_read);
if (NULL == ptr )
return NULL;
ReadProcessMemory(process_,
ptr,
buffer,
num,
&bytes_read);
return buffer;
}
char *child_process::get_debug_string(void *string, DWORD num) const {
static char buffer[FILENAME_MAX];
SIZE_T bytes_read;
if ( string == NULL )
return NULL;
ReadProcessMemory(process_,
string,
buffer,
num,
&bytes_read);
return buffer;
}
That's not enough to do everything you want yet, but at least it should give you a start in the general direction.
Oh, one disclaimer: I wrote most of this code quite a long time ago. There are parts I'd certainly do differently if I were to write it today.

programming c threaded io

Hi what i want to do is read from a text file do something to the text and write it back out to a file. I need it to be threaded so all 3 party can run at the same time. I am trying to use a buffer to read in to and a buffer to write out from but cant work it out.
My code :
#include <stdio.h>
#include <pthread.h>
char inBuf[1000];
//char outBuf[];
void *readerFun(void *meg){
char *inputFile;
FILE *input_ptr;
inputFile = (char *) meg;
input_ptr = fopen(inputFile, "r");
if(input_ptr == NULL){
printf("%s\n", inputFile);
printf("input file not working\n");
return;
}
while(!feof(input_ptr)){
fscanf(input_ptr, "%s", &inBuf);
sleep(1);
// printf("%s\n", &inBuf );
// printf("test _____________\n" );
}
return NULL;
}
void *modifierFun(void *meg){
//char c;
//while((c = getc(inBuf) != EOF)){
//strcat(outBuf, c);
//}
//}
return NULL;
}
void *writerFun(void *meg){
char *outFile;
FILE *output_ptr;
outFile = (char *) meg;
output_ptr = fopen(outFile, "a");
while(inBuf != NULL){
printf("%s\n", inBuf );
fprintf(output_ptr, "%s", inBuf);
}
return NULL;
}
int
main (int argc, char **argv){
pthread_t reader, modifier, writer;
char *meg = argv[1];
char *meg2 = argv[2];
int ret1, ret2, ret3;
ret1 = pthread_create(&reader, NULL, readerFun, (void *) meg);
ret2 = pthread_create(&modifier, NULL, modifierFun, (void *) meg);
ret3 = pthread_create(&writer, NULL, writerFun, (void *) meg2);
pthread_join(reader, NULL);
pthread_join(modifier, NULL);
pthread_join(writer, NULL);
return 0;
}
Would be a big help is someone could point me down the right road. I have looked all over the net and cant really find what im looking for.

How to CreateFileMapping in C++?

I am coding a game preloader (a simple program that loads certain files [maps] into cache before starting the program. I was told to use CreateFileMapping which I am still unsure whether it loads it into the physical or virtual memory...
Anyway, where would I put what files I need to load?
Here is my code (actually coded by someone else on stack overflow who told me to use it)
#include <windows.h>
#include <cstdio>
void pf(const char* name) {
HANDLE file = CreateFile(name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if(file == INVALID_HANDLE_VALUE) { printf("couldn't open %s\n", name); return; };
unsigned int len = GetFileSize(file, 0);
HANDLE mapping = CreateFileMapping(file, 0, PAGE_READONLY, 0, 0, 0);
if(mapping == 0) { printf("couldn't map %s\n", name); return; }
const char* data = (const char*) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
if(data)
{
printf("prefetching %s... ", name);
// need volatile or need to use result - compiler will otherwise optimize out whole loop
volatile unsigned int touch = 0;
for(unsigned int i = 0; i < len; i += 4096)
touch += data[i];
}
else
printf("couldn't create view of %s\n", name);
UnmapViewOfFile(data);
CloseHandle(mapping);
CloseHandle(file);
}
int main(int argc, const char** argv)
{
if(argc >= 2) for(int i = 1; argv[i]; ++i) pf(argv[i]);
return 0;
}
The pf function accepts a file path as its parameter. The touch loop causes the file (or at least 4 KB portions of it) to be loaded into physical memory.

Espeak SAPI/dll usage on Windows?

Question: I am trying to use the espeak text-to-speech engine.
So for I got it working wounderfully on linux (code below).
Now I wanted to port this basic program to windows, too, but it's nearly impossible...
Part of the problem is that the windows dll only allows for AUDIO_OUTPUT_SYNCHRONOUS, which means it requires a callback, but I can't figure out how to play the audio from the callback... First it crashed, then I realized, I need a callback function, now I get the data in the callback function, but I don't know how to play it... as it is neither a wav file nor plays automatically as on Linux.
The sourceforge site is rather useless, because it basically says use the SAPI version, but then there is no example on how to use the sapi espeak dll...
Anyway, here's my code, can anybody help?
#ifdef __cplusplus
#include <cstdio>
#include <cstdlib>
#include <cstring>
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include <assert.h>
#include <ctype.h>
//#include "speak_lib.h"
#include "espeak/speak_lib.h"
// libespeak-dev: /usr/include/espeak/speak_lib.h
// apt-get install libespeak-dev
// apt-get install libportaudio-dev
// g++ -o mine mine.cpp -lespeak
// g++ -o mine mine.cpp -I/usr/include/espeak/ -lespeak
// gcc -o mine mine.cpp -I/usr/include/espeak/ -lespeak
char voicename[40];
int samplerate;
int quiet = 0;
static char genders[4] = {' ','M','F',' '};
//const char *data_path = "/usr/share/"; // /usr/share/espeak-data/
const char *data_path = NULL; // use default path for espeak-data
int strrcmp(const char *s, const char *sub)
{
int slen = strlen(s);
int sublen = strlen(sub);
return memcmp(s + slen - sublen, sub, sublen);
}
char * strrcpy(char *dest, const char *source)
{
// Pre assertions
assert(dest != NULL);
assert(source != NULL);
assert(dest != source);
// tk: parentheses
while((*dest++ = *source++))
;
return(--dest);
}
const char* GetLanguageVoiceName(const char* pszShortSign)
{
#define LANGUAGE_LENGTH 30
static char szReturnValue[LANGUAGE_LENGTH] ;
memset(szReturnValue, 0, LANGUAGE_LENGTH);
for (int i = 0; pszShortSign[i] != '\0'; ++i)
szReturnValue[i] = (char) tolower(pszShortSign[i]);
const espeak_VOICE **voices;
espeak_VOICE voice_select;
voices = espeak_ListVoices(NULL);
const espeak_VOICE *v;
for(int ix=0; (v = voices[ix]) != NULL; ix++)
{
if( !strrcmp( v->languages, szReturnValue) )
{
strcpy(szReturnValue, v->name);
return szReturnValue;
}
} // End for
strcpy(szReturnValue, "default");
return szReturnValue;
} // End function getvoicename
void ListVoices()
{
const espeak_VOICE **voices;
espeak_VOICE voice_select;
voices = espeak_ListVoices(NULL);
const espeak_VOICE *v;
for(int ix=0; (v = voices[ix]) != NULL; ix++)
{
printf("Shortsign: %s\n", v->languages);
printf("age: %d\n", v->age);
printf("gender: %c\n", genders[v->gender]);
printf("name: %s\n", v->name);
printf("\n\n");
} // End for
} // End function getvoicename
int main()
{
printf("Hello World!\n");
const char* szVersionInfo = espeak_Info(NULL);
printf("Espeak version: %s\n", szVersionInfo);
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,0);
strcpy(voicename, "default");
// espeak --voices
strcpy(voicename, "german");
strcpy(voicename, GetLanguageVoiceName("DE"));
if(espeak_SetVoiceByName(voicename) != EE_OK)
{
printf("Espeak setvoice error...\n");
}
static char word[200] = "Hello World" ;
strcpy(word, "TV-fäns aufgepasst, es ist 20 Uhr 15. Zeit für Rambo 3");
strcpy(word, "Unnamed Player wurde zum Opfer von GSG9");
int speed = 220;
int volume = 500; // volume in range 0-100 0=silence
int pitch = 50; // base pitch, range 0-100. 50=normal
// espeak.cpp 625
espeak_SetParameter(espeakRATE, speed, 0);
espeak_SetParameter(espeakVOLUME,volume,0);
espeak_SetParameter(espeakPITCH,pitch,0);
// espeakRANGE: pitch range, range 0-100. 0-monotone, 50=normal
// espeakPUNCTUATION: which punctuation characters to announce:
// value in espeak_PUNCT_TYPE (none, all, some),
espeak_VOICE *voice_spec = espeak_GetCurrentVoice();
voice_spec->gender=2; // 0=none 1=male, 2=female,
//voice_spec->age = age;
espeak_SetVoiceByProperties(voice_spec);
espeak_Synth( (char*) word, strlen(word)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL);
espeak_Synchronize();
strcpy(voicename, GetLanguageVoiceName("EN"));
espeak_SetVoiceByName(voicename);
strcpy(word, "Geany was fragged by GSG9 Googlebot");
strcpy(word, "Googlebot");
espeak_Synth( (char*) word, strlen(word)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL);
espeak_Synchronize();
espeak_Terminate();
printf("Espeak terminated\n");
return EXIT_SUCCESS;
}
/*
if(espeak_SetVoiceByName(voicename) != EE_OK)
{
memset(&voice_select,0,sizeof(voice_select));
voice_select.languages = voicename;
if(espeak_SetVoiceByProperties(&voice_select) != EE_OK)
{
fprintf(stderr,"%svoice '%s'\n",err_load,voicename);
exit(2);
}
}
*/
The above code is for Linux.
The below code is about as far as I got on Vista x64 (32 bit emu):
#ifdef __cplusplus
#include <cstdio>
#include <cstdlib>
#include <cstring>
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include <assert.h>
#include <ctype.h>
#include "speak_lib.h"
//#include "espeak/speak_lib.h"
// libespeak-dev: /usr/include/espeak/speak_lib.h
// apt-get install libespeak-dev
// apt-get install libportaudio-dev
// g++ -o mine mine.cpp -lespeak
// g++ -o mine mine.cpp -I/usr/include/espeak/ -lespeak
// gcc -o mine mine.cpp -I/usr/include/espeak/ -lespeak
char voicename[40];
int iSampleRate;
int quiet = 0;
static char genders[4] = {' ','M','F',' '};
//const char *data_path = "/usr/share/"; // /usr/share/espeak-data/
//const char *data_path = NULL; // use default path for espeak-data
const char *data_path = "C:\\Users\\Username\\Desktop\\espeak-1.43-source\\espeak-1.43-source\\";
int strrcmp(const char *s, const char *sub)
{
int slen = strlen(s);
int sublen = strlen(sub);
return memcmp(s + slen - sublen, sub, sublen);
}
char * strrcpy(char *dest, const char *source)
{
// Pre assertions
assert(dest != NULL);
assert(source != NULL);
assert(dest != source);
// tk: parentheses
while((*dest++ = *source++))
;
return(--dest);
}
const char* GetLanguageVoiceName(const char* pszShortSign)
{
#define LANGUAGE_LENGTH 30
static char szReturnValue[LANGUAGE_LENGTH] ;
memset(szReturnValue, 0, LANGUAGE_LENGTH);
for (int i = 0; pszShortSign[i] != '\0'; ++i)
szReturnValue[i] = (char) tolower(pszShortSign[i]);
const espeak_VOICE **voices;
espeak_VOICE voice_select;
voices = espeak_ListVoices(NULL);
const espeak_VOICE *v;
for(int ix=0; (v = voices[ix]) != NULL; ix++)
{
if( !strrcmp( v->languages, szReturnValue) )
{
strcpy(szReturnValue, v->name);
return szReturnValue;
}
} // End for
strcpy(szReturnValue, "default");
return szReturnValue;
} // End function getvoicename
void ListVoices()
{
const espeak_VOICE **voices;
espeak_VOICE voice_select;
voices = espeak_ListVoices(NULL);
const espeak_VOICE *v;
for(int ix=0; (v = voices[ix]) != NULL; ix++)
{
printf("Shortsign: %s\n", v->languages);
printf("age: %d\n", v->age);
printf("gender: %c\n", genders[v->gender]);
printf("name: %s\n", v->name);
printf("\n\n");
} // End for
} // End function getvoicename
/* Callback from espeak. Directly speaks using AudioTrack. */
#define LOGI(x) printf("%s\n", x)
static int AndroidEspeakDirectSpeechCallback(short *wav, int numsamples, espeak_EVENT *events)
{
char buf[100];
sprintf(buf, "AndroidEspeakDirectSpeechCallback: %d samples", numsamples);
LOGI(buf);
if (wav == NULL)
{
LOGI("Null: speech has completed");
}
if (numsamples > 0)
{
//audout->write(wav, sizeof(short) * numsamples);
sprintf(buf, "AudioTrack wrote: %d bytes", sizeof(short) * numsamples);
LOGI(buf);
}
return 0; // continue synthesis (1 is to abort)
}
static int AndroidEspeakSynthToFileCallback(short *wav, int numsamples,espeak_EVENT *events)
{
char buf[100];
sprintf(buf, "AndroidEspeakSynthToFileCallback: %d samples", numsamples);
LOGI(buf);
if (wav == NULL)
{
LOGI("Null: speech has completed");
}
// The user data should contain the file pointer of the file to write to
//void* user_data = events->user_data;
FILE* user_data = fopen ( "myfile1.wav" , "ab" );
FILE* fp = static_cast<FILE *>(user_data);
// Write all of the samples
fwrite(wav, sizeof(short), numsamples, fp);
return 0; // continue synthesis (1 is to abort)
}
int main()
{
printf("Hello World!\n");
const char* szVersionInfo = espeak_Info(NULL);
printf("Espeak version: %s\n", szVersionInfo);
iSampleRate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 4096, data_path, 0);
if (iSampleRate <= 0)
{
printf("Unable to initialize espeak");
return EXIT_FAILURE;
}
//samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,0);
//ListVoices();
strcpy(voicename, "default");
// espeak --voices
//strcpy(voicename, "german");
//strcpy(voicename, GetLanguageVoiceName("DE"));
if(espeak_SetVoiceByName(voicename) != EE_OK)
{
printf("Espeak setvoice error...\n");
}
static char word[200] = "Hello World" ;
strcpy(word, "TV-fäns aufgepasst, es ist 20 Uhr 15. Zeit für Rambo 3");
strcpy(word, "Unnamed Player wurde zum Opfer von GSG9");
int speed = 220;
int volume = 500; // volume in range 0-100 0=silence
int pitch = 50; // base pitch, range 0-100. 50=normal
// espeak.cpp 625
espeak_SetParameter(espeakRATE, speed, 0);
espeak_SetParameter(espeakVOLUME,volume,0);
espeak_SetParameter(espeakPITCH,pitch,0);
// espeakRANGE: pitch range, range 0-100. 0-monotone, 50=normal
// espeakPUNCTUATION: which punctuation characters to announce:
// value in espeak_PUNCT_TYPE (none, all, some),
//espeak_VOICE *voice_spec = espeak_GetCurrentVoice();
//voice_spec->gender=2; // 0=none 1=male, 2=female,
//voice_spec->age = age;
//espeak_SetVoiceByProperties(voice_spec);
//espeak_SetSynthCallback(AndroidEspeakDirectSpeechCallback);
espeak_SetSynthCallback(AndroidEspeakSynthToFileCallback);
unsigned int unique_identifier;
espeak_ERROR err = espeak_Synth( (char*) word, strlen(word)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, &unique_identifier, NULL);
err = espeak_Synchronize();
/*
strcpy(voicename, GetLanguageVoiceName("EN"));
espeak_SetVoiceByName(voicename);
strcpy(word, "Geany was fragged by GSG9 Googlebot");
strcpy(word, "Googlebot");
espeak_Synth( (char*) word, strlen(word)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL);
espeak_Synchronize();
*/
// espeak_Cancel();
espeak_Terminate();
printf("Espeak terminated\n");
system("pause");
return EXIT_SUCCESS;
}
Have you tried passing the buffer you obtain in your callback to sndplaysnd()??
Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
Its standard winAPI is as follows:
sndPlaySound(buffer[0], SND_ASYNC | SND_MEMORY)
Alternately, if you have a wav-file that has the audio to play:
sndPlaySound(filename, SND_ASYNC)
playsound has a ASYNC mode that wouldn't block your program's execution while the audio is being played.
NOTE: I have used it in VB and the above snippets are for use in VB. If you are coding in VC++, you might have to modify them accordingly. But the basic intention remains the same; to pass the buffer to sndPlaySound with the ASYNC flag set.
Good LUCK!!
Several changes in source code are needed to make the windows library have the same functionality as the one on Linux. I listed the changes here. The ready to use binary is also available.
All the patches and the description were also sent to espeak maintainer (publicly, through the mailing list and patches tracker), so maybe in future it will be available directly.