[vlc-commits] text renderer: add basic text to speech synthesis for OS X (#11893)

Felix Paul Kühne git at videolan.org
Wed Jul 29 20:15:01 CEST 2015


vlc | branch: master | Felix Paul Kühne <fkuehne at videolan.org> | Wed Jul 29 20:11:00 2015 +0200| [7ea5c465d01551059c3168802fb2f7b76a8d0dfe] | committer: Felix Paul Kühne

text renderer: add basic text to speech synthesis for OS X (#11893)

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=7ea5c465d01551059c3168802fb2f7b76a8d0dfe
---

 modules/text_renderer/Makefile.am           |    6 +
 modules/text_renderer/nsspeechsynthesizer.m |  160 +++++++++++++++++++++++++++
 po/POTFILES.in                              |    1 +
 3 files changed, 167 insertions(+)

diff --git a/modules/text_renderer/Makefile.am b/modules/text_renderer/Makefile.am
index d41bc6d..43ccb67 100644
--- a/modules/text_renderer/Makefile.am
+++ b/modules/text_renderer/Makefile.am
@@ -36,6 +36,12 @@ libquartztext_plugin_la_LDFLAGS = $(AM_LDLFAGS) -rpath '$(textdir)' \
 EXTRA_LTLIBRARIES += libquartztext_plugin.la
 text_LTLIBRARIES += $(LTLIBquartztext)
 
+if HAVE_OSX
+libnsspeechsynthesizer_plugin_la_SOURCES = text_renderer/nsspeechsynthesizer.m
+libnsspeechsynthesizer_plugin_la_LDFLAGS = -Wl,-framework,Cocoa
+text_LTLIBRARIES += libnsspeechsynthesizer_plugin.la
+endif
+
 libsvg_plugin_la_SOURCES = text_renderer/svg.c
 libsvg_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(SVG_CFLAGS)
 libsvg_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(textdir)'
diff --git a/modules/text_renderer/nsspeechsynthesizer.m b/modules/text_renderer/nsspeechsynthesizer.m
new file mode 100644
index 0000000..47101f0
--- /dev/null
+++ b/modules/text_renderer/nsspeechsynthesizer.m
@@ -0,0 +1,160 @@
+/*****************************************************************************
+ * nsspeechsynthesizer.m: Simple text to Speech renderer for Mac OS X
+ *****************************************************************************
+ * Copyright (C) 2015 VLC authors and VideoLAN
+ * $Id$
+ *
+ * Authors: Felix Paul Kühne <fkuehne # videolan # org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_filter.h>
+
+#import <Cocoa/Cocoa.h>
+
+static int Create (vlc_object_t *);
+static void Destroy(vlc_object_t *);
+static int RenderText(filter_t *,
+                      subpicture_region_t *,
+                      subpicture_region_t *,
+                      const vlc_fourcc_t *);
+
+vlc_module_begin ()
+set_description(N_("Speech synthesis for Mac OS X"))
+set_category(CAT_VIDEO)
+set_subcategory(SUBCAT_VIDEO_SUBPIC)
+
+set_capability("text renderer", 50)
+set_callbacks(Create, Destroy)
+vlc_module_end ()
+
+struct filter_sys_t
+{
+    NSSpeechSynthesizer *speechSynthesizer;
+    NSString *currentLocale;
+    NSString *lastString;
+};
+
+static int  Create (vlc_object_t *p_this)
+{
+    filter_t *p_filter = (filter_t *)p_this;
+    filter_sys_t *p_sys;
+
+    p_filter->p_sys = p_sys = malloc(sizeof(filter_sys_t));
+    if (!p_sys)
+        return VLC_ENOMEM;
+
+    p_sys->currentLocale = p_sys->lastString = @"";
+    p_sys->speechSynthesizer = [[NSSpeechSynthesizer alloc] init];
+
+    p_filter->pf_render = RenderText;
+
+    return VLC_SUCCESS;
+}
+
+static void Destroy(vlc_object_t *p_this)
+{
+    filter_t *p_filter = (filter_t *)p_this;
+    filter_sys_t *p_sys = p_filter->p_sys;
+
+    [p_sys->speechSynthesizer stopSpeaking];
+    [p_sys->speechSynthesizer release];
+    p_sys->speechSynthesizer = nil;
+
+    [p_sys->lastString release];
+    p_sys->lastString = nil;
+
+    [p_sys->currentLocale release];
+    p_sys->currentLocale = nil;
+
+    free(p_sys);
+}
+
+static NSString * languageCodeForString(NSString *string) {
+    return (NSString *)CFStringTokenizerCopyBestStringLanguage((CFStringRef)string, CFRangeMake(0, [string length]));
+}
+
+static int RenderText(filter_t *p_filter,
+                      subpicture_region_t *p_region_out,
+                      subpicture_region_t *p_region_in,
+                      const vlc_fourcc_t *p_chroma_list)
+{
+    @autoreleasepool {
+        filter_sys_t *p_sys = p_filter->p_sys;
+        text_segment_t *p_segment = p_region_in->p_text;
+
+        if (!p_segment)
+            return VLC_EGENERIC;
+
+        for ( const text_segment_t *s = p_segment; s != NULL; s = s->p_next ) {
+            if ( !s->psz_text )
+                continue;
+
+            if (strlen(s->psz_text) == 0)
+                continue;
+
+            NSString *stringToSpeech = [NSString stringWithUTF8String:s->psz_text];
+
+            if ([p_sys->lastString isEqualToString:stringToSpeech])
+                continue;
+
+            if ([stringToSpeech isEqualToString:@"\n"])
+                continue;
+
+            p_sys->lastString = [stringToSpeech retain];
+
+            msg_Dbg(p_filter, "Speaking '%s'", [stringToSpeech UTF8String]);
+
+            NSString *detectedLocale = languageCodeForString(stringToSpeech);
+            if (detectedLocale != nil) {
+                if (![detectedLocale isEqualToString:p_sys->currentLocale]) {
+                    p_sys->currentLocale = [detectedLocale retain];
+                    msg_Dbg(p_filter, "switching speaker locale to '%s'", [p_sys->currentLocale UTF8String]);
+                    NSArray *voices = [NSSpeechSynthesizer availableVoices];
+                    NSUInteger count = voices.count;
+                    NSRange range = NSMakeRange(0, 2);
+
+                    for (NSUInteger i = 0; i < count; i++) {
+                        NSDictionary *voiceAttributes = [NSSpeechSynthesizer attributesForVoice:voices[i]];
+                        NSString *voiceLanguage = voiceAttributes[@"VoiceLanguage"];
+                        if ([p_sys->currentLocale isEqualToString:[voiceLanguage substringWithRange:range]]) {
+                            NSString *voiceName = voiceAttributes[@"VoiceName"];
+                            msg_Dbg(p_filter, "switched to voice '%s'", [voiceName UTF8String]);
+                            if ([voiceName isEqualToString:@"Agnes"] || [voiceName isEqualToString:@"Albert"])
+                                continue;
+                            [p_sys->speechSynthesizer setVoice:voices[i]];
+                            break;
+                        }
+                    }
+                }
+            }
+
+            [p_sys->speechSynthesizer startSpeakingString:stringToSpeech];
+        }
+
+        return VLC_SUCCESS;
+    }
+}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2e7245d..9f728d9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1059,6 +1059,7 @@ modules/stream_out/stats.c
 modules/stream_out/standard.c
 modules/stream_out/transcode/transcode.c
 modules/text_renderer/freetype.c
+modules/text_renderer/nsspeechsynthesizer.m
 modules/text_renderer/quartztext.c
 modules/text_renderer/svg.c
 modules/text_renderer/tdummy.c



More information about the vlc-commits mailing list