1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
|
/*
* Copyright (C) 2021 Linux Studio Plugins Project <https://lsp-plug.in/>
* (C) 2021 Vladimir Sadovnikov <sadko4u@gmail.com>
*
* This file is part of lsp-plugins-sampler
* Created on: 12 июл. 2021 г.
*
* lsp-plugins-sampler is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* lsp-plugins-sampler is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with lsp-plugins-sampler. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef PRIVATE_PLUGINS_SAMPLER_KERNEL_H_
#define PRIVATE_PLUGINS_SAMPLER_KERNEL_H_
#include <lsp-plug.in/plug-fw/plug.h>
#include <lsp-plug.in/dsp-units/ctl/Toggle.h>
#include <lsp-plug.in/dsp-units/ctl/Bypass.h>
#include <lsp-plug.in/dsp-units/ctl/Blink.h>
#include <lsp-plug.in/dsp-units/sampling/Sample.h>
#include <lsp-plug.in/dsp-units/sampling/SamplePlayer.h>
#include <lsp-plug.in/dsp-units/util/Randomizer.h>
#include <lsp-plug.in/lltl/parray.h>
#include <lsp-plug.in/ipc/ITask.h>
#include <private/meta/sampler.h>
namespace lsp
{
namespace plugins
{
/**
* Sampler implementation for single-channel audio sampler
*/
class sampler_kernel
{
protected:
struct afile_t;
class AFLoader: public ipc::ITask
{
private:
sampler_kernel *pCore;
afile_t *pFile;
public:
explicit AFLoader(sampler_kernel *base, afile_t *descr);
virtual ~AFLoader();
public:
virtual status_t run();
void dump(dspu::IStateDumper *v) const;
};
class AFRenderer: public ipc::ITask
{
private:
sampler_kernel *pCore;
afile_t *pFile;
public:
explicit AFRenderer(sampler_kernel *base, afile_t *descr);
virtual ~AFRenderer();
public:
virtual status_t run();
void dump(dspu::IStateDumper *v) const;
};
class GCTask: public ipc::ITask
{
private:
sampler_kernel *pCore;
public:
explicit GCTask(sampler_kernel *base);
virtual ~GCTask();
public:
virtual status_t run();
void dump(dspu::IStateDumper *v) const;
};
protected:
enum crossfade_t
{
XFADE_LINEAR,
XFADE_CONST_POWER,
XFADE_DFL = XFADE_CONST_POWER
};
enum play_mode_t
{
PLAY_NOTE,
PLAY_INSTRUMENT,
PLAY_FILE
};
enum loop_mode_t
{
LOOP_DIRECT,
LOOP_REVERSE,
LOOP_DIRECT_HALF_PP,
LOOP_REVERSE_HALF_PP,
LOOP_DIRECT_FULL_PP,
LOOP_REVERSE_FULL_PP,
LOOP_DIRECT_SMART_PP,
LOOP_REVERSE_SMART_PP
};
struct render_params_t
{
ssize_t nLength; // Length before head & tail cut
ssize_t nHeadCut; // The amount of head cut
ssize_t nTailCut; // The amount of tail cut
ssize_t nCutLength; // Length after head & tail cut
ssize_t nStretchDelta; // Stretch delta
ssize_t nStretchStart; // Stretch start position
ssize_t nStretchEnd; // Stretch end position
};
struct afile_t
{
size_t nID; // ID of sample
AFLoader *pLoader; // Audio file loader task
AFRenderer *pRenderer; // Audio file renderer task
dspu::Toggle sListen; // Listen toggle
dspu::Blink sNoteOn; // Note on led
dspu::Playback vPlayback[4]; // Active playback handle
dspu::Playback vListen[4]; // Listen playback handle
dspu::Sample *pOriginal; // Source sample (original, as from source file)
dspu::Sample *pProcessed; // Processed sample
float *vThumbs[meta::sampler_metadata::TRACKS_MAX]; // List of thumbnails
size_t nUpdateReq; // Update request
size_t nUpdateResp; // Update response
bool bSync; // Sync flag
float fVelocity; // Velocity
float fPitch; // Pitch (st)
bool bStretchOn; // Stretch enabled
float fStretch; // Stretch (sec)
float fStretchStart; // Stretch start (ms)
float fStretchEnd; // Stretch end (ms)
float fStretchChunk; // Stretch chunk (bar)
float fStretchFade; // Stretch cross-fade length
size_t nStretchFadeType; // Stretch cross-fade type
dspu::sample_loop_t enLoopMode; // Loop mode
float fLoopStart; // Stretch start (ms)
float fLoopEnd; // Stretch end (ms)
float fLoopFade; // Loop cross-fade length
size_t nLoopFadeType; // Loop cross-fade type
float fHeadCut; // Head cut (ms)
float fTailCut; // Tail cut (ms)
float fFadeIn; // Fade In (ms)
float fFadeOut; // Fade Out (ms)
bool bReverse; // Reverse sample
bool bCompensate; // Compensate time
float fCompensateFade; // Compensate fade
float fCompensateChunk; // Compensate chunk
size_t nCompensateFadeType; // Compensate fade type
float fPreDelay; // Pre-delay
float fMakeup; // Makeup gain
float fGains[meta::sampler_metadata::TRACKS_MAX]; // List of gain values
float fLength; // Length of source sample in milliseconds
float fActualLength; // Length of processed sample in milliseconds
status_t nStatus; // Loading status
bool bOn; // On flag
plug::IPort *pFile; // Audio file port
plug::IPort *pPitch; // Pitch
plug::IPort *pStretchOn; // Stretch enabled
plug::IPort *pStretch; // Stretch amount
plug::IPort *pStretchStart; // Start of the stretch region
plug::IPort *pStretchEnd; // End of the stretch region
plug::IPort *pStretchChunk; // Stretch chunk
plug::IPort *pStretchFade; // Stretch cross-fade length
plug::IPort *pStretchFadeType; // Stretch cross-fade type
plug::IPort *pLoopOn; // Loop enabled
plug::IPort *pLoopMode; // Loop mode
plug::IPort *pLoopStart; // Start of the loop region
plug::IPort *pLoopEnd; // End of the loop region
plug::IPort *pLoopFadeType; // Loop cross-fade type
plug::IPort *pLoopFade; // Loop cross-fade length
plug::IPort *pHeadCut; // Head cut
plug::IPort *pTailCut; // Tail cut
plug::IPort *pFadeIn; // Fade in length
plug::IPort *pFadeOut; // Fade out length
plug::IPort *pMakeup; // Makup gain
plug::IPort *pVelocity; // Velocity range top
plug::IPort *pPreDelay; // Pre-delay
plug::IPort *pOn; // Sample on outputflag
plug::IPort *pListen; // Listen trigger
plug::IPort *pReverse; // Reverse sample
plug::IPort *pCompensate; // Compensate
plug::IPort *pCompensateFade; // Compensate fade
plug::IPort *pCompensateChunk; // Compensate chunk
plug::IPort *pCompensateFadeType; // Compensate fade type
plug::IPort *pGains[meta::sampler_metadata::TRACKS_MAX]; // List of gain ports
plug::IPort *pActive; // Sample activity flag
plug::IPort *pPlayPosition; // Output current playback position
plug::IPort *pNoteOn; // Note on flag
plug::IPort *pLength; // Length of the file
plug::IPort *pActualLength; // Actual length of the file
plug::IPort *pStatus; // Status of the file
plug::IPort *pMesh; // Dump of the file data
};
protected:
ipc::IExecutor *pExecutor; // Executor service
dspu::Sample *pGCList; // Garbage collection list
afile_t *vFiles; // List of audio files
afile_t **vActive; // List of active audio files
dspu::SamplePlayer vChannels[meta::sampler_metadata::TRACKS_MAX]; // List of channels
dspu::Bypass vBypass[meta::sampler_metadata::TRACKS_MAX]; // List of bypasses
dspu::Playback vListen[4]; // Listen playback handle for instrument
dspu::Blink sActivity; // Note on led for instrument
dspu::Toggle sListen; // Listen toggle
dspu::Randomizer sRandom; // Randomizer
GCTask sGCTask; // Garbage collection task
size_t nFiles; // Number of files
size_t nActive; // Number of active files
size_t nChannels; // Number of audio channels (mono/stereo)
float *vBuffer; // Buffer
bool bBypass; // Bypass flag
bool bReorder; // Reorder flag
float fFadeout; // Fadeout in milliseconds
float fDynamics; // Dynamics
float fDrift; // Time drifting
size_t nSampleRate; // Sample rate
plug::IPort *pDynamics; // Dynamics port
plug::IPort *pDrift; // Time drifting port
plug::IPort *pActivity; // Activity port
plug::IPort *pListen; // Listen trigger
uint8_t *pData; // Pointer to aligned data
protected:
void destroy_state();
status_t load_file(afile_t *file);
status_t render_sample(afile_t *af);
void play_sample(afile_t *af, float gain, size_t delay, play_mode_t mode);
void cancel_sample(afile_t *af, size_t delay);
void start_listen_file(afile_t *af, float gain);
void stop_listen_file(afile_t *af, bool force);
void start_listen_instrument(float velocity, float gain);
void stop_listen_instrument(bool force);
void process_file_load_requests();
void process_file_render_requests();
void process_gc_tasks();
void reorder_samples();
void process_listen_events();
void play_samples(float **outs, const float **ins, size_t samples);
void output_parameters(size_t samples);
afile_t *select_active_sample(float velocity);
template <class T>
static void commit_value(size_t & counter, T & field, plug::IPort *port);
static void commit_value(size_t & counter, bool & field, plug::IPort *port);
protected:
static void unload_afile(afile_t *file);
static void destroy_afile(afile_t *af);
static void destroy_samples(dspu::Sample *gc_list);
static void destroy_sample(dspu::Sample * &sample);
static ssize_t compute_loop_point(const dspu::Sample *s, size_t position);
static dspu::sample_loop_t decode_loop_mode(plug::IPort *on, plug::IPort *mode);
float compute_play_position(const afile_t *f);
void dump_afile(dspu::IStateDumper *v, const afile_t *f) const;
void perform_gc();
public:
explicit sampler_kernel();
virtual ~sampler_kernel();
public:
void trigger_on(size_t timestamp, float level);
void trigger_off(size_t timestamp, bool handle);
void trigger_cancel(size_t timestamp);
public:
void set_fadeout(float length);
public:
bool init(ipc::IExecutor *executor, size_t files, size_t channels);
size_t bind(plug::IPort **ports, size_t port_id, bool dynamics);
void bind_activity(plug::IPort *activity);
void destroy();
void update_settings();
void update_sample_rate(long sr);
void sync_samples_with_ui();
/** Process the sampler kernel
*
* @param outs list of outputs (should be not the sampe as ins)
* @param ins list of inputs, elements may be NULL
* @param samples number of samples to process
*/
void process(float **outs, const float **ins, size_t samples);
void dump(dspu::IStateDumper *v) const;
};
} /* namespace plugins */
} /* namespace lsp */
#endif /* PRIVATE_PLUGINS_SAMPLER_KERNEL_H_ */
|