~alcinnz/rhapsode

49f4b9eb5322912c92f401a411729ebfeb16497f — Adrian Cochrane 4 years ago 8ff372b
Use libsndfile to write audio files.
1 files changed, 19 insertions(+), 34 deletions(-)

M src/main.c
M src/main.c => src/main.c +19 -34
@@ 24,41 24,23 @@ char **c_extractLinks(struct page*);
char **c_docLinksAndRendering(struct session*, struct page*); // FIXME segfaults.

/* espeak-ng integration. Based on the espeak-ng command source code. */
FILE *fd_wav = NULL;
SNDFILE *fd_wav = NULL;
char *path_wav = NULL;
static int samplerate;
espeak_ng_ERROR_CONTEXT context;

void write4b(int value) {
    // Write 4 bytes to a file, least significant first
	int ix;
int choose_format(char *path) {
    SF_FORMAT_INFO	format_info;
    int k, count;

	for (ix = 0; ix < 4; ix++) {
		fputc(value & 0xff, fd_wav);
		value = value >> 8;
	}
}

void write_header() {
    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
    	};

    fwrite(wave_hdr, 1, 24, fd_wav);
	write4b(samplerate);
	write4b(samplerate * 2);
	fwrite(&wave_hdr[32], 1, 12, fd_wav);
}
void close_wav_file() {
    fflush(fd_wav);
	unsigned int pos = ftell(fd_wav);

	if (fseek(fd_wav, 4, SEEK_SET) != -1) write4b(pos - 8);
	if (fseek(fd_wav, 40, SEEK_SET) != -1) write4b(pos - 44);

	fclose(fd_wav);
    sf_command(fd_wav, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof (int));
    for (k = 0; k < count; k++) {
        format_info.format = k;
        sf_command(fd_wav, SFC_GET_FORMAT_MAJOR, &format_info, sizeof (format_info));
        char *suffix = path + strlen(path) - strlen(format_info.extension);
        if (strcmp(path, format_info.extension) == 0) return format_info.format;
    }
    return SF_FORMAT_WAV;
}

int synth_callback(short *wav, int numsamples, espeak_EVENT *events) {


@@ 70,10 52,13 @@ int synth_callback(short *wav, int numsamples, espeak_EVENT *events) {
    }

    if (fd_wav == NULL) {
        fd_wav = fopen(path_wav, "wb");
        write_header();
        SF_INFO info;
        info.samplerate = samplerate;
        info.channels = 1;
        info.format = choose_format(path_wav) | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE;
        fd_wav = sf_open(path_wav, SFM_WRITE, &info);
    }
    if (numsamples > 0) fwrite(wav, numsamples*2, 1, fd_wav);
    if (numsamples > 0) sf_writef_short(fd_wav, wav, numsamples);
    return 0;
}



@@ 112,7 97,7 @@ int speak_finalize() {
        return 4;
    }

    if (path_wav != NULL) close_wav_file();
    if (path_wav != NULL) sf_close(fd_wav);
    espeak_ng_Terminate();
    return 0;
}