- PVQA/AQuA interface files

This commit is contained in:
Dmytro Bogovych 2020-06-27 13:41:04 +03:00
parent 7b78c3ce73
commit 345853f941
4 changed files with 628 additions and 0 deletions

View File

@ -0,0 +1,121 @@
#ifndef _AQUA_CPP_H
#define _AQUA_CPP_H
#include <string>
#include <vector>
#include <memory>
#include <mutex>
#include <atomic>
#include <map>
#include <memory.h>
#include "aqua.h"
namespace sevana
{
class aqua
{
protected:
void* mContext = nullptr;
std::mutex mMutex;
public:
// Returns 0 (zero) on successful initialization, otherwise it is error code
static int initialize(const std::string& pathToLicenseFile);
static int initialize(const void* buffer, size_t len);
// Deinitialize library
static void release();
// Current version number
static std::string version();
aqua();
~aqua();
// Open library instance
void open();
// Close library instance
void close();
bool is_open() const;
// Config
typedef std::map<std::string, std::string> config;
void configure_with(const config& config);
static config parse(const std::string& line);
struct audio_buffer
{
audio_buffer()
{}
audio_buffer(int size)
{
mData = std::make_shared<std::vector<unsigned char>>();
mData->resize(size);
}
audio_buffer(const void* data, int size)
{
mData = std::make_shared<std::vector<unsigned char>>();
mData->resize(size);
memcpy(mData->data(), data, size);
}
void* data()
{
return mData ? mData->data() : nullptr;
}
const void* data() const
{
return mData ? mData->data() : nullptr;
}
int size() const
{
return mData ? mData->size() : 0;
}
int mRate = 8000;
int mChannels = 1;
std::shared_ptr<std::vector<unsigned char>> mData;
bool is_initialized() const { return mRate > 0 && mChannels > 0 && mData; }
};
struct faults_report
{
float mSignalAdvancedInMilliseconds = -5000.0;
float mMistimingInPercents = -5000.0;
struct item
{
std::string mSource, mDegrated, mUnit;
};
typedef std::map<std::string, item> result_map;
result_map mResultMap;
std::string text() const;
};
static faults_report load_report(std::istream& input);
// Compare in one shot. Report will include text representation of json report.
struct result
{
float mMos = 0.0f, mPercents = 0.0f, mPesqLike = 0.0f;
faults_report mFaults;
// This can be both plain text or json depending on configuration parameter 'output': 'txt' or 'json'
std::string mFaultsText;
};
result compare(audio_buffer& reference, audio_buffer& test);
};
}
#endif

View File

@ -0,0 +1,174 @@
#ifndef __A_Qu_A_dll_h__
#define __A_Qu_A_dll_h__
#ifdef _WINDOWS
# if defined(AQUA_STATIC_LIBRARY)
# define SSA_SDK_API extern "C"
# else
# ifdef SSA_HEADERS_EXPORTS
# define SSA_SDK_API extern "C" __declspec(dllexport)
# else
# define SSA_SDK_API extern "C" __declspec(dllimport)
# endif
# endif
#else
# define SSA_SDK_API
#endif
// The structure containing information about AQuA library
struct TSSA_AQuA_Info
{
int dStructSize; // Structure size
char * dCopyrightString; // Copyright string
char * dVersionString; // Product name and version number string
int dSampleRateLimit; // Maximal sampling frequency supported by the library
int dChannelsLimit; // Maximal amount of channels supported by the library
bool isDifferentFFmtCheckingEnabled;
// If comparison of audio files in different formats is allowed
const char * pSupportedBitsPerSampleList;
// List of supported sample bits
const char * pSupportedCodecsList; // List of supported audio compression algorithms
};
// The structure contains received quality measurement estimations
struct TSSA_AQuA_Results
{
double dPercent; // Percentage
double dMOSLike; // MOS-like
double dPESQLike; // PESQ-like
};
// The structure containing audio data from a single source
struct TSSA_AQuA_AudioItem
{
long dSampleRate; // Sampling frequency
long dNChannels; // The number of channels in the sound (1 mono, 2 stereo, etc.)
short * pSamples; // The signal samples
long dNSamples; // Number of signal samples
};
// The structure contains the audio data for comparison
struct TSSA_AQuA_AudioData
{
TSSA_AQuA_AudioItem dSrcData; // Data reference signal
TSSA_AQuA_AudioItem dTstData; // These degraded signal
};
// Library initialization, check library copyrights and software license period and validity.
// If initialization is successful the function returns 0, otherwise returns error code.
SSA_SDK_API int SSA_InitLib(char * aPLicFName);
SSA_SDK_API int SSA_InitLibWithData(const void* buffer, size_t len);
// This function is called when work with the library is finished.
// Invoking this function is important for further work with the library.
SSA_SDK_API void SSA_ReleaseLib(void);
// Returns pointer to data structure containing information about AQuA library
SSA_SDK_API TSSA_AQuA_Info * SSA_GetPAQuAInfo(void);
// Creates audio analyzer. If successful returns analyzer's handle,
// if unsuccessful the function returns NULL.
SSA_SDK_API void * SSA_CreateAudioQualityAnalyzer(void);
// Finishes working with analyzer and deletes all variables used during analyzer work.
SSA_SDK_API void SSA_ReleaseAudioQualityAnalyzer(void * anSSA_ID);
// Performs audio files quality estimation according to the files passed
// to the analyzer in the setting functions.
SSA_SDK_API int SSA_OnTestAudioFiles(void * anSSA_ID);
// Performs audio quality estimation according to the data passed
// to the analyzer in aSSA_PAudio structure.
SSA_SDK_API int SSA_OnTestAudioData(void * anSSA_ID, TSSA_AQuA_AudioData * aSSA_PAudio);
// Performs audio quality estimation according to the data passed
// to the analyzer in aSSA_PAudio structure (with accumulation).
SSA_SDK_API int SSA_OnTestAddAudioData(void * anSSA_ID, TSSA_AQuA_AudioData * aSSA_PAudio);
// --------------------------------------------------------------------------------------
// Checking file formats
// --------------------------------------------------------------------------------------
// Checks if file formats are supported by the library. If the format is supported
// the function returns "true", otherwise the return value is "false".
SSA_SDK_API bool SSA_IsFileFormatSupportable(void * anSSA_ID, char * aPFName);
// Checks if file comparison is possible. If files format is supported and
// file comparison is supported for these file formats then the return value
// is "true", otherwise the function returns "false".
SSA_SDK_API bool SSA_AreFilesComparable(void * anSSA_ID, char * aPSrcFName, char * aPTstFName);
// --------------------------------------------------------------------------------------
// Displaying audio quality testing results
// --------------------------------------------------------------------------------------
// Returns string length containing test results in text.
SSA_SDK_API int SSA_GetQualityStringSize(void * anSSA_ID);
// Fills string with the text of the test result. User should allocate memory
// for the string by himself. Amount of the memory required can be found
// by function SSA_GetQualityStringSize.
SSA_SDK_API int SSA_FillQualityString(void * anSSA_ID, char * aPString);
// Fills the structure with results of audio quality measurements.
SSA_SDK_API int SSA_FillQualityResultsStruct(void * anSSA_ID, TSSA_AQuA_Results * aPQResults);
// Returns size of array for integral energy spectrum of the original signal.
// Note that signal spectrum is available only after quality estimation has been performed
// and only in the mode "QualityMode" = 0. If signal spectrum was not calculated
// the function returns 0, in case of error the function returns -1.
SSA_SDK_API int SSA_GetSrcSignalSpecSize(void * anSSA_ID);
// Returns size of array for integral energy spectrum of the signal under test.
// Note that signal spectrum is available only after quality estimation has been performed
// and only in the mode "QualityMode" = 0. If signal spectrum was not calculated
// the function returns 0, in case of error the function returns -1.
SSA_SDK_API int SSA_GetTstSignalSpecSize(void * anSSA_ID);
// Fills array with integral energy spectrum of the original signal.
// Note that signal spectrum is available only after quality estimation has been performed
// and only in the mode "QualityMode" = 0. If signal spectrum was not calculated
// the function returns 0, in case of error the function returns -1.
SSA_SDK_API int SSA_FillSrcSignalSpecArray(void * anSSA_ID, float * aPSpecArray);
// Fills array with integral energy spectrum of the signal under test.
// Note that signal spectrum is available only after quality estimation has been performed
// and only in the mode "QualityMode" = 0. If signal spectrum was not calculated
// the function returns 0, in case of error the function returns -1.
SSA_SDK_API int SSA_FillTstSignalSpecArray(void * anSSA_ID, float * aPSpecArray);
// Returns size of the string containing reasons for quality loss.
// String size does not consider 0 symbol in the end of the string.
SSA_SDK_API int SSA_GetFaultsAnalysisStringSize(void * anSSA_ID);
// Fills string with reasons for audio quality loss. String aPString contains only
// meaningful symbols and does not contain 0 symbol in the end.
SSA_SDK_API int SSA_FillFaultsAnalysisString(void * anSSA_ID, char * aPString);
// Returns size of the string containing signals spectrums pairs.
SSA_SDK_API int SSA_GetSpecPairsStringSize(void * anSSA_ID);
// Fills string with signals spectrums pairs.
SSA_SDK_API int SSA_FillSpecPairsString(void * anSSA_ID, char * aPString, int aSSize);
SSA_SDK_API int SSA_GetSpecPairsSize(void * anSSA_ID);
SSA_SDK_API int SSA_GetSpecPairsArray(void * anSSA_ID, float * aPArray);
// Sets any parameter of the analyzer
SSA_SDK_API bool SSA_SetAnyString(void * anSSA_ID, char * aPParName, char * aPParValue);
//
SSA_SDK_API int SSA_OnHSMGenerate(void * anSSA_ID, bool aFmtID);
#endif // __A_Qu_A_dll_h__

View File

@ -0,0 +1,178 @@
#ifndef _SEVANA_MOS_H
#define _SEVANA_MOS_H
#include <string>
#include <vector>
#include <memory>
#include <mutex>
#include <atomic>
#include <map>
#include <memory.h>
# include "pvqa.h"
# if !defined(PVQA_INTERVAL)
# define PVQA_INTERVAL (0.68)
# endif
namespace sevana {
enum
{
pvqa_success = 0,
pvqa_bad_config = 1,
pvqa_not_initialized = 1000,
pvqa_too_much_streams = 1001,
pvqa_no_context = 1002
};
class detector_report
{
public:
detector_report();
detector_report(const std::string& report);
~detector_report();
// Detector names
const std::vector<std::string>& names() const;
enum status
{
status_ok,
status_poor,
status_uncertain
};
// Row for single time interval
struct row
{
float mStart = 0.0f, mEnd = 0.0f;
std::vector<float> mData;
status mStatus;
};
// All rows
const std::vector<row>& rows() const;
// Find difference in impairements
detector_report get_changes(const detector_report& reference);
// Get short report
std::string to_string() const;
enum display_options
{
show_regular,
show_difference
};
std::string to_table(display_options options = show_regular, const char delimiter = ';') const;
std::string to_json(display_options options = show_regular, bool dedicated_time_fields = true) const;
// Find number of impairements for whole report
size_t count_of(const std::string& detector_name) const;
private:
std::vector<row> mRows;
std::vector<std::string> mDetectorNames;
};
class pvqa
{
private:
static void* mLibraryConfiguration;
static int mLibraryErrorCode;
static std::atomic_int mInstanceCounter;
static std::atomic_uint_least64_t mAllProcessedMilliseconds;
static bool mPvqaLoaded;
void* mContext = nullptr;
double mIntervalLength = 0.68;
size_t mProcessedSamples = 0,
mProcessedMilliseconds = 0;
bool mAudioLineInitialized = false;
std::string mDumpWavPath;
int mErrorCode = 0;
size_t mRate = 0, mChannels = 1;
public:
static std::string version();
static std::string mos_to_color(float mos);
struct DetectorsList
{
std::vector<std::string> mNames;
int mStartIndex = 0;
};
static DetectorsList detectors_names(const std::string& report);
#if defined(TARGET_ANDROID)
// Required to call before any call to SevanaPVQA instance methods
static void setupAndroidEnvironment(void* environment, void* appcontext);
#endif
// Path to config file can be empty
// In this case library will be considered initialized (but will produce zero MOS)
static bool initialize(const std::string& pathToLicenseFile, const std::string& pathToConfigFile);
static bool initialize(const void* license_buffer, size_t license_len,
const void* config_buffer, size_t config_len);
static bool is_initialized();
static int library_error();
static void release();
static int instance_counter() { return mInstanceCounter; }
static uint64_t processed_milliseconds() { return mAllProcessedMilliseconds; }
enum class Codec
{
None,
G711,
ILBC,
G722,
G729,
GSM,
AMRNB,
AMRWB,
OPUS
};
static float max_mos(Codec c);
pvqa();
~pvqa();
bool open(size_t rate, size_t channels, double interval = 0.680);
void close();
bool is_open() const;
// Update/Get model. pcm_length is bytes.
bool update(const void* pcm_buffer, size_t pcm_length);
int error() const;
typedef std::vector<std::vector<float>> echo_data;
struct result
{
float mMos = 0.0f;
std::string mReport;
size_t mIntervals = 0, mPoorIntervals = 0;
};
bool get_result(result& r, size_t last_milliseconds = 0);
struct detector_data
{
// Names corresponding to mData array
std::vector<std::string> mNames;
// Zero element in every row is time offset (in milliseconds)
std::vector<std::vector<float>> mData;
};
detector_data get_detector(const std::string& name, float start_time, float end_time);
echo_data get_echo();
// Combines update & get_result calls
bool singleshot(result& r, const void* pcm_buffer, size_t pcm_length);
};
} // end of namespace
#endif

View File

@ -0,0 +1,155 @@
#ifndef __P_V_Q_A_dll_h__
#define __P_V_Q_A_dll_h__
#ifdef _WINDOWS
#if defined(PVQA_STATIC_LIBRARY)
# define PVQA_API extern "C"
#else
# ifdef PVQADLL_EXPORTS
#define PVQA_API extern "C" __declspec(dllexport)
# else
#define PVQA_API extern "C" __declspec(dllimport)
# endif
#endif
#else
# if defined(__cplusplus)
# define PVQA_API extern "C"
# else
# define PVQA_API extern
# endif
#endif
// It is for size_t type
#include <stddef.h>
// The structure contains received quality measurement estimations
typedef struct
{
double dMOSLike; // MOS-like
long dNumPoorIntervals;
long dNumTotalIntervals;
double dTimeShift;
} TPVQA_Results;
//
typedef struct
{
long dSampleRate; // Sample rate of signal
long dNChannels; // Number of sound channels in audio
short * pSamples; // Pointer to the samples of signal
long dNSamples; // Number of samples
} TPVQA_AudioItem;
#if defined(__ANDROID__)
// Init Android related part. System info and JNI environment context sometimes has to be initialized in separate from other calls.
PVQA_API void PVQA_SetupAndroidEnvironment(void* /* JNIEnv* inside */environment, void* /* jobject */ appcontext);
#endif
// Library initialization, check library copyrights and software license period and validity.
// If initialization is successful the function returns 0, otherwise returns error code.
PVQA_API int PVQA_InitLib(const char * aPLicFName);
PVQA_API int PVQA_InitLibWithLicData(const void* buffer, size_t length);
// Returns a string with the name
PVQA_API const char * PVQA_GetName(void);
// Returns a string with the version number
PVQA_API const char * PVQA_GetVersion(void);
// Returns a string with the copyright
PVQA_API const char * PVQA_GetCopyrightString(void);
// This function is called when work with the library is finished.
// Invoking this function is important for further work with the library.
PVQA_API void PVQA_ReleaseLib(void);
// Creates audio analyzer. If successful returns analyzer's handle,
// if unsuccessful the function returns NULL.
PVQA_API void * PVQA_CreateAudioQualityAnalyzer(void * aCFG_ID);
// Finishes working with analyzer and deletes all variables used during analyzer work.
PVQA_API int PVQA_ReleaseAudioQualityAnalyzer(void * aPVQA_ID);
// Set length of samples delay line
PVQA_API int PVQA_AudioQualityAnalyzerSetIntervalLength(void * aPVQA_ID, double length);
// Create audio-processing delay-line
PVQA_API int PVQA_AudioQualityAnalyzerCreateDelayLine(void * aPVQA_ID, long aSampleRate, long aNChannels, double aLineTime);
// Start recording a debug sound file
PVQA_API int PVQA_StartRecordingWave(void * aPVQA_ID, const char * aPWavFName, long aSampleRate, long aNChannels);
// Performs audio file quality estimation
PVQA_API int PVQA_OnTestAudioFile(void * aPVQA_ID, const char * aPFileName);
// Process loaded in memory audio data
PVQA_API int PVQA_OnTestAudioData(void * aPVQA_ID, TPVQA_AudioItem * aPVQA_PAudio);
// Put Audio data to delay-line and process it
PVQA_API int PVQA_OnTestAddAudioData(void * aPVQA_ID, TPVQA_AudioItem * aPVQA_PAudio);
// Start audio-stream processing
PVQA_API int PVQA_OnStartStreamData(void * aPVQA_ID);
// Process streaming Audio data
PVQA_API int PVQA_OnAddStreamAudioData(void * aPVQA_ID, TPVQA_AudioItem * aPVQA_PAudio);
PVQA_API int PVQA_OnAddStreamAudioDataHex(void * aPVQA_ID, int rate, int channels, const char* samples);
// Updates quality results data
PVQA_API int PVQA_OnUpdateStreamQualityResults(void * aPVQA_ID, int rate, int millisecondsFromEnd);
// Finalize quality measurements at this moment (not finalize stream processing)
PVQA_API int PVQA_OnFinalizeStream(void * aPVQA_ID, long aSampleRate);
// --------------------------------------------------------------------------------------
// Displaying audio quality testing results
// --------------------------------------------------------------------------------------
// Returns string length containing test results in text.
PVQA_API int PVQA_GetQualityStringSize(void * anPVQA_ID);
// Fills string with the text of the test result. User should allocate memory
// for the string by himself. Amount of the memory required can be found
// by function PVQA_GetQualityStringSize.
PVQA_API int PVQA_FillQualityString(void * aPVQA_ID, char * aPString);
// Returns string by combining PVQA_GetQualityStringSize() + PVQA_FillQualityString() + PVQA_FillQualityResultsStruct()
PVQA_API char* PVQA_GetQualityString(void * ctx, double* mos, int* errCode);
// Fills the structure with results of audio quality measurements.
PVQA_API int PVQA_FillQualityResultsStruct(void * aPVQA_ID, TPVQA_Results * aPQResults);
// Get a list of the names of the values of the detector
// No need to free() the pointer.
PVQA_API const char ** PVQA_GetProcessorValuesNamesList(void * aPVQA_ID, const char * aPDetectorName, int * errCode);
typedef struct
{
int columns, rows;
float* data;
} PVQA_Array2D;
// Get a list of the values of the detector
// Returned value has to be released via PVQA_ReleaseArray2D
PVQA_API PVQA_Array2D* PVQA_GetProcessorValuesList(void * aPVQA_ID, const char * aPDetectorName, long aStartTime,
long aStopTime, const char * aStatType, int * errCode);
// Release allocated 2D array
PVQA_API void PVQA_ReleaseArray2D(PVQA_Array2D* array);
// --------------------------------------------------------------------------------------
// Working with configuration files
// --------------------------------------------------------------------------------------
// Load settings File in memory
PVQA_API void * PVQA_LoadCFGFile(const char * aFileName, int * errCode);
PVQA_API void * PVQA_LoadCFGData(const void* buffer, size_t length, int* errCode);
// Release settings file structures
PVQA_API int PVQA_ReleaseCFGFile(void * aCFG_ID);
#endif // __P_V_Q_A_dll_h__