У меня есть приложение, которое использует libespeak (версия 1.47.11) для объявления различных сообщений о статусе человеческим голосом.
Это работало хорошо, пока новый поток не был введен в приложение. Теперь обычно за ожидаемыми словами следует тарабарщина. Иногда это последние слоги более длинного, ранее объявленного сообщения. В других случаях это цифры или просто случайные буквы.
Мой код напоминает:
#include <espeak/speak_lib.h>
// ...
std::string message = "The rain in Spain falls mainly in the plain.";
espeak_Initialize(
AUDIO_OUTPUT_PLAYBACK, // plays audio data asynchronously
500, // length of buffers for synth function, in ms
nullptr, // dir containing espeak-data, or null for default
0); // options are mostly for phoneme callbacks, so 0
espeak_ERROR err = espeak_Synth(
message.c_str(), // text
message.size(), // size
0, // position to start from
POS_CHARACTER, // whether above 0 pos is chars/word/sentences
message.size(), // end position, 0 indicating no end
espeakCHARS_AUTO | // flags: AUTO 8 bit or UTF8 automatically
espeakENDPAUSE, // ENDPAUSE sentence pause at end of text
nullptr, // message identifier given to callback (unused)
nullptr); // user data, passed to the callback function (unused)
if (err != EE_OK)
cerr << "Error synthesising speech" << endl;
// Wait until everything has been spoken
espeak_Synchronize();
Я попытался выделить большой обнуленный буфер и скопировать в него свою строку перед передачей в libespeak, но это не помогло.
Объем этих вызовов сохраняется как призыв к espeak_Synchronize
блокирует, пока речь не завершится, поэтому ничего не удаляется message
строка. Как будто libespeak игнорирует длину, которую я запрашиваю.
Обратите внимание, что если я укоротю size
аргумент (второй), тогда разговорная строка усекается.
Обратите внимание, что я вызываю libespeak только из одного потока в моем многопоточном приложении.
Я нашел решение этой проблемы, которое не объясняет, почему речь раньше терпела неудачу, но заставляет речь звучать, как и ожидалось. И на самом деле код теперь выглядит немного лучше.
Вместо того, чтобы использовать AUDIO_OUTPUT_PLAYBACK
для асинхронного воспроизведения, а затем ожидания завершения речи через espeak_Synchronize
использовать AUDIO_OUTPUT_SYNCH_PLAYBACK
для синхронного воспроизведения и удаления последнего звонка (это не больно, но больше не нужно.)
Других решений пока нет …