//simple low pass filter void reduce_noise(u::bytes& s, size_t len) { REQUIRE_EQUAL(s.size() % 2, 0); auto ss = reinterpret_cast<short*>(s.data()); len /= 2; for(size_t i = 1; i < len; i++) ss[i] = (0.333 * ss[i]) + ((1 - 0.333) * ss[i-1]) + 0.5; }
//decimate sound to SAMPLE_RATE, using averaging void decimate(const u::bytes& s, u::bytes& d, size_t channels, size_t skip) { REQUIRE_FALSE(s.empty()); REQUIRE_EQUAL(s.size() % 2, 0); //get sizes auto dz = (s.size() / skip); auto nz = d.size() + dz; //add padding if(nz % 2 == 1) nz += 1; CHECK_EQUAL(nz % 2, 0); //resize dest const auto odz = d.size(); d.resize(nz); //cast to short arrays auto ss = reinterpret_cast<const short*>(s.data()); const auto sz = s.size() / 2; auto sd = reinterpret_cast<short*>(d.data()); const auto sdz = nz / 2; int accum = 0; size_t c = 1; size_t si = 0; auto di = odz / 2; for(;si < sz; si+=channels) { accum += static_cast<int>(ss[si]); if(c == skip) { accum /= c; sd[di] = accum; di++; accum = 0; c = 1; continue; } c++; } //repeat last value if we have padding si = sz-1; while(di < sdz) { sd[di] = ss[si]; di++; } CHECK_EQUAL(di, sdz); }
u::bytes microphone::encode(const u::bytes& b) { REQUIRE(_opus); REQUIRE_FALSE(b.empty()); return _opus->encode({b}).data; }
void speaker::play(const u::bytes& d) { INVARIANT(_o); if(_mute) return; if(d.empty()) return; const u::bytes* data = &d; u::bytes dec; if(_t == codec_type::opus) { dec = decode(d); data = &dec; } CHECK(data); //repeat to match speaker sample rate u::bytes r; inflate(*data, r, _channels, _rep); if(_d) { _d->write(r.data(), r.size()); if(_o->state() == QAudio::SuspendedState) { _o->reset(); _o->resume(); } } else { _d = _o->start(); _d->write(r.data(), r.size()); } }
u::bytes private_key::sign(const u::bytes& b) const { INVARIANT(_k); u::mutex_scoped_lock l(BOTAN_MUTEX); init_rng(); CHECK(RNG); b::PK_Signer s{*_k, EMSA_SCHEME}; auto r = s.sign_message(reinterpret_cast<const unsigned char*>(b.data()), b.size(), *RNG); ENSURE_EQUAL(r.size(), SIGNATURE_SIZE); return u::bytes {std::begin(r), std::end(r)}; }
u::bytes public_key::encrypt(const u::bytes& b) const { INVARIANT(_k); INVARIANT_FALSE(_ks.empty()); u::mutex_scoped_lock l(BOTAN_MUTEX); init_rng(); CHECK(RNG); std::stringstream rs; b::PK_Encryptor_EME e{*_k, EME_SCHEME}; size_t advance = 0; while(advance < b.size()) { size_t size = std::min(e.maximum_input_size(), b.size()-advance); auto c = e.encrypt(reinterpret_cast<const unsigned char*>(b.data())+advance, size, *RNG); u::bytes bs{std::begin(c), std::end(c)}; rs << bs; advance+=size; } return u::to_bytes(rs.str()); }
void inflate(const u::bytes& s, u::bytes& d, size_t channels, size_t rep) { REQUIRE_EQUAL(s.size() % 2, 0); rep*=channels; d.resize(s.size() * rep); auto ss = reinterpret_cast<const short*>(s.data()); auto sz = s.size() / 2; auto sd = reinterpret_cast<short*>(d.data()); size_t di = 0; for(size_t si = 0; si < sz; si++) for(size_t p = 0; p < rep; p++, di++) sd[di] = ss[si]; }