// Copyright 2014 Olivier Gillet.
//
// Author: Olivier Gillet (ol.gillet@gmail.com)
//
// 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
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program 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 General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
#include
#include
#include
#include
#include
#include "elements/dsp/exciter.h"
#include "elements/dsp/part.h"
#include "elements/dsp/resonator.h"
#include "elements/dsp/voice.h"
using namespace elements;
using namespace stmlib;
const uint32_t kSampleRate = 32000;
const uint16_t kAudioBlockSize = 32;
void write_wav_header(FILE* fp, int num_samples, int num_channels) {
uint32_t l;
uint16_t s;
fwrite("RIFF", 4, 1, fp);
l = 36 + num_samples * 2 * num_channels;
fwrite(&l, 4, 1, fp);
fwrite("WAVE", 4, 1, fp);
fwrite("fmt ", 4, 1, fp);
l = 16;
fwrite(&l, 4, 1, fp);
s = 1;
fwrite(&s, 2, 1, fp);
s = num_channels;
fwrite(&s, 2, 1, fp);
l = ::kSampleRate;
fwrite(&l, 4, 1, fp);
l = static_cast(::kSampleRate) * 2 * num_channels;
fwrite(&l, 4, 1, fp);
s = 2 * num_channels;
fwrite(&s, 2, 1, fp);
s = 16;
fwrite(&s, 2, 1, fp);
fwrite("data", 4, 1, fp);
l = num_samples * 2 * num_channels;
fwrite(&l, 4, 1, fp);
}
void TestResonator() {
FILE* fp = fopen("elements_resonator.wav", "wb");
write_wav_header(fp, ::kSampleRate * 40, 1);
Resonator resonator;
resonator.Init();
resonator.set_frequency(110.0f / ::kSampleRate);
resonator.set_geometry(0.2f);
resonator.set_brightness(0.4f);
resonator.set_damping(0.4f);
resonator.set_position(0.5f);
// resonator.set_resolution(1);
float impulse = 1.0f;
float noise_level = 0.0f;
for (uint32_t i = 0; i < ::kSampleRate * 40; ++i) {
uint16_t tri = (i / 2);
tri = tri > 32767 ? 65535 - tri : tri;
uint16_t tri2 = (i / 25);
tri2 = tri2 > 32767 ? 65535 - tri2 : tri2;
resonator.set_position(tri / 32768.0f);
if (i % (::kSampleRate / 8) == 0 && (rand() % 8 > 2)) {
float frequencies[5] = { 110.0f, 220.0f * powf(2, 3/12.0f), 220.0f, 880.0f, 55.0f };
resonator.set_frequency(frequencies[rand() % 5] / ::kSampleRate);
resonator.set_geometry((rand() % 32768) / 32768.0f);
resonator.set_brightness((rand() % 32768) / 32768.0f);
resonator.set_damping((rand() % 32768) / 32768.0f);
noise_level = (rand() % 4) == 1 ? 1.0f : 0.0f;
if (noise_level) {
resonator.set_damping(0.7f);
resonator.set_brightness((rand() % 32768) / 65535.0f);
} else{
impulse = 1.0f;
}
}
impulse = impulse * 0.99f;
float bow_strength = 0.0f;
float output;
float aux;
float input = impulse;
input += ((rand() % 32768) - 16384) / 65535.0f * noise_level;
resonator.Process(&bow_strength, &input, &output, &aux, 1);
output = output * 32768.0f;
if (output > 32767) output = 32767;
if (output < -32767) output = -32767;
short output_sample = output;
fwrite(&output_sample, sizeof(int16_t), 1, fp);
}
fclose(fp);
}
void TestExciter() {
FILE* fp = fopen("elements_exciter.wav", "wb");
write_wav_header(fp, ::kSampleRate * 10, 4);
float diffuser_buffer[1024];
Exciter exciter;
exciter.Init();
exciter.set_model(EXCITER_MODEL_PLECTRUM);
exciter.set_parameter(0.7f);
exciter.set_timbre(0.5f);
exciter.set_signature(0.1f);
Resonator resonator;
resonator.Init();
resonator.set_frequency(262.0f / ::kSampleRate / 2);
resonator.set_geometry(0.3f);
resonator.set_brightness(0.8f);
resonator.set_damping(0.3f);
resonator.set_position(0.1f);
resonator.set_resolution(48);
bool previous_gate = false;
for (uint32_t i = 0; i < ::kSampleRate * 10; ++i) {
uint16_t tri = (i / 8);
tri = tri > 32767 ? 65535 - tri : tri;
uint16_t tri2 = (i * 1.5);
tri2 = tri2 > 32767 ? 65535 - tri2 : tri2;
bool gate = (i % (::kSampleRate / 2)) < (::kSampleRate / 4);
uint8_t flags = 0;
if (gate) flags |= EXCITER_FLAG_GATE;
if (gate && !previous_gate) flags |= EXCITER_FLAG_RISING_EDGE;
if (!gate && previous_gate) flags |= EXCITER_FLAG_FALLING_EDGE;
previous_gate = gate;
exciter.set_parameter(tri / 32768.0f);
// exciter.set_timbre(tri / 32768.0f);
float bow_strength = 0.0f;
float output[4];
short output_sample[4];
exciter.Process(flags, &output[0], 1);
// output[0] *= 0.15;
output[1] = exciter.damping();
resonator.Process(&bow_strength, &output[0], &output[2], &output[3], 1);
for (int j = 0; j < 4; ++j) {
output[j] *= 32767.0f;
if (output[j] > 32767) output[j] = 32767;
if (output[j] < -32767) output[j] = -32767;
output_sample[j] = output[j];
}
fwrite(output_sample, sizeof(int16_t), 4, fp);
}
fclose(fp);
}
void TestVoice() {
FILE* fp = fopen("elements_voice.wav", "wb");
write_wav_header(fp, ::kSampleRate * 20, 4);
Voice voice;
Patch p;
p.exciter_envelope_shape = 0.95f;
p.exciter_bow_level = 0.5f;
p.exciter_bow_timbre = 0.6f;
p.exciter_blow_level = 0.0f;
p.exciter_blow_meta = 0.5f;
p.exciter_blow_timbre = 0.2f;
p.exciter_strike_level = 0.0f;
p.exciter_strike_meta = 0.5f;
p.exciter_strike_timbre = 0.5f;
p.resonator_geometry = 0.2f;
p.resonator_brightness = 0.9f;
p.resonator_damping = 0.3f;
p.resonator_position = 0.3f;
voice.Init();
for (uint32_t i = 0; i < ::kSampleRate * 20; ++i) {
uint16_t tri = (i / 8);
tri = tri > 32767 ? 65535 - tri : tri;
p.resonator_damping = tri / 32768.0;
bool gate = (i % (::kSampleRate * 4)) < (::kSampleRate * 2);
float blow_in = 0.0f;
float strike_in = 0.0f;
float raw_out = 0.0f;
float center = 0.0f;
float sides = 0.0f;
voice.Process(
p,
262.0f / ::kSampleRate / 2.0f,
1.0f,
gate,
&blow_in,
&strike_in,
&raw_out,
¢er,
&sides, 1);
float output[4];
short output_sample[4];
output[0] = center + (sides) * 0.5f;
output[1] = center - (sides) * 0.5f;
output[2] = center;
output[3] = raw_out;
for (int j = 0; j < 4; ++j) {
output[j] *= 32767.0f * (j != 3 ? 0.5f : 1.0f);
if (output[j] > 32767) output[j] = 32767;
if (output[j] < -32767) output[j] = -32767;
output_sample[j] = output[j];
}
fwrite(output_sample, sizeof(int16_t), 4, fp);
}
fclose(fp);
}
void TestPart() {
FILE* fp = fopen("elements_part.wav", "wb");
write_wav_header(fp, ::kSampleRate * 20, 2);
uint16_t reverb_buffer[32768];
Part part;
part.Init(reverb_buffer);
Patch* p = part.mutable_patch();
p->exciter_envelope_shape = 0.0f;
p->exciter_bow_level = 0.0f;
p->exciter_bow_timbre = 0.0f;
p->exciter_blow_level = 0.0f;
p->exciter_blow_meta = 0.0f;
p->exciter_blow_timbre = 0.0f;
p->exciter_strike_level = 0.5f;
p->exciter_strike_meta = 0.5f;
p->exciter_strike_timbre = 0.3f;
p->resonator_geometry = 0.4f;
p->resonator_brightness = 0.7f;
p->resonator_damping = 0.8f;
p->resonator_position = 0.3f;
p->space = 0.1f;
// p->exciter_envelope_shape = 0.99f;
// p->exciter_bow_level = 0.0f;
// p->exciter_bow_timbre = 0.6f;
// p->exciter_blow_level = 0.0f;
// p->exciter_blow_meta = 0.0f;
// p->exciter_blow_timbre = 0.0f;
// p->exciter_strike_level = 0.6f;
// p->exciter_strike_meta = 0.5f;
// p->exciter_strike_timbre = 0.5f;
// p->resonator_geometry = 0.85f;
// p->resonator_brightness = 1.0f;
// p->resonator_damping = 0.6f;
// p->resonator_position = 0.3f;
// p->space = 0.1f;
// p->exciter_envelope_shape = 0.0f;
// p->exciter_bow_level = 0.0f;
// p->exciter_bow_timbre = 0.5f;
// p->exciter_blow_level = 0.0f;
// p->exciter_blow_meta = 0.0f;
// p->exciter_blow_timbre = 0.5f;
// p->exciter_strike_level = 1.0f;
// p->exciter_strike_meta = 0.2f;
// p->exciter_strike_timbre = 0.6f;
// p->resonator_geometry = 0.25f;
// p->resonator_brightness = 0.3f;
// p->resonator_damping = 0.5f;
// p->resonator_position = 0.4f;
// p->space = 1.0;
// p->exciter_envelope_shape = 0.99f;
// p->exciter_bow_level = 0.6f;
// p->exciter_bow_timbre = 0.6f;
// p->exciter_blow_level = 0.0f;
// p->exciter_blow_meta = 0.0f;
// p->exciter_blow_timbre = 0.0f;
// p->exciter_strike_level = 0.0f;
// p->exciter_strike_meta = 0.0f;
// p->exciter_strike_timbre = 0.0f;
// p->resonator_geometry = 0.25f;
// p->resonator_brightness = 0.8f;
// p->resonator_damping = 0.3f;
// p->resonator_position = 0.3f;
// p->space = 0.9f;
float sequence[] = { 69.0f, 57.0f, 45.0f, 57.0f, 69.0f };
// float sequence[] = { 19, 19, 19, 19, 19 };
int sequence_counter = -1;
float silence[16];
std::fill(&silence[0], &silence[16], 0.0f);
for (uint32_t i = 0; i < ::kSampleRate * 20; i += 16) {
uint16_t tri = (i * 1);
tri = tri > 32767 ? 65535 - tri : tri;
uint16_t tri2 = (i / 6);
tri2 = tri2 > 32767 ? 65535 - tri2 : tri2;
float main[16];
float aux[16];
// p->resonator_position = int(256.0f * tri / 32768.0f) / 256.0f;
// p->resonator_geometry = 0.5f + 0.5f * tri / 32768.0f;
//p->exciter_strike_meta = 0.0f + 1.0f * tri / 32768.0f;
if (i % (::kSampleRate * 2) == 0) {
sequence_counter = (sequence_counter + 1) % 5;
}
PerformanceState performance;
performance.note = sequence[sequence_counter] - 12.0f;
performance.modulation = 0.0f; /*i & 16 ? 60.0f : -60.0f;
if (i > ::kSampleRate * 5) {
performance.modulation = 0;
}*/
performance.strength = 0.5f;
performance.gate = (i % (::kSampleRate / 1)) < (::kSampleRate / 2);
part.Process(performance, silence, silence, main, aux, 16);
for (size_t j = 0; j < 16; ++j) {
float output[2];
short output_sample[2];
output[0] = main[j];
output[1] = aux[j];
for (int k = 0; k < 2; ++k) {
output[k] *= 32767.0f;
if (output[k] > 32767) output[k] = 32767;
if (output[k] < -32767) output[k] = -32767;
output_sample[k] = output[k];
}
fwrite(output_sample, sizeof(int16_t), 2, fp);
}
}
fclose(fp);
}
void TestEasterEgg() {
FILE* fp = fopen("elements_easter_egg.wav", "wb");
write_wav_header(fp, ::kSampleRate * 20, 2);
uint16_t reverb_buffer[32768];
Part part;
part.Init(reverb_buffer);
Patch* p = part.mutable_patch();
part.set_easter_egg(true);
// p->exciter_envelope_shape = 1.0f;
// p->exciter_bow_level = 0.0f;
// p->exciter_bow_timbre = 1.0f;
// p->exciter_blow_level = 0.0f;
// p->exciter_blow_meta = 0.27f;
// p->exciter_blow_timbre = 0.3f;
// p->exciter_strike_level = 1.0f;
// p->exciter_strike_meta = 0.5f;
// p->exciter_strike_timbre = 0.8f;
// p->resonator_geometry = 0.3f;
// p->resonator_brightness = 0.2f;
// p->resonator_damping = 0.9f;
// p->resonator_position = 0.0f;
// p->space = 0.5f;
p->exciter_envelope_shape = 0.2f;
p->exciter_bow_level = 0.52f;
p->exciter_bow_timbre = 0.8f;
p->exciter_blow_level = 0.5f;
p->exciter_blow_meta = 0.5f;
p->exciter_blow_timbre = 0.0f;
p->exciter_strike_level = 0.0f;
p->exciter_strike_meta = 0.83f;
p->exciter_strike_timbre = 0.5f;
p->resonator_geometry = 0.0f;
p->resonator_brightness = 1.0f;
p->resonator_damping = 0.0f;
p->resonator_position = 0.0f;
p->space = 0.2f;
float sequence[] = { 69.0f, 57.0f, 45.0f, 57.0f, 55.0f };
int sequence_counter = -1;
float silence[16];
std::fill(&silence[0], &silence[16], 0.0f);
for (uint32_t i = 0; i < ::kSampleRate * 20; i += 16) {
uint16_t tri = (i / 2);
tri = tri > 32767 ? 65535 - tri : tri;
uint16_t tri2 = (i * 3);
tri2 = tri2 > 32767 ? 65535 - tri2 : tri2;
float main[16];
float aux[16];
// p->exciter_blow_meta = 0.5f + 0.5f * (tri / 32768.0f);
// p->resonator_brightness = 0.0f + 1.0f * tri2 / 32768.0f;
// p->resonator_position = 0.0f + 0.3f * tri / 32768.0f;
// p->resonator_brightness = 0.0f + 1.0f * tri2 / 32768.0f;
if (i % (::kSampleRate / 2) == 0) {
sequence_counter = (sequence_counter + 1) % 5;
}
PerformanceState performance;
//performance.note = sequence[sequence_counter] - 12;
performance.note = 96.0f + (tri / 32768.0f) * 48.0;
performance.modulation = 0.0f;
performance.strength = 1.0f;
performance.gate = true; // (i % (::kSampleRate / 2)) < (::kSampleRate / 4);
part.Process(performance, silence, silence, main, aux, 16);
for (size_t j = 0; j < 16; ++j) {
float output[2];
short output_sample[2];
output[0] = main[j];
output[1] = aux[j];
for (int k = 0; k < 2; ++k) {
output[k] *= 32767.0f;
if (output[k] > 32767) output[k] = 32767;
if (output[k] < -32767) output[k] = -32767;
output_sample[k] = output[k];
}
fwrite(output_sample, sizeof(int16_t), 2, fp);
}
}
fclose(fp);
}
void TestFilterAccuracy() {
Svf f;
for (int i = 0; i < 128; ++i) {
float midi_note = i / 1.0f;
float frequency = 440.0f * powf(2.0f, (midi_note - 69.0f) / 12.0f);
frequency /= ::kSampleRate;
float g[4];
f.set_f_q(frequency, 0.5f);
g[0] = f.g();
f.set_f_q(frequency, 0.5f);
g[1] = f.g();
f.set_f_q(frequency, 0.5f);
g[2] = f.g();
f.set_f_q(frequency, 0.5f);
g[3] = f.g();
printf("Frequency: %f", frequency * ::kSampleRate);
for (int j = 0; j < 4; ++j) {
float error_cts = logf(atanf(g[j]) / M_PI / frequency) / logf(2) * 1200;
printf("\t%.2f", error_cts);
}
printf("\n");
}
}
int main(void) {
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
// TestFilterAccuracy();
TestPart();
// TestExciter();
// TestResonator();
// TestEasterEgg();
}