Module requests


#145

and got it working again.
Was searching for the mistake in the wrong place...accidentilly tried to write to position 64 of the 64-tablesize.. (as it starts at 0, max entry would be 63..)

*update
yes yes yes, thiz iz nize :stuck_out_tongue:

I saved a bunch of wav files as BD000.wave, BD001.wav etc etc and the module is able to automatically load a set of samples one after another to the same array. I'm gonna add some more goodies now, like a text attribute to pre-set a set of samples to be loaded, start/end positions, reverse, pitch, normalising, sample-morphing/mixing/layering...
more ideas are welcome (also about how we would like to control them!)! Let's enable the axoloti to be the sample-master!


#146

That will be totally wonderfull!!!


#147

hi @SirSickSik sounds great!
I'm currently working on a 'sample-bank-recorder' , which is the same direction..
..got some ideas/wishes/proposals

-how about keeping this as modular as possible?
(one object to load the samples to an array,and fill another array with the start / end info,
other objects to normalize/porcess the samples and handle the actual playback)

-how about using the same 'format' for the array that stores the sample info ?
for these looper/player objects I'm doing,I decided for this approach::

-first of all,it's all expressed as 'blue float -64 ... 64 '

then,for each sample, I use blocks of data in this format :

0. offset 0 - 64 -->sample start relative to table length
1. range 0 - 64 -->sample length relative to table length
2. startpoint 0 - 64 -->when recording in sync with a clock,at what clock position did recording start?
..useful for syncing loops.
4. speed -64 64 -->playback speed (-64 = full speed reverse, +64 = full speed ahead)

maybe you feel like adding,here ?


#148

hi rbrt,
most of the things I already do, like the 0-64 controls, as this is widely used within the axo environment.

At the moment the sample-data and sample length info are saved in the same module, but I'll change this to 2 array's. Also because at the moment I'm saving to an array that's not called array, so saving/loading the table ain't possible yet without a dedicated table-save/load code.. I first wanted to get the code working nicely.
So in the end I'll just use the factory table modules to save the info into, so different modules can read/write to it.

Also, all the controls on the module are inputs, not knobs/buttons, most are floats (-64 to 64) and some are integer (eg. sample number), so these could also be controlled by universal table-preset-modules/pattern generators.

About the "float-values".. I think you mean the blue fractional outputs? As these are just integer values that are shown as decimal values on the knobs and displays. An actual float-value costs more cpu to calculate, so I mostly try to not use them if possible (or only as k-rate or updated at input-trigger/gate/change).

The start, end, loop-start and loop-end of the sample is already done in 0-64 values, but the offset is saved as the integer offset in the table to prevent mis-calculations. If you'ld use 0-64 values(of course with the <<21 behind it) with scaling, you'll probably have some mistakes at some points about where to start/end the sample, possibly adding unwanted clicks (-1/+1 sample and perhaps even more if more bits are lost in the calculation process) .
This sample-start-position info should be enough information to calculate the 0-64 offset and range in the module that's reading the array (that's what I'm also doing now).
As the recording rate is always the same (48000hz), all the needed read-out values should able to be calculated using known scalings.
Next to this, if somebody would use a smaller/larger array then the table is saved as, all these offset and range positions would be off. By saving the actual positions, you can just make your table smaller with a loss of some samples if you need the sdram space for something else.

About the playback speed, I'm using a phazor that is rescaled back to the right size using the start-position of the sample and starting position of the next sample ("next sample start"-"current sample start"-1=width) and use the width to rescale the frequency of the phazor, so a 0 for pitch is the normal play rate. The ratio-play-rate can easily be done by just multiplying the frequency. So the playspeed can be adjusted in ratio, integer multiplications and in semitones.


#149

hi @SirSickSik

makes sense!

ah..true!

..sounds interesting.could you post a 'prototype' ?


#150

it's actually quite simple..
if you have a sample-size of 795 samples, you just multiply this value with the phase and add the sample-offset (start position)..
position=___SMMUL(samplesize,phase)+sampleoffset;

so I've put all the start-positions of the soundsamples into an array. And as every sound-sample ends at one sample before the next one, you can always get the width of each sample by subtracting the starting positions minus one.


#151

current setup for the sample loading train
ps. nice thing about the BPM-control, it automatically in/de-creases pitch when changing the control-BPM while linked.
When unlinking, it matches up the base-BPM with the control-BPM, so pitch goes back to normal. So you can kind of fake slowing down or speeding up a complete track, but actually all individually with samples and synths :stuck_out_tongue:


#152

Looks great!!!
Could be posible to save the wavetable? So I could use a patch to load the samples into the array and save the table, then I could use the table in other patches (saving a bit of recourses).


#153

yes, it's just two normal array files. One small one of 32bit for the start-positions and one big one of 16bit for the samples.
So you can use the normal table save/load modules to load them.


#154

That's great!!!
I cant't wait to try it :slight_smile:


#155

hmm, just found out the start-positions are still not saved right... :frowning:
still trying to figure out how to get the last loaded array-position..


#156

kind of fixed it with a work around, though it takes quite a while longer.. though then again, every last part of a sample that is just silence, will be automatically cut off by overwriting with the next sample :slight_smile:
So if used to make sample-tables that can be loaded with the factory load/save modules, it's still pretty useful.
Though, be warned.. loading 2.000.000 16 bit values of sample-table will always take a quite a while.


#157

Got a new request, Remco, if you're up for it!

Would it be possible to first create an oscillator where you dial-in functions to shape a single cycle of a custom waveform, then create an object that can take numerous blocks of these oscillators, say in configurations of 2,4,8, and allow morphing between them by attaching a dial to it?

The order of the morph sequence is determined by the order of the oscillators connected to the morph dial object, so I suppose something like this would consist of a morphing control that you attach the morphable oscillators to, and the morphable oscillator itself, that can be attached to that object.

It would be something like that dial they have on the Streichfett, cause I believe it morphs between the waveforms rather than blends between them. The difference with what I'm requesting is that you also have the ability to dial-in various functions to shape the waveforms you're blending between.


#158

I'm not entirely sure I understand what you ask for.

I've made a couple of modules that are able to create waveforms and wavetables, which can then be loaded in the wavetable oscillators and mix from any waveform to any other waveform. But I get the feeling that you want maths functions to transform waveforms and to be able to somehow morph between these math functions?
Also, what do you understand as the difference between morphing and blending, as these names are often used for the same thing?


#159

It sounds like you have the right basic idea, but I'll split it up and be very precise.

What I'm requesting is really a set of objects that comprises of a Morphing Mixer that has at least two inputs that is specifically designed to take a Morphable Oscillator.

  • Morphable Oscillator object only needs to come in one variant.
  • Morphing Mixer object could come in 2,3,4,5,6 or more input variants to take Morphable Oscillators.

The Morphable Oscillator:

The Morphable Oscillator is basically a single oscillator object with dials on it that allow you to dial-in a custom procedurally produced waveform by dialing-in any mixture of Sine, Square, Triangle, Ramp Up, Ramp Down, Noise, S&H etc, in varying amounts to create the oscillator waveform. The waveform it creates is just a single cycle and is looped to create the oscillation just like regular oscillators do. The important thing about it is that the waveform is generated procedurally so that it's parameters can be morphed from one custom waveform to another. However, the actual morphing is not handled by the oscillator object, it is handled by a Morphing Mixer object designed to drive it.

The Morphing Mixer Object:

The role of the Morphing Mixer is to take multiple Morphable Oscillators and morph between them using just a single dial. The amount of Morphing Oscillators it has to morph between, is determined by the variant of the object itself. For example, a 2-Input Morphing Mixer would accept just two Morphable Oscillators. Having the dial set to minimum would output the waveform of the first Morphable Oscillator, and set to maximum you would hear only the second. Twelve o'clock position would output a 50/50 morph of the two Morphable Oscillators.

It gets even better the more inputs a Morphing Mixer object has. So a 3-Input Morphing Mixer for example, would output only oscillator 1 at minimum value, only oscillator 3 at maximum value, and only oscillator two at twelve o'clock. Moving between minimum and twelve o'clock would give you a morph between oscillator 1 and 2, and moving between twelve o'clock and maximum would give you a morph between oscillator 2 and 3.

It basically works the same no matter how many inputs the Morphing Mixer has, cause all it does is divide the knob travel by how many inputs it has. So basically, this mixer is driving the oscillators attached to it, because turning the dial basically sends the signals to the attached Morphable Oscillators, telling them how they need to adjust their parameters in order to morph from one waveform to another.

Quite a task I suppose, but remember there are really only two main object designs. The Morphing Mixer objects are all basically the same, they only differ in how many inputs they have. And the Morphable Object is just one object that the user adds to the patch how many they need. The oscillators differ because the oscillators themselves are customisable by the user adjusting the oscillators dials.

I suppose you could even skip the Morphing Mixer objects altogether and it would still work, cause basically, all the user would have to do is attach their own form of modulation to the Morphable Oscillators. It would be nice to have those purpose-built Morphing Mixers for them though, that would be much more elegant and feel like a full-on complete 'system' in its own right.

Crazy or what? :stuck_out_tongue_winking_eye:


#160

Ah ok, I think I understand.
There are just a couple of things I'm a bit skeptical about whether it is usable in the axoloti because of the limited cpu/memory.
If you want to use anti-alliased waveform generators, this will take an individual generator for each waveform. As the blepped-oscillators take around 3-5%, a single "morphable oscillator" with sine, tri, saw, ramp and square will already use roughly 18%, so this will already limit the amount of oscillators you could use quite a bit as you'll also still need filters, gain, morphing, etc.

For what you want to do, I think I've already made a couple of modules.
So for this I think the best way to go would be to use 4 bleppedCore&slave modules, so you could combine any of the waveforms. After this a simple allpass filter after each waveform to offset the various phases of the frequencies so you can set which of the frequencies will neutralise or strengthen each other.
To blend the waveforms, you could use the "mux/smoothRotator4A". This module is basically your morphing mixer that allows different ways to morph through the input waveforms:
1->2->3->4
1->3->2->4
1->4->3->2
(though not sure about the second, I can update this module so you could select between different orders from an internal table. As it's just 4 inputs, the amount of combinations isn't that big, so wouldn't need too much memory)

As for the morphing control, I've been working on a couple of modules to save presets and morph between them, but it's a bit hard to really make a universal control for this that is easily customisable to the amount of controls that people need.

Btw, if you need oscillators for a bass, you don't necessarily need anti-alliased oscillators. I've made several oscillators that are able to morph between sine,tri,saw and pulse and anything in between as it's either based on mathematical shaping or different ways of self-modulation (last one can go into a bit higher pitches without alliasing)
some morphable oscillators:
STO
SiTriSaPu_OSC
bassOsc
classic (this one is self-modulating through phase and FM and is personally one of my own favorites)
rubisik (two source waveforms and self-modulation&mixing with their own selectable waveforms, though by far not anti-alliased)
sawtrimod (saw/triangle/ramp)
sintri (sine/triangle)
trisaw (another saw/triangle/ramp)


#161

Cheers Remco, and nah, was nothing to do with anti-aliasing, it was just the desire to morph between two waveforms rather than blend between their levels (although I do like blending between levels too, it's just a different effect). It's really that knob on the Streichfett that got me curious, cause it sounds as if its actually morphing between waveforms rather than blending between them (I could be wrong though).

Sounds as if you might have something what I was after already though, so thanks for the heads-up about them. Form what you've told me about them, it looks like only square with PWM and S&H is missing, so it would be cool to have those versions as well, but either way it does sound as if the ones you've created are the sort of thing I'm after.

Will be having a play with those!


#162

if I were you, I'ld just use the factory sample&hold module... then you can just use this together with any oscillator you want.
I added the functionality to an oscillator a couple of times, but in the end I always removed it and made the S&H external..
Also an anti-alliased PWM-pulse can be made using the S&H (oscillator&slider into comparator at audio rate, whenever it changes value->hold)


#163

well, finally starting to get a more or less complete loading system:
At the moment I've got 3 sample-loading systems/modules which can be used together.
They can be put one after another and load their samples to a single table or each to their own table (eg. basskicks,snares, hihats each get their own tables), so it's up to you to decide how you handle your samples.

-select by name:
use directories&names to load 8 samples in a row. Useful in case you want to load a specific set of samples from different folders and/or different names.

-select by ordered indexnumber:
using the same prefix, this loads a set of samples in consecutive indexnumbers, eg.
drum001 up to drum008, useful to load preset drumskits where you've made sure that the index numbers relate to drum-types, eg. basskick is dr001,dr009,dr017. snare is dr002,dr010,dr018, etc.

-random selection of samples within a range of indexnumbers:
using the same prefix, but random indexnumbers, you set the lowest index number and range for the index that could be randomly selected. Currently this index goes from 000 up to 999, so you could randomly combine samples from a set of 1000 samples.

As for the sample playing, I've made 3 different modules:
-a complex sampler with start, loopstart,loopend and end positions, reverse, repeat on/off (using loop positions and only for sample 2, but sample selection for 1 and 2 can be swapped with a gate-input), 2 samples with an tiltable envelope to mix between them and of course individual pitch control for both samples.
-a simple multi sampler to trigger 4 different samples, each with their own pitch-control, sample-select and gate inputs.
-wavetable-oscillator with zero-crossing detection that can use the sounds to create weird bass/glitch sounds. Sounds are created by setting sample-index, start-position within sample and amount of zero-crossings in the loop.


#164

Cool! I just wonder if there shouldnt be a volume control per sample to?