ru_tts-for-nvda
99 строк · 2.7 Кб
1// Copyright (C) 2021 - 2023 Александр Линьков <kvark128@yandex.ru>
2// Этот файл распространяется под лицензией MIT
3
4#include <stdlib.h>5
6#include <sonic.h>7#include <ru_tts.h>8#include "ru_tts_nvda.h"9
10#define SUCCESS 011#define FAILURE 112
13#define WAVE_SIZE 409614#define SAMPLE_RATE 1000015#define NUM_CHANNELS 116
17int writeToConsumer(const TTS_t *tts, const int minSamples) {18int numSamples = sonicSamplesAvailable(tts->stream);19while (numSamples >= minSamples) {20int n = sonicReadShortFromStream(tts->stream, tts->buffer, WAVE_SIZE);21if (tts->consumer(tts->buffer, n, NULL)) {22// Пользователь прервал синтез. Необходимо сбросить внутренние буферы sonic23sonicFlushStream(tts->stream);24while (sonicReadShortFromStream(tts->stream, tts->buffer, WAVE_SIZE));25return FAILURE;26}27numSamples -= n;28}29return SUCCESS;30}
31
32int audio_callback(void *buffer, size_t size, void *user_data) {33signed char *samples = (signed char*) buffer;34TTS_t *tts = (TTS_t*) user_data;35for (size_t i = 0; i < size; i++) {36// Sonic не поддерживает аудиоданные в форме signed char. Преобразуем signed char в unsigned char37samples[i] ^= 0x80;38}39if (sonicWriteUnsignedCharToStream(tts->stream, buffer, size) == 0) {40return FAILURE;41}42return writeToConsumer(tts, WAVE_SIZE);43}
44
45RUTTS_EXPORT TTS_t* tts_create(ru_tts_callback wave_consumer) {46if (wave_consumer == NULL) {47return NULL;48}49sonicStream stream = sonicCreateStream(SAMPLE_RATE, NUM_CHANNELS);50if (stream == NULL) {51return NULL;52}53// Буфер для short-сэмплов54void *buffer = malloc(WAVE_SIZE * sizeof(short));55if (buffer == NULL) {56sonicDestroyStream(stream);57return NULL;58}59TTS_t *tts = malloc(sizeof(TTS_t));60if (tts == NULL) {61sonicDestroyStream(stream);62free(buffer);63return NULL;64}65tts->stream = stream;66tts->buffer = buffer;67tts->consumer = wave_consumer;68return tts;69}
70
71RUTTS_EXPORT void tts_destroy(TTS_t *tts) {72if (tts == NULL) {73return;74}75if (tts->stream != NULL) {76sonicDestroyStream(tts->stream);77tts->stream = NULL;78}79if (tts->buffer != NULL) {80free(tts->buffer);81tts->buffer = NULL;82}83tts->consumer = NULL;84free(tts);85}
86
87RUTTS_EXPORT void tts_speak(const TTS_t *tts, const ru_tts_conf_t *config, const char *text) {88ru_tts_transfer(config, text, tts->buffer, WAVE_SIZE, audio_callback, (void*)tts);89sonicFlushStream(tts->stream);90writeToConsumer(tts, 1);91}
92
93RUTTS_EXPORT void tts_setVolume(const TTS_t *tts, float volume) {94sonicSetVolume(tts->stream, volume);95}
96
97RUTTS_EXPORT void tts_setSpeed(const TTS_t *tts, float speed) {98sonicSetSpeed(tts->stream, speed);99}
100