From 8ff372bd5e005f82493738bb7e33e88af1aa9c2a Mon Sep 17 00:00:00 2001 From: Adrian Cochrane Date: Tue, 7 Apr 2020 07:51:30 +1200 Subject: [PATCH] Import libsndfile, prepare to use it for writing audio files. --- rhapsode.cabal | 2 +- src/main.c | 34 ++++++++++++++++++++-------------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/rhapsode.cabal b/rhapsode.cabal index 1cf6464..5a32941 100644 --- a/rhapsode.cabal +++ b/rhapsode.cabal @@ -75,7 +75,7 @@ library executable rhapsode main-is: main.c ghc-options: -no-hs-main - extra-libraries: espeak-ng + extra-libraries: espeak-ng, sndfile build-depends: base >=4.9 && <=4.12, rhapsode other-modules: Stub hs-source-dirs: src diff --git a/src/main.c b/src/main.c index 83a7cb0..d5e664f 100644 --- a/src/main.c +++ b/src/main.c @@ -6,6 +6,7 @@ #include "HsFFI.h" #include +#include /* Exported Haskell functions/types */ struct session; @@ -24,6 +25,7 @@ char **c_docLinksAndRendering(struct session*, struct page*); // FIXME segfaults /* espeak-ng integration. Based on the espeak-ng command source code. */ FILE *fd_wav = NULL; +char *path_wav = NULL; static int samplerate; espeak_ng_ERROR_CONTEXT context; @@ -37,7 +39,6 @@ void write4b(int value) { } } -int wrote_header = 0; void write_header() { static unsigned char wave_hdr[44] = { 'R', 'I', 'F', 'F', 0x24, 0xf0, 0xff, 0x7f, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ', @@ -68,7 +69,10 @@ int synth_callback(short *wav, int numsamples, espeak_EVENT *events) { events++; } - if (!wrote_header) write_header(); + if (fd_wav == NULL) { + fd_wav = fopen(path_wav, "wb"); + write_header(); + } if (numsamples > 0) fwrite(wav, numsamples*2, 1, fd_wav); return 0; } @@ -83,7 +87,7 @@ int speak_initialize() { return 2; } - if (fd_wav != stdout) { + if (path_wav != NULL) { result = espeak_ng_InitializeOutput(ENOUTPUT_MODE_SYNCHRONOUS, 0, NULL); espeak_SetSynthCallback(synth_callback); } else { @@ -108,7 +112,7 @@ int speak_finalize() { return 4; } - if (fd_wav != stdout) close_wav_file(); + if (path_wav != NULL) close_wav_file(); espeak_ng_Terminate(); return 0; } @@ -120,8 +124,8 @@ void write_links(FILE *dest, char **links) { } } -FILE *parse_opt_file(char *mode) { - FILE *ret = optarg != NULL ? fopen(optarg, mode) : stdout; +FILE *parse_opt_file() { + FILE *ret = optarg != NULL ? fopen(optarg, "w") : stdout; if (ret == NULL) { fprintf(stderr, "Failed to open file %s\n", optarg); hs_exit(); @@ -137,6 +141,7 @@ int main(int argc, char **argv) { char *mimes = "text/html text/xml application/xml application/xhtml+xml text/plain"; FILE *fd_ssml = NULL; FILE *fd_links = NULL; + int use_espeak = 0; int c; opterr = 0; @@ -146,13 +151,14 @@ int main(int argc, char **argv) { mimes = "text/xml application/xml application/xhtml+xml text/html text/plain"; break; case 's': - fd_ssml = parse_opt_file("w"); + fd_ssml = parse_opt_file(); break; case 'l': - fd_links = parse_opt_file("w"); + fd_links = parse_opt_file(); break; case 'w': - fd_wav = parse_opt_file("wb"); + use_espeak = 1; + path_wav = optarg; break; case '?': fprintf(stderr, "Invalid flag %c\n\n", optopt); @@ -170,14 +176,14 @@ int main(int argc, char **argv) { } } if (fd_ssml == stdout && fd_links == stdout) fd_links = stderr; - if (fd_ssml == NULL && fd_links == NULL && fd_wav == NULL) fd_wav = stdout; + if (fd_ssml == NULL && fd_links == NULL && !use_espeak) use_espeak = 1; struct session *session = c_newSession(); struct page *referer = c_initialReferer(); - if (fd_wav != NULL) speak_err = speak_initialize(); + if (use_espeak) speak_err = speak_initialize(); for (int i = optind; i < argc; i++) { - if (fd_wav != NULL && speak_err == 0) speak(argv[i]); + if (use_espeak && speak_err == 0) speak(argv[i]); else printf("%s\n", argv[i]); struct page *page = c_fetchURL(session, mimes, referer, argv[i]); @@ -186,11 +192,11 @@ int main(int argc, char **argv) { if (fd_ssml != NULL) fprintf(fd_ssml, "%s\n", ssml); if (fd_links != NULL) write_links(fd_links, links); - if (fd_wav != NULL& speak_err == 0) speak(ssml); + if (use_espeak & speak_err == 0) speak(ssml); c_freePage(page); } - if (fd_wav != NULL & speak_err == 0) speak_err = speak_finalize(); + if (use_espeak & speak_err == 0) speak_err = speak_finalize(); c_freePage(referer); c_freeSession(session); -- 2.30.2