ref: 9902cb9f346c78aa0bb4ea27e9c39dcedd60ed80
dir: /LEAF/Src/leaf-sample.c/
/*
==============================================================================
LEAFUtilities.c
Created: 20 Jan 2017 12:02:17pm
Author: Michael R Mulshine
==============================================================================
*/
#if _WIN32 || _WIN64
#include "..\Inc\leaf-sample.h"
#include "..\leaf.h"
#else
#include "../Inc/leaf-sample.h"
#include "../leaf.h"
#endif
//==============================================================================
void tSample_init (tSample* const s, uint32_t length)
{
s->buff = (float*) leaf_alloc( sizeof(float) * length);
s->length = length;
s->active = 0;
s->idx = 0;
s->mode = RecordOneShot;
tSample_clear(s);
}
void tSample_free (tSample* const s)
{
leaf_free(s->buff);
leaf_free(s);
}
void tSample_tick (tSample* const s, float sample)
{
if (s->active == 1)
{
s->buff[s->idx] = sample;
s->idx += 1;
if (s->idx >= s->length)
{
if (s->mode == RecordOneShot)
{
tSample_stop(s);
}
else if (s->mode == RecordLoop)
{
s->idx = 0;
}
}
}
}
void tSample_read(tSample* const s, float* buff, uint32_t len)
{
for (int i = 0; i < s->length; i++)
{
if (i < len) s->buff[i] = buff[i];
else s->buff[i] = 0.f;
}
}
float tSample_get (tSample* const s, int idx)
{
if ((idx < 0) || (idx >= s->length)) return 0.f;
return s->buff[idx];
}
void tSample_start(tSample* const s)
{
s->active = 1;
s->idx = 0;
}
void tSample_stop(tSample* const s)
{
s->active = 0;
}
void tSample_setRecordMode (tSample* const s, RecordMode mode)
{
s->mode = mode;
}
void tSample_clear (tSample* const s)
{
for (int i = 0; i < s->length; i++)
{
s->buff[i] = 0.f;
}
}
//==============================================================================
void tSamplePlayer_init (tSamplePlayer* const p, tSample* s)
{
p->samp = s;
p->active = 0;
p->start = 0;
p->end = p->samp->length - 1;
p->len = p->end - p->start;
p->idx = 0.f;
p->inc = 1.f;
p->dir = 1;
p->flip = 0;
p->mode = Normal;
p->gain = 1.;
}
void tSamplePlayer_free (tSamplePlayer* const p)
{
leaf_free(p->samp);
leaf_free(p);
}
float tSamplePlayer_tick (tSamplePlayer* const p)
{
if ((p->mode == Normal) && (p->cnt > 0)) p->active = 0;
if (p->active == 0 || (p->len < 4)) return 0.f;
float sample = 0.f;
float* buff = p->samp->buff;
int idx = (int) p->idx;
// Check dir (direction bit) to interpolate properly
if (p->dir > 0)
{
// FORWARD
float alpha = p->idx - idx;
int i1 = idx-1;
int i3 = idx+1;
int i4 = idx+2;
if (i1 < p->start) i1 += p->len;
if (i3 > p->end) i3 -= p->len;
if (i4 > p->end) i4 -= p->len;
sample = LEAF_interpolate_hermite (buff[i1],
buff[idx],
buff[i3],
buff[i4],
alpha);
}
else
{
// REVERSE
float alpha = 1.0f - (p->idx - idx);
int i1 = idx+1;
int i3 = idx-1;
int i4 = idx-2;
if (i1 > p->start) i1 -= p->len;
if (i3 < p->end) i3 += p->len;
if (i4 < p->end) i4 += p->len;
sample = LEAF_interpolate_hermite (buff[i1],
buff[idx],
buff[i3],
buff[i4],
alpha);
}
p->idx += (p->dir * p->inc);
if (p->mode != BackAndForth)
{
// Check flip bit to change loop test
if (p->flip > 0)
{
if (idx <= p->end)
{
p->idx += (float)(p->len);
p->cnt++;
}
else if (idx >= p->start)
{
p->idx -= (float)(p->len);
p->cnt++;
}
}
else
{
if (idx <= p->start)
{
p->idx += (float)(p->len);
p->cnt++;
}
else if (idx >= p->end)
{
p->idx -= (float)(p->len);
p->cnt++;
}
}
}
else // BackAndForth
{
if (p->flip > 0)
{
if ((idx < p->start) || (idx > p->end))
{
p->dir = -p->dir;
p->idx += (2*p->inc);
p->cnt++;
}
}
else
{
if ((idx > p->start) || (idx < p->end))
{
p->dir = -p->dir;
p->idx += (2*p->inc);
p->cnt++;
}
}
}
return sample * p->gain;
}
void tSamplePlayer_setSample (tSamplePlayer* const p, tSample* s)
{
p->samp = s;
}
void tSamplePlayer_setMode (tSamplePlayer* const p, Mode mode)
{
p->mode = mode;
}
void tSamplePlayer_play (tSamplePlayer* const p)
{
p->active = 1;
p->cnt = 0;
}
void tSamplePlayer_stop (tSamplePlayer* const p)
{
p->active = 0;
}
static void handleStartEndChange(tSamplePlayer* const p)
{
if (p->start > p->end)
{
p->dir = -1;
p->flip = 1;
}
else
{
p->dir = 1;
p->flip = 0;
}
}
void tSamplePlayer_setStart (tSamplePlayer* const p, int32_t start)
{
p->start = LEAF_clipInt(0, start, (p->samp->length - 1));
p->len = abs(p->end - p->start);
handleStartEndChange(p);
}
void tSamplePlayer_setEnd (tSamplePlayer* const p, int32_t end)
{
p->end = LEAF_clipInt(0, end, (p->samp->length - 1));
p->len = abs(p->end - p->start);
handleStartEndChange(p);
}
void tSamplePlayer_setRate (tSamplePlayer* const p, float rate)
{
if (rate < 0.f)
{
rate = -rate;
p->dir = -1;
}
else
{
p->dir = 1;
}
p->inc = LEAF_clip(0.f, rate, 8.0f);
}
//==============================================================================