Class: Flite::Voice

Inherits:
Object
  • Object
show all
Defined in:
ext/flite/rbflite.c

Instance Method Summary collapse

Constructor Details

#initialize(name = nil) ⇒ Object

Create a new voice specified by name. If name includes ‘.’ or ‘/’ and ruby flite is compiled for CMU Flite 2.0.0 or upper, try to use a loadable voice.

Examples:


# Use default voice. It is 'kal' usually.
voice = Flite::Voice.new

# Use a builtin voice.
voice = Flite::Voice.new('awb')

# Use a lodable voice.
voice = Flite::Voice.new('/path/to/cmu_us_gka.flitevox')

Parameters:

  • name (String) (defaults to: nil)

See Also:



363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# File 'ext/flite/rbflite.c', line 363

static VALUE
rbflite_voice_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE name;
    const rbflite_builtin_voice_t *builtin = rbflite_builtin_voice_list;
    rbflite_voice_t *voice = DATA_PTR(self);

    rb_scan_args(argc, argv, "01", &name);
    if (!NIL_P(name)) {
        char *voice_name = StringValueCStr(name);
        while (builtin->name != NULL) {
            if (strcmp(voice_name, builtin->name) == 0) {
                break;
            }
            builtin++;
        }
        if (builtin->name == NULL) {
#ifdef HAVE_FLITE_VOICE_LOAD
            if (strchr(voice_name, '/') != NULL || strchr(voice_name, '.') != NULL) {
                voice->voice = rb_thread_call_without_gvl(rbflite_voice_load, voice_name, NULL, NULL);
                RB_GC_GUARD(name);
                if (voice->voice != NULL) {
                    return self;
                }
            }
#endif
            rb_raise(rb_eArgError, "Unkonw voice %s", voice_name);
        }
    }
    *builtin->cached = NULL; /* disable voice caching in libflite.so. */
    voice->voice = builtin->register_(NULL);
    return self;
}

Instance Method Details

#inspectString

Returns the value as a string for inspection.

Returns:



831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
# File 'ext/flite/rbflite.c', line 831

static VALUE
rbflite_voice_inspect(VALUE self)
{
    rbflite_voice_t *voice = DATA_PTR(self);
    const char *class_name = rb_obj_classname(self);
    const char *voice_name;
    const char *pathname;

    if (voice->voice == NULL) {
        return rb_sprintf("#<%s: not initialized>", class_name);
    }
    voice_name = voice->voice->name;

    pathname = flite_get_param_string(voice->voice->features, "pathname", "");
    if (pathname[0] == '\0') {
        return rb_sprintf("#<%s: %s>", class_name, voice_name);
    } else {
        return rb_sprintf("#<%s: %s (%s)>", class_name, voice_name, pathname);
    }
}

#nameString

Returns voice name.

Examples:

voice = Flite::Voice.new('slt')
voice.name => 'slt'

# voice loading is a new feature of CMU Flite 2.0.0.
voice = Flite::Voice.new('/path/to/cmu_us_fem.flitevox')
voice.name => 'cmu_us_fem'

Returns:



780
781
782
783
784
785
786
787
788
789
# File 'ext/flite/rbflite.c', line 780

static VALUE
rbflite_voice_name(VALUE self)
{
    rbflite_voice_t *voice = DATA_PTR(self);

    if (voice->voice == NULL) {
        rb_raise(rb_eFliteRuntimeError, "%s is not initialized", rb_obj_classname(self));
    }
    return rb_usascii_str_new_cstr(voice->voice->name);
}

#pathnameString

Returns the path of the voice if the voice is a loadable voice. Otherwise, nil.

Examples:

voice = Flite::Voice.new
voice.pathname => 'kal'

# voice loading is a new feature of CMU Flite 2.0.0.
voice = Flite::Voice.new('/path/to/cmu_us_aup.flitevox')
voice.pathname => '/path/to/cmu_us_aup.flitevox'

Returns:



807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
# File 'ext/flite/rbflite.c', line 807

static VALUE
rbflite_voice_pathname(VALUE self)
{
    rbflite_voice_t *voice = DATA_PTR(self);
    const char *pathname;

    if (voice->voice == NULL) {
        rb_raise(rb_eFliteRuntimeError, "%s is not initialized", rb_obj_classname(self));
    }
    pathname = flite_get_param_string(voice->voice->features, "pathname", "");
    if (pathname[0] == '\0') {
        return Qnil;
    }
    return rb_usascii_str_new_cstr(pathname);
}

#speak(text) ⇒ Object

Speak the text.

Examples:

voice = Flite::Voice.new

# Speak 'Hello Flite World!'
voice.speak('Hello Flite World!')

Parameters:



608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
# File 'ext/flite/rbflite.c', line 608

static VALUE
rbflite_voice_speak(VALUE self, VALUE text)
{
    rbflite_voice_t *voice = DATA_PTR(self);
    voice_speech_data_t vsd;
    thread_queue_entry_t entry;

    if (voice->voice == NULL) {
        rb_raise(rb_eFliteRuntimeError, "%s is not initialized", rb_obj_classname(self));
    }

    vsd.voice = voice->voice;
    vsd.text = StringValueCStr(text);
    vsd.outtype = "play";
    vsd.buffer_list = NULL;
    vsd.buffer_list_last = NULL;
    vsd.error = RBFLITE_ERROR_SUCCESS;

    lock_thread(&voice->queue, &entry);

    rb_thread_call_without_gvl(voice_speech_without_gvl, &vsd, NULL, NULL);
    RB_GC_GUARD(text);

    unlock_thread(&voice->queue);

    check_error(&vsd);

    if (sleep_time_after_speaking.tv_sec != 0 || sleep_time_after_speaking.tv_usec != 0) {
        rb_thread_wait_for(sleep_time_after_speaking);
    }

    return self;
}

#to_speech(text, audio_type = :wav, opts = {}) ⇒ String

Converts text to audio data.

Examples:

voice = Flite::Voice.new

# Save speech as wav
File.binwrite('hello_flite_world.wav',
              voice.to_speech('Hello Flite World!'))

# Save speech as raw pcm (signed 16 bit little endian, rate 8000 Hz, mono)
File.binwrite('hello_flite_world.raw',
              voice.to_speech('Hello Flite World!', :raw))

# Save speech as mp3
File.binwrite('hello_flite_world.mp3',
              voice.to_speech('Hello Flite World!', :mp3))

# Save speech as mp3 whose bitrate is 128k.
File.binwrite('hello_flite_world.mp3',
              voice.to_speech('Hello Flite World!', :mp3, :bitrate => 128))

Parameters:

  • text (String)
  • audo_type (Symbol)

    :wav, :raw or :mp3 (when mp3 support is enabled)

  • opts (Hash) (defaults to: {})

    audio encoder options

Returns:

See Also:



672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
# File 'ext/flite/rbflite.c', line 672

static VALUE
rbflite_voice_to_speech(int argc, VALUE *argv, VALUE self)
{
    rbflite_voice_t *voice = DATA_PTR(self);
    VALUE text;
    VALUE audio_type;
    VALUE opts;
    cst_audio_streaming_info *asi = NULL;
    audio_stream_encoder_t *encoder;
    voice_speech_data_t vsd;
    thread_queue_entry_t entry;
    buffer_list_t *list, *list_next;
    size_t size;
    VALUE speech_data;
    char *ptr;

    if (voice->voice == NULL) {
        rb_raise(rb_eFliteRuntimeError, "%s is not initialized", rb_obj_classname(self));
    }

    rb_scan_args(argc, argv, "12", &text, &audio_type, &opts);

    if (NIL_P(audio_type)) {
        encoder = &wav_encoder;
    } else {
        if (rb_equal(audio_type, sym_wav)) {
            encoder = &wav_encoder;
        } else if (rb_equal(audio_type, sym_raw)) {
            encoder = &raw_encoder;
#ifdef HAVE_MP3LAME
        } else if (rb_equal(audio_type, sym_mp3)) {
            encoder = &mp3_encoder;
#endif
        } else {
            rb_raise(rb_eArgError, "unknown audio type");
        }
    }

    vsd.voice = voice->voice;
    vsd.text = StringValueCStr(text);
    vsd.outtype = "stream";
    vsd.encoder = NULL;
    vsd.buffer_list = NULL;
    vsd.buffer_list_last = NULL;
    vsd.error = RBFLITE_ERROR_SUCCESS;

    if (encoder->encoder_init) {
        vsd.encoder = encoder->encoder_init(opts);
    }

    /* write to an object */
    asi = new_audio_streaming_info();
    if (asi == NULL) {
        if (encoder->encoder_fini) {
            encoder->encoder_fini(vsd.encoder);
        }
        rb_raise(rb_eNoMemError, "failed to allocate audio_streaming_info");
    }
    asi->asc = encoder->asc;
    asi->userdata = (void*)&vsd;

    lock_thread(&voice->queue, &entry);

    flite_feat_set(voice->voice->features, "streaming_info", audio_streaming_info_val(asi));
    rb_thread_call_without_gvl(voice_speech_without_gvl, &vsd, NULL, NULL);
    flite_feat_remove(voice->voice->features, "streaming_info");
    RB_GC_GUARD(text);

    unlock_thread(&voice->queue);

    if (encoder->encoder_fini) {
        encoder->encoder_fini(vsd.encoder);
    }

    check_error(&vsd);

    size = 0;
    for (list = vsd.buffer_list; list != NULL; list = list->next) {
        size += list->used;
    }
    speech_data = rb_str_buf_new(size);
    ptr = RSTRING_PTR(speech_data);
    for (list = vsd.buffer_list; list != NULL; list = list_next) {
        memcpy(ptr, list->buf, list->used);
        ptr += list->used;
        list_next = list->next;
        xfree(list);
    }
    rb_str_set_len(speech_data, size);

    return speech_data;
}