/* Do window management once we have a complete window, including mangling * the current window. */ static int process_window(reddata_t data, int chan_num, int num_chans, st_sample_t *obuf, int len) { int j; float* nextwindow; int use = min(len, WINDOWSIZE)-(WINDOWSIZE/2); chandata_t *chan = &(data->chandata[chan_num]); int first = (chan->lastwindow == NULL); nextwindow = (float*)calloc(WINDOWSIZE, sizeof(float)); memcpy(nextwindow, chan->window+WINDOWSIZE/2, sizeof(float)*(WINDOWSIZE/2)); reduce_noise(chan, chan->window, data->threshold); if (!first) { for (j = 0; j < use; j ++) { float s = chan->window[j] + chan->lastwindow[WINDOWSIZE/2 + j]; if (s < -1 || s > 1) { float news; if (s > 1) news = 1; else news = -1; st_warn("noisered: Output clipped from %f to %f.\n", s, news); } obuf[chan_num + num_chans * j] = ST_FLOAT_DWORD_TO_SAMPLE(s); } free(chan->lastwindow); } else { for (j = 0; j < use; j ++) { assert(chan->window[j] >= -1 && chan->window[j] <= 1); obuf[chan_num + num_chans * j] = ST_FLOAT_DWORD_TO_SAMPLE(chan->window[j]); } } chan->lastwindow = chan->window; chan->window = nextwindow; return use; }
u::bytes microphone::read_data() { REQUIRE(_d); if(!_d) return {}; INVARIANT(_i); auto len = _i->bytesReady(); if(len <= 0) return {}; if(static_cast<size_t>(len) > MAX_SAMPLE_BYTES) len = MAX_SAMPLE_BYTES; u::bytes data; data.resize(len); auto l = _d->read(data.data(), len); if(l <= 0) return {}; data.resize(l); //decimate and add to buffer decimate(data, _buffer, _channels, _skip); if(_buffer.size() < MIN_BUF_SIZE) return {}; //once we have enough data, do noise reduction reduce_noise(_buffer, MIN_BUF_SIZE); //copy buffer to result u::bytes r(_buffer.begin(), _buffer.begin() + MIN_BUF_SIZE); //copy extra to front and resize. Probably a better idea to use a circular buf here. auto final_buf_size = _buffer.size() - MIN_BUF_SIZE; std::copy(_buffer.begin() + MIN_BUF_SIZE, _buffer.end(), _buffer.begin()); _buffer.resize(final_buf_size); return r; }