Skip to content

Commit

Permalink
Implemented caching signals to prevent not generated sound in case of…
Browse files Browse the repository at this point in the history
… framesBuff from PortAudio is too small

If we don't specify framesPerBuffer parameter in Pa_OpenStream, PortAudio will choose optimal value for particular callback call. It can vary from run to run even on the same hardware depending on available system resources.

While generating signal, interpolating and applying effects, we assume that framesBuffer contains more than minimal number of frames to generate envelope. BTW, it is not true. If framesBuffer is smaller, algos cannot generate correct sound and just keep silence.

I've implemented cache which keeps generated values from dsp algorithms and applies it step-by-step to buffer values from pa_callback. Cache is filled each time algos generate dsp values. If buffer frames are not enough to generate envelope, algos generate values for further calls and keep it in cache.

Required number of frames has been selected as a number of frames for one phase multiplying by number of phases. Actually, smaller numbers of this value generates good results, but it is better to keep it as max as possible to provide perfect sound.

Code changes:
 - Replaced C-like variables with std containers for comfortable debugging and better usage
 - Extracted similar code calls to separate methods
 - Implemented cache as std constainers, so also implemented convertion from std::vector to C-like float* to fill the pa buffer
 - Changed the logic of applying effects and interpolation, it is now possible to use them separately. This is required to fill effects several times after calculating the interpolation is finished.

Removed std::vector<float> to keep cache - process buff values on the fly. Performance is better, but still glitches on https://musescore.com/user/166080/scores/175421. BuffSize = 64 with my wired headphones.
  • Loading branch information
anatoly-os committed Mar 7, 2018
1 parent e37f251 commit 596f6c2
Show file tree
Hide file tree
Showing 4 changed files with 494 additions and 423 deletions.
39 changes: 20 additions & 19 deletions fluid/dsp.cpp
Expand Up @@ -146,7 +146,6 @@ int Voice::dsp_float_interpolate_none(unsigned n)
Phase dsp_phase = voice->phase;
Phase dsp_phase_incr; // end_phase;
short int *dsp_data = voice->sample->data;
float *dsp_buf = voice->dsp_buf;
auto curSample2AmpInc = Sample2AmpInc.begin();
qreal dsp_amp_incr = curSample2AmpInc->second;
unsigned int nextNewAmpInc = curSample2AmpInc->first;
Expand Down Expand Up @@ -212,7 +211,6 @@ int Voice::dsp_float_interpolate_linear(unsigned n)
Phase dsp_phase = voice->phase;
Phase dsp_phase_incr; // end_phase;
short int *dsp_data = voice->sample->data;
float *dsp_buf = voice->dsp_buf;
auto curSample2AmpInc = Sample2AmpInc.begin();
qreal dsp_amp_incr = curSample2AmpInc->second;
unsigned int nextNewAmpInc = curSample2AmpInc->first;
Expand Down Expand Up @@ -352,10 +350,11 @@ int Voice::dsp_float_interpolate_4th_order(unsigned n)
/* interpolate first sample point (start or loop start) if needed */
for ( ; dsp_phase_index == start_index && dsp_i < n; dsp_i++) {
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (phase)];
dsp_buf[dsp_i] = amp * (coeffs[0] * start_point
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * dsp_data[dsp_phase_index+2]);
auto val = amp * (coeffs[0] * start_point
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * dsp_data[dsp_phase_index+2]);
dsp_buf[dsp_i] = val;

/* increment phase and amplitude */
phase += dsp_phase_incr;
Expand All @@ -368,10 +367,11 @@ int Voice::dsp_float_interpolate_4th_order(unsigned n)
/* interpolate the sequence of sample points */
for ( ; dsp_i < n && dsp_phase_index <= end_index; dsp_i++) {
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (phase)];
dsp_buf[dsp_i] = amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * dsp_data[dsp_phase_index+2]);
auto val = amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * dsp_data[dsp_phase_index+2]);
dsp_buf[dsp_i] = val;

/* increment phase and amplitude */
phase += dsp_phase_incr;
Expand All @@ -390,10 +390,11 @@ int Voice::dsp_float_interpolate_4th_order(unsigned n)
/* interpolate within 2nd to last point */
for (; dsp_phase_index <= end_index && dsp_i < n; dsp_i++) {
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (phase)];
dsp_buf[dsp_i] = amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * end_point1);
auto val = amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * dsp_data[dsp_phase_index+1]
+ coeffs[3] * end_point1);
dsp_buf[dsp_i] = val;

/* increment phase and amplitude */
phase += dsp_phase_incr;
Expand All @@ -408,10 +409,11 @@ int Voice::dsp_float_interpolate_4th_order(unsigned n)
/* interpolate within the last point */
for (; dsp_phase_index <= end_index && dsp_i < n; dsp_i++) {
coeffs = interp_coeff[fluid_phase_fract_to_tablerow (phase)];
dsp_buf[dsp_i] = amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * end_point1
+ coeffs[3] * end_point2);
auto val = amp * (coeffs[0] * dsp_data[dsp_phase_index-1]
+ coeffs[1] * dsp_data[dsp_phase_index]
+ coeffs[2] * end_point1
+ coeffs[3] * end_point2);
dsp_buf[dsp_i] = val;

/* increment phase and amplitude */
phase += dsp_phase_incr;
Expand Down Expand Up @@ -455,7 +457,6 @@ int Voice::dsp_float_interpolate_7th_order(unsigned n)
Phase dsp_phase = voice->phase;
Phase dsp_phase_incr; // end_phase;
short int *dsp_data = voice->sample->data;
float *dsp_buf = voice->dsp_buf;
auto curSample2AmpInc = Sample2AmpInc.begin();
qreal dsp_amp_incr = curSample2AmpInc->second;
unsigned int nextNewAmpInc = curSample2AmpInc->first;
Expand Down

0 comments on commit 596f6c2

Please sign in to comment.