NO-OP: whitespace (remove vi modelines)
This commit is contained in:
parent
9131cd17a0
commit
959947e7f8
|
@ -20,81 +20,74 @@
|
|||
#include <math.h>
|
||||
#include "ardour/iec1ppmdsp.h"
|
||||
|
||||
|
||||
float Iec1ppmdsp::_w1;
|
||||
float Iec1ppmdsp::_w2;
|
||||
float Iec1ppmdsp::_w3;
|
||||
float Iec1ppmdsp::_g;
|
||||
|
||||
Iec1ppmdsp::Iec1ppmdsp (void)
|
||||
: _z1 (0)
|
||||
, _z2 (0)
|
||||
, _m (0)
|
||||
, _res (true)
|
||||
{}
|
||||
|
||||
Iec1ppmdsp::Iec1ppmdsp (void) :
|
||||
_z1 (0),
|
||||
_z2 (0),
|
||||
_m (0),
|
||||
_res (true)
|
||||
Iec1ppmdsp::~Iec1ppmdsp (void) {}
|
||||
|
||||
void
|
||||
Iec1ppmdsp::process (float const* p, int n)
|
||||
{
|
||||
float z1, z2, m, t;
|
||||
|
||||
z1 = _z1 > 20 ? 20 : (_z1 < 0 ? 0 : _z1);
|
||||
z2 = _z2 > 20 ? 20 : (_z2 < 0 ? 0 : _z2);
|
||||
m = _res ? 0: _m;
|
||||
_res = false;
|
||||
|
||||
n /= 4;
|
||||
while (n--) {
|
||||
z1 *= _w3;
|
||||
z2 *= _w3;
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = z1 + z2;
|
||||
if (t > m) m = t;
|
||||
}
|
||||
|
||||
_z1 = z1 + 1e-10f;
|
||||
_z2 = z2 + 1e-10f;
|
||||
_m = m;
|
||||
}
|
||||
|
||||
|
||||
Iec1ppmdsp::~Iec1ppmdsp (void)
|
||||
float
|
||||
Iec1ppmdsp::read (void)
|
||||
{
|
||||
_res = true;
|
||||
return _g * _m;
|
||||
}
|
||||
|
||||
|
||||
void Iec1ppmdsp::process (float const *p, int n)
|
||||
void
|
||||
Iec1ppmdsp::reset ()
|
||||
{
|
||||
float z1, z2, m, t;
|
||||
|
||||
z1 = _z1 > 20 ? 20 : (_z1 < 0 ? 0 : _z1);
|
||||
z2 = _z2 > 20 ? 20 : (_z2 < 0 ? 0 : _z2);
|
||||
m = _res ? 0: _m;
|
||||
_res = false;
|
||||
|
||||
n /= 4;
|
||||
while (n--)
|
||||
{
|
||||
z1 *= _w3;
|
||||
z2 *= _w3;
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = z1 + z2;
|
||||
if (t > m) m = t;
|
||||
}
|
||||
|
||||
_z1 = z1 + 1e-10f;
|
||||
_z2 = z2 + 1e-10f;
|
||||
_m = m;
|
||||
_z1 = _z2 = _m = .0f;
|
||||
_res = true;
|
||||
}
|
||||
|
||||
|
||||
float Iec1ppmdsp::read (void)
|
||||
void
|
||||
Iec1ppmdsp::init (float fsamp)
|
||||
{
|
||||
_res = true;
|
||||
return _g * _m;
|
||||
_w1 = 450.0f / fsamp;
|
||||
_w2 = 1300.0f / fsamp;
|
||||
_w3 = 1.0f - 5.4f / fsamp;
|
||||
_g = 0.5108f;
|
||||
}
|
||||
|
||||
void Iec1ppmdsp::reset ()
|
||||
{
|
||||
_z1 = _z2 = _m = .0f;
|
||||
_res = true;
|
||||
}
|
||||
|
||||
void Iec1ppmdsp::init (float fsamp)
|
||||
{
|
||||
_w1 = 450.0f / fsamp;
|
||||
_w2 = 1300.0f / fsamp;
|
||||
_w3 = 1.0f - 5.4f / fsamp;
|
||||
_g = 0.5108f;
|
||||
}
|
||||
|
||||
/* vi:set ts=8 sts=8 sw=4: */
|
||||
|
|
|
@ -20,81 +20,74 @@
|
|||
#include <math.h>
|
||||
#include "ardour/iec2ppmdsp.h"
|
||||
|
||||
|
||||
float Iec2ppmdsp::_w1;
|
||||
float Iec2ppmdsp::_w2;
|
||||
float Iec2ppmdsp::_w3;
|
||||
float Iec2ppmdsp::_g;
|
||||
|
||||
Iec2ppmdsp::Iec2ppmdsp (void)
|
||||
: _z1 (0)
|
||||
, _z2 (0)
|
||||
, _m (0)
|
||||
, _res (true)
|
||||
{}
|
||||
|
||||
Iec2ppmdsp::Iec2ppmdsp (void) :
|
||||
_z1 (0),
|
||||
_z2 (0),
|
||||
_m (0),
|
||||
_res (true)
|
||||
Iec2ppmdsp::~Iec2ppmdsp (void) {}
|
||||
|
||||
void
|
||||
Iec2ppmdsp::process (float const* p, int n)
|
||||
{
|
||||
float z1, z2, m, t;
|
||||
|
||||
z1 = _z1 > 20 ? 20 : (_z1 < 0 ? 0 : _z1);
|
||||
z2 = _z2 > 20 ? 20 : (_z2 < 0 ? 0 : _z2);
|
||||
m = _res ? 0: _m;
|
||||
_res = false;
|
||||
|
||||
n /= 4;
|
||||
while (n--) {
|
||||
z1 *= _w3;
|
||||
z2 *= _w3;
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = z1 + z2;
|
||||
if (t > m) m = t;
|
||||
}
|
||||
|
||||
_z1 = z1 + 1e-10f;
|
||||
_z2 = z2 + 1e-10f;
|
||||
_m = m;
|
||||
}
|
||||
|
||||
|
||||
Iec2ppmdsp::~Iec2ppmdsp (void)
|
||||
float
|
||||
Iec2ppmdsp::read (void)
|
||||
{
|
||||
_res = true;
|
||||
return _g * _m;
|
||||
}
|
||||
|
||||
|
||||
void Iec2ppmdsp::process (float const *p, int n)
|
||||
void
|
||||
Iec2ppmdsp::reset ()
|
||||
{
|
||||
float z1, z2, m, t;
|
||||
|
||||
z1 = _z1 > 20 ? 20 : (_z1 < 0 ? 0 : _z1);
|
||||
z2 = _z2 > 20 ? 20 : (_z2 < 0 ? 0 : _z2);
|
||||
m = _res ? 0: _m;
|
||||
_res = false;
|
||||
|
||||
n /= 4;
|
||||
while (n--)
|
||||
{
|
||||
z1 *= _w3;
|
||||
z2 *= _w3;
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = fabsf (*p++);
|
||||
if (t > z1) z1 += _w1 * (t - z1);
|
||||
if (t > z2) z2 += _w2 * (t - z2);
|
||||
t = z1 + z2;
|
||||
if (t > m) m = t;
|
||||
}
|
||||
|
||||
_z1 = z1 + 1e-10f;
|
||||
_z2 = z2 + 1e-10f;
|
||||
_m = m;
|
||||
_z1 = _z2 = _m = .0f;
|
||||
_res = true;
|
||||
}
|
||||
|
||||
|
||||
float Iec2ppmdsp::read (void)
|
||||
void
|
||||
Iec2ppmdsp::init (float fsamp)
|
||||
{
|
||||
_res = true;
|
||||
return _g * _m;
|
||||
_w1 = 200.0f / fsamp;
|
||||
_w2 = 860.0f / fsamp;
|
||||
_w3 = 1.0f - 4.0f / fsamp;
|
||||
_g = 0.5141f;
|
||||
}
|
||||
|
||||
void Iec2ppmdsp::reset ()
|
||||
{
|
||||
_z1 = _z2 = _m = .0f;
|
||||
_res = true;
|
||||
}
|
||||
|
||||
void Iec2ppmdsp::init (float fsamp)
|
||||
{
|
||||
_w1 = 200.0f / fsamp;
|
||||
_w2 = 860.0f / fsamp;
|
||||
_w3 = 1.0f - 4.0f / fsamp;
|
||||
_g = 0.5141f;
|
||||
}
|
||||
|
||||
/* vi:set ts=8 sts=8 sw=4: */
|
||||
|
|
|
@ -20,93 +20,82 @@
|
|||
#include <math.h>
|
||||
#include "ardour/kmeterdsp.h"
|
||||
|
||||
|
||||
float Kmeterdsp::_omega;
|
||||
|
||||
Kmeterdsp::Kmeterdsp (void)
|
||||
: _z1 (0)
|
||||
, _z2 (0)
|
||||
, _rms (0)
|
||||
, _flag (false)
|
||||
{}
|
||||
|
||||
Kmeterdsp::Kmeterdsp (void) :
|
||||
_z1 (0),
|
||||
_z2 (0),
|
||||
_rms (0),
|
||||
_flag (false)
|
||||
Kmeterdsp::~Kmeterdsp (void) {}
|
||||
|
||||
void
|
||||
Kmeterdsp::init (int fsamp)
|
||||
{
|
||||
_omega = 9.72f / fsamp; // ballistic filter coefficient
|
||||
}
|
||||
|
||||
|
||||
Kmeterdsp::~Kmeterdsp (void)
|
||||
void
|
||||
Kmeterdsp::process (float const* p, int n)
|
||||
{
|
||||
}
|
||||
float s, z1, z2;
|
||||
|
||||
void Kmeterdsp::init (int fsamp)
|
||||
{
|
||||
_omega = 9.72f / fsamp; // ballistic filter coefficient
|
||||
}
|
||||
// Get filter state.
|
||||
z1 = _z1 > 50 ? 50 : (_z1 < 0 ? 0 : _z1);
|
||||
z2 = _z2 > 50 ? 50 : (_z2 < 0 ? 0 : _z2);
|
||||
|
||||
void Kmeterdsp::process (float const *p, int n)
|
||||
{
|
||||
// Called by JACK's process callback.
|
||||
//
|
||||
// p : pointer to sample buffer
|
||||
// n : number of samples to process
|
||||
// Perform filtering. The second filter is evaluated
|
||||
// only every 4th sample - this is just an optimisation.
|
||||
n /= 4; // Loop is unrolled by 4.
|
||||
while (n--) {
|
||||
s = *p++;
|
||||
s *= s;
|
||||
z1 += _omega * (s - z1); // Update first filter.
|
||||
s = *p++;
|
||||
s *= s;
|
||||
z1 += _omega * (s - z1); // Update first filter.
|
||||
s = *p++;
|
||||
s *= s;
|
||||
z1 += _omega * (s - z1); // Update first filter.
|
||||
s = *p++;
|
||||
s *= s;
|
||||
z1 += _omega * (s - z1); // Update first filter.
|
||||
z2 += 4 * _omega * (z1 - z2); // Update second filter.
|
||||
}
|
||||
|
||||
float s, z1, z2;
|
||||
if (isnan(z1)) z1 = 0;
|
||||
if (isnan(z2)) z2 = 0;
|
||||
|
||||
// Get filter state.
|
||||
z1 = _z1 > 50 ? 50 : (_z1 < 0 ? 0 : _z1);
|
||||
z2 = _z2 > 50 ? 50 : (_z2 < 0 ? 0 : _z2);
|
||||
// Save filter state. The added constants avoid denormals.
|
||||
_z1 = z1 + 1e-20f;
|
||||
_z2 = z2 + 1e-20f;
|
||||
|
||||
// Perform filtering. The second filter is evaluated
|
||||
// only every 4th sample - this is just an optimisation.
|
||||
n /= 4; // Loop is unrolled by 4.
|
||||
while (n--)
|
||||
{
|
||||
s = *p++;
|
||||
s *= s;
|
||||
z1 += _omega * (s - z1); // Update first filter.
|
||||
s = *p++;
|
||||
s *= s;
|
||||
z1 += _omega * (s - z1); // Update first filter.
|
||||
s = *p++;
|
||||
s *= s;
|
||||
z1 += _omega * (s - z1); // Update first filter.
|
||||
s = *p++;
|
||||
s *= s;
|
||||
z1 += _omega * (s - z1); // Update first filter.
|
||||
z2 += 4 * _omega * (z1 - z2); // Update second filter.
|
||||
}
|
||||
s = sqrtf (2.0f * z2);
|
||||
|
||||
if (isnan(z1)) z1 = 0;
|
||||
if (isnan(z2)) z2 = 0;
|
||||
// Save filter state. The added constants avoid denormals.
|
||||
_z1 = z1 + 1e-20f;
|
||||
_z2 = z2 + 1e-20f;
|
||||
|
||||
s = sqrtf (2.0f * z2);
|
||||
|
||||
if (_flag) // Display thread has read the rms value.
|
||||
{
|
||||
_rms = s;
|
||||
_flag = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Adjust RMS value and update maximum since last read().
|
||||
if (s > _rms) _rms = s;
|
||||
}
|
||||
if (_flag) {
|
||||
// Display thread has read the rms value.
|
||||
_rms = s;
|
||||
_flag = false;
|
||||
} else {
|
||||
// Adjust RMS value and update maximum since last read().
|
||||
if (s > _rms) _rms = s;
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns highest _rms value since last call */
|
||||
float Kmeterdsp::read ()
|
||||
float
|
||||
Kmeterdsp::read ()
|
||||
{
|
||||
float rv= _rms;
|
||||
_flag = true; // Resets _rms in next process().
|
||||
return rv;
|
||||
float rv= _rms;
|
||||
_flag = true; // Resets _rms in next process().
|
||||
return rv;
|
||||
}
|
||||
|
||||
void Kmeterdsp::reset ()
|
||||
void
|
||||
Kmeterdsp::reset ()
|
||||
{
|
||||
_z1 = _z2 = _rms = .0f;
|
||||
_flag = false;
|
||||
_z1 = _z2 = _rms = .0f;
|
||||
_flag = false;
|
||||
}
|
||||
|
||||
/* vi:set ts=8 sts=8 sw=4: */
|
||||
|
|
|
@ -480,5 +480,3 @@ void gdither_runf(GDither s, uint32_t channel, uint32_t length,
|
|||
s->clamp_l);
|
||||
}
|
||||
}
|
||||
|
||||
/* vi:set ts=8 sts=4 sw=4: */
|
||||
|
|
|
@ -42,82 +42,82 @@ static uint32_t synth_sound (void *, uint32_t written, uint32_t nframes, fl
|
|||
#include "rsynth.c"
|
||||
|
||||
typedef enum {
|
||||
RSY_MIDIIN = 0,
|
||||
RSY_OUTL,
|
||||
RSY_OUTR
|
||||
RSY_MIDIIN = 0,
|
||||
RSY_OUTL,
|
||||
RSY_OUTR
|
||||
} PortIndex;
|
||||
|
||||
typedef struct {
|
||||
const LV2_Atom_Sequence* midiin;
|
||||
float* outL;
|
||||
float* outR;
|
||||
const LV2_Atom_Sequence* midiin;
|
||||
float* outL;
|
||||
float* outR;
|
||||
|
||||
LV2_URID_Map* map;
|
||||
LV2_URID midi_MidiEvent;
|
||||
LV2_URID_Map* map;
|
||||
LV2_URID midi_MidiEvent;
|
||||
|
||||
double SampleRateD;
|
||||
void *synth;
|
||||
bool xmas;
|
||||
double SampleRateD;
|
||||
void *synth;
|
||||
bool xmas;
|
||||
} RSynth;
|
||||
|
||||
/* main LV2 */
|
||||
|
||||
static LV2_Handle
|
||||
instantiate(const LV2_Descriptor* descriptor,
|
||||
double rate,
|
||||
const char* bundle_path,
|
||||
const LV2_Feature* const* features)
|
||||
instantiate (const LV2_Descriptor* descriptor,
|
||||
double rate,
|
||||
const char* bundle_path,
|
||||
const LV2_Feature* const* features)
|
||||
{
|
||||
(void) descriptor; /* unused variable */
|
||||
(void) bundle_path; /* unused variable */
|
||||
(void) descriptor; /* unused variable */
|
||||
(void) bundle_path; /* unused variable */
|
||||
|
||||
if (rate < 8000) {
|
||||
fprintf(stderr, "RSynth.lv2 error: unsupported sample-rate (must be > 8k)\n");
|
||||
return NULL;
|
||||
}
|
||||
RSynth* self = (RSynth*)calloc(1, sizeof(RSynth));
|
||||
if(!self) {
|
||||
return NULL;
|
||||
}
|
||||
if (rate < 8000) {
|
||||
fprintf(stderr, "RSynth.lv2 error: unsupported sample-rate (must be > 8k)\n");
|
||||
return NULL;
|
||||
}
|
||||
RSynth* self = (RSynth*)calloc(1, sizeof(RSynth));
|
||||
if(!self) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->SampleRateD = rate;
|
||||
self->SampleRateD = rate;
|
||||
|
||||
int i;
|
||||
for (i=0; features[i]; ++i) {
|
||||
if (!strcmp(features[i]->URI, LV2_URID__map)) {
|
||||
self->map = (LV2_URID_Map*)features[i]->data;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
for (i=0; features[i]; ++i) {
|
||||
if (!strcmp(features[i]->URI, LV2_URID__map)) {
|
||||
self->map = (LV2_URID_Map*)features[i]->data;
|
||||
}
|
||||
}
|
||||
|
||||
if (!self->map) {
|
||||
fprintf(stderr, "RSynth.lv2 error: Host does not support urid:map\n");
|
||||
free(self);
|
||||
return NULL;
|
||||
}
|
||||
if (!self->map) {
|
||||
fprintf(stderr, "RSynth.lv2 error: Host does not support urid:map\n");
|
||||
free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->midi_MidiEvent = self->map->map(self->map->handle, LV2_MIDI__MidiEvent);
|
||||
self->midi_MidiEvent = self->map->map(self->map->handle, LV2_MIDI__MidiEvent);
|
||||
|
||||
self->synth = synth_alloc();
|
||||
synth_init(self->synth, rate);
|
||||
self->synth = synth_alloc();
|
||||
synth_init(self->synth, rate);
|
||||
|
||||
#ifndef PLATFORM_WINDOWS // easter egg is for sane platforms with native support for localtime_r only
|
||||
struct tm date;
|
||||
time_t now;
|
||||
time(&now);
|
||||
localtime_r(&now, &date);
|
||||
if (getenv("ITSXMAS") || (date.tm_mon == 11 /*dec*/ && date.tm_mday == 25)) {
|
||||
printf("reasonable synth.lv2 says: happy holidays!\n");
|
||||
self->xmas = true;
|
||||
}
|
||||
struct tm date;
|
||||
time_t now;
|
||||
time(&now);
|
||||
localtime_r(&now, &date);
|
||||
if (getenv("ITSXMAS") || (date.tm_mon == 11 /*dec*/ && date.tm_mday == 25)) {
|
||||
printf("reasonable synth.lv2 says: happy holidays!\n");
|
||||
self->xmas = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (LV2_Handle)self;
|
||||
return (LV2_Handle)self;
|
||||
}
|
||||
|
||||
static void
|
||||
connect_port(LV2_Handle handle,
|
||||
uint32_t port,
|
||||
void* data)
|
||||
connect_port (LV2_Handle handle,
|
||||
uint32_t port,
|
||||
void* data)
|
||||
{
|
||||
RSynth* self = (RSynth*)handle;
|
||||
|
||||
|
@ -135,76 +135,76 @@ connect_port(LV2_Handle handle,
|
|||
}
|
||||
|
||||
static void
|
||||
run(LV2_Handle handle, uint32_t n_samples)
|
||||
run (LV2_Handle handle, uint32_t n_samples)
|
||||
{
|
||||
RSynth* self = (RSynth*)handle;
|
||||
float* audio[2];
|
||||
RSynth* self = (RSynth*)handle;
|
||||
float* audio[2];
|
||||
|
||||
audio[0] = self->outL;
|
||||
audio[1] = self->outR;
|
||||
audio[0] = self->outL;
|
||||
audio[1] = self->outR;
|
||||
|
||||
uint32_t written = 0;
|
||||
uint32_t written = 0;
|
||||
|
||||
/* Process incoming MIDI events */
|
||||
if (self->midiin) {
|
||||
LV2_Atom_Event const* ev = (LV2_Atom_Event const*)((uintptr_t)((&(self->midiin)->body) + 1)); // lv2_atom_sequence_begin
|
||||
while( // !lv2_atom_sequence_is_end
|
||||
(const uint8_t*)ev < ((const uint8_t*) &(self->midiin)->body + (self->midiin)->atom.size)
|
||||
)
|
||||
{
|
||||
if (ev->body.type == self->midi_MidiEvent) {
|
||||
/* Process incoming MIDI events */
|
||||
if (self->midiin) {
|
||||
LV2_Atom_Event const* ev = (LV2_Atom_Event const*)((uintptr_t)((&(self->midiin)->body) + 1)); // lv2_atom_sequence_begin
|
||||
while( // !lv2_atom_sequence_is_end
|
||||
(const uint8_t*)ev < ((const uint8_t*) &(self->midiin)->body + (self->midiin)->atom.size)
|
||||
)
|
||||
{
|
||||
if (ev->body.type == self->midi_MidiEvent) {
|
||||
#ifdef DEBUG_MIDI_EVENT // debug midi messages in synth -- not rt-safe(!)
|
||||
printf ("%5d (%d):", ev->time.frames, ev->body.size);
|
||||
for (uint8_t i = 0; i < ev->body.size; ++i) {
|
||||
printf (" %02x", ((const uint8_t*)(ev+1))[i]);
|
||||
}
|
||||
printf ("\n");
|
||||
printf ("%5d (%d):", ev->time.frames, ev->body.size);
|
||||
for (uint8_t i = 0; i < ev->body.size; ++i) {
|
||||
printf (" %02x", ((const uint8_t*)(ev+1))[i]);
|
||||
}
|
||||
printf ("\n");
|
||||
#endif
|
||||
if (written + BUFFER_SIZE_SAMPLES < ev->time.frames
|
||||
&& ev->time.frames < n_samples) {
|
||||
/* first synthesize sound up until the message timestamp */
|
||||
written = synth_sound(self->synth, written, ev->time.frames, audio);
|
||||
}
|
||||
/* send midi message to synth */
|
||||
if (self->xmas) {
|
||||
synth_parse_xmas(self->synth, (const uint8_t*)(ev+1), ev->body.size);
|
||||
} else {
|
||||
synth_parse_midi(self->synth, (const uint8_t*)(ev+1), ev->body.size);
|
||||
}
|
||||
}
|
||||
ev = (LV2_Atom_Event const*) // lv2_atom_sequence_next()
|
||||
((uintptr_t)((const uint8_t*)ev + sizeof(LV2_Atom_Event) + ((ev->body.size + 7) & ~7)));
|
||||
}
|
||||
}
|
||||
if (written + BUFFER_SIZE_SAMPLES < ev->time.frames
|
||||
&& ev->time.frames < n_samples) {
|
||||
/* first synthesize sound up until the message timestamp */
|
||||
written = synth_sound(self->synth, written, ev->time.frames, audio);
|
||||
}
|
||||
/* send midi message to synth */
|
||||
if (self->xmas) {
|
||||
synth_parse_xmas(self->synth, (const uint8_t*)(ev+1), ev->body.size);
|
||||
} else {
|
||||
synth_parse_midi(self->synth, (const uint8_t*)(ev+1), ev->body.size);
|
||||
}
|
||||
}
|
||||
ev = (LV2_Atom_Event const*) // lv2_atom_sequence_next()
|
||||
((uintptr_t)((const uint8_t*)ev + sizeof(LV2_Atom_Event) + ((ev->body.size + 7) & ~7)));
|
||||
}
|
||||
}
|
||||
|
||||
/* synthesize [remaining] sound */
|
||||
synth_sound(self->synth, written, n_samples, audio);
|
||||
/* synthesize [remaining] sound */
|
||||
synth_sound(self->synth, written, n_samples, audio);
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup(LV2_Handle handle)
|
||||
{
|
||||
RSynth* self = (RSynth*)handle;
|
||||
synth_free(self->synth);
|
||||
free(handle);
|
||||
RSynth* self = (RSynth*)handle;
|
||||
synth_free(self->synth);
|
||||
free(handle);
|
||||
}
|
||||
|
||||
static const void*
|
||||
extension_data(const char* uri)
|
||||
{
|
||||
(void) uri; /* unused variable */
|
||||
return NULL;
|
||||
(void) uri; /* unused variable */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const LV2_Descriptor descriptor = {
|
||||
RSY_URI,
|
||||
instantiate,
|
||||
connect_port,
|
||||
NULL,
|
||||
run,
|
||||
NULL,
|
||||
cleanup,
|
||||
extension_data
|
||||
RSY_URI,
|
||||
instantiate,
|
||||
connect_port,
|
||||
NULL,
|
||||
run,
|
||||
NULL,
|
||||
cleanup,
|
||||
extension_data
|
||||
};
|
||||
|
||||
#if defined(COMPILER_MSVC)
|
||||
|
@ -215,12 +215,10 @@ __attribute__ ((visibility ("default")))
|
|||
const LV2_Descriptor*
|
||||
lv2_descriptor(uint32_t idx)
|
||||
{
|
||||
switch (idx) {
|
||||
case 0:
|
||||
return &descriptor;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
switch (idx) {
|
||||
case 0:
|
||||
return &descriptor;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* vi:set ts=8 sts=2 sw=2 et: */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* reasonable simple synth
|
||||
/* reasonably simple synth
|
||||
*
|
||||
* Copyright (C) 2013 Robin Gareus <robin@gareus.org>
|
||||
* Copyright (C) 2013, 2019 Robin Gareus <robin@gareus.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -42,65 +42,67 @@
|
|||
|
||||
/* internal MIDI event abstraction */
|
||||
enum RMIDI_EV_TYPE {
|
||||
INVALID=0,
|
||||
NOTE_ON,
|
||||
NOTE_OFF,
|
||||
PROGRAM_CHANGE,
|
||||
CONTROL_CHANGE,
|
||||
INVALID=0,
|
||||
NOTE_ON,
|
||||
NOTE_OFF,
|
||||
PROGRAM_CHANGE,
|
||||
CONTROL_CHANGE,
|
||||
};
|
||||
|
||||
struct rmidi_event_t {
|
||||
enum RMIDI_EV_TYPE type;
|
||||
uint8_t channel; /**< the MIDI channel number 0-15 */
|
||||
union {
|
||||
struct {
|
||||
uint8_t note;
|
||||
uint8_t velocity;
|
||||
} tone;
|
||||
struct {
|
||||
uint8_t param;
|
||||
uint8_t value;
|
||||
} control;
|
||||
} d;
|
||||
enum RMIDI_EV_TYPE type;
|
||||
uint8_t channel; /**< the MIDI channel number 0-15 */
|
||||
union {
|
||||
struct {
|
||||
uint8_t note;
|
||||
uint8_t velocity;
|
||||
} tone;
|
||||
struct {
|
||||
uint8_t param;
|
||||
uint8_t value;
|
||||
} control;
|
||||
} d;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t tme[3]; // attack, decay, release times [settings:ms || internal:samples]
|
||||
float vol[2]; // attack, sustain volume [0..1]
|
||||
uint32_t off[3]; // internal use (added attack,decay,release times)
|
||||
uint32_t tme[3]; // attack, decay, release times [settings:ms || internal:samples]
|
||||
float vol[2]; // attack, sustain volume [0..1]
|
||||
uint32_t off[3]; // internal use (added attack,decay,release times)
|
||||
} ADSRcfg;
|
||||
|
||||
typedef struct _RSSynthChannel {
|
||||
uint32_t keycomp;
|
||||
uint32_t adsr_cnt[128];
|
||||
float adsr_amp[128];
|
||||
float phase[128]; // various use, zero'ed on note-on
|
||||
int8_t miditable[128]; // internal, note-on/off velocity
|
||||
int8_t midimsgs [128]; // internal, note-off + on in same cycle, sustained-off
|
||||
int8_t sustain; // sustain pedal pressed
|
||||
ADSRcfg adsr;
|
||||
void (*synthesize) (struct _RSSynthChannel* sc,
|
||||
const uint8_t note, const float vol, const float pc,
|
||||
const size_t n_samples, float* left, float* right);
|
||||
uint32_t keycomp;
|
||||
uint32_t adsr_cnt[128];
|
||||
float adsr_amp[128];
|
||||
float phase[128]; // various use, zero'ed on note-on
|
||||
int8_t miditable[128]; // internal, note-on/off velocity
|
||||
int8_t midimsgs [128]; // internal, note-off + on in same cycle, sustained-off
|
||||
int8_t sustain; // sustain pedal pressed
|
||||
ADSRcfg adsr;
|
||||
void (*synthesize) (struct _RSSynthChannel* sc,
|
||||
const uint8_t note, const float vol, const float pc,
|
||||
const size_t n_samples, float* left, float* right);
|
||||
} RSSynthChannel;
|
||||
|
||||
typedef void (*SynthFunction) (RSSynthChannel* sc,
|
||||
const uint8_t note, const float vol, const float pc,
|
||||
const size_t n_samples, float* left, float* right);
|
||||
const uint8_t note,
|
||||
const float vol,
|
||||
const float pc,
|
||||
const size_t n_samples,
|
||||
float* left, float* right);
|
||||
|
||||
typedef struct {
|
||||
uint32_t boffset;
|
||||
float buf [2][BUFFER_SIZE_SAMPLES];
|
||||
RSSynthChannel sc[16];
|
||||
float freqs[128];
|
||||
float kcgain;
|
||||
float kcfilt;
|
||||
double rate;
|
||||
uint32_t xmas_on;
|
||||
uint32_t xmas_off;
|
||||
uint32_t boffset;
|
||||
float buf [2][BUFFER_SIZE_SAMPLES];
|
||||
RSSynthChannel sc[16];
|
||||
float freqs[128];
|
||||
float kcgain;
|
||||
float kcfilt;
|
||||
double rate;
|
||||
uint32_t xmas_on;
|
||||
uint32_t xmas_off;
|
||||
} RSSynthesizer;
|
||||
|
||||
|
||||
/* initialize ADSR values
|
||||
*
|
||||
* @param rate sample-rate
|
||||
|
@ -110,286 +112,298 @@ typedef struct {
|
|||
* @param avol attack gain [0..1]
|
||||
* @param svol sustain volume level [0..1]
|
||||
*/
|
||||
static void init_adsr(ADSRcfg *adsr, const double rate,
|
||||
const uint32_t a, const uint32_t d, const uint32_t r,
|
||||
const float avol, const float svol) {
|
||||
static void
|
||||
init_adsr (ADSRcfg *adsr, const double rate,
|
||||
const uint32_t a, const uint32_t d, const uint32_t r,
|
||||
const float avol, const float svol)
|
||||
{
|
||||
adsr->vol[0] = avol;
|
||||
adsr->vol[1] = svol;
|
||||
adsr->tme[0] = a * rate / 1000.0;
|
||||
adsr->tme[1] = d * rate / 1000.0;
|
||||
adsr->tme[2] = r * rate / 1000.0;
|
||||
|
||||
adsr->vol[0] = avol;
|
||||
adsr->vol[1] = svol;
|
||||
adsr->tme[0] = a * rate / 1000.0;
|
||||
adsr->tme[1] = d * rate / 1000.0;
|
||||
adsr->tme[2] = r * rate / 1000.0;
|
||||
assert(adsr->tme[0] > 32);
|
||||
assert(adsr->tme[1] > 32);
|
||||
assert(adsr->tme[2] > 32);
|
||||
assert(adsr->vol[0] >=0 && adsr->vol[1] <= 1.0);
|
||||
assert(adsr->vol[1] >=0 && adsr->vol[1] <= 1.0);
|
||||
|
||||
assert(adsr->tme[0] > 32);
|
||||
assert(adsr->tme[1] > 32);
|
||||
assert(adsr->tme[2] > 32);
|
||||
assert(adsr->vol[0] >=0 && adsr->vol[1] <= 1.0);
|
||||
assert(adsr->vol[1] >=0 && adsr->vol[1] <= 1.0);
|
||||
|
||||
adsr->off[0] = adsr->tme[0];
|
||||
adsr->off[1] = adsr->tme[1] + adsr->off[0];
|
||||
adsr->off[2] = adsr->tme[2] + adsr->off[1];
|
||||
adsr->off[0] = adsr->tme[0];
|
||||
adsr->off[1] = adsr->tme[1] + adsr->off[0];
|
||||
adsr->off[2] = adsr->tme[2] + adsr->off[1];
|
||||
}
|
||||
|
||||
/* calculate per-sample, per-key envelope */
|
||||
static inline float adsr_env(RSSynthChannel *sc, const uint8_t note) {
|
||||
|
||||
if (sc->adsr_cnt[note] < sc->adsr.off[0]) {
|
||||
// attack
|
||||
const uint32_t p = ++sc->adsr_cnt[note];
|
||||
if (p == sc->adsr.tme[0]) {
|
||||
sc->adsr_amp[note] = sc->adsr.vol[0];
|
||||
return sc->adsr.vol[0];
|
||||
} else {
|
||||
const float d = sc->adsr.vol[0] - sc->adsr_amp[note];
|
||||
return sc->adsr_amp[note] + (p / (float) sc->adsr.tme[0]) * d;
|
||||
}
|
||||
}
|
||||
else if (sc->adsr_cnt[note] < sc->adsr.off[1]) {
|
||||
// decay
|
||||
const uint32_t p = ++sc->adsr_cnt[note] - sc->adsr.off[0];
|
||||
if (p == sc->adsr.tme[1]) {
|
||||
sc->adsr_amp[note] = sc->adsr.vol[1];
|
||||
return sc->adsr.vol[1];
|
||||
} else {
|
||||
const float d = sc->adsr.vol[1] - sc->adsr_amp[note];
|
||||
return sc->adsr_amp[note] + (p / (float) sc->adsr.tme[1]) * d;
|
||||
}
|
||||
}
|
||||
else if (sc->adsr_cnt[note] == sc->adsr.off[1]) {
|
||||
// sustain
|
||||
return sc->adsr.vol[1];
|
||||
}
|
||||
else if (sc->adsr_cnt[note] < sc->adsr.off[2]) {
|
||||
// release
|
||||
const uint32_t p = ++sc->adsr_cnt[note] - sc->adsr.off[1];
|
||||
if (p == sc->adsr.tme[2]) {
|
||||
sc->adsr_amp[note] = 0;
|
||||
return 0;
|
||||
} else {
|
||||
const float d = 0 - sc->adsr_amp[note];
|
||||
return sc->adsr_amp[note] + (p / (float) sc->adsr.tme[2]) * d;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sc->adsr_cnt[note] = 0;
|
||||
return 0;
|
||||
}
|
||||
static inline float
|
||||
adsr_env(RSSynthChannel *sc, const uint8_t note)
|
||||
{
|
||||
if (sc->adsr_cnt[note] < sc->adsr.off[0]) {
|
||||
// attack
|
||||
const uint32_t p = ++sc->adsr_cnt[note];
|
||||
if (p == sc->adsr.tme[0]) {
|
||||
sc->adsr_amp[note] = sc->adsr.vol[0];
|
||||
return sc->adsr.vol[0];
|
||||
} else {
|
||||
const float d = sc->adsr.vol[0] - sc->adsr_amp[note];
|
||||
return sc->adsr_amp[note] + (p / (float) sc->adsr.tme[0]) * d;
|
||||
}
|
||||
}
|
||||
else if (sc->adsr_cnt[note] < sc->adsr.off[1]) {
|
||||
// decay
|
||||
const uint32_t p = ++sc->adsr_cnt[note] - sc->adsr.off[0];
|
||||
if (p == sc->adsr.tme[1]) {
|
||||
sc->adsr_amp[note] = sc->adsr.vol[1];
|
||||
return sc->adsr.vol[1];
|
||||
} else {
|
||||
const float d = sc->adsr.vol[1] - sc->adsr_amp[note];
|
||||
return sc->adsr_amp[note] + (p / (float) sc->adsr.tme[1]) * d;
|
||||
}
|
||||
}
|
||||
else if (sc->adsr_cnt[note] == sc->adsr.off[1]) {
|
||||
// sustain
|
||||
return sc->adsr.vol[1];
|
||||
}
|
||||
else if (sc->adsr_cnt[note] < sc->adsr.off[2]) {
|
||||
// release
|
||||
const uint32_t p = ++sc->adsr_cnt[note] - sc->adsr.off[1];
|
||||
if (p == sc->adsr.tme[2]) {
|
||||
sc->adsr_amp[note] = 0;
|
||||
return 0;
|
||||
} else {
|
||||
const float d = 0 - sc->adsr_amp[note];
|
||||
return sc->adsr_amp[note] + (p / (float) sc->adsr.tme[2]) * d;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sc->adsr_cnt[note] = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* piano like sound w/slight stereo phase */
|
||||
static void synthesize_sineP (RSSynthChannel* sc,
|
||||
const uint8_t note, const float vol, const float fq,
|
||||
const size_t n_samples, float* left, float* right) {
|
||||
static void
|
||||
synthesize_sineP (RSSynthChannel* sc,
|
||||
const uint8_t note, const float vol, const float fq,
|
||||
const size_t n_samples, float* left, float* right)
|
||||
{
|
||||
size_t i;
|
||||
float phase = sc->phase[note];
|
||||
|
||||
size_t i;
|
||||
float phase = sc->phase[note];
|
||||
|
||||
for (i=0; i < n_samples; ++i) {
|
||||
float env = adsr_env(sc, note);
|
||||
if (sc->adsr_cnt[note] == 0) break;
|
||||
const float amp = vol * env;
|
||||
if (amp > 1e-10) {
|
||||
left[i] += amp * sinf(2.0 * M_PI * phase);
|
||||
left[i] += .300 * amp * sinf(2.0 * M_PI * phase * 2.0);
|
||||
left[i] += .150 * amp * sinf(2.0 * M_PI * phase * 3.0);
|
||||
left[i] += .080 * amp * sinf(2.0 * M_PI * phase * 4.0);
|
||||
//left[i] -= .007 * amp * sinf(2.0 * M_PI * phase * 5.0);
|
||||
//left[i] += .010 * amp * sinf(2.0 * M_PI * phase * 6.0);
|
||||
left[i] += .020 * amp * sinf(2.0 * M_PI * phase * 7.0);
|
||||
phase += fq;
|
||||
right[i] += amp * sinf(2.0 * M_PI * phase);
|
||||
right[i] += .300 * amp * sinf(2.0 * M_PI * phase * 2.0);
|
||||
right[i] += .150 * amp * sinf(2.0 * M_PI * phase * 3.0);
|
||||
right[i] -= .080 * amp * sinf(2.0 * M_PI * phase * 4.0);
|
||||
//right[i] += .007 * amp * sinf(2.0 * M_PI * phase * 5.0);
|
||||
//right[i] += .010 * amp * sinf(2.0 * M_PI * phase * 6.0);
|
||||
right[i] -= .020 * amp * sinf(2.0 * M_PI * phase * 7.0);
|
||||
} else {
|
||||
phase += fq;
|
||||
}
|
||||
if (phase > 1.0) phase -= 2.0;
|
||||
}
|
||||
sc->phase[note] = phase;
|
||||
for (i=0; i < n_samples; ++i) {
|
||||
float env = adsr_env(sc, note);
|
||||
if (sc->adsr_cnt[note] == 0) break;
|
||||
const float amp = vol * env;
|
||||
if (amp > 1e-10) {
|
||||
left[i] += amp * sinf(2.0 * M_PI * phase);
|
||||
left[i] += .300 * amp * sinf(2.0 * M_PI * phase * 2.0);
|
||||
left[i] += .150 * amp * sinf(2.0 * M_PI * phase * 3.0);
|
||||
left[i] += .080 * amp * sinf(2.0 * M_PI * phase * 4.0);
|
||||
//left[i] -= .007 * amp * sinf(2.0 * M_PI * phase * 5.0);
|
||||
//left[i] += .010 * amp * sinf(2.0 * M_PI * phase * 6.0);
|
||||
left[i] += .020 * amp * sinf(2.0 * M_PI * phase * 7.0);
|
||||
phase += fq;
|
||||
right[i] += amp * sinf(2.0 * M_PI * phase);
|
||||
right[i] += .300 * amp * sinf(2.0 * M_PI * phase * 2.0);
|
||||
right[i] += .150 * amp * sinf(2.0 * M_PI * phase * 3.0);
|
||||
right[i] -= .080 * amp * sinf(2.0 * M_PI * phase * 4.0);
|
||||
//right[i] += .007 * amp * sinf(2.0 * M_PI * phase * 5.0);
|
||||
//right[i] += .010 * amp * sinf(2.0 * M_PI * phase * 6.0);
|
||||
right[i] -= .020 * amp * sinf(2.0 * M_PI * phase * 7.0);
|
||||
} else {
|
||||
phase += fq;
|
||||
}
|
||||
if (phase > 1.0) phase -= 2.0;
|
||||
}
|
||||
sc->phase[note] = phase;
|
||||
}
|
||||
|
||||
static const ADSRcfg piano_adsr = {{ 5, 800, 100}, { 1.0, 0.0}, {0,0,0}};
|
||||
static const ADSRcfg piano_adsr = {{ 5, 800, 100}, { 1.0, 0.0}, {0, 0, 0}};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
/* process note - move through ADSR states, count active keys,.. */
|
||||
static void process_key (void *synth,
|
||||
const uint8_t chn, const uint8_t note,
|
||||
const size_t n_samples, float *left, float *right)
|
||||
static void
|
||||
process_key (void *synth,
|
||||
const uint8_t chn, const uint8_t note,
|
||||
const size_t n_samples,
|
||||
float *left, float *right)
|
||||
{
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
RSSynthChannel* sc = &rs->sc[chn];
|
||||
const int8_t vel = sc->miditable[note];
|
||||
const int8_t msg = sc->midimsgs[note];
|
||||
const float vol = /* master_volume */ 0.1f * abs(vel) / 127.f;
|
||||
const float phase = sc->phase[note];
|
||||
const int8_t sus = sc->sustain;
|
||||
sc->midimsgs[note] &= ~3;
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
RSSynthChannel* sc = &rs->sc[chn];
|
||||
const int8_t vel = sc->miditable[note];
|
||||
const int8_t msg = sc->midimsgs[note];
|
||||
const float vol = /* master_volume */ 0.1f * abs(vel) / 127.f;
|
||||
const float phase = sc->phase[note];
|
||||
const int8_t sus = sc->sustain;
|
||||
sc->midimsgs[note] &= ~3;
|
||||
|
||||
if (phase == -10 && vel > 0) {
|
||||
// new note on
|
||||
sc->midimsgs[note] &= ~4;
|
||||
assert(sc->adsr_cnt[note] == 0);
|
||||
sc->adsr_amp[note] = 0;
|
||||
sc->adsr_cnt[note] = 0;
|
||||
sc->phase[note] = 0;
|
||||
sc->keycomp++;
|
||||
//printf("[On] Now %d keys active on chn %d\n", sc->keycomp, chn);
|
||||
}
|
||||
else if (phase >= -1.0 && phase <= 1.0 && vel > 0) {
|
||||
// sustain note or re-start note while adsr in progress:
|
||||
if (sc->adsr_cnt[note] > sc->adsr.off[1] || msg == 3 || msg == 5 || msg == 7) {
|
||||
sc->midimsgs[note] &= ~4;
|
||||
// x-fade to attack
|
||||
sc->adsr_amp[note] = adsr_env(sc, note);
|
||||
sc->adsr_cnt[note] = 0;
|
||||
}
|
||||
}
|
||||
else if (phase >= -1.0 && phase <= 1.0 && vel < 0) {
|
||||
sc->midimsgs[note] |= 4;
|
||||
// note off
|
||||
if (sc->adsr_cnt[note] <= sc->adsr.off[1] && !sus) {
|
||||
if (sc->adsr_cnt[note] != sc->adsr.off[1]) {
|
||||
// x-fade to release
|
||||
sc->adsr_amp[note] = adsr_env(sc, note);
|
||||
}
|
||||
sc->adsr_cnt[note] = sc->adsr.off[1] + 1;
|
||||
}
|
||||
else if (sus && sc->adsr_cnt[note] == sc->adsr.off[1]) {
|
||||
sc->adsr_cnt[note] = sc->adsr.off[1] + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//printf("FORCE NOTE OFF: %d %d\n", vel, sus);
|
||||
/* note-on + off in same cycle */
|
||||
sc->miditable[note] = 0;
|
||||
sc->adsr_cnt[note] = 0;
|
||||
sc->phase[note] = -10;
|
||||
return;
|
||||
}
|
||||
//printf("NOTE: %d (%d %d %d)\n", sc->adsr_cnt[note], sc->adsr.off[0], sc->adsr.off[1], sc->adsr.off[2]);
|
||||
if (phase == -10 && vel > 0) {
|
||||
// new note on
|
||||
sc->midimsgs[note] &= ~4;
|
||||
assert(sc->adsr_cnt[note] == 0);
|
||||
sc->adsr_amp[note] = 0;
|
||||
sc->adsr_cnt[note] = 0;
|
||||
sc->phase[note] = 0;
|
||||
sc->keycomp++;
|
||||
//printf("[On] Now %d keys active on chn %d\n", sc->keycomp, chn);
|
||||
}
|
||||
else if (phase >= -1.0 && phase <= 1.0 && vel > 0) {
|
||||
// sustain note or re-start note while adsr in progress:
|
||||
if (sc->adsr_cnt[note] > sc->adsr.off[1] || msg == 3 || msg == 5 || msg == 7) {
|
||||
sc->midimsgs[note] &= ~4;
|
||||
// x-fade to attack
|
||||
sc->adsr_amp[note] = adsr_env(sc, note);
|
||||
sc->adsr_cnt[note] = 0;
|
||||
}
|
||||
}
|
||||
else if (phase >= -1.0 && phase <= 1.0 && vel < 0) {
|
||||
sc->midimsgs[note] |= 4;
|
||||
// note off
|
||||
if (sc->adsr_cnt[note] <= sc->adsr.off[1] && !sus) {
|
||||
if (sc->adsr_cnt[note] != sc->adsr.off[1]) {
|
||||
// x-fade to release
|
||||
sc->adsr_amp[note] = adsr_env(sc, note);
|
||||
}
|
||||
sc->adsr_cnt[note] = sc->adsr.off[1] + 1;
|
||||
}
|
||||
else if (sus && sc->adsr_cnt[note] == sc->adsr.off[1]) {
|
||||
sc->adsr_cnt[note] = sc->adsr.off[1] + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//printf("FORCE NOTE OFF: %d %d\n", vel, sus);
|
||||
/* note-on + off in same cycle */
|
||||
sc->miditable[note] = 0;
|
||||
sc->adsr_cnt[note] = 0;
|
||||
sc->phase[note] = -10;
|
||||
return;
|
||||
}
|
||||
//printf("NOTE: %d (%d %d %d)\n", sc->adsr_cnt[note], sc->adsr.off[0], sc->adsr.off[1], sc->adsr.off[2]);
|
||||
|
||||
// synthesize actual sound
|
||||
sc->synthesize(sc, note, vol, rs->freqs[note], n_samples, left, right);
|
||||
// synthesize actual sound
|
||||
sc->synthesize(sc, note, vol, rs->freqs[note], n_samples, left, right);
|
||||
|
||||
if (sc->adsr_cnt[note] == 0) {
|
||||
//printf("Note %d,%d released\n", chn, note);
|
||||
sc->midimsgs[note] = 0;
|
||||
sc->miditable[note] = 0;
|
||||
sc->adsr_amp[note] = 0;
|
||||
sc->phase[note] = -10;
|
||||
sc->keycomp--;
|
||||
//printf("[off] Now %d keys active on chn %d\n", sc->keycomp, chn);
|
||||
}
|
||||
if (sc->adsr_cnt[note] == 0) {
|
||||
//printf("Note %d,%d released\n", chn, note);
|
||||
sc->midimsgs[note] = 0;
|
||||
sc->miditable[note] = 0;
|
||||
sc->adsr_amp[note] = 0;
|
||||
sc->phase[note] = -10;
|
||||
sc->keycomp--;
|
||||
//printf("[off] Now %d keys active on chn %d\n", sc->keycomp, chn);
|
||||
}
|
||||
}
|
||||
|
||||
/* synthesize a BUFFER_SIZE_SAMPLES's of audio-data */
|
||||
static void synth_fragment (void *synth, const size_t n_samples, float *left, float *right) {
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
memset (left, 0, n_samples * sizeof(float));
|
||||
memset (right, 0, n_samples * sizeof(float));
|
||||
uint8_t keycomp = 0;
|
||||
int c,k;
|
||||
size_t i;
|
||||
static void
|
||||
synth_fragment (void *synth, const size_t n_samples, float *left, float *right)
|
||||
{
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
memset (left, 0, n_samples * sizeof(float));
|
||||
memset (right, 0, n_samples * sizeof(float));
|
||||
uint8_t keycomp = 0;
|
||||
int c,k;
|
||||
size_t i;
|
||||
|
||||
for (c=0; c < 16; ++c) {
|
||||
for (k=0; k < 128; ++k) {
|
||||
if (rs->sc[c].miditable[k] == 0) continue;
|
||||
process_key(synth, c, k, n_samples, left, right);
|
||||
}
|
||||
keycomp += rs->sc[c].keycomp;
|
||||
}
|
||||
for (c=0; c < 16; ++c) {
|
||||
for (k=0; k < 128; ++k) {
|
||||
if (rs->sc[c].miditable[k] == 0) continue;
|
||||
process_key(synth, c, k, n_samples, left, right);
|
||||
}
|
||||
keycomp += rs->sc[c].keycomp;
|
||||
}
|
||||
|
||||
#if 1 // key-compression
|
||||
float kctgt = 8.0 / (float)(keycomp + 7.0);
|
||||
if (kctgt < .5) kctgt = .5;
|
||||
if (kctgt > 1.0) kctgt = 1.0;
|
||||
const float _w = rs->kcfilt;
|
||||
for (i=0; i < n_samples; ++i) {
|
||||
rs->kcgain += _w * (kctgt - rs->kcgain);
|
||||
left[i] *= rs->kcgain;
|
||||
right[i] *= rs->kcgain;
|
||||
}
|
||||
rs->kcgain += 1e-12;
|
||||
float kctgt = 8.0 / (float)(keycomp + 7.0);
|
||||
if (kctgt < .5) kctgt = .5;
|
||||
if (kctgt > 1.0) kctgt = 1.0;
|
||||
const float _w = rs->kcfilt;
|
||||
for (i=0; i < n_samples; ++i) {
|
||||
rs->kcgain += _w * (kctgt - rs->kcgain);
|
||||
left[i] *= rs->kcgain;
|
||||
right[i] *= rs->kcgain;
|
||||
}
|
||||
rs->kcgain += 1e-12;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void synth_reset_channel(RSSynthChannel* sc) {
|
||||
int k;
|
||||
for (k=0; k < 128; ++k) {
|
||||
sc->adsr_cnt[k] = 0;
|
||||
sc->adsr_amp[k] = 0;
|
||||
sc->phase[k] = -10;
|
||||
sc->miditable[k] = 0;
|
||||
sc->midimsgs[k] = 0;
|
||||
}
|
||||
sc->keycomp = 0;
|
||||
static void
|
||||
synth_reset_channel(RSSynthChannel* sc)
|
||||
{
|
||||
for (int k = 0; k < 128; ++k) {
|
||||
sc->adsr_cnt[k] = 0;
|
||||
sc->adsr_amp[k] = 0;
|
||||
sc->phase[k] = -10;
|
||||
sc->miditable[k] = 0;
|
||||
sc->midimsgs[k] = 0;
|
||||
}
|
||||
sc->keycomp = 0;
|
||||
}
|
||||
|
||||
static void synth_reset(void *synth) {
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
int c;
|
||||
for (c=0; c < 16; ++c) {
|
||||
synth_reset_channel(&(rs->sc[c]));
|
||||
}
|
||||
rs->kcgain = 0;
|
||||
static void
|
||||
synth_reset(void *synth)
|
||||
{
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
int c;
|
||||
for (c=0; c < 16; ++c) {
|
||||
synth_reset_channel(&(rs->sc[c]));
|
||||
}
|
||||
rs->kcgain = 0;
|
||||
}
|
||||
|
||||
static void synth_load(RSSynthChannel *sc, const double rate,
|
||||
SynthFunction synthesize,
|
||||
ADSRcfg const * const adsr) {
|
||||
synth_reset_channel(sc);
|
||||
init_adsr(&sc->adsr, rate,
|
||||
adsr->tme[0], adsr->tme[1], adsr->tme[2],
|
||||
adsr->vol[0], adsr->vol[1]);
|
||||
sc->synthesize = synthesize;
|
||||
static void
|
||||
synth_load (RSSynthChannel *sc, const double rate,
|
||||
SynthFunction synthesize,
|
||||
ADSRcfg const * const adsr)
|
||||
{
|
||||
synth_reset_channel(sc);
|
||||
init_adsr(&sc->adsr, rate,
|
||||
adsr->tme[0], adsr->tme[1], adsr->tme[2],
|
||||
adsr->vol[0], adsr->vol[1]);
|
||||
sc->synthesize = synthesize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* internal abstraction of MIDI data handling
|
||||
*/
|
||||
static void synth_process_midi_event(void *synth, struct rmidi_event_t *ev) {
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
switch(ev->type) {
|
||||
case NOTE_ON:
|
||||
rs->sc[ev->channel].midimsgs[ev->d.tone.note] |= 1;
|
||||
if (rs->sc[ev->channel].miditable[ev->d.tone.note] <= 0)
|
||||
rs->sc[ev->channel].miditable[ev->d.tone.note] = ev->d.tone.velocity;
|
||||
break;
|
||||
case NOTE_OFF:
|
||||
rs->sc[ev->channel].midimsgs[ev->d.tone.note] |= 2;
|
||||
if (rs->sc[ev->channel].miditable[ev->d.tone.note] > 0)
|
||||
rs->sc[ev->channel].miditable[ev->d.tone.note] *= -1.0;
|
||||
break;
|
||||
case PROGRAM_CHANGE:
|
||||
break;
|
||||
case CONTROL_CHANGE:
|
||||
if (ev->d.control.param == 0x00 || ev->d.control.param == 0x20) {
|
||||
/* 0x00 and 0x20 are used for BANK select */
|
||||
} else if (ev->d.control.param == 64) {
|
||||
/* damper pedal*/
|
||||
rs->sc[ev->channel].sustain = ev->d.control.value < 64 ? 0: 1;
|
||||
} else if (ev->d.control.param == 121) {
|
||||
/* reset all controllers */
|
||||
} else if (ev->d.control.param == 120 || ev->d.control.param == 123) {
|
||||
/* Midi panic: 120: all sound off, 123: all notes off*/
|
||||
synth_reset_channel(&(rs->sc[ev->channel]));
|
||||
} else if (ev->d.control.param >= 120) {
|
||||
/* params 122-127 are reserved - skip them. */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
static void
|
||||
synth_process_midi_event(void *synth, struct rmidi_event_t *ev)
|
||||
{
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
switch(ev->type) {
|
||||
case NOTE_ON:
|
||||
rs->sc[ev->channel].midimsgs[ev->d.tone.note] |= 1;
|
||||
if (rs->sc[ev->channel].miditable[ev->d.tone.note] <= 0)
|
||||
rs->sc[ev->channel].miditable[ev->d.tone.note] = ev->d.tone.velocity;
|
||||
break;
|
||||
case NOTE_OFF:
|
||||
rs->sc[ev->channel].midimsgs[ev->d.tone.note] |= 2;
|
||||
if (rs->sc[ev->channel].miditable[ev->d.tone.note] > 0)
|
||||
rs->sc[ev->channel].miditable[ev->d.tone.note] *= -1.0;
|
||||
break;
|
||||
case PROGRAM_CHANGE:
|
||||
break;
|
||||
case CONTROL_CHANGE:
|
||||
if (ev->d.control.param == 0x00 || ev->d.control.param == 0x20) {
|
||||
/* 0x00 and 0x20 are used for BANK select */
|
||||
} else if (ev->d.control.param == 64) {
|
||||
/* damper pedal*/
|
||||
rs->sc[ev->channel].sustain = ev->d.control.value < 64 ? 0: 1;
|
||||
} else if (ev->d.control.param == 121) {
|
||||
/* reset all controllers */
|
||||
} else if (ev->d.control.param == 120 || ev->d.control.param == 123) {
|
||||
/* Midi panic: 120: all sound off, 123: all notes off*/
|
||||
synth_reset_channel(&(rs->sc[ev->channel]));
|
||||
} else if (ev->d.control.param >= 120) {
|
||||
/* params 122-127 are reserved - skip them. */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -406,27 +420,29 @@ static void synth_process_midi_event(void *synth, struct rmidi_event_t *ev) {
|
|||
* @param out pointer to stereo output buffers
|
||||
* @return end of buffer (written + nframes)
|
||||
*/
|
||||
static uint32_t synth_sound (void *synth, uint32_t written, const uint32_t nframes, float **out) {
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
static uint32_t
|
||||
synth_sound (void *synth, uint32_t written, const uint32_t nframes, float **out)
|
||||
{
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
|
||||
while (written < nframes) {
|
||||
uint32_t nremain = nframes - written;
|
||||
while (written < nframes) {
|
||||
uint32_t nremain = nframes - written;
|
||||
|
||||
if (rs->boffset >= BUFFER_SIZE_SAMPLES) {
|
||||
const uint32_t tosynth = MIN(BUFFER_SIZE_SAMPLES, nremain);
|
||||
rs->boffset = BUFFER_SIZE_SAMPLES - tosynth;
|
||||
synth_fragment(rs, tosynth, &(rs->buf[0][rs->boffset]), &(rs->buf[1][rs->boffset]));
|
||||
}
|
||||
if (rs->boffset >= BUFFER_SIZE_SAMPLES) {
|
||||
const uint32_t tosynth = MIN(BUFFER_SIZE_SAMPLES, nremain);
|
||||
rs->boffset = BUFFER_SIZE_SAMPLES - tosynth;
|
||||
synth_fragment(rs, tosynth, &(rs->buf[0][rs->boffset]), &(rs->buf[1][rs->boffset]));
|
||||
}
|
||||
|
||||
uint32_t nread = MIN(nremain, (BUFFER_SIZE_SAMPLES - rs->boffset));
|
||||
uint32_t nread = MIN(nremain, (BUFFER_SIZE_SAMPLES - rs->boffset));
|
||||
|
||||
memcpy(&out[0][written], &rs->buf[0][rs->boffset], nread*sizeof(float));
|
||||
memcpy(&out[1][written], &rs->buf[1][rs->boffset], nread*sizeof(float));
|
||||
memcpy(&out[0][written], &rs->buf[0][rs->boffset], nread*sizeof(float));
|
||||
memcpy(&out[1][written], &rs->buf[1][rs->boffset], nread*sizeof(float));
|
||||
|
||||
written += nread;
|
||||
rs->boffset += nread;
|
||||
}
|
||||
return written;
|
||||
written += nread;
|
||||
rs->boffset += nread;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -436,80 +452,84 @@ static uint32_t synth_sound (void *synth, uint32_t written, const uint32_t nfram
|
|||
* @param data 8bit midi message
|
||||
* @param size number of bytes in the midi-message
|
||||
*/
|
||||
static void synth_parse_midi(void *synth, const uint8_t *data, const size_t size) {
|
||||
if (size < 2 || size > 3) return;
|
||||
// All messages need to be 3 bytes; except program-changes: 2bytes.
|
||||
if (size == 2 && (data[0] & 0xf0) != 0xC0) return;
|
||||
static void
|
||||
synth_parse_midi (void *synth, const uint8_t *data, const size_t size)
|
||||
{
|
||||
if (size < 2 || size > 3) return;
|
||||
// All messages need to be 3 bytes; except program-changes: 2bytes.
|
||||
if (size == 2 && (data[0] & 0xf0) != 0xC0) return;
|
||||
|
||||
struct rmidi_event_t ev;
|
||||
struct rmidi_event_t ev;
|
||||
|
||||
ev.channel = data[0]&0x0f;
|
||||
switch (data[0] & 0xf0) {
|
||||
case 0x80:
|
||||
ev.type=NOTE_OFF;
|
||||
ev.d.tone.note=data[1]&0x7f;
|
||||
ev.d.tone.velocity=data[2]&0x7f;
|
||||
break;
|
||||
case 0x90:
|
||||
ev.type=NOTE_ON;
|
||||
ev.d.tone.note=data[1]&0x7f;
|
||||
ev.d.tone.velocity=data[2]&0x7f;
|
||||
if (ev.d.tone.velocity == 0) {
|
||||
ev.type=NOTE_OFF;
|
||||
}
|
||||
break;
|
||||
case 0xB0:
|
||||
ev.type=CONTROL_CHANGE;
|
||||
ev.d.control.param=data[1]&0x7f;
|
||||
ev.d.control.value=data[2]&0x7f;
|
||||
break;
|
||||
case 0xC0:
|
||||
ev.type=PROGRAM_CHANGE;
|
||||
ev.d.control.value=data[1]&0x7f;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
synth_process_midi_event(synth, &ev);
|
||||
ev.channel = data[0]&0x0f;
|
||||
switch (data[0] & 0xf0) {
|
||||
case 0x80:
|
||||
ev.type=NOTE_OFF;
|
||||
ev.d.tone.note=data[1]&0x7f;
|
||||
ev.d.tone.velocity=data[2]&0x7f;
|
||||
break;
|
||||
case 0x90:
|
||||
ev.type=NOTE_ON;
|
||||
ev.d.tone.note=data[1]&0x7f;
|
||||
ev.d.tone.velocity=data[2]&0x7f;
|
||||
if (ev.d.tone.velocity == 0) {
|
||||
ev.type=NOTE_OFF;
|
||||
}
|
||||
break;
|
||||
case 0xB0:
|
||||
ev.type=CONTROL_CHANGE;
|
||||
ev.d.control.param=data[1]&0x7f;
|
||||
ev.d.control.value=data[2]&0x7f;
|
||||
break;
|
||||
case 0xC0:
|
||||
ev.type=PROGRAM_CHANGE;
|
||||
ev.d.control.value=data[1]&0x7f;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
synth_process_midi_event(synth, &ev);
|
||||
}
|
||||
|
||||
static const uint8_t jingle[] = { 71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,71 ,69 ,69 ,71 ,69 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,74 ,74 ,72 ,69 ,67 ,62 ,62 ,71 ,69 ,67 ,62 ,62 ,62 ,62 ,71 ,69 ,67 ,64 ,64 ,64 ,72 ,71 ,69 ,66 ,74 ,76 ,74 ,72 ,69 ,71 ,62 ,62 ,71 ,69 ,67 ,62 ,62 ,62 ,62 ,71 ,69 ,67 ,64 ,64 ,64 ,72 ,71 ,69 ,74 ,74 ,74 ,74 ,76 ,74 ,72 ,69 ,67 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,71 ,69 ,69 ,71 ,69 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,74 ,74 ,72 ,69 ,67 };
|
||||
|
||||
static void synth_parse_xmas(void *synth, const uint8_t *data, const size_t size) {
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
if (size < 2 || size > 3) return;
|
||||
// All messages need to be 3 bytes; except program-changes: 2bytes.
|
||||
if (size == 2 && (data[0] & 0xf0) != 0xC0) return;
|
||||
static void
|
||||
synth_parse_xmas(void *synth, const uint8_t *data, const size_t size)
|
||||
{
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
if (size < 2 || size > 3) return;
|
||||
// All messages need to be 3 bytes; except program-changes: 2bytes.
|
||||
if (size == 2 && (data[0] & 0xf0) != 0xC0) return;
|
||||
|
||||
struct rmidi_event_t ev;
|
||||
struct rmidi_event_t ev;
|
||||
|
||||
ev.channel = data[0]&0x0f;
|
||||
switch (data[0] & 0xf0) {
|
||||
case 0x80:
|
||||
ev.type=NOTE_OFF;
|
||||
ev.d.tone.note=jingle[rs->xmas_off++];
|
||||
ev.d.tone.velocity=data[2]&0x7f;
|
||||
if (rs->xmas_off >= sizeof(jingle)) rs->xmas_off = 0;
|
||||
break;
|
||||
case 0x90:
|
||||
ev.type=NOTE_ON;
|
||||
ev.d.tone.note=jingle[rs->xmas_on++];
|
||||
ev.d.tone.velocity=data[2]&0x7f;
|
||||
if (rs->xmas_on >= sizeof(jingle)) rs->xmas_on = 0;
|
||||
break;
|
||||
case 0xB0:
|
||||
ev.type=CONTROL_CHANGE;
|
||||
ev.d.control.param=data[1]&0x7f;
|
||||
ev.d.control.value=data[2]&0x7f;
|
||||
break;
|
||||
case 0xC0:
|
||||
ev.type=PROGRAM_CHANGE;
|
||||
ev.d.control.value=data[1]&0x7f;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
synth_process_midi_event(synth, &ev);
|
||||
ev.channel = data[0]&0x0f;
|
||||
switch (data[0] & 0xf0) {
|
||||
case 0x80:
|
||||
ev.type=NOTE_OFF;
|
||||
ev.d.tone.note=jingle[rs->xmas_off++];
|
||||
ev.d.tone.velocity=data[2]&0x7f;
|
||||
if (rs->xmas_off >= sizeof(jingle)) rs->xmas_off = 0;
|
||||
break;
|
||||
case 0x90:
|
||||
ev.type=NOTE_ON;
|
||||
ev.d.tone.note=jingle[rs->xmas_on++];
|
||||
ev.d.tone.velocity=data[2]&0x7f;
|
||||
if (rs->xmas_on >= sizeof(jingle)) rs->xmas_on = 0;
|
||||
break;
|
||||
case 0xB0:
|
||||
ev.type=CONTROL_CHANGE;
|
||||
ev.d.control.param=data[1]&0x7f;
|
||||
ev.d.control.value=data[2]&0x7f;
|
||||
break;
|
||||
case 0xC0:
|
||||
ev.type=PROGRAM_CHANGE;
|
||||
ev.d.control.value=data[1]&0x7f;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
synth_process_midi_event(synth, &ev);
|
||||
}
|
||||
/**
|
||||
* initialize the synth
|
||||
|
@ -519,24 +539,25 @@ static void synth_parse_xmas(void *synth, const uint8_t *data, const size_t size
|
|||
* @param synth synth-handle
|
||||
* @param rate sample-rate
|
||||
*/
|
||||
static void synth_init(void *synth, double rate) {
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
rs->rate = rate;
|
||||
rs->boffset = BUFFER_SIZE_SAMPLES;
|
||||
const float tuning = 440;
|
||||
int c,k;
|
||||
for (k=0; k < 128; k++) {
|
||||
rs->freqs[k] = (tuning / 32.0f) * powf(2, (k - 9.0) / 12.0) / rate;
|
||||
assert(rs->freqs[k] < M_PI/2); // otherwise spatialization may phase out..
|
||||
}
|
||||
rs->kcfilt = 12.0 / rate;
|
||||
synth_reset(synth);
|
||||
static void
|
||||
synth_init(void* synth, double rate) {
|
||||
RSSynthesizer* rs = (RSSynthesizer*)synth;
|
||||
rs->rate = rate;
|
||||
rs->boffset = BUFFER_SIZE_SAMPLES;
|
||||
const float tuning = 440;
|
||||
int c,k;
|
||||
for (k=0; k < 128; k++) {
|
||||
rs->freqs[k] = (tuning / 32.0f) * powf(2, (k - 9.0) / 12.0) / rate;
|
||||
assert(rs->freqs[k] < M_PI/2); // otherwise spatialization may phase out..
|
||||
}
|
||||
rs->kcfilt = 12.0 / rate;
|
||||
synth_reset(synth);
|
||||
|
||||
for (c=0; c < 16; c++) {
|
||||
synth_load(&rs->sc[c], rate, &synthesize_sineP, &piano_adsr);
|
||||
}
|
||||
rs->xmas_on = 0;
|
||||
rs->xmas_off = 0;
|
||||
for (c=0; c < 16; c++) {
|
||||
synth_load(&rs->sc[c], rate, &synthesize_sineP, &piano_adsr);
|
||||
}
|
||||
rs->xmas_on = 0;
|
||||
rs->xmas_off = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -549,15 +570,18 @@ static void synth_init(void *synth, double rate) {
|
|||
*
|
||||
* @return synth-handle
|
||||
*/
|
||||
static void * synth_alloc(void) {
|
||||
return calloc(1, sizeof(RSSynthesizer));
|
||||
static void*
|
||||
synth_alloc(void)
|
||||
{
|
||||
return calloc(1, sizeof(RSSynthesizer));
|
||||
}
|
||||
|
||||
/**
|
||||
* release synth data structure
|
||||
* @param synth synth-handle
|
||||
*/
|
||||
static void synth_free(void *synth) {
|
||||
free(synth);
|
||||
static void
|
||||
synth_free(void *synth)
|
||||
{
|
||||
free(synth);
|
||||
}
|
||||
/* vi:set ts=8 sts=2 sw=2 et: */
|
||||
|
|
Loading…
Reference in New Issue