diff --git a/src/phone_extraction.cpp b/src/phone_extraction.cpp index 32459e3..4a00336 100644 --- a/src/phone_extraction.cpp +++ b/src/phone_extraction.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "phone_extraction.h" #include "audio_input/SampleRateConverter.h" #include "audio_input/ChannelDownmixer.h" @@ -120,7 +122,42 @@ map getPhones(ps_decoder_t& recognizer) { return result; }; +void sphinxErrorCallback(void* user_data, err_lvl_t errorLevel, const char* format, ...) { + if (errorLevel < ERR_WARN) return; + + // Create varArgs list + va_list args; + va_start(args, format); + auto _ = finally([&args](){ va_end(args); }); + + // Format message + const int initialSize = 256; + std::vector chars(initialSize); + bool success = false; + while (!success) { + int charsWritten = vsnprintf(chars.data(), chars.size(), format, args); + if (charsWritten < 0) throw runtime_error("Error formatting Pocketsphinx log message."); + + success = charsWritten < static_cast(chars.size()); + if (!success) chars.resize(chars.size() * 2); + } + string message(chars.data()); + boost::algorithm::trim(message); + + // Append message to error string + string* errorString = static_cast(user_data); + if (errorString->size() > 0) *errorString += "\n"; + *errorString += message; +} + map detectPhones(unique_ptr audioStream) { + // Discard Pocketsphinx output + err_set_logfp(nullptr); + + // Collect all Pocketsphinx error messages in a string + string errorMessage; + err_set_callback(sphinxErrorCallback, &errorMessage); + try { // Create PocketSphinx configuration path sphinxModelDirectory(getBinDirectory().parent_path() / "res/sphinx"); @@ -138,6 +175,6 @@ map detectPhones(unique_ptr audioStream) { // Collect results into map return getPhones(*recognizer.get()); } catch (...) { - std::throw_with_nested(runtime_error("Error detecting phones via Pocketsphinx.")); + std::throw_with_nested(runtime_error("Error detecting phones via Pocketsphinx. " + errorMessage)); } }