13
0

fix and optimize DummyBackend generators

* use Wavetable for sine
* lock generator (concurrency issue)
* always initialize variables
This commit is contained in:
Robin Gareus 2014-07-08 15:52:22 +02:00
parent b7f918bdb7
commit 941701574e
2 changed files with 55 additions and 27 deletions

View File

@ -1288,45 +1288,55 @@ DummyAudioPort::DummyAudioPort (DummyAudioBackend &b, const std::string& name, P
: DummyPort (b, name, flags)
, _gen_type (Silence)
, _gen_cycle (false)
, _b0 (0)
, _b1 (0)
, _b2 (0)
, _b3 (0)
, _b4 (0)
, _b5 (0)
, _b6 (0)
, _wavetable (0)
, _tbl_length (0)
, _tbl_offset (0)
, _pass (false)
, _rn1 (0)
{
memset (_buffer, 0, sizeof (_buffer));
}
DummyAudioPort::~DummyAudioPort () { }
DummyAudioPort::~DummyAudioPort () {
free(_wavetable);
_wavetable = 0;
}
void DummyAudioPort::setup_generator (GeneratorType const g, float const samplerate)
{
_gen_type = g;
_rseed = g_get_monotonic_time() % UINT_MAX;
_pass = false;
#ifdef COMPILER_MSVC
srand (_rseed);
#endif
switch (_gen_type) {
case PinkNoise:
case PonyNoise:
case WhiteNoise:
case Silence:
break;
case SineWave:
_b1 = 0;
{
#ifdef COMPILER_MSVC
srand (_rseed);
const unsigned int k = rand () % 128;
const unsigned int rnd = rand ();
#else
const unsigned int k = rand_r (&_rseed) % 128;
const unsigned int rnd = rand_r (&_rseed);
#endif
// midi note, chromatic scale
_b0 = (440.f / 32.f) * powf(2, (k - 9.0) / 12.0) / samplerate;
assert (_b0 < M_PI/2); // fine when samplerate >= 8K
_tbl_length = 5 + rnd % (int)(samplerate / 20.f);
_wavetable = (Sample*) malloc( _tbl_length * sizeof(Sample));
for (uint32_t i = 0 ; i < _tbl_length; ++i) {
_wavetable[i] = .12589f * sinf(2.0 * M_PI * (float)i / (float)_tbl_length);
}
}
break;
case PinkNoise:
case PonyNoise:
_b0 = _b1 = _b2 = _b3 = _b4 = _b5 = _b6 = 0.f;
// fall trhu, no break
case WhiteNoise:
#ifdef COMPILER_MSVC
srand (_rseed);
#endif
break;
}
}
@ -1364,17 +1374,30 @@ float DummyAudioPort::grandf ()
return r * x1;
}
void DummyAudioPort::generate (pframes_t n_samples)
void DummyAudioPort::generate (const pframes_t n_samples)
{
Glib::Threads::Mutex::Lock lm (generator_lock);
if (_gen_cycle) {
return;
}
switch (_gen_type) {
case Silence:
memset (_buffer, 0, n_samples * sizeof (Sample));
break;
case SineWave:
for (pframes_t i = 0 ; i < n_samples; ++i) {
_buffer[i] = .12589f * sinf(2.0 * M_PI * _b1);
_b1 += _b0;
if (_b1 > 1.0) _b1 -= 2.0;
assert(_wavetable && _tbl_length > 0);
{
pframes_t written = 0;
while (written < n_samples) {
const uint32_t remain = n_samples - written;
const uint32_t to_copy = std::min(remain, _tbl_length - _tbl_offset);
memcpy((void*)&_buffer[written],
(void*)&_wavetable[_tbl_offset],
to_copy * sizeof(Sample));
written += to_copy;
_tbl_offset = (_tbl_offset + to_copy) % _tbl_length;
}
}
break;
case WhiteNoise:
@ -1411,6 +1434,7 @@ void DummyAudioPort::generate (pframes_t n_samples)
}
break;
}
_gen_cycle = true;
}
void* DummyAudioPort::get_buffer (pframes_t n_samples)
@ -1441,7 +1465,6 @@ void* DummyAudioPort::get_buffer (pframes_t n_samples)
}
} else if (is_output () && is_physical () && is_terminal()) {
if (!_gen_cycle) {
_gen_cycle = true;
generate(n_samples);
}
}

View File

@ -139,13 +139,18 @@ class DummyAudioPort : public DummyPort {
Sample _buffer[8192];
// signal generator ('fake' physical inputs)
void generate (pframes_t n_samples);
void generate (const pframes_t n_samples);
GeneratorType _gen_type;
bool _gen_cycle;
Glib::Threads::Mutex generator_lock;
volatile bool _gen_cycle;
// generator buffers
// (used for pink-noise filters and sine-phase)
// pink-noise filters
float _b0, _b1, _b2, _b3, _b4, _b5, _b6;
// generated sinf() samples
Sample * _wavetable;
uint32_t _tbl_length;
uint32_t _tbl_offset;
// (per thread) random seed
unsigned int _rseed;