Rev 2302 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* play.cc
* DIN Is Noise is copyright (c) 2006-2025 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/
#include "audio.h"
#include "play.h"
#include "multi_curve.h"
#include <string.h>
void play::init () {
sol = 0;
x = 0.0f;
dx = 0.0f;
vol = 0.0f;
pdx = pvol = 0;
alloc ();
pdx [0] = 0.0f; pdx [n_1] = 1.0f;
pvol [0] = 0.0f; pvol [n_1] = 1.0f;
}
void play::alloc () {
n = aout.samples_per_channel;
n_1 = n - 1;
da = 1.0f / n_1;
if (pdx) delete [] pdx;
if (pvol) delete [] pvol;
pdx = new float [n];
pvol = new float [n];
int sz = n * sizeof (float);
memset (pdx, 0, sz);
memset (pvol, 0, sz);
}
void play::realloc () {
alloc ();
fill_pitch (dx);
fill_volume (vol);
}
play::play (solver *w) {
init ();
set_wave (w);
}
play::play () {
init ();
}
play::play (const play& p) {
sol = p.sol;
x = p.x;
dx = p.dx;
vol = p.vol;
n = p.n;
n_1 = p.n_1;
da = p.da;
pdx = new float [n];
pvol = new float [n];
for (int i = 0; i < n; ++i) {
pdx [i] = p.pdx [i];
pvol [i] = p.pvol [i];
}
}
play::~play () {
if (pdx) delete[] pdx;
if (pvol) delete[] pvol;
}
void play::fill_pitch (float xd) {
for (int i = 0; i < n; ++i) pdx[i] = xd;
dx = xd;
}
void play::fill_volume (float v) {
for (int i = 0; i < n; ++i) pvol[i] = v;
vol = v;
}
void play::interpolate_buffer (float* buf, float s, float e) {
float a = 0;
float es = e - s;
for (int i = 0; i < n; ++i) {
buf[i] = s + a * es;
a += da;
}
}
void play::set_interpolated_volume (float v) {
interpolate_buffer (pvol, vol, v);
vol = v;
}
void play::set_interpolated_pitch (float xd) {
interpolate_buffer (pdx, dx, xd);
dx = xd;
}
void play::set_interpolated_pitch (float xd, int check) {
if ((pdx[0] == pdx[n_1]) && (pdx[0] == xd)) return; // pitch is same
else
if (xd == dx)
for (int i = 0; i < n; ++i) pdx[i] = dx; // same as last pitch so just fill ie no interpolation needed
else
set_interpolated_pitch (xd);
}
void play::set_interpolated_volume (float v, int check) {
if ((pvol[0]==pvol[n_1]) && (pvol[0]==v)) return; // volume is same
else
if (v == vol)
for (int i = 0; i < n; ++i) pvol[i] = v; // same as last volume so just fill ie no interpolation needed
else
set_interpolated_volume (v);
}
void play::gen_wav_and_mix (float* wav, int n) {
(*sol) (x, pdx, n, wav);
if (mixer.active) {
mixer.gen_mix (aout.mix, n);
mixer.do_mix (wav, aout.mix, aout.mixa, n);
}
}
void play::master (float* L, float* R, float* wav, int n, float* vola) { // master with volume array
gen_wav_and_mix (wav, n); // mix waveforms
operator() (L, n, wav, vola); // multiply volumes
memcpy (R, L, aout.samples_channel_size); // copy to R
}
void play::master (float* L, float* R, float* wav, int n, float vol) { // master with volume
gen_wav_and_mix (wav, n); // mix waveforms
operator() (L, n, wav, vol); // apply volume
memcpy (R, L, aout.samples_channel_size); // copy to R
}
void play::master (float* L, float* wav, int n, float vol) { // master with volume
gen_wav_and_mix (wav, n); // mix waveforms
operator() (L, n, wav, vol); // apply volume
}
void play::master (float* L, float* wav, int n, float* vola) { // master with volume array
gen_wav_and_mix (wav, n); // mix waveforms
operator() (L, n, wav, vola); // apply volume
}
void play::gen_wav_fm (solver& _sol, float& _x, float* wav, float* fm, int n) {
// generate waveform samples with FM
_sol (_x, pdx, n, fm, wav);
}
void play::gen_wav_am (float* out, float* wav, float* am, int n) { // apply AM to waveform samples
for (int i = 0; i < n; ++i) out[i] = ((pvol[i] + am[i]) * wav[i]);
}
void play::gen_wav_fm_am_mix (float* out, int n) { // generate waveform samples, apply AM and FM and mix (if present)
gen_wav_fm (*sol, x, aout.result, aout.fms, n);
gen_wav_am (out, aout.result, aout.ams, n);
if (mixer.active) {
mixer.gen_fm (aout.result, n, aout.fms);
gen_wav_am (aout.mix, aout.result, aout.ams, n);
mixer.do_mix (out, aout.mix, aout.mixa, n);
}
}
void play::gen_wav_mix (float* out, float* vola, int n) {
gen_wav_and_mix (aout.result, n);
operator() (out, n, aout.result, vola);
}
void play::gen_wav_mix (float* out, float vol, int n) {
gen_wav_and_mix (aout.result, n);
operator() (out, n, aout.result, vol);
}
void play::set_mix (multi_curve& crv, const std::string& nam) {
mixer.setup (crv, x, dx);
mixer.name = nam;
}