bc0cb70b13
Developer: Roman Shuvalov git-svn-id: svn://kolibrios.org@5235 a494cfbc-eb01-0410-851d-a64ba20cac60
462 lines
14 KiB
C
462 lines
14 KiB
C
#include "rssoundgen.h"
|
|
|
|
#include "rsnoise.h"
|
|
|
|
#include "rs/rsmx.h"
|
|
|
|
|
|
#ifdef RS_KOS
|
|
#include "rs/rsplatform.h"
|
|
#else
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#endif
|
|
|
|
rs_sgen_reg_t rs_sgen_reg;
|
|
|
|
void rs_sgen_init(int waves_count, int wave_length) {
|
|
rs_sgen_reg.waves_count = waves_count;
|
|
rs_sgen_reg.wave_length = wave_length;
|
|
rs_sgen_reg.wave = malloc(waves_count * wave_length * 4); // float
|
|
rs_sgen_reg.wave_out = malloc(wave_length * 2); // signed short
|
|
|
|
memset(rs_sgen_reg.wave, 0, waves_count * wave_length * 4);
|
|
memset(rs_sgen_reg.wave_out, 0, wave_length * 2);
|
|
};
|
|
|
|
void rs_sgen_term() {
|
|
free(rs_sgen_reg.wave);
|
|
free(rs_sgen_reg.wave_out);
|
|
};
|
|
|
|
int wave_shot_index = 0;
|
|
|
|
void rs_sgen_wave_out(int index) {
|
|
int i;
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
rs_sgen_reg.wave_out[i] = 32767* (rs_clamp (rs_sgen_reg.wave[index*rs_sgen_reg.wave_length + i], -1.0, 1.0 ));
|
|
};
|
|
|
|
|
|
// char cmd[330];
|
|
// memset(cmd, 0, 330);
|
|
// sprintf(cmd, "/home/romik/temp/images/sound%d.data", wave_shot_index);
|
|
//
|
|
// RS_IO_FILE* fp = rs_io_fopen( cmd, "wb");
|
|
//
|
|
// rs_io_fwrite(fp, rs_sgen_reg.wave_out, rs_sgen_reg.wave_length*2);
|
|
// rs_io_fclose(fp);
|
|
//
|
|
// wave_shot_index++;
|
|
|
|
|
|
|
|
};
|
|
|
|
// --------------------
|
|
|
|
|
|
//float rs_sgen_osc_sin(int i, float freq, float p) {
|
|
// //
|
|
//};
|
|
|
|
|
|
|
|
|
|
float phaser_alps_a1[6];
|
|
float phaser_alps_zm1[6];
|
|
|
|
float phaser_dmin, phaser_dmax; //range
|
|
float phaser_fb; //feedback
|
|
float phaser_lfoPhase;
|
|
float phaser_lfoInc;
|
|
float phaser_depth;
|
|
float phaser_sample_rate;
|
|
int phaser_value_index = -1;
|
|
|
|
float phaser_zm1;
|
|
|
|
void phaser_set_range(float f1, float f2);
|
|
void phaser_set_rate(float f);
|
|
void phaser_alps_delay(int i, float f);
|
|
float phaser_alps_update(int i, float f);
|
|
|
|
void phaser_reset( float fb, float lfoPhase, float depth, float range_start, float range_end, float rate ) {
|
|
memset(phaser_alps_a1, 0, 6*4);
|
|
memset(phaser_alps_zm1, 0, 6*4);
|
|
|
|
phaser_sample_rate = 44100.0; // !!!!
|
|
|
|
phaser_fb = fb;
|
|
phaser_lfoPhase = lfoPhase;
|
|
phaser_depth = depth;
|
|
phaser_zm1 = 0.0;
|
|
// phaser_set_range( 440.f, 1600.f );
|
|
phaser_set_range( range_start, range_end );
|
|
phaser_set_rate( rate );
|
|
|
|
};
|
|
|
|
void phaser_set_range(float fMin, float fMax) { // Hz
|
|
phaser_dmin = fMin / (phaser_sample_rate/2.f);
|
|
phaser_dmax = fMax / (phaser_sample_rate/2.f);
|
|
};
|
|
|
|
void phaser_set_rate( float rate ){ // cps
|
|
phaser_lfoInc = 2.0f * M_PI * (rate / phaser_sample_rate);
|
|
};
|
|
|
|
float phaser_update_sample( float inSamp, int ind ){
|
|
//calculate and update phaser sweep lfo...
|
|
float d;
|
|
if (phaser_value_index == -1) {
|
|
d = phaser_dmin + (phaser_dmax-phaser_dmin) * ((sin( phaser_lfoPhase ) + 1.0f)/2.0f);
|
|
}
|
|
else {
|
|
d = phaser_dmin + (phaser_dmax-phaser_dmin) * (0.5+0.5*rs_sgen_reg.wave[ phaser_value_index*rs_sgen_reg.wave_length + ind ]);
|
|
};
|
|
|
|
phaser_lfoPhase += phaser_lfoInc;
|
|
if( phaser_lfoPhase >= M_PI * 2.0f )
|
|
phaser_lfoPhase -= M_PI * 2.0f;
|
|
|
|
//update filter coeffs
|
|
int i;
|
|
for(i = 0; i < 6; i++) {
|
|
phaser_alps_delay(i, d);
|
|
};
|
|
|
|
//calculate output
|
|
float y = phaser_alps_update(0,
|
|
phaser_alps_update(1,
|
|
phaser_alps_update(2,
|
|
phaser_alps_update(3,
|
|
phaser_alps_update(4,
|
|
phaser_alps_update(5,
|
|
inSamp + phaser_zm1 * phaser_fb
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
// float y = _alps[0].Update(
|
|
// _alps[1].Update(
|
|
// _alps[2].Update(
|
|
// _alps[3].Update(
|
|
// _alps[4].Update(
|
|
// _alps[5].Update( inSamp + _zm1 * _fb ))))));
|
|
phaser_zm1 = y;
|
|
|
|
// return sin(440.0*phaser_lfoPhase);
|
|
|
|
return inSamp + y * phaser_depth;
|
|
}
|
|
|
|
void phaser_alps_delay(int i, float delay) {
|
|
phaser_alps_a1[i] = (1.0f - delay) / (1.0f + delay);
|
|
};
|
|
|
|
float phaser_alps_update(int i, float inSamp) {
|
|
float y = inSamp * - phaser_alps_a1[i] + phaser_alps_zm1[i];
|
|
phaser_alps_zm1[i] = y * phaser_alps_a1[i] + inSamp;
|
|
return y;
|
|
};
|
|
|
|
// -----------------------
|
|
|
|
|
|
void rs_sgen_func_speaker(int index) {
|
|
|
|
|
|
|
|
int i;
|
|
|
|
float alpha = 0.3 ;// dt / (RC+dt)
|
|
|
|
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
|
|
|
|
if (i == 0) {
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i] = 0.4 * rs_noise(i, 0);
|
|
continue;
|
|
};
|
|
|
|
|
|
// Low-pass
|
|
// rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i] =
|
|
// alpha * 0.4 * rs_noise(i, 0) + (1.0 - alpha) * (rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i - 1 ]);
|
|
|
|
|
|
// High-pass
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i] =
|
|
alpha * ( rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i - 1 ] + 0.4 * rs_noise(i, 0) - 0.4 * rs_noise(i-1, 0) );
|
|
|
|
|
|
|
|
//// rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i] = 0.1 * sin( (2.0f * M_PI * 440.0 * i ) / 44100.0 + 9.0*sin(0.12*i) );
|
|
// int t = i + 4*65536;
|
|
// int p = (unsigned char) ((((t * (t >> 8 | t >> 9) & 46 & t >> 8)) ^ (t & t >> 13 | t >> 6)) & 0xFF);
|
|
//// rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i] = (float)(p-128) / 128.0; // (float) 1.0 / 256.0 * (p);
|
|
};
|
|
|
|
// rs_sound_create_from_data(&game.test_sound, 688200, audiodata);
|
|
|
|
// for (i = 0; i < 20; i++) {
|
|
// rs_sound_create_from_data(& (sounds[i]), 11025 * (1 + i % 3) , audiodata2);
|
|
// rs_sound_adjust_pitch( &sounds[i], 0.5 + 1.0f * i / 20.0f );
|
|
// };
|
|
|
|
// DEBUG10f("sound is created. length = %d \n", game.test_sound.Length);
|
|
|
|
|
|
// memset(audiodata, 0, 688200);
|
|
// free(audiodata);
|
|
|
|
};
|
|
|
|
|
|
void rs_sgen_func_noise(int index, int seed) {
|
|
int i;
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i] = rs_noise(seed + i, 0);
|
|
};
|
|
};
|
|
|
|
|
|
|
|
void rs_sgen_func_sin(int index, float freq, float p) {
|
|
int i;
|
|
float f;
|
|
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
f = sin( (2.0f * M_PI * freq * i ) / 44100.0 ); // !!! Only for 44100 kHz
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i] = rs_sign(f) * pow( fabs(f) , p ); // remove koef!
|
|
// rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i] = 0.1 * sin( (2.0f * M_PI * 440.0 * i ) / 44100.0 + 9.0*sin(0.12*i) );
|
|
// rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i] = -1.0 + 2.0 * ( (44100.0 / freq) ) sin( (2.0f * M_PI * freq * i ) / 44100.0 ); // !!! Only for 44100 kHz
|
|
};
|
|
};
|
|
|
|
|
|
|
|
void rs_sgen_func_pm(int index, float freq, float p, float k, float freq2, float p2) {
|
|
int i;
|
|
float f;
|
|
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
f = sin( (2.0f * M_PI * freq * i ) / 44100.0 + k*rs_pow(sin( 2.0f * M_PI * freq2 * i / 44100.0 ), p2) ); // !!! Only for 44100 kHz
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i] = rs_pow(f, p);
|
|
// rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i] = 0.1 * sin( (2.0f * M_PI * 440.0 * i ) / 44100.0 + 9.0*sin(0.12*i) );
|
|
// rs_sgen_reg.wave[ rs_sgen_reg.wave_length * index + i] = -1.0 + 2.0 * ( (44100.0 / freq) ) sin( (2.0f * M_PI * freq * i ) / 44100.0 ); // !!! Only for 44100 kHz
|
|
};
|
|
};
|
|
|
|
void rs_sgen_func_add(int dest, int src1, int src2, float k1, float k2) {
|
|
int i;
|
|
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i] =
|
|
k1 * rs_sgen_reg.wave[ rs_sgen_reg.wave_length * src1 + i]
|
|
+ k2 * rs_sgen_reg.wave[ rs_sgen_reg.wave_length * src2 + i];
|
|
};
|
|
|
|
};
|
|
|
|
void rs_sgen_func_mult(int dest, int src1, int src2) {
|
|
int i;
|
|
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i] =
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * src1 + i]
|
|
* rs_sgen_reg.wave[ rs_sgen_reg.wave_length * src2 + i];
|
|
};
|
|
|
|
};
|
|
|
|
|
|
void rs_sgen_func_normalize(int dest, float amp) {
|
|
|
|
// DEBUG10("Normalize...");
|
|
|
|
float val_max = 0.0; // fabs(rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest ]);
|
|
float f;
|
|
|
|
int i;
|
|
|
|
// Step 1: Normalize Mid-line
|
|
|
|
const int mar_samples_count = 512;
|
|
|
|
float *mar = malloc( 4 * (2 + rs_sgen_reg.wave_length / mar_samples_count) );
|
|
memset(mar, 0, 4 * (2 + rs_sgen_reg.wave_length / mar_samples_count) );
|
|
|
|
// DEBUG10("label 1");
|
|
|
|
int length_512 = mar_samples_count*(rs_sgen_reg.wave_length/mar_samples_count); // 1024 for 1027
|
|
|
|
int last_length = rs_sgen_reg.wave_length - length_512;
|
|
if (!last_length) {
|
|
last_length = length_512;
|
|
};
|
|
|
|
float koef[2] = { 1.0/mar_samples_count, 1.0/(last_length) };
|
|
|
|
// DEBUG10f("\nkoef 0: %.6f\nkoef 1: %.6f (last_length = %d)\n", koef[0], koef[1], last_length);
|
|
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
mar[1+i/mar_samples_count] += koef[ i / (length_512) ] * rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i];
|
|
};
|
|
|
|
// DEBUG10("label 2");
|
|
|
|
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i] -= //mar[i/mar_samples_count];
|
|
rs_linear_interpolate( mar[i/mar_samples_count], mar[1+i/mar_samples_count], rs_fract(1.0*i/mar_samples_count) );
|
|
};
|
|
//
|
|
// DEBUG10("label 3");
|
|
|
|
free(mar);
|
|
|
|
// DEBUG10("label 4");
|
|
|
|
|
|
// Step 2: Normalize Amplitude
|
|
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
f = rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i];
|
|
val_max = rs_max(val_max, fabs(f) );
|
|
};
|
|
|
|
float val_scale = amp / val_max;
|
|
|
|
// DEBUG10f("SGEN Normalize: val_max %.3f, val_scale = %.3f \n", val_max, val_scale);
|
|
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i] = val_scale * rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i];
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
void rs_sgen_func_limiter(int dest, float val) {
|
|
|
|
rs_sgen_func_normalize(dest, 1.0/val);
|
|
|
|
int i;
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i] = rs_clamp(
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i ], -1.0, 1.0 );
|
|
};
|
|
|
|
// float val_scale = amp / val_max;
|
|
//
|
|
// DEBUG10f("SGEN Normalize: val_max %.3f, val_scale = %.3f \n", val_max, val_scale);
|
|
//
|
|
// for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
// rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i] = val_scale * rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i];
|
|
// };
|
|
};
|
|
|
|
|
|
void rs_sgen_func_reverb(int dest, int src, int echo_delay, float echo_decay_koef) {
|
|
|
|
//
|
|
|
|
int i;
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
|
|
if (i + echo_delay > rs_sgen_reg.wave_length-1) {
|
|
break;
|
|
};
|
|
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i + echo_delay] +=
|
|
echo_decay_koef * rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i];
|
|
};
|
|
|
|
};
|
|
|
|
|
|
void rs_sgen_func_lowpass(int dest, int src, float alpha_start, float alpha_end, float alpha_pow) {
|
|
|
|
int i;
|
|
float alpha, t;
|
|
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
|
|
if (i == 0) {
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i] =
|
|
0; // rs_sgen_reg.wave[ rs_sgen_reg.wave_length * src + i];
|
|
continue;
|
|
};
|
|
|
|
t = (float) i / rs_sgen_reg.wave_length;
|
|
alpha = (1.0 - t) * alpha_start + t * alpha_end;
|
|
alpha = pow(alpha, alpha_pow);
|
|
|
|
// Low-pass
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i] =
|
|
alpha * rs_sgen_reg.wave[ rs_sgen_reg.wave_length * src + i]
|
|
+ (1.0 - alpha) * (rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i - 1 ]);
|
|
|
|
};
|
|
};
|
|
|
|
|
|
void rs_sgen_func_highpass(int dest, int src, float alpha_start, float alpha_end, float alpha_pow) {
|
|
|
|
int i;
|
|
float t, alpha;
|
|
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
|
|
if (i == 0) {
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i] = 0; // rs_sgen_reg.wave[ rs_sgen_reg.wave_length * src + i];
|
|
continue;
|
|
};
|
|
|
|
t = (float) i / rs_sgen_reg.wave_length;
|
|
alpha = (1.0 - t) * alpha_start + t * alpha_end;
|
|
alpha = pow(alpha, alpha_pow);
|
|
|
|
// High-pass
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i] =
|
|
alpha * ( rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i - 1]
|
|
+ rs_sgen_reg.wave[ rs_sgen_reg.wave_length * src + i]
|
|
- rs_sgen_reg.wave[ rs_sgen_reg.wave_length * src + i - 1] );
|
|
|
|
};
|
|
|
|
};
|
|
|
|
void rs_sgen_func_phaser(int dest, int src, float fb, float lfoPhase, float depth, float range_start, float range_end, float rate) {
|
|
|
|
//phaser_reset(0.97, 1.67, 0.5, 1.0, 22050.0, 1.5);
|
|
phaser_reset(fb, lfoPhase, depth, range_start, range_end, rate);
|
|
|
|
int i;
|
|
// float t, alpha;
|
|
|
|
for (i = 0; i < rs_sgen_reg.wave_length + 12; i++) {
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i%rs_sgen_reg.wave_length] = phaser_update_sample( rs_sgen_reg.wave[ rs_sgen_reg.wave_length * src + i%rs_sgen_reg.wave_length], i%rs_sgen_reg.wave_length );
|
|
};
|
|
|
|
};
|
|
|
|
void rs_sgen_func_shift(int dest, int src) {
|
|
int i;
|
|
for (i = 0; i < rs_sgen_reg.wave_length; i++) {
|
|
rs_sgen_reg.wave[ rs_sgen_reg.wave_length * dest + i % rs_sgen_reg.wave_length]
|
|
= rs_sgen_reg.wave[ rs_sgen_reg.wave_length * src + (i + rs_sgen_reg.wave_length/2 )%rs_sgen_reg.wave_length];
|
|
};
|
|
};
|
|
|
|
|