Discussion:
[Linuxsampler-devel] Experimenting with sinc-based resampling
JP Cimalando
2016-04-18 20:51:37 UTC
Permalink
Hi, lately I've stumbled upon an old article that sings praise of
Akai S1000 samplers and the resampling algorithm it used.
This piqued my curiosity and inspired me to try implementing a sinc
resampler into LS for comparison.

I attach my code to the message, as patch against svn trunk.
Link to the article: http://martin78.com/samplers/akai-s1000-s1100/

-- some implementation notes:
* this is a N-point sinc resampler, where N is defined in code by
parameter SINC_NPTOTAL=SINC_NPBEFORE+SINC_NPAFTER
* code uses optimization to reduce the number of trig operations/sample
from N sin() to 1 sin() + 1 cos()

As default I have used parameters NPBEFORE=1 NPAFTER=7, the number of
past and future samples used respectively.
This happens in some situations, with some samples of my set, to crash
LS with segfault, presumably because of out-of-bounds access by
getSample().

The question is: where in LS is defined how many past/future samples are
available to the resampling?
I note LS already has linear and cubic which require 2 and 4. How
to control this number? Akai S1000 supposedly has N=8, but I'd like to
also to try larger lengths.
Christian Schoenebeck
2016-04-19 17:51:27 UTC
Permalink
Post by JP Cimalando
Hi, lately I've stumbled upon an old article that sings praise of
Akai S1000 samplers and the resampling algorithm it used.
This piqued my curiosity and inspired me to try implementing a sinc
resampler into LS for comparison.
Hi JP,

interesting stuff!
Post by JP Cimalando
I attach my code to the message, as patch against svn trunk.
Link to the article: http://martin78.com/samplers/akai-s1000-s1100/
* this is a N-point sinc resampler, where N is defined in code by
parameter SINC_NPTOTAL=SINC_NPBEFORE+SINC_NPAFTER
* code uses optimization to reduce the number of trig operations/sample
from N sin() to 1 sin() + 1 cos()
As default I have used parameters NPBEFORE=1 NPAFTER=7, the number of
past and future samples used respectively.
This happens in some situations, with some samples of my set, to crash
LS with segfault, presumably because of out-of-bounds access by
getSample().
That suspicion is correct.
Post by JP Cimalando
The question is: where in LS is defined how many past/future samples are
available to the resampling?
I note LS already has linear and cubic which require 2 and 4. How
to control this number? Akai S1000 supposedly has N=8, but I'd like to
also to try larger lengths.
There is no such check. Branches in the synthesis core are always a bad thing,
because they reduce runtime efficiency i.e. due to instruction pipelining
issues, so we try to avoid branches there whenever possible.

The trick is: all samples are loaded with a certain amount of additional NULL
samples at their end (that is additional silence). That way the resampler will
never bite beyond the scope of the allocated sample data.

So you need to adjust some few files. grep for
"LoadSampleDataWithNullSamplesExtension" and you will find the relevant
locations. For example in file src/engines/gig/InstrumentResourceManager.cpp
you find in line 676:

const uint neededSilenceSamples =
(maxSamplesPerCycle << CONFIG_MAX_PITCH) + 3;

So the 3 here is too small for your patch. I guess you get the rest of it.

Any plans to post some comparison audio files?

CU
Christian

Loading...