forked from tignear/node-openjtalk-binding
-
Notifications
You must be signed in to change notification settings - Fork 0
/
options.cc
138 lines (126 loc) · 3.25 KB
/
options.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <napi.h>
#include <open_jtalk.hpp>
#include <limits>
/**compatibility of c++14**/
#if __cplusplus >= 201703L
/**c++17**/
#include <optional>
using std::optional;
#else
/**c++14**/
#include "nonstd/optional.hpp"
using nonstd::optional;
#endif
struct Options
{
optional<size_t> sampling_frequency;
optional<size_t> frame_period;
optional<size_t> audio_buffer_size;
optional<double> all_pass_constant;
optional<double> postfiltering_coefficient;
optional<double> speech_speed_rate;
optional<double> additional_half_tone;
optional<double> voiced_unvoiced_threshold;
optional<double> weight_of_GV_for_spectrum;
optional<double> weight_of_GV_for_log_F0;
optional<double> volume_in_dB;
};
#if __cplusplus >= 201703L
#define option_return auto
#else
#include <array>
#include <functional>
#define option_return std::tuple<std::function<void(Options &options, Napi::Object &js_options)>, std::function<void(Open_JTalk *open_jtalk,const Options &opt)>>
template <size_t N>
using option_list = std::array<option_return, N>;
template <typename... Args>
static constexpr inline option_list<sizeof...(Args)> make_array(Args &&... args)
{
return option_list<sizeof...(Args)>{std::forward<Args>(args)...};
}
#endif
using namespace std::literals::string_literals;
void CheckNullish(Napi::Value &value, const std::string &key)
{
if (!(value.IsNull() || value.IsUndefined()))
{
throw Napi::TypeError::New(value.Env(), "Invalid "s + key + " type."s);
}
}
template <class T>
constexpr auto range(T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max())
{
return [min, max](T value) {
return min <= value && value <= max;
};
}
template <class T = Napi::Number, class U = T, class F>
constexpr option_return option(
const char *key,
optional<U> Options::*m,
F r,
void (*config_fn)(Open_JTalk *, U))
{
auto extract = [key, r, m](Options &options,
Napi::Object &js_options) {
Napi::Env env = js_options.Env();
auto v = js_options.Get(key);
if (v.IsNumber())
{
T d = v.As<Napi::Number>();
if (!r(d))
{
throw Napi::TypeError::New(env, key + " is out of range."s);
}
options.*m = d;
}
else
{
CheckNullish(v, key);
}
};
auto set = [m, config_fn](Open_JTalk *open_jtalk, const Options &opt) {
auto v = opt.*m;
if (v)
{
config_fn(open_jtalk, *v);
}
};
return std::make_tuple(extract, set);
}
#if __cplusplus >= 201703L
const static constexpr auto int_option_list = {
#include "int_options"
};
const static constexpr auto double_option_list = {
#include "double_options"
};
#endif
template <size_t idx, class Dst, class Src>
inline void OptionsLoop(Dst &dst, Src src)
{
#if __cplusplus < 201703L
auto int_option_list = make_array(
#include "int_options"
);
auto double_option_list = make_array(
#include "double_options"
);
#endif
for (auto &entry : int_option_list)
{
std::get<idx>(entry)(dst, src);
}
for (auto &entry : double_option_list)
{
std::get<idx>(entry)(dst, src);
}
}
void ExtractOptions(Options &options, Napi::Object &js_options)
{
OptionsLoop<0>(options, js_options);
}
void SetOptions(Open_JTalk *open_jtalk,const Options &options)
{
OptionsLoop<1>(open_jtalk, options);
}