Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
217 lines (183 sloc) 5.46 KB
#include <math.h>
#include <stdlib.h>
#include "SDTCommon.h"
#include "SDTFilters.h"
#include "SDTLiquids.h"
#include "SDTStructs.h"
#define MIN_RADIUS 0.00015
#define MAX_RADIUS 0.150
#define MAX_EXP 10.0
#define MAX_RISE 3.0
#define MAX_RATE 100000.0
struct SDTBubble {
double radius, depth, riseFactor,
amp, decay, gain, phaseStep, phaseRise,
phase, out, lastOut;
};
SDTBubble *SDTBubble_new() {
SDTBubble *x;
x = (SDTBubble *)malloc(sizeof(SDTBubble));
x->radius = 1.0;
x->depth = 0.0;
x->riseFactor = 0.0;
x->amp = 0.0;
x->decay = 0.0;
x->gain = 0.0;
x->phaseStep = 0.0;
x->phaseRise = 0.0;
x->phase = 0.0;
x->out = 0.0;
x->lastOut = 0.0;
return x;
}
void SDTBubble_free(SDTBubble *x) {
free(x);
}
SDT_TYPE_COPY(SDT_BUBBLE)
SDT_DEFINE_HASHMAP(SDT_BUBBLE, 59)
SDT_TYPE_MAKE_GETTERS(SDT_BUBBLE)
SDT_JSON_SERIALIZE(SDT_BUBBLE)
SDT_JSON_DESERIALIZE(SDT_BUBBLE)
void SDTBubble_setRadius(SDTBubble *x, double f) {
x->radius = SDT_fclip(f, MIN_RADIUS, MAX_RADIUS);
}
void SDTBubble_setDepth(SDTBubble *x, double f) {
x->depth = SDT_fclip(f, 0.0, 1.0);
}
void SDTBubble_setRiseFactor(SDTBubble *x, double f) {
x->riseFactor = SDT_fclip(f, 0.0, MAX_RISE);
}
void SDTBubble_update(SDTBubble *x) {
double pRadius;
x->lastOut = x->out;
pRadius = x->radius * sqrt(x->radius);
x->amp = 17.2133 * pRadius * x->depth;
x->decay = 0.13 / x->radius + 0.0072 / pRadius;
x->gain = exp(-x->decay * SDT_timeStep);
x->phaseStep = 3.0 / x->radius * SDT_timeStep;
x->phaseRise = x->phaseStep * x->decay * x->riseFactor * SDT_timeStep;
x->phase = 0.0;
}
void SDTBubble_normAmp(SDTBubble *x) {
x->amp = 1.0;
}
double SDTBubble_dsp(SDTBubble *x) {
double alpha;
if (x->amp < SDT_QUIET && x->phase > 1.0) return 0.0;
alpha = x->phase < 1.0 ? x->phase : 1.0;
x->out = (1.0 - alpha) * x->lastOut + alpha * x->amp * sin(SDT_TWOPI * x->phase);
x->phase += x->phaseStep;
x->phaseStep += x->phaseRise;
x->amp *= x->gain;
return x->out;
}
//-------------------------------------------------------------------------------------//
struct SDTFluidFlow {
SDTBubble **bubbles;
double minRadius, maxRadius, expRadius,
minDepth, maxDepth, expDepth,
riseFactor, riseCutoff, avgRate,
success, gain;
int nBubbles;
};
SDTFluidFlow *SDTFluidFlow_new(int nBubbles) {
SDTFluidFlow *x;
int i;
x = (SDTFluidFlow *)malloc(sizeof(SDTFluidFlow));
x->bubbles = (SDTBubble **)malloc(nBubbles * sizeof(SDTBubble *));
for (i = 0; i < nBubbles; i++) {
x->bubbles[i] = SDTBubble_new();
}
x->minRadius = 0.00015;
x->maxRadius = 0.015;
x->expRadius = 1.0;
x->minDepth = 0.0;
x->maxDepth = 1.0;
x->expDepth = 1.0;
x->riseFactor = 0.1;
x->riseCutoff = 0.9;
x->avgRate = 0.0;
x->success = 0.0;
x->gain = 1.0;
x->nBubbles = nBubbles;
return x;
}
void SDTFluidFlow_free(SDTFluidFlow *x) {
int i;
for (i = 0; i < x->nBubbles; i++) {
SDTBubble_free(x->bubbles[i]);
}
free(x->bubbles);
free(x);
}
void SDTFluidFlow_setNBubbles(SDTFluidFlow *x, int f) {
for (unsigned int i = 0; i < x->nBubbles; i++)
SDTBubble_free(x->bubbles[i]);
free(x->bubbles);
x->nBubbles = f;
x->bubbles = (SDTBubble **) malloc(x->nBubbles * sizeof(SDTBubble *));
for (unsigned int i = 0; i < x->nBubbles; i++)
x->bubbles[i] = SDTBubble_new();
}
SDT_TYPE_COPY(SDT_FLUIDFLOW)
SDT_DEFINE_HASHMAP(SDT_FLUIDFLOW, 59)
SDT_TYPE_MAKE_GETTERS(SDT_FLUIDFLOW)
SDT_JSON_SERIALIZE(SDT_FLUIDFLOW)
SDT_JSON_DESERIALIZE(SDT_FLUIDFLOW)
void SDTFluidFlow_setMinRadius(SDTFluidFlow *x, double f) {
x->minRadius = SDT_fclip(f, MIN_RADIUS, x->maxRadius);
}
void SDTFluidFlow_setMaxRadius(SDTFluidFlow *x, double f) {
x->maxRadius = SDT_fclip(f, x->minRadius, MAX_RADIUS);
x->gain = MAX_RADIUS / x->maxRadius;
}
void SDTFluidFlow_setExpRadius(SDTFluidFlow *x, double f) {
x->expRadius = SDT_fclip(f, 0.0, MAX_EXP);
}
void SDTFluidFlow_setMinDepth(SDTFluidFlow *x, double f) {
x->minDepth = SDT_fclip(f, 0.0, x->maxDepth);
}
void SDTFluidFlow_setMaxDepth(SDTFluidFlow *x, double f) {
x->maxDepth = SDT_fclip(f, x->minDepth, 1.0);
}
void SDTFluidFlow_setExpDepth(SDTFluidFlow *x, double f) {
x->expDepth = SDT_fclip(f, 0.0, MAX_EXP);
}
void SDTFluidFlow_setRiseFactor(SDTFluidFlow *x, double f) {
x->riseFactor = SDT_fclip(f, 0.0, MAX_RISE);
}
void SDTFluidFlow_setRiseCutoff(SDTFluidFlow *x, double f) {
x->riseCutoff = SDT_fclip(f, 0.0, 1.0);
}
void SDTFluidFlow_setAvgRate(SDTFluidFlow *x, double f) {
x->avgRate = SDT_fclip(f, 0.0, MAX_RATE);
x->success = x->avgRate * SDT_timeStep;
}
double SDTFluidFlow_dsp(SDTFluidFlow *x) {
SDTBubble *bubble;
double minAmp, radius, depth, riseFactor, result;
int i;
if (SDT_frand() < x->success) {
minAmp = x->bubbles[0]->amp;
bubble = x->bubbles[0];
for (i = 1; i < x->nBubbles; i++) {
if (x->bubbles[i]->amp < minAmp) {
minAmp = x->bubbles[i]->amp;
bubble = x->bubbles[i];
}
}
radius = SDT_scale(rand(), 0.0, RAND_MAX, x->minRadius, x->maxRadius, x->expRadius);
depth = SDT_scale(rand(), 0.0, RAND_MAX, x->minDepth, x->maxDepth, x->expDepth);
riseFactor = depth > x->riseCutoff ? x->riseFactor : 0.0;
SDTBubble_setRadius(bubble, radius);
SDTBubble_setDepth(bubble, depth);
SDTBubble_setRiseFactor(bubble, riseFactor);
SDTBubble_update(bubble);
}
result = 0.0;
for (i = 0; i < x->nBubbles; i++) {
result += SDTBubble_dsp(x->bubbles[i]);
}
result *= x->gain;
return result;
}