diff options
author | Bent Bisballe Nyeng <deva@aasimon.org> | 2018-08-03 20:02:04 +0200 |
---|---|---|
committer | Bent Bisballe Nyeng <deva@aasimon.org> | 2018-08-05 16:19:57 +0200 |
commit | a0e2b9398a06ca2ea164c2ffd6fd89f713b93598 (patch) | |
tree | f070de47673f32903eae30ddbc57232e2b13db4e /src/drumgizmo.cc | |
parent | ea743668192e0921ab46d5e863df5b754ce82656 (diff) |
Add support for partial buffers in cache and rendering engine - fixes dropouts on framesize changes for example when looping.
Diffstat (limited to 'src/drumgizmo.cc')
-rw-r--r-- | src/drumgizmo.cc | 155 |
1 files changed, 73 insertions, 82 deletions
diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index 2d3e410..81db5c5 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -93,12 +93,6 @@ void DrumGizmo::setFrameSize(size_t framesize) this->framesize = framesize; - // Remove all active events as they are cached using the old framesize. - for(std::size_t ch = 0; ch < MAX_NUM_CHANNELS; ++ch) - { - activeevents[ch].clear(); - } - // Update framesize in drumkitloader and cachemanager: loader.setFrameSize(framesize); audio_cache.setFrameSize(framesize); @@ -240,11 +234,69 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples) return true; } -#undef SSE // SSE broken for now ... so disable it. -#ifdef SSE -#define N 8 -typedef float vNsf __attribute__ ((vector_size(sizeof(sample_t)*N))); -#endif/*SSE*/ +void DrumGizmo::renderSampleEvent(EventSample& evt, int pos, sample_t *s, std::size_t sz) +{ + size_t n = 0; // default start point is 0. + + // If we are not at offset 0 in current buffer: + if(evt.offset > (size_t)pos) + { + n = evt.offset - pos; + } + + size_t end = sz; // default end point is the end of the buffer. + + // Find the end point intra-buffer + if((evt.t + end - n) > evt.sample_size) + { + end = evt.sample_size - evt.t + n; + } + + // This should not be necessary but make absolutely sure that we do + // not write over the end of the buffer. + if(end > sz) + { + end = sz; + } + + size_t t = 0; // Internal buffer counter + +repeat: + float scale = 1.0f; + for(; (n < end) && (t < (evt.buffer_size - evt.buffer_ptr)); ++n) + { + assert(n >= 0); + assert(n < sz); + + assert(t >= 0); + assert(t < evt.buffer_size - evt.buffer_ptr); + + if(evt.rampdownInProgress() && evt.rampdown_count > 0) + { + scale = std::min((float)evt.rampdown_count/evt.ramp_length, 1.f); + evt.rampdown_count--; + } + + s[n] += evt.buffer[evt.buffer_ptr + t] * evt.scale * scale; + ++t; + } + + // Add internal buffer counter to "global" event counter. + evt.t += t;//evt.buffer_size; + evt.buffer_ptr += t; + + if(n != sz && evt.t < evt.sample_size) + { + evt.buffer_size = sz - n;// Hint new size + + // More samples needed for current buffer + evt.buffer = audio_cache.next(evt.cache_id, evt.buffer_size); + + evt.buffer_ptr = 0; + t = 0; + goto repeat; + } +} void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz) { @@ -260,7 +312,8 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz) Event* event = *i; Event::type_t type = event->getType(); - switch(type) { + switch(type) + { case Event::sample: { EventSample& evt = *static_cast<EventSample*>(event); @@ -272,9 +325,9 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz) break; } - // Don't handle event now is is scheduled for a future iteration? if(evt.offset > (pos + sz)) { + // Don't handle event now. It is scheduled for a future iteration. continue; } @@ -290,86 +343,24 @@ void DrumGizmo::getSamples(int ch, int pos, sample_t* s, size_t sz) } evt.buffer_size = initial_chunksize; + evt.sample_size = af.size; } { std::lock_guard<std::mutex> guard(af.mutex); - size_t n = 0; // default start point is 0. - - // If we are not at offset 0 in current buffer: - if(evt.offset > (size_t)pos) - { - n = evt.offset - pos; - } - - size_t end = sz; // default end point is the end of the buffer. - - // Find the end point intra-buffer - if((evt.t + end - n) > af.size) - { - end = af.size - evt.t + n; - } + renderSampleEvent(evt, pos, s, sz); - // This should not be necessary but make absolutely sure that we do - // not write over the end of the buffer. - if(end > sz) + if((evt.t >= evt.sample_size) || (evt.rampdown_count == 0)) { - end = sz; - } - - size_t t = 0; // Internal buffer counter - if(!evt.rampdownInProgress()) - { -#ifdef SSE - size_t optend = ((end - n) / N) * N + n; - - // Force source addr to be 16 byte aligned... - // (might skip 1 or 2 samples) - while((size_t)&evt.buffer[t] % 16) - { - ++t; - } - - for(; (n < optend) && (t < evt.buffer_size); n += N) - { - *(vNsf*)&(s[n]) += *(vNsf*)&(evt.buffer[t]) * evt.scale; - t += N; - } -#endif - for(; (n < end) && (t < evt.buffer_size); ++n) - { - assert(n >= 0); - assert(n < sz); - - assert(t >= 0); - assert(t < evt.buffer_size); - - s[n] += evt.buffer[t] * evt.scale; - ++t; - } - } - else - { // Ramp down in progress. - for(; (n < end) && (t < evt.buffer_size) && evt.rampdown_count; ++n) - { - float scale = std::min((float)evt.rampdown_count/evt.ramp_length, 1.f); - s[n] += evt.buffer[t] * evt.scale * scale; - ++t; - evt.rampdown_count--; - } + removeevent = true; } - // Add internal buffer counter to "global" event counter. - evt.t += evt.buffer_size; - - if((evt.t < af.size) && (evt.rampdown_count != 0)) + if(evt.buffer_ptr >= evt.buffer_size && removeevent == false) { + evt.buffer_size = sz; evt.buffer = audio_cache.next(evt.cache_id, evt.buffer_size); - } - else - { - removeevent = true; + evt.buffer_ptr = 0; } if(removeevent) |