Вопрос: Чтобы написать C#
интерфейс для libespeak, мне нужно преобразовать обратный вызов SynthCallback
в C#
.
См. Ниже C
код.
Вам может понадобиться это для справки:
https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
http://www -mmsp.ece.mcgill.ca / документы / Аудиоформаты / волна / wave.html
В основном,
espeak_initialize
espeak_SetSynthCallback(SynthCallback);
espeak_SetParameter(espeakRATE, 510, 0);
espeak_Synth(".", 20, 0, POS_CHARACTER, 0, 0, NULL, NULL);
- функция DllImport-ed.
И они у меня уже работают асинхронно, без файла.
Теперь я хочу, чтобы синхронная версия работала с файлами, но у меня есть небольшая проблема:
Функция обратного вызова
static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events)
Во-первых, мне нужно создать делегата, для которого я могу передать эту функцию в C
dll / so.
Что не проблема, но если я сделаю short *wav to a System.IntPtr
, как мне записать данные в файл?
Другими словами: может ли кто-нибудь помочь мне с fwrite
, fputc
, Write4Bytes
, преобразовав это в правильное C#
?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <espeak/speak_lib.h>
// gcc -o mine speak.cpp -I/usr/include/espeak/ -lespeak
FILE *f_wavfile = NULL;
static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events);
// Write 4 bytes to a file, least significant first
static void Write4Bytes(FILE *f, int value)
{
int ix;
for(ix=0; ix<4; ix++)
{
fputc(value & 0xff,f);
value = value >> 8;
}
}
int OpenWavFile(char *path, int rate)
{
static unsigned char wave_hdr[44] = {
'R','I','F','F',0x24,0xf0,0xff,0x7f,'W','A','V','E','f','m','t',' ',
0x10,0,0,0,1,0,1,0, 9,0x3d,0,0,0x12,0x7a,0,0,
2,0,0x10,0,'d','a','t','a', 0x00,0xf0,0xff,0x7f
};
if(path == NULL)
return(2);
if(path[0] == 0)
return(0);
if(strcmp(path,"stdout")==0)
f_wavfile = stdout;
else
f_wavfile = fopen(path,"wb");
if(f_wavfile == NULL)
{
fprintf(stderr,"Can't write to: '%s'\n",path);
return(1);
}
fwrite(wave_hdr, 1, 24, f_wavfile);
Write4Bytes(f_wavfile, rate);
Write4Bytes(f_wavfile, rate * 2);
fwrite(&wave_hdr[32], 1, 12, f_wavfile);
return(0);
} // end of OpenWavFile
static void CloseWavFile()
{
unsigned int pos;
if((f_wavfile==NULL) || (f_wavfile == stdout))
return;
fflush(f_wavfile);
pos = ftell(f_wavfile);
fseek(f_wavfile, 4, SEEK_SET);
Write4Bytes(f_wavfile, pos - 8);
fseek(f_wavfile, 40, SEEK_SET);
Write4Bytes(f_wavfile, pos - 44);
fclose(f_wavfile);
} // end of CloseWavFile
int main()
{
char buf[22050];
int i = 0;
memset(&buf, 0, sizeof(buf));
// OpenWavFile((char*) "test.wav", 22050);
int SampleRate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 300, NULL, 0);
OpenWavFile((char*) "test.wav", SampleRate);
espeak_SetSynthCallback(SynthCallback);
//espeak_SetParameter(espeakRATE, 510, 0);
//espeak_SetParameter(espeakRANGE, 75, 0);
for (i=0; i < 9;i++)
{
/*
espeak_ERROR espeak_Synth(
const void *text,
size_t size,
unsigned int position,
espeak_POSITION_TYPE position_type,
unsigned int end_position,
unsigned int flags,
unsigned int* unique_identifier,
void* user_data);
*/
//espeak_POSITION_TYPE.POS_CHARACTER
espeak_Synth("test", 10, 0, POS_CHARACTER, 0, 0, NULL, NULL);
fwrite(buf, 1, 5512, f_wavfile);
espeak_Synth(".", 20, 0, POS_CHARACTER, 0, 0, NULL, NULL);
fwrite(buf, 1, 22050, f_wavfile);
}
CloseWavFile();
}
static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events)
{
if (wav == NULL)
return 0;
if (numsamples > 0)
{
fwrite(wav, numsamples * 2, 1, f_wavfile);
}
return 0;
}