This repository has been archived on 2017-07-22. You can view files and clone it, but cannot push or open issues/pull-requests.
jlsampler/fsample.c

209 lines
5.2 KiB
C
Raw Permalink Normal View History

#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
#include <string.h>
#include "jl_mem.h"
#include "soundfile.h"
#include "sample.h"
#include "fx.h"
static bool starts_with(char *s, char *prefix)
{
int n = strlen(prefix);
if(n > strlen(s)) {
return false;
}
for(int i = 0; i < n; ++i) {
if(s[i] != prefix[i]) {
return false;
}
}
return true;
}
static void fsample_apply_effect(FSample *s, char *txt)
{
// Attempt to parse each effect until one works.
if(starts_with(txt, "amp(")) {
double gain;
if(sscanf(txt, "amp(%lf)", &gain) != 1) {
goto apply_fx_err;
}
fx_amp(s, gain);
}
else if(starts_with(txt, "balance(")) {
double balance;
if(sscanf(txt, "balance(%lf)", &balance) != 1) {
goto apply_fx_err;
}
fx_balance(s, balance);
}
else if(starts_with(txt, "divide_rms(")) {
double t_ms;
if(sscanf(txt, "divide_rms(%lf)", &t_ms) != 1) {
goto apply_fx_err;
}
fx_divide_rms(s, t_ms);
}
else if(starts_with(txt, "fade_in(")) {
double t_ms;
if(sscanf(txt, "fade_in(%lf)", &t_ms) != 1) {
goto apply_fx_err;
}
fx_fade_in(s, t_ms);
}
else if(starts_with(txt, "ir(")) {
char path[MAX_FX_LINE];
double mix;
if(sscanf(txt, "ir(%[^,], %lf)", path, &mix) != 2) {
goto apply_fx_err;
}
fx_ir(s, path, mix);
}
else if(starts_with(txt, "mono()")) {
fx_mono(s);
}
else if(starts_with(txt, "pan(")) {
double pan;
if(sscanf(txt, "pan(%lf)", &pan) != 1) {
goto apply_fx_err;
}
fx_pan(s, pan);
}
else if(starts_with(txt, "pre_cut(")) {
double pct, fade_ms;
if(sscanf(txt, "pre_cut(%lf, %lf)", &pct, &fade_ms) != 2) {
goto apply_fx_err;
}
fx_pre_cut(s, pct, fade_ms);
}
else if(starts_with(txt, "playback_speed(")) {
double speed;
if(sscanf(txt, "playback_speed(%lf)", &speed) != 1) {
goto apply_fx_err;
}
fx_playback_speed(s, speed);
}
else if(starts_with(txt, "pre_delay(")) {
double left_ms, right_ms;
if(sscanf(txt, "pre_delay(%lf, %lf)", &left_ms, &right_ms) != 2) {
goto apply_fx_err;
}
fx_pre_delay(s, left_ms, right_ms);
}
else if(starts_with(txt, "rc_highpass(")) {
double freq;
int order;
if(sscanf(txt, "rc_highpass(%lf, %d)", &freq, &order) != 2) {
goto apply_fx_err;
}
fx_rc_highpass(s, freq, order);
}
else if(starts_with(txt, "rc_lowpass(")) {
double freq;
int order;
if(sscanf(txt, "rc_lowpass(%lf, %d)", &freq, &order) != 2) {
goto apply_fx_err;
}
fx_rc_lowpass(s, freq, order);
}
else if(starts_with(txt, "rc_highshelf(")) {
double freq, gain;
int order;
if(sscanf(txt, "rc_highshelf(%lf, %d, %lf)", &freq, &order, &gain) != 3) {
goto apply_fx_err;
}
fx_rc_highshelf(s, freq, order, gain);
}
else if(starts_with(txt, "rc_lowshelf(")) {
double freq, gain;
int order;
if(sscanf(txt, "rc_lowshelf(%lf, %d, %lf)", &freq, &order, &gain) != 3) {
goto apply_fx_err;
}
fx_rc_lowshelf(s, freq, order, gain);
}
else if(starts_with(txt, "stereo_width(")) {
double width;
if(sscanf(txt, "stereo_width(%lf)", &width) != 1) {
goto apply_fx_err;
}
fx_stereo_width(s, width);
}
else {
printf("Unknown effect: %s\n", txt);
}
return;
apply_fx_err:
printf("Parsing error: %s\n", txt);
exit(1);
}
void fsample_load(FSample *s, char *path, SoundConfig *conf, int buf_size)
{
s->len = soundfile_load_stereo(path, &s->L, &s->R);
// Apply global pre effects.
for(int i = 0; conf->global_fx_pre[i][0] != '\0'; ++i) {
fsample_apply_effect(s, conf->global_fx_pre[i]);
}
// Apply pre effects.
for(int i = 0; conf->fx_pre[i][0] != '\0'; ++i) {
fsample_apply_effect(s, conf->fx_pre[i]);
}
// Apply post effets.
for(int i = 0; conf->fx_post[i][0] != '\0'; ++i) {
fsample_apply_effect(s, conf->fx_post[i]);
}
// Apply global post effects.
for(int i = 0; conf->global_fx_post[i][0] != '\0'; ++i) {
fsample_apply_effect(s, conf->global_fx_post[i]);
}
}
void fsample_set_data(FSample *s, float *L, float *R, int len)
{
jl_free(s->L);
jl_free(s->R);
s->L = L;
s->R = R;
s->len = len;
}
double fsample_max_amp(FSample *s)
{
double max = 0;
for(int i = 0; i < s->len; i++) {
if(max < s->L[i]) {
max = s->L[i];
} else if(max < -s->L[i]) {
max = -s->L[i];
}
if(max < s->R[i]) {
max = s->R[i];
} else if(max < -s->R[i]) {
max = -s->R[i];
}
}
return max;
}
void fsample_free(FSample *s)
{
jl_free(s->L);
jl_free(s->R);
s->R = s->L = NULL;
s->len = 0;
}