M banner.png => banner.png +0 -0
M libpippi/src/oscs.pulsar.c => libpippi/src/oscs.pulsar.c +28 -16
@@ 54,7 54,6 @@ lppulsarosc_t * create_pulsarosc(
}
lpfloat_t process_pulsarosc(lppulsarosc_t * p) {
- /*
lpfloat_t ipw, isr, sample, mod, burst, a, b,
wavetable_phase, window_phase,
wtmorphpos, wtmorphfrac,
@@ 79,58 78,71 @@ lpfloat_t process_pulsarosc(lppulsarosc_t * p) {
burst = 1.f;
isr = 1.f / p->samplerate;
+ /* Store the inverse pulsewidth if non-zero */
if(p->pulsewidth > 0) ipw = 1.0/p->pulsewidth;
+ /* Look up the burst value if there's a burst table */
+ if(p->burst != NULL) {
+
+ }
+
+ /*
if(p->burst != NULL && p->burst->data != NULL && p->burst->phase < p->burst->length) {
burst = p->burst->data[(int)p->burst->phase];
}
+ */
+ /* Override burst if desaturation is triggered */
if(p->saturation < 1.f && LPRand.rand(0.f, 1.f) > p->saturation) {
burst = 0;
}
+ /* If there's a non-zero pulsewidth, and the burst value is 1,
+ * then syntesize a pulse */
if(ipw > 0 && burst > 0) {
if(p->num_wavetables == 1) {
sample = interpolate_waveset(p->wavetables, wavetable_phase * ipw, p->wavetable_lengths[0]);
} else {
wavetable_length = p->wavetable_lengths[wavetable_index];
wtmorphmul = wavetable_length-1 > 1 ? wavetable_length-1 : 1;
-
- wtmorphpos = lpwv(p->wts->pos, 0, 1) * wtmorphmul;
+ wtmorphpos = lpwv(p->wavetable_positions[wavetable_index], 0, 1) * wtmorphmul;
wavetable_index = (int)wtmorphpos;
wtmorphfrac = wtmorphpos - wavetable_index;
- a = LPInterpolation.linear_pos(p->wavetables[wavetable_index], p->wts->phase * ipw);
- b = LPInterpolation.linear_pos(p->wavetables[wtmorphidx+1], p->wts->phase * ipw);
+
+ a = LPInterpolation.linear_pos2(&p->wavetables[wavetable_index], p->wavetable_lengths[wavetable_index], p->wavetable_phase * ipw);
+ b = LPInterpolation.linear_pos2(&p->wavetables[wtmorphidx+1], p->wavetable_lengths[wtmorphidx+1], p->wavetable_phase * ipw);
sample = (1.0 - wtmorphfrac) * a + (wtmorphfrac * b);
}
if(p->num_windows == 1) {
mod = interpolate_waveset(p->windows, window_phase * ipw, p->window_lengths[0]);
} else {
- winmorphmul = p->wins->length-1 > 1 ? p->wins->length-1 : 1;
- winmorphpos = p->wins->pos * winmorphmul;
- winmorphidx = (int)winmorphpos;
- winmorphfrac = winmorphpos - winmorphidx;
- a = LPInterpolation.linear_pos(p->wins->stack[winmorphidx], p->wins->phase * ipw);
- b = LPInterpolation.linear_pos(p->wins->stack[winmorphidx+1], p->wins->phase * ipw);
+ window_length = p->window_lengths[window_index];
+ winmorphmul = window_length-1 > 1 ? window_length-1 : 1;
+ winmorphpos = lpwv(p->window_positions[window_index], 0, 1) * winmorphmul;
+ window_index = (int)winmorphpos;
+ winmorphfrac = winmorphpos - window_index;
+
+ a = LPInterpolation.linear_pos2(&p->windows[window_index], p->window_lengths[window_index], p->window_phase * ipw);
+ b = LPInterpolation.linear_pos2(&p->windows[winmorphidx+1], p->window_lengths[winmorphidx+1], p->window_phase * ipw);
mod = (1.0 - winmorphfrac) * a + (winmorphfrac * b);
}
}
- p->wts->phase += isr * p->freq;
- p->wins->phase += isr * p->freq;
+ p->wavetable_phase += isr * p->freq;
+ p->window_phase += isr * p->freq;
+ /*
if(p->burst != NULL && window_phase >= p->window_lengths[window_index]) {
p->burst->phase += 1;
}
+ */
if(wavetable_phase >= 1.f) wavetable_phase -= 1.f;
if(window_phase >= 1.f) window_phase -= 1.f;
- if(p->burst != NULL && p->burst->phase >= p->burst->length) p->burst->phase -= p->burst->length;
+ //if(p->burst != NULL && p->burst->phase >= p->burst->length) p->burst->phase -= p->burst->length;
return sample * mod;
- */
- return 0.f * p->freq;
}
void destroy_pulsarosc(lppulsarosc_t* p) {
M libpippi/src/oscs.pulsar.h => libpippi/src/oscs.pulsar.h +7 -1
@@ 8,13 8,19 @@ typedef struct lppulsarosc_t {
int num_wavetables;
size_t * wavetable_onsets;
size_t * wavetable_lengths;
+ lpfloat_t * wavetable_positions;
+ lpfloat_t wavetable_phase;
lpfloat_t * windows; /* Window stack */
int num_windows;
size_t * window_onsets;
size_t * window_lengths;
+ lpfloat_t * window_positions;
+ lpfloat_t window_phase;
- lparray_t * burst; /* Burst table - null always on */
+ void * burst; /* Burst table - null table == pulses always on */
+ size_t burst_size;
+ lpfloat_t burst_pos;
lpfloat_t saturation; /* Probability of all pulses to no pulses */
lpfloat_t pulsewidth;
M libpippi/src/pippicore.c => libpippi/src/pippicore.c +23 -2
@@ 92,6 92,7 @@ lpfloat_t interpolate_hermite(lpbuffer_t * buf, lpfloat_t phase);
lpfloat_t interpolate_hermite_pos(lpbuffer_t * buf, lpfloat_t pos);
lpfloat_t interpolate_linear(lpbuffer_t * buf, lpfloat_t phase);
lpfloat_t interpolate_linear_pos(lpbuffer_t * buf, lpfloat_t pos);
+lpfloat_t interpolate_linear_pos2(lpfloat_t * buf, size_t length, lpfloat_t pos);
lpfloat_t interpolate_linear_channel(lpbuffer_t* buf, lpfloat_t phase, int channel);
lpbuffer_t * param_create_from_float(lpfloat_t value);
@@ 121,7 122,7 @@ lprand_t LPRand = { LOGISTIC_SEED_DEFAULT, LOGISTIC_X_DEFAULT, \
lpmemorypool_factory_t LPMemoryPool = { 0, 0, 0, memorypool_init, memorypool_custom_init, memorypool_alloc, memorypool_custom_alloc, memorypool_free };
const lparray_factory_t LPArray = { create_array, create_array_from, destroy_array };
const lpbuffer_factory_t LPBuffer = { create_buffer, create_buffer_from_float, create_buffer_from_bytes, create_uniform_stack, copy_buffer, clear_buffer, split2_buffer, scale_buffer, min_buffer, max_buffer, mag_buffer, play_buffer, pan_stereo_buffer, mix_buffers, remix_buffer, clip_buffer, cut_buffer, cut_into_buffer, varispeed_buffer, resample_buffer, multiply_buffer, scalar_multiply_buffer, add_buffers, scalar_add_buffer, subtract_buffers, scalar_subtract_buffer, divide_buffers, scalar_divide_buffer, concat_buffers, buffers_are_equal, buffers_are_close, dub_buffer, dub_scalar, env_buffer, pad_buffer, taper_buffer, trim_buffer, fill_buffer, repeat_buffer, reverse_buffer, resize_buffer, plot_buffer, destroy_buffer, destroy_stack };
-const lpinterpolation_factory_t LPInterpolation = { interpolate_linear_pos, interpolate_linear, interpolate_linear_channel, interpolate_hermite_pos, interpolate_hermite };
+const lpinterpolation_factory_t LPInterpolation = { interpolate_linear_pos, interpolate_linear_pos2, interpolate_linear, interpolate_linear_channel, interpolate_hermite_pos, interpolate_hermite };
const lpparam_factory_t LPParam = { param_create_from_float, param_create_from_int };
const lpwavetable_factory_t LPWavetable = { create_wavetable, create_wavetable_stack, destroy_wavetable };
const lpwindow_factory_t LPWindow = { create_window, create_window_stack, destroy_window };
@@ 253,7 254,7 @@ int rand_randbool(void) {
int rand_choice(int numchoices) {
assert(numchoices > 0);
if(numchoices == 1) return 0;
- return rand_randint(0, numchoices-1);
+ return rand_randint(0, numchoices);
}
lparray_t * create_array(size_t length) {
@@ 1586,6 1587,26 @@ lpfloat_t interpolate_linear_pos(lpbuffer_t* buf, lpfloat_t pos) {
return interpolate_linear(buf, pos * buf->length);
}
+lpfloat_t interpolate_linear_pos2(lpfloat_t * buf, size_t length, lpfloat_t pos) {
+ lpfloat_t frac, a, b, phase;
+ size_t i;
+
+ phase = pos * length;
+
+ if(length == 1) return buf[0];
+
+ frac = phase - (int)phase;
+ i = (int)phase;
+
+ if (i >= length-1) return 0;
+
+ a = buf[i];
+ b = buf[i+1];
+
+ return (1.0f - frac) * a + (frac * b);
+}
+
+
/* Wavetable generators
*
* All these functions return a table of values
M libpippi/src/pippicore.h => libpippi/src/pippicore.h +1 -0
@@ 282,6 282,7 @@ typedef struct lpmemorypool_factory_t {
typedef struct lpinterpolation_factory_t {
lpfloat_t (*linear_pos)(lpbuffer_t *, lpfloat_t);
+ lpfloat_t (*linear_pos2)(lpfloat_t *, size_t, lpfloat_t);
lpfloat_t (*linear)(lpbuffer_t *, lpfloat_t);
lpfloat_t (*linear_channel)(lpbuffer_t *, lpfloat_t, int);
lpfloat_t (*hermite_pos)(lpbuffer_t *, lpfloat_t);
M pippi/shapes.pxd => pippi/shapes.pxd +3 -3
@@ 5,7 5,7 @@ from pippi.soundbuffer cimport SoundBuffer
cpdef list onsets(double length, object density, object periodicity, object stability, double minfreq, double maxfreq)
cpdef SoundBuffer synth(object wt, double length=*, object density=*, object periodicity=*, object stability=*, double minfreq=*, double maxfreq=*, int samplerate=*, int channels=*)
-cdef double[:] _table(double[:] out, unsigned int length, double[:] wt, double[:] density, double[:] periodicity, double[:] stability, double maxfreq, double minfreq, int samplerate)
-cpdef Wavetable win(object waveform, double lowvalue=*, double highvalue=*, double length=*, object density=*, object periodicity=*, object stability=*, double minfreq=*, double maxfreq=*, int samplerate=*)
-cpdef Wavetable wt(object waveform, double lowvalue=*, double highvalue=*, double length=*, object density=*, object periodicity=*, object stability=*, double minfreq=*, double maxfreq=*, int samplerate=*)
+cdef double[:] _table(double[:] out, unsigned int length, double[:] wt, double[:] density, double[:] periodicity, double[:] stability, double[:] maxfreq, double[:] minfreq, int samplerate)
+cpdef Wavetable win(object waveform, double lowvalue=*, double highvalue=*, double length=*, object density=*, object periodicity=*, object stability=*, object minfreq=*, object maxfreq=*, int samplerate=*)
+cpdef Wavetable wt(object waveform, double lowvalue=*, double highvalue=*, double length=*, object density=*, object periodicity=*, object stability=*, object minfreq=*, object maxfreq=*, int samplerate=*)
M pippi/shapes.pyx => pippi/shapes.pyx +23 -12
@@ 102,18 102,21 @@ cpdef SoundBuffer synth(
return SoundBuffer(out, samplerate=samplerate, channels=channels)
-cdef double[:] _table(double[:] out, unsigned int length, double[:] wt, double[:] density, double[:] periodicity, double[:] stability, double maxfreq, double minfreq, int samplerate):
+cdef double[:] _table(double[:] out, unsigned int length, double[:] wt, double[:] density, double[:] periodicity, double[:] stability, double[:] maxfreq, double[:] minfreq, int samplerate):
cdef unsigned int wt_length = len(wt)
cdef unsigned int wt_boundry = max(wt_length-1, 1)
cdef int i=0
cdef double isamplerate = 1.0/samplerate
cdef double pos=0, d=0, p=0, s=0, freq=1, phase=0
- cdef double freqwidth = maxfreq - minfreq
+ cdef double freqwidth, _maxfreq, _minfreq
d = density[0]
p = 1 - periodicity[0]
- freq = max((d * freqwidth) + minfreq + rand(freqwidth * -p, freqwidth * p), minfreq)
+ _minfreq = minfreq[0]
+ _maxfreq = maxfreq[0]
+ freqwidth = _maxfreq - _minfreq
+ freq = max((d * freqwidth) + _minfreq + rand(freqwidth * -p, freqwidth * p), _minfreq)
for i in range(length):
pos = <double>i / <double>length
@@ 128,44 131,52 @@ cdef double[:] _table(double[:] out, unsigned int length, double[:] wt, double[:
d = math.log(d * (math.e-1) + 1)
p = 1 - _linear_pos(periodicity, pos)
#p = math.log(p * (math.e-1) + 1)
- freq = max((d * freqwidth) + minfreq + rand(freqwidth * -p, freqwidth * p), minfreq)
+ _minfreq = _linear_pos(minfreq, pos)
+ _maxfreq = _linear_pos(maxfreq, pos)
+ freqwidth = _maxfreq - _minfreq
+ freq = max((d * freqwidth) + _minfreq + rand(freqwidth * -p, freqwidth * p), _minfreq)
while phase >= wt_boundry:
phase -= wt_boundry
return out
-cpdef Wavetable win(object waveform, double lowvalue=0, double highvalue=1, double length=1, object density=0.5, object periodicity=0.5, object stability=0.5, double minfreq=0, double maxfreq=0, int samplerate=DEFAULT_SAMPLERATE):
- if minfreq <= 0:
+cpdef Wavetable win(object waveform, double lowvalue=0, double highvalue=1, double length=1, object density=0.5, object periodicity=0.5, object stability=0.5, object minfreq=None, object maxfreq=None, int samplerate=DEFAULT_SAMPLERATE):
+ if minfreq is None:
minfreq = MIN_WT_FREQ
- if maxfreq <= 0:
+ if maxfreq is None:
maxfreq = MAX_WT_FREQ
cdef double[:] _wt = to_window(waveform)
cdef double[:] _density = to_window(density)
cdef double[:] _periodicity = to_window(periodicity)
cdef double[:] _stability = to_window(stability)
+ cdef double[:] _minfreq = to_window(minfreq)
+ cdef double[:] _maxfreq = to_window(maxfreq)
cdef unsigned int framelength = <unsigned int>(length * samplerate)
cdef double[:] out = np.zeros(framelength, dtype='d')
- return Wavetable(_table(out, framelength, _wt, _density, _periodicity, _stability, maxfreq, minfreq, samplerate), lowvalue, highvalue)
+ return Wavetable(_table(out, framelength, _wt, _density, _periodicity, _stability, _maxfreq, _minfreq, samplerate), lowvalue, highvalue)
-cpdef Wavetable wt(object waveform, double lowvalue=-1, double highvalue=1, double length=1, object density=0.5, object periodicity=0.5, object stability=0.5, double minfreq=0, double maxfreq=0, int samplerate=DEFAULT_SAMPLERATE):
- if minfreq <= 0:
+cpdef Wavetable wt(object waveform, double lowvalue=-1, double highvalue=1, double length=1, object density=0.5, object periodicity=0.5, object stability=0.5, object minfreq=None, object maxfreq=None, int samplerate=DEFAULT_SAMPLERATE):
+ if minfreq is None:
minfreq = MIN_WT_FREQ
- if maxfreq <= 0:
+ if maxfreq is None:
maxfreq = MAX_WT_FREQ
cdef double[:] _wt = to_wavetable(waveform)
cdef double[:] _density = to_window(density)
cdef double[:] _periodicity = to_window(periodicity)
cdef double[:] _stability = to_window(stability)
+ cdef double[:] _minfreq = to_window(minfreq)
+ cdef double[:] _maxfreq = to_window(maxfreq)
+
cdef unsigned int framelength = <unsigned int>(length * samplerate)
cdef double[:] out = np.zeros(framelength, dtype='d')
- return Wavetable(_table(out, framelength, _wt, _density, _periodicity, _stability, maxfreq, minfreq, samplerate), lowvalue, highvalue)
+ return Wavetable(_table(out, framelength, _wt, _density, _periodicity, _stability, _maxfreq, _minfreq, samplerate), lowvalue, highvalue)
M requirements.txt => requirements.txt +1 -1
@@ 1,4 1,4 @@
-Cython==3.0.0a11
+Cython==3.0.5
importlib-resources==5.12.0
mido==1.2.10
numpy==1.24.2
M rpi-requirements.txt => rpi-requirements.txt +4 -4
@@ 1,5 1,5 @@
-Cython==3.0.0a11
-importlib-resources==5.4.0
-soundfile==0.11.0
+Cython==3.0.5
+importlib-resources==5.12.0
+soundfile==0.12.1
python-rtmidi==1.5.4
-wheel==0.37.1
+wheel==0.41.3