# Carvello

> Beat slicer: each bar is cut into equal slices, and Shuffle is the chance that a slice is replaced by an earlier slice of the same bar (Reverse the chance it plays backwards), so loops are broken up and rebuilt on the fly. Hold keeps one pattern for every bar (above half) instead of a new one each bar. Slices: 0 = 4, 1 = 8, 2 = 16, 3 = 32 per bar. Seed picks the pattern.

- Engine id: `org.sournd.performance.carvello`
- Category: Performance
- Licence: paid: £2.99 an effect or £4.99 a synth, once (owned for good, with updates), or included in the Everything plan (£14.99 a month)
- Version: 1.0.0
- Latency: 0 samples
- Tail: 6.5 s
- Sidechain input: no
- Channels: mono or stereo
- Audio demo: https://sournd.com/static/preview/demos/carvello.mp3 (a drum loop, default settings)

## Parameters

The id is the C ABI parameter id and the JUCE parameter id (as a decimal string).

| Id | Key | Name | Min | Max | Default | Unit | Taper |
|---|---|---|---|---|---|---|---|
| 0 | `slices` | Slices | 0 | 3 | 2 | - | linear |
| 1 | `shuffle` | Shuffle | 0 | 100 | 50 | % | linear |
| 2 | `reverse` | Reverse | 0 | 100 | 0 | % | linear |
| 3 | `hold` | Hold | 0 | 1 | 0 | - | linear |
| 4 | `seed` | Seed | 1 | 64 | 1 | - | linear |
| 5 | `tempo` | Tempo | 40 | 300 | 120 | bpm | linear |
| 6 | `mix` | Mix | 0 | 100 | 100 | % | linear |

## Use it in JUCE

CMake ([quick start](/docs/juce/index.md)):

```cmake
juce_add_module(path/to/sournd_engine)
target_include_directories(MyPlugin PRIVATE path/to/include)
target_link_libraries(MyPlugin PRIVATE sournd_engine path/to/libsournd_cabi.a)
```

C++:

```cpp
#include <sournd_engine/sournd_engine.h>

sournd::SourndEngine engine { "org.sournd.performance.carvello" };
juce::AudioProcessorValueTreeState parameters { *this, nullptr, "Parameters",
    sournd::SourndEngineParameters::createLayout (engine) };
sournd::SourndEngineParameters bridge { engine, parameters };

// prepareToPlay
engine.prepare ({ sampleRate, (juce::uint32) maximumBlock, 2 });
bridge.prepare (sampleRate);
setLatencySamples ((int) engine.latency());

// processBlock
bridge.apply ((uint32_t) buffer.getNumSamples());
juce::dsp::AudioBlock<float> block { buffer };
engine.process (juce::dsp::ProcessContextReplacing<float> { block });

// get/setStateInformation: hold getCallbackLock() around saveState / loadState,
// so state work never overlaps processBlock (full example: /docs/juce/)
```

Plain C:

```c
sournd_engine *e = NULL;
if (sournd_engine_create("org.sournd.performance.carvello", &e) == SOURND_OK) {
    sournd_engine_prepare(e, 48000.0, 512);
    sournd_engine_set_param(e, 0, 2); /* Slices */
    sournd_engine_process(e, in, out, 2, frames);
    sournd_engine_destroy(e);
}
```

## How it is made

Original sOURnd design: bar-locked recording into preallocated memory from the musical clock, per-slice decisions from a seeded hash of the slice and bar indices (source restricted to already-recorded slices, so no latency is needed), forward or reversed reads with raised-sine slice edges crossfaded against the live signal.

## Ask your AI

Paste this into your coding assistant:

```text
Add the sournd engine org.sournd.performance.carvello to my JUCE plugin. Follow https://sournd.com/docs/juce/index.md
and the engine reference at https://sournd.com/engines/carvello/index.md. Expose every parameter through APVTS.
```
