Last active
September 3, 2016 03:32
-
-
Save planaria/e51e92d406f73c4994526cfa162b6726 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <fstream> | |
#include <array> | |
#include <map> | |
#include <algorithm> | |
#include <boost/iterator/transform_iterator.hpp> | |
#include <boost/numeric/odeint.hpp> | |
namespace cvcpp | |
{ | |
double lerp(double x1, double x2, double ratio) | |
{ | |
return x1 + (x2 - x1) * ratio; | |
} | |
double pow2(double x) | |
{ | |
return x * x; | |
} | |
static const std::size_t num_vocal_tracts = 46; | |
struct key_frame | |
{ | |
double pressure = 0.0; | |
double tension = 0.0; | |
std::array<double, num_vocal_tracts> tract_widths = {}; | |
}; | |
key_frame lerp(const key_frame& k1, const key_frame& k2, double ratio) | |
{ | |
key_frame result; | |
result.pressure = lerp(k1.pressure, k2.pressure, ratio); | |
result.tension = lerp(k1.tension, k2.tension, ratio); | |
for (std::size_t i = 0; i < num_vocal_tracts; ++i) | |
result.tract_widths[i] = lerp(k1.tract_widths[i], k2.tract_widths[i], ratio); | |
return result; | |
} | |
struct cord_state | |
{ | |
double x1; | |
double x2; | |
double x1v; | |
double x2v; | |
double ug; | |
std::array<double, num_vocal_tracts> u; | |
std::array<double, num_vocal_tracts> p; | |
}; | |
class cord_system | |
{ | |
public: | |
static const int num_variables = sizeof(cord_state) / sizeof(double); | |
static_assert(sizeof(cord_state) == sizeof(double) * num_variables, ""); | |
cord_system(const key_frame& begin_key, const key_frame& end_key, double end_time) | |
: begin_key_(begin_key) | |
, end_key_(end_key) | |
, end_time_(end_time) | |
{ | |
} | |
template <class state_type> | |
void operator ()(const state_type& x_, state_type& dxdt_, double t) const | |
{ | |
const cord_state& x = state(x_); | |
cord_state& dxdt = state(dxdt_); | |
double ratio = t / end_time_; | |
key_frame key = lerp(begin_key_, end_key_, ratio); | |
double ps = key.pressure * 5.0; | |
double k1 = 5000000.0 * key.tension; | |
double k2 = 3900000.0 * key.tension; | |
double k12 = 2000000.0 * key.tension; | |
static const double length1 = 1.0; | |
static const double length2 = 1.0; | |
static const double mass_fluid = 0.02; | |
static const double mass1 = 1.0; | |
static const double mass2 = 1.0; | |
static const double c1 = 30.0; | |
static const double c2 = 30.0; | |
static const double density = 100000.0; | |
static const double x1_base = 0.1; | |
static const double x2_base = 0.1; | |
static const double x1_min = 0.01; | |
static const double x2_min = 0.01; | |
static const double x1_max = 10.0; | |
static const double x2_max = 10.0; | |
static const double friction1 = 1.0; | |
static const double friction2 = 1.0; | |
double x1_shift = std::max(x1_min, std::min(x1_max, x.x1 + x1_base)); | |
double x2_shift = std::max(x2_min, std::min(x2_max, x.x2 + x2_base)); | |
double velocity1 = x.ug / x1_shift; | |
double velocity2 = x.ug / x2_shift; | |
double pressure1 = ps - length1 * pow2(velocity1) * density; | |
double pressure2 = ps - length2 * pow2(velocity2) * density; | |
dxdt.x1v = (pressure1 - x.x1 * k1 - x.x1v * c1 + (x.x2 - x.x1) * k12) / mass1; | |
dxdt.x2v = (pressure2 - x.x2 * k2 - x.x2v * c2 + (x.x1 - x.x2) * k12) / mass2; | |
dxdt.x1 = x.x1v; | |
dxdt.x2 = x.x2v; | |
double resistance1 = length1 * friction1 * velocity1; | |
double resistance2 = length2 * friction2 * velocity2; | |
double dp = ps - x.p[0] - resistance1 - resistance2; | |
dxdt.ug = dp / mass_fluid; | |
static const double tract_length = 3.2; | |
static const double tract_friction = 0.01; | |
static const double rho = 0.0001; | |
static const double speed_of_sound = 340290.0; | |
static const double width_min = 0.01; | |
double r = tract_friction * tract_length; | |
double inv_l_base = 1.0 / (rho * tract_length); | |
double inv_c_base = rho * pow2(speed_of_sound) / tract_length; | |
for (std::size_t i = 0; i < num_vocal_tracts; ++i) | |
{ | |
double width = key.tract_widths[i]; | |
if (width < width_min) | |
{ | |
double inv_l = inv_l_base * width_min; | |
dxdt.u[i] = (-x.u[i] * r) * inv_l; | |
dxdt.p[i] = 0.0; | |
} | |
else | |
{ | |
double inv_l = inv_l_base * width; | |
double inv_c = inv_c_base / width; | |
if (i != num_vocal_tracts - 1) | |
dxdt.u[i] = (x.p[i] - x.p[i + 1] - x.u[i] * r) * inv_l; | |
else | |
dxdt.u[i] = (x.p[i] - x.u[i] * r) * inv_l; | |
if (i == 0) | |
dxdt.p[i] = (x.ug - x.u[i]) * inv_c; | |
else | |
dxdt.p[i] = (x.u[i - 1] - x.u[i]) * inv_c; | |
} | |
} | |
} | |
template <class state_type> | |
const cord_state& state(const state_type& x) const | |
{ | |
return *reinterpret_cast<const cord_state*>(&x[0]); | |
} | |
template <class state_type> | |
cord_state& state(state_type& x) const | |
{ | |
return *reinterpret_cast<cord_state*>(&x[0]); | |
} | |
private: | |
key_frame begin_key_; | |
key_frame end_key_; | |
double end_time_; | |
}; | |
void normalize(std::vector<double>& values, double volume) | |
{ | |
if (values.empty()) | |
return; | |
auto begin = boost::make_transform_iterator(values.begin(), &std::abs<double>); | |
auto end = boost::make_transform_iterator(values.end(), &std::abs<double>); | |
double maximum = *std::max_element(begin, end); | |
double magnify = volume / maximum; | |
for (double& value : values) | |
value *= magnify; | |
} | |
#pragma pack(push, 1) | |
struct wav_header | |
{ | |
static const std::uint16_t format_linear = 1; | |
static const std::uint16_t bytes_per_sample = 2; | |
wav_header( | |
std::uint16_t num_channels_, | |
std::uint32_t sampling_rate_) | |
: riff({ 'R', 'I', 'F', 'F' }) | |
, file_size() | |
, wave({ 'W', 'A', 'V', 'E' }) | |
, fmt({ 'f', 'm', 't', ' ' }) | |
, fmt_size(16) | |
, format_id(format_linear) | |
, num_channels(num_channels_) | |
, sampling_rate(sampling_rate_) | |
, bytes_per_sec(num_channels_ * sampling_rate_ * bytes_per_sample) | |
, block_size(num_channels_ * bytes_per_sample) | |
, bits_per_sample(bytes_per_sample * 8) | |
, data({ 'd', 'a', 't', 'a' }) | |
, data_size() | |
{ | |
} | |
std::array<char, 4> riff; | |
std::uint32_t file_size; | |
std::array<char, 4> wave; | |
std::array<char, 4> fmt; | |
std::uint32_t fmt_size; | |
std::uint16_t format_id; | |
std::uint16_t num_channels; | |
std::uint32_t sampling_rate; | |
std::uint32_t bytes_per_sec; | |
std::uint16_t block_size; | |
std::uint16_t bits_per_sample; | |
std::array<char, 4> data; | |
std::uint32_t data_size; | |
}; | |
#pragma pack(pop) | |
void write_wav( | |
std::ostream& os, | |
const std::vector<double>& wave, | |
std::uint16_t num_channels, | |
std::uint32_t sampling_rate) | |
{ | |
wav_header header(num_channels, sampling_rate); | |
std::size_t data_size = wave.size() * wav_header::bytes_per_sample; | |
header.file_size = boost::numeric_cast<std::uint32_t>(sizeof(header) + data_size - 8); | |
header.data_size = boost::numeric_cast<std::uint32_t>(data_size); | |
os.write(reinterpret_cast<const char*>(&header), sizeof(header)); | |
for (double value : wave) | |
{ | |
double f = std::max(-32768.0, std::min(32767.0, std::round(value * 32767.0))); | |
std::int16_t v = static_cast<std::int16_t>(f); | |
os.write(reinterpret_cast<const char*>(&v), sizeof(v)); | |
} | |
} | |
void output(const std::map<double, cvcpp::key_frame>& key_frames, std::uint32_t sampling_rate) | |
{ | |
namespace odeint = boost::numeric::odeint; | |
std::vector<double> values; | |
for (auto it = key_frames.begin(); it != std::prev(key_frames.end()); ++it) | |
{ | |
auto next_it = std::next(it); | |
std::size_t num_steps = static_cast<std::size_t>(std::ceil((next_it->first - it->first) * static_cast<double>(sampling_rate))); | |
double dt = 1.0 / static_cast<double>(sampling_rate); | |
double end_time = static_cast<double>(num_steps) * dt; | |
typedef std::array<double, cord_system::num_variables> state_type; | |
state_type state = {}; | |
static const double abs_error = 0.00001; | |
static const double rel_error = 0.00001; | |
typedef odeint::runge_kutta_dopri5<state_type> base_stepper_type; | |
auto stepper = odeint::make_controlled(abs_error, rel_error, base_stepper_type()); | |
cord_system system(it->second, next_it->second, end_time); | |
std::size_t index = 0; | |
odeint::integrate_n_steps(stepper, system, state, 0.0, dt, num_steps, | |
[&](const state_type& x, double t) | |
{ | |
if (index++ < num_steps) | |
values.push_back(system.state(x).u.back()); | |
}); | |
} | |
normalize(values, 0.1); | |
{ | |
std::fstream os("output.wav", std::ios_base::out | std::ios_base::binary); | |
write_wav(os, values, 1, sampling_rate); | |
os.flush(); | |
} | |
} | |
key_frame base_i(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 3.3, 3.0, 3.6, 3.4, 6.8, 5.0, 24.3, 31.5, 26.6, 24.9, 33.9, 38.0, 37.8, 43.5, 45.0, 44.3, 46.8, 45.2, 41.5, 40.9, 35.1, 29.5, 20.3, 16.6, 13.8, 10.5, 6.0, 3.5, 3.2, 1.2, 1.0, 1.6, 2.5, 2.4, 3.8, 2.8, 3.6, 6.5, 15.8, 20.5, 20.1, 15.8, 100.0, 100.0, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_e1(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 2.0, 1.7, 1.8, 1.8, 1.0, 10.8, 16.6, 16.4, 11.9, 9.2, 11.3, 24.8, 27.6, 29.7, 34.3, 33.2, 34.8, 39.6, 37.9, 38.8, 34.7, 29.8, 26.2, 23.7, 19.9, 19.0, 17.0, 14.4, 14.5, 10.6, 8.7, 7.5, 10.6, 12.9, 17.8, 18.3, 17.0, 19.7, 19.2, 16.2, 13.6, 11.8, 100.0, 100.0, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_e2(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 2.1, 1.3, 1.6, 1.4, 0.6, 7.8, 12.5, 12.4, 9.9, 7.2, 7.3, 10.6, 17.7, 19.7, 24.6, 27.0, 29.2, 30.3, 28.4, 28.4, 28.3, 23.6, 21.4, 20.0, 17.8, 18.1, 17.9, 15.0, 13.7, 13.6, 14.3, 18.3, 20.8, 25.9, 25.4, 21.1, 23.4, 27.4, 21.9, 16.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_e3(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 2.2, 2.6, 2.6, 1.6, 1.3, 2.1, 8.3, 15.0, 13.5, 9.9, 6.9, 13.5, 23.2, 21.3, 19.4, 21.7, 28.5, 32.6, 37.3, 38.0, 36.9, 38.7, 36.8, 32.0, 32.6, 32.9, 31.9, 32.3, 32.3, 34.0, 37.8, 38.4, 39.8, 44.1, 45.6, 47.9, 43.9, 44.2, 42.3, 45.6, 43.1, 39.4, 100.0, 100.0, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_a1(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 3.3, 2.8, 2.3, 1.5, 1.7, 3.3, 3.9, 10.2, 12.2, 11.4, 8.2, 7.6, 6.6, 8.0, 7.2, 6.6, 10.8, 9.1, 10.9, 10.6, 10.9, 11.7, 13.9, 15.5, 18.9, 21.7, 24.6, 26.5, 31.3, 38.1, 43.0, 45.7, 49.4, 55.8, 57.9, 55.1, 54.9, 46.9, 45.0, 32.1, 27.9, 21.1, 19.8, 11.7, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_a2(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 4.5, 2.0, 2.6, 2.1, 3.2, 3.0, 3.3, 10.5, 11.2, 8.5, 6.3, 3.9, 2.6, 2.8, 2.3, 3.2, 2.9, 2.8, 4.0, 6.6, 12.0, 10.5, 16.2, 20.9, 25.6, 27.8, 28.6, 30.2, 37.5, 46.0, 50.9, 60.2, 65.5, 62.9, 62.7, 59.4, 52.8, 47.0, 38.7, 41.3, 42.5, 42.7, 46.9, 50.3, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_a3(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 6.1, 2.8, 1.9, 1.0, 0.7, 3.0, 1.8, 11.3, 14.2, 12.1, 6.9, 5.1, 4.3, 6.6, 5.7, 3.2, 4.3, 4.5, 5.3, 6.0, 7.7, 6.5, 5.8, 9.4, 20.2, 25.0, 24.1, 26.2, 32.9, 43.4, 47.8, 52.4, 60.7, 70.8, 68.1, 62.0, 58.9, 50.4, 42.9, 24.9, 18.4, 13.3, 11.9, 8.8, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_o1(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 1.8, 1.7, 2.3, 2.8, 5.9, 14.6, 16.0, 11.1, 8.2, 10.1, 27.2, 27.1, 19.6, 19.2, 17.0, 16.6, 15.2, 12.8, 14.4, 12.8, 8.9, 12.5, 13.8, 10.9, 7.1, 4.6, 3.9, 3.2, 5.7, 10.6, 13.8, 22.9, 29.9, 37.4, 43.9, 53.8, 72.5, 70.0, 45.7, 27.5, 14.8, 6.8, 3.9, 1.4, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_o2(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 3.2, 3.9, 3.9, 4.3, 5.6, 14.6, 22.0, 20.6, 15.8, 11.1, 11.1, 12.6, 13.0, 9.8, 9.3, 8.3, 6.1, 9.7, 7.5, 9.3, 5.3, 6.5, 9.5, 9.9, 10.7, 13.9, 14.7, 17.9, 23.4, 26.8, 33.6, 39.8, 47.4, 54.8, 56.9, 55.7, 49.9, 44.8, 30.7, 16.7, 11.3, 6.4, 1.5, 2.2, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_u(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 4.0, 3.8, 2.8, 4.3, 5.5, 17.2, 29.1, 28.8, 23.7, 21.0, 36.3, 58.6, 56.3, 54.3, 48.0, 45.6, 42.9, 36.3, 33.7, 31.6, 33.1, 32.2, 23.3, 20.7, 20.7, 15.2, 7.4, 2.3, 1.5, 2.2, 2.2, 3.7, 6.0, 7.6, 8.6, 18.2, 23.5, 25.5, 37.3, 54.7, 44.6, 23.9, 11.0, 7.7, 4.1, 8.6 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_e4(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 4.1, 3.8, 4.0, 2.9, 1.3, 5.3, 15.8, 15.6, 12.2, 11.9, 10.0, 7.7, 9.2, 11.9, 12.7, 13.5, 14.8, 15.6, 16.1, 18.7, 21.0, 20.1, 26.2, 29.6, 30.7, 31.1, 27.7, 26.7, 24.7, 23.4, 22.5, 19.0, 13.2, 7.6, 4.4, 4.5, 9.2, 20.5, 32.5, 36.3, 35.9, 30.7, 22.5, 12.0, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_l(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 5.5, 6.3, 7.5, 18.0, 29.8, 35.6, 34.5, 32.2, 32.0, 26.7, 30.2, 35.5, 37.6, 35.3, 26.2, 24.0, 23.2, 24.3, 21.3, 22.7, 22.8, 22.6, 23.3, 24.3, 24.4, 25.4, 26.4, 26.7, 31.6, 36.8, 43.0, 51.4, 58.3, 64.4, 65.4, 69.1, 67.2, 56.1, 40.8, 27.3, 4.5, 9.0, 39.2, 49.9, 45.7, 37.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_m(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 5.7, 5.7, 2.1, 5.8, 21.8, 31.5, 29.6, 28.9, 37.0, 42.1, 35.7, 35.9, 29.7, 31.7, 32.5, 25.8, 27.4, 27.7, 24.9, 29.3, 33.3, 22.7, 25.7, 21.7, 18.4, 19.8, 17.3, 14.3, 17.3, 20.8, 23.2, 28.4, 35.1, 42.5, 47.9, 46.1, 40.7, 36.4, 28.4, 14.2, 2.9, 0.0, 0.0, 0.0, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_n(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 2.6, 2.4, 1.7, 2.1, 1.5, 3.6, 13.7, 16.6, 13.5, 9.0, 7.1, 9.3, 14.1, 20.7, 21.2, 20.4, 21.6, 23.6, 25.2, 28.8, 23.0, 19.3, 17.7, 9.6, 8.9, 12.2, 13.0, 13.0, 11.4, 7.7, 3.4, 1.5, 2.2, 2.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 15.9, 16.0, 16.9, 11.7, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_ou(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 5.1, 4.7, 4.5, 3.0, 4.8, 6.7, 8.3, 9.6, 14.3, 11.4, 8.4, 6.9, 8.2, 8.6, 5.7, 8.1, 10.0, 6.6, 8.0, 9.7, 7.8, 5.8, 4.6, 4.4, 4.7, 4.1, 1.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 21.8, 47.2, 68.6, 85.8, 87.6, 72.1, 49.2, 32.1, 21.7, 14.1, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_p(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 3.1, 3.9, 4.2, 7.1, 12.8, 18.0, 17.0, 14.3, 12.5, 9.0, 20.6, 27.7, 21.9, 23.5, 26.7, 21.7, 17.7, 20.9, 21.6, 22.6, 22.6, 22.9, 21.7, 21.3, 26.4, 26.5, 23.0, 21.2, 16.7, 14.4, 11.6, 15.1, 17.6, 19.3, 19.8, 22.1, 23.5, 24.5, 23.7, 24.7, 17.5, 10.9, 7.0, 0.0, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_t(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 3.8, 5.0, 4.0, 10.7, 13.8, 16.5, 12.9, 10.1, 9.2, 8.6, 10.3, 16.0, 24.6, 22.4, 24.7, 28.6, 27.4, 33.2, 38.3, 39.7, 41.6, 44.1, 41.1, 39.5, 36.4, 33.7, 28.9, 26.1, 26.9, 23.2, 20.4, 16.4, 13.9, 12.6, 8.7, 6.0, 1.0, 0.0, 0.0, 1.3, 1.8, 14.8, 16.0, 14.3, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_k(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 3.4, 3.5, 4.9, 7.8, 13.1, 13.4, 11.9, 9.4, 6.9, 9.2, 14.5, 17.3, 16.7, 21.3, 16.1, 15.6, 15.4, 11.8, 14.4, 11.2, 7.6, 9.6, 10.9, 7.9, 2.5, 0.0, 0.6, 0.3, 0.9, 1.0, 0.6, 0.3, 4.8, 12.7, 22.8, 23.5, 24.0, 24.1, 42.1, 33.7, 24.6, 24.6, 21.4, 15.0, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
key_frame base_c(double tension = 1.0, double pressure = 1.0) | |
{ | |
key_frame result; | |
std::array<double, num_vocal_tracts> widths = { 3.3, 3.0, 3.6, 3.4, 6.8, 5.0, 24.3, 31.5, 26.6, 24.9, 33.9, 38.0, 37.8, 43.5, 45.0, 44.3, 46.8, 45.2, 41.5, 40.9, 35.1, 29.5, 20.3, 16.6, 13.8, 10.5, 6.0, 3.5, 3.2, 1.2, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.6, 6.5, 15.8, 20.5, 20.1, 15.8, 100.0, 100.0, 100.0, 100.0 }; | |
result.tension = tension; | |
result.pressure = pressure; | |
result.tract_widths = widths; | |
return result; | |
} | |
} | |
int main(int /*argc*/, char* /*argv*/[]) | |
{ | |
cvcpp::key_frame rest; | |
std::map<double, cvcpp::key_frame> key_frames = | |
{ | |
{ 0.0, rest }, | |
{ 1.0, rest }, | |
{ 1.03, cvcpp::base_a1() }, | |
{ 1.97, cvcpp::base_a1() }, | |
{ 2.0, rest }, | |
{ 3.0, rest }, | |
{ 3.03, cvcpp::base_i() }, | |
{ 3.97, cvcpp::base_i() }, | |
{ 4.0, rest }, | |
{ 5.0, rest }, | |
{ 5.03, cvcpp::base_u() }, | |
{ 5.97, cvcpp::base_u() }, | |
{ 6.0, rest }, | |
{ 7.0, rest }, | |
{ 7.03, cvcpp::base_e1() }, | |
{ 7.97, cvcpp::base_e1() }, | |
{ 8.0, rest }, | |
{ 9.0, rest }, | |
{ 9.03, cvcpp::base_o1() }, | |
{ 9.97, cvcpp::base_o1() }, | |
{ 10.0, rest }, | |
{ 11.0, rest }, | |
}; | |
std::int32_t sampling_rate = 44100; | |
cvcpp::output(key_frames, sampling_rate); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment