ajout effets audio
This commit is contained in:
1 parent
f8a79b08bf
commit
44a43828f1
14 files changed
+541
-6
No files matched your search
@@ -0,0 +1,26 @@
|
||||
#ifndef AUDIO_EFFECTS_H
|
||||
#define AUDIO_EFFECTS_H
|
||||
|
||||
#include "fx_equalizer.h"
|
||||
#include "fx_overdrive.h"
|
||||
#include "fx_saturation.h"
|
||||
#include "fx_echo.h"
|
||||
#include "fx_reverb.h"
|
||||
|
||||
/* Structure regroupant les parametres de tous les effets. Modifiable directement
|
||||
* (ex: depuis l'IHM) via AudioEffects_GetParams(). L'ordre de traitement fixe est :
|
||||
* egaliseur -> overdrive -> saturation -> echo -> reverberation. */
|
||||
typedef struct
|
||||
{
|
||||
FxEqualizerParams equalizer;
|
||||
FxOverdriveParams overdrive;
|
||||
FxSaturationParams saturation;
|
||||
FxEchoParams echo;
|
||||
FxReverbParams reverb;
|
||||
} AudioEffectsParams;
|
||||
|
||||
void AudioEffects_Init(void);
|
||||
float AudioEffects_Process(float input);
|
||||
AudioEffectsParams *AudioEffects_GetParams(void);
|
||||
|
||||
#endif /* AUDIO_EFFECTS_H */
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef FX_ECHO_H
|
||||
#define FX_ECHO_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define FX_ECHO_SAMPLE_RATE 48000U
|
||||
#define FX_ECHO_MAX_DELAY_MS 1000U
|
||||
#define FX_ECHO_BUFFER_SIZE (FX_ECHO_SAMPLE_RATE * FX_ECHO_MAX_DELAY_MS / 1000U)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool enabled;
|
||||
float delay_ms; /* 0 a FX_ECHO_MAX_DELAY_MS */
|
||||
float feedback; /* 0.0 a <1.0 */
|
||||
float mix; /* 0.0 (sec) a 1.0 (100% repetitions) */
|
||||
} FxEchoParams;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int16_t buffer[FX_ECHO_BUFFER_SIZE];
|
||||
uint32_t write_idx;
|
||||
} FxEchoState;
|
||||
|
||||
void FxEcho_Init(FxEchoState *state, FxEchoParams *params);
|
||||
float FxEcho_Process(FxEchoState *state, const FxEchoParams *params, float input);
|
||||
|
||||
#endif /* FX_ECHO_H */
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef FX_EQUALIZER_H
|
||||
#define FX_EQUALIZER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define FX_EQ_NUM_BANDS 10U
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float freq_hz; /* frequence centrale de la bande */
|
||||
float gain_db; /* -24.0 a +24.0 dB */
|
||||
float q; /* facteur de qualite, typiquement 0.5 a 5.0 */
|
||||
} FxEqBand;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool enabled;
|
||||
FxEqBand bands[FX_EQ_NUM_BANDS];
|
||||
} FxEqualizerParams;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* coefficients biquad mis en cache, recalcules seulement si les parametres changent */
|
||||
float b0, b1, b2, a1, a2;
|
||||
/* dernieres valeurs de parametres utilisees pour calculer les coefficients ci-dessus */
|
||||
float last_freq_hz;
|
||||
float last_gain_db;
|
||||
float last_q;
|
||||
} FxEqBandState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FxEqBandState band_state[FX_EQ_NUM_BANDS];
|
||||
/* etat du filtre (direct form 1), par bande */
|
||||
float x1[FX_EQ_NUM_BANDS];
|
||||
float x2[FX_EQ_NUM_BANDS];
|
||||
float y1[FX_EQ_NUM_BANDS];
|
||||
float y2[FX_EQ_NUM_BANDS];
|
||||
} FxEqualizerState;
|
||||
|
||||
void FxEqualizer_Init(FxEqualizerState *state, FxEqualizerParams *params);
|
||||
float FxEqualizer_Process(FxEqualizerState *state, const FxEqualizerParams *params, float input);
|
||||
|
||||
#endif /* FX_EQUALIZER_H */
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef FX_OVERDRIVE_H
|
||||
#define FX_OVERDRIVE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool enabled;
|
||||
float drive; /* 0.0 a 1.0 : quantite de distorsion */
|
||||
float tone; /* 0.0 (sombre) a 1.0 (brillant) : filtre passe-bas post-distorsion */
|
||||
float level; /* gain de compensation en sortie */
|
||||
} FxOverdriveParams;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float tone_lp_state;
|
||||
} FxOverdriveState;
|
||||
|
||||
void FxOverdrive_Init(FxOverdriveState *state, FxOverdriveParams *params);
|
||||
float FxOverdrive_Process(FxOverdriveState *state, const FxOverdriveParams *params, float input);
|
||||
|
||||
#endif /* FX_OVERDRIVE_H */
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef FX_REVERB_H
|
||||
#define FX_REVERB_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define FX_REVERB_NUM_COMBS 8U
|
||||
#define FX_REVERB_NUM_ALLPASS 4U
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool enabled;
|
||||
float room_size; /* 0.0 a 1.0 */
|
||||
float damping; /* 0.0 (brillant) a 1.0 (etouffe) */
|
||||
float mix; /* 0.0 (sec) a 1.0 (100% reverbere) */
|
||||
} FxReverbParams;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float *buffer;
|
||||
uint32_t size;
|
||||
uint32_t idx;
|
||||
float filter_store;
|
||||
} FxCombState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float *buffer;
|
||||
uint32_t size;
|
||||
uint32_t idx;
|
||||
} FxAllpassState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FxCombState combs[FX_REVERB_NUM_COMBS];
|
||||
FxAllpassState allpass[FX_REVERB_NUM_ALLPASS];
|
||||
} FxReverbState;
|
||||
|
||||
void FxReverb_Init(FxReverbState *state, FxReverbParams *params);
|
||||
float FxReverb_Process(FxReverbState *state, const FxReverbParams *params, float input);
|
||||
|
||||
#endif /* FX_REVERB_H */
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef FX_SATURATION_H
|
||||
#define FX_SATURATION_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool enabled;
|
||||
float drive; /* 0.0 (aucun effet) a 1.0 (saturation maximale) */
|
||||
float level; /* gain de compensation en sortie, typiquement 0.0 - 1.0 */
|
||||
} FxSaturationParams;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float dc_block_x1;
|
||||
float dc_block_y1;
|
||||
} FxSaturationState;
|
||||
|
||||
void FxSaturation_Init(FxSaturationState *state, FxSaturationParams *params);
|
||||
float FxSaturation_Process(FxSaturationState *state, const FxSaturationParams *params, float input);
|
||||
|
||||
#endif /* FX_SATURATION_H */
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "audio_effects.h"
|
||||
|
||||
static AudioEffectsParams g_params;
|
||||
|
||||
static FxEqualizerState g_eqState;
|
||||
static FxOverdriveState g_overdriveState;
|
||||
static FxSaturationState g_saturationState;
|
||||
static FxEchoState g_echoState;
|
||||
static FxReverbState g_reverbState;
|
||||
|
||||
void AudioEffects_Init(void)
|
||||
{
|
||||
FxEqualizer_Init(&g_eqState, &g_params.equalizer);
|
||||
FxOverdrive_Init(&g_overdriveState, &g_params.overdrive);
|
||||
FxSaturation_Init(&g_saturationState, &g_params.saturation);
|
||||
FxEcho_Init(&g_echoState, &g_params.echo);
|
||||
FxReverb_Init(&g_reverbState, &g_params.reverb);
|
||||
}
|
||||
|
||||
float AudioEffects_Process(float input)
|
||||
{
|
||||
float sample = input;
|
||||
sample = FxEqualizer_Process(&g_eqState, &g_params.equalizer, sample);
|
||||
sample = FxOverdrive_Process(&g_overdriveState, &g_params.overdrive, sample);
|
||||
sample = FxSaturation_Process(&g_saturationState, &g_params.saturation, sample);
|
||||
sample = FxEcho_Process(&g_echoState, &g_params.echo, sample);
|
||||
sample = FxReverb_Process(&g_reverbState, &g_params.reverb, sample);
|
||||
return sample;
|
||||
}
|
||||
|
||||
AudioEffectsParams *AudioEffects_GetParams(void)
|
||||
{
|
||||
return &g_params;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "fx_echo.h"
|
||||
#include <string.h>
|
||||
|
||||
void FxEcho_Init(FxEchoState *state, FxEchoParams *params)
|
||||
{
|
||||
memset(state->buffer, 0, sizeof(state->buffer));
|
||||
state->write_idx = 0;
|
||||
|
||||
params->enabled = false;
|
||||
params->delay_ms = 300.0f;
|
||||
params->feedback = 0.35f;
|
||||
params->mix = 0.3f;
|
||||
}
|
||||
|
||||
float FxEcho_Process(FxEchoState *state, const FxEchoParams *params, float input)
|
||||
{
|
||||
if (!params->enabled)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
uint32_t delay_samples = (uint32_t)(params->delay_ms * (FX_ECHO_SAMPLE_RATE / 1000.0f));
|
||||
if (delay_samples >= FX_ECHO_BUFFER_SIZE)
|
||||
{
|
||||
delay_samples = FX_ECHO_BUFFER_SIZE - 1U;
|
||||
}
|
||||
|
||||
uint32_t read_idx = (state->write_idx + FX_ECHO_BUFFER_SIZE - delay_samples) % FX_ECHO_BUFFER_SIZE;
|
||||
float delayed = (float)state->buffer[read_idx] / 32768.0f;
|
||||
|
||||
float to_store = input + delayed * params->feedback;
|
||||
if (to_store > 1.0f) to_store = 1.0f;
|
||||
if (to_store < -1.0f) to_store = -1.0f;
|
||||
state->buffer[state->write_idx] = (int16_t)(to_store * 32767.0f);
|
||||
state->write_idx = (state->write_idx + 1U) % FX_ECHO_BUFFER_SIZE;
|
||||
|
||||
return input * (1.0f - params->mix) + delayed * params->mix;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "fx_equalizer.h"
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define FX_EQ_SAMPLE_RATE 48000.0f
|
||||
|
||||
static const float fx_eq_default_freqs[FX_EQ_NUM_BANDS] =
|
||||
{
|
||||
31.0f, 62.0f, 125.0f, 250.0f, 500.0f, 1000.0f, 2000.0f, 4000.0f, 8000.0f, 16000.0f
|
||||
};
|
||||
|
||||
void FxEqualizer_Init(FxEqualizerState *state, FxEqualizerParams *params)
|
||||
{
|
||||
params->enabled = false;
|
||||
for (uint32_t i = 0; i < FX_EQ_NUM_BANDS; i++)
|
||||
{
|
||||
params->bands[i].freq_hz = fx_eq_default_freqs[i];
|
||||
params->bands[i].gain_db = 0.0f;
|
||||
params->bands[i].q = 1.0f;
|
||||
|
||||
state->band_state[i].last_freq_hz = -1.0f; /* force le calcul des coefficients au 1er sample */
|
||||
state->band_state[i].last_gain_db = 0.0f;
|
||||
state->band_state[i].last_q = 0.0f;
|
||||
state->x1[i] = state->x2[i] = state->y1[i] = state->y2[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Filtre "peaking EQ" (cloche), formule de l'Audio EQ Cookbook (Robert Bristow-Johnson). */
|
||||
static void FxEq_ComputeBandCoeffs(FxEqBandState *bs, const FxEqBand *band)
|
||||
{
|
||||
float A = powf(10.0f, band->gain_db / 40.0f);
|
||||
float w0 = 2.0f * (float)M_PI * band->freq_hz / FX_EQ_SAMPLE_RATE;
|
||||
float alpha = sinf(w0) / (2.0f * band->q);
|
||||
float cosw0 = cosf(w0);
|
||||
|
||||
float a0 = 1.0f + alpha / A;
|
||||
bs->b0 = (1.0f + alpha * A) / a0;
|
||||
bs->b1 = (-2.0f * cosw0) / a0;
|
||||
bs->b2 = (1.0f - alpha * A) / a0;
|
||||
bs->a1 = (-2.0f * cosw0) / a0;
|
||||
bs->a2 = (1.0f - alpha / A) / a0;
|
||||
|
||||
bs->last_freq_hz = band->freq_hz;
|
||||
bs->last_gain_db = band->gain_db;
|
||||
bs->last_q = band->q;
|
||||
}
|
||||
|
||||
float FxEqualizer_Process(FxEqualizerState *state, const FxEqualizerParams *params, float input)
|
||||
{
|
||||
if (!params->enabled)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
float y = input;
|
||||
for (uint32_t i = 0; i < FX_EQ_NUM_BANDS; i++)
|
||||
{
|
||||
const FxEqBand *band = ¶ms->bands[i];
|
||||
FxEqBandState *bs = &state->band_state[i];
|
||||
|
||||
if (band->freq_hz != bs->last_freq_hz || band->gain_db != bs->last_gain_db || band->q != bs->last_q)
|
||||
{
|
||||
FxEq_ComputeBandCoeffs(bs, band);
|
||||
}
|
||||
|
||||
float x = y;
|
||||
y = bs->b0 * x + bs->b1 * state->x1[i] + bs->b2 * state->x2[i]
|
||||
- bs->a1 * state->y1[i] - bs->a2 * state->y2[i];
|
||||
|
||||
state->x2[i] = state->x1[i];
|
||||
state->x1[i] = x;
|
||||
state->y2[i] = state->y1[i];
|
||||
state->y1[i] = y;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "fx_overdrive.h"
|
||||
#include <math.h>
|
||||
|
||||
void FxOverdrive_Init(FxOverdriveState *state, FxOverdriveParams *params)
|
||||
{
|
||||
state->tone_lp_state = 0.0f;
|
||||
|
||||
params->enabled = false;
|
||||
params->drive = 0.4f;
|
||||
params->tone = 0.6f;
|
||||
params->level = 0.7f;
|
||||
}
|
||||
|
||||
float FxOverdrive_Process(FxOverdriveState *state, const FxOverdriveParams *params, float input)
|
||||
{
|
||||
if (!params->enabled)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
float driven = input * (1.0f + params->drive * 20.0f);
|
||||
|
||||
/* Ecretage asymetrique (exponentiel) : plus caracteristique/agressif qu'un tanh symetrique. */
|
||||
float shaped;
|
||||
if (driven >= 0.0f)
|
||||
{
|
||||
shaped = 1.0f - expf(-driven);
|
||||
}
|
||||
else
|
||||
{
|
||||
shaped = -1.0f + expf(driven);
|
||||
}
|
||||
|
||||
/* Filtre passe-bas une pole pour la tonalite : coefficient = tone (0..1). */
|
||||
float coeff = 0.05f + params->tone * 0.9f;
|
||||
state->tone_lp_state += coeff * (shaped - state->tone_lp_state);
|
||||
|
||||
return state->tone_lp_state * params->level;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
#include "fx_reverb.h"
|
||||
#include <string.h>
|
||||
|
||||
/* Lignes a retard inspirees de Freeverb (Jezar), redimensionnees de 44.1kHz vers 48kHz. */
|
||||
#define FX_REVERB_COMB0 1215U
|
||||
#define FX_REVERB_COMB1 1293U
|
||||
#define FX_REVERB_COMB2 1390U
|
||||
#define FX_REVERB_COMB3 1476U
|
||||
#define FX_REVERB_COMB4 1548U
|
||||
#define FX_REVERB_COMB5 1623U
|
||||
#define FX_REVERB_COMB6 1695U
|
||||
#define FX_REVERB_COMB7 1761U
|
||||
|
||||
#define FX_REVERB_ALLPASS0 605U
|
||||
#define FX_REVERB_ALLPASS1 480U
|
||||
#define FX_REVERB_ALLPASS2 371U
|
||||
#define FX_REVERB_ALLPASS3 245U
|
||||
|
||||
static float fx_reverb_comb_buf0[FX_REVERB_COMB0];
|
||||
static float fx_reverb_comb_buf1[FX_REVERB_COMB1];
|
||||
static float fx_reverb_comb_buf2[FX_REVERB_COMB2];
|
||||
static float fx_reverb_comb_buf3[FX_REVERB_COMB3];
|
||||
static float fx_reverb_comb_buf4[FX_REVERB_COMB4];
|
||||
static float fx_reverb_comb_buf5[FX_REVERB_COMB5];
|
||||
static float fx_reverb_comb_buf6[FX_REVERB_COMB6];
|
||||
static float fx_reverb_comb_buf7[FX_REVERB_COMB7];
|
||||
|
||||
static float fx_reverb_allpass_buf0[FX_REVERB_ALLPASS0];
|
||||
static float fx_reverb_allpass_buf1[FX_REVERB_ALLPASS1];
|
||||
static float fx_reverb_allpass_buf2[FX_REVERB_ALLPASS2];
|
||||
static float fx_reverb_allpass_buf3[FX_REVERB_ALLPASS3];
|
||||
|
||||
static float FxComb_Process(FxCombState *c, float input, float feedback, float damp1, float damp2)
|
||||
{
|
||||
float output = c->buffer[c->idx];
|
||||
c->filter_store = (output * damp2) + (c->filter_store * damp1);
|
||||
c->buffer[c->idx] = input + (c->filter_store * feedback);
|
||||
c->idx = (c->idx + 1U) % c->size;
|
||||
return output;
|
||||
}
|
||||
|
||||
static float FxAllpass_Process(FxAllpassState *a, float input, float feedback)
|
||||
{
|
||||
float buf_out = a->buffer[a->idx];
|
||||
float output = -input + buf_out;
|
||||
a->buffer[a->idx] = input + buf_out * feedback;
|
||||
a->idx = (a->idx + 1U) % a->size;
|
||||
return output;
|
||||
}
|
||||
|
||||
void FxReverb_Init(FxReverbState *state, FxReverbParams *params)
|
||||
{
|
||||
params->enabled = false;
|
||||
params->room_size = 0.5f;
|
||||
params->damping = 0.5f;
|
||||
params->mix = 0.3f;
|
||||
|
||||
float *comb_buffers[FX_REVERB_NUM_COMBS] = {
|
||||
fx_reverb_comb_buf0, fx_reverb_comb_buf1, fx_reverb_comb_buf2, fx_reverb_comb_buf3,
|
||||
fx_reverb_comb_buf4, fx_reverb_comb_buf5, fx_reverb_comb_buf6, fx_reverb_comb_buf7
|
||||
};
|
||||
uint32_t comb_sizes[FX_REVERB_NUM_COMBS] = {
|
||||
FX_REVERB_COMB0, FX_REVERB_COMB1, FX_REVERB_COMB2, FX_REVERB_COMB3,
|
||||
FX_REVERB_COMB4, FX_REVERB_COMB5, FX_REVERB_COMB6, FX_REVERB_COMB7
|
||||
};
|
||||
for (uint32_t i = 0; i < FX_REVERB_NUM_COMBS; i++)
|
||||
{
|
||||
state->combs[i].buffer = comb_buffers[i];
|
||||
state->combs[i].size = comb_sizes[i];
|
||||
state->combs[i].idx = 0;
|
||||
state->combs[i].filter_store = 0.0f;
|
||||
memset(comb_buffers[i], 0, comb_sizes[i] * sizeof(float));
|
||||
}
|
||||
|
||||
float *allpass_buffers[FX_REVERB_NUM_ALLPASS] = {
|
||||
fx_reverb_allpass_buf0, fx_reverb_allpass_buf1, fx_reverb_allpass_buf2, fx_reverb_allpass_buf3
|
||||
};
|
||||
uint32_t allpass_sizes[FX_REVERB_NUM_ALLPASS] = {
|
||||
FX_REVERB_ALLPASS0, FX_REVERB_ALLPASS1, FX_REVERB_ALLPASS2, FX_REVERB_ALLPASS3
|
||||
};
|
||||
for (uint32_t i = 0; i < FX_REVERB_NUM_ALLPASS; i++)
|
||||
{
|
||||
state->allpass[i].buffer = allpass_buffers[i];
|
||||
state->allpass[i].size = allpass_sizes[i];
|
||||
state->allpass[i].idx = 0;
|
||||
memset(allpass_buffers[i], 0, allpass_sizes[i] * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
float FxReverb_Process(FxReverbState *state, const FxReverbParams *params, float input)
|
||||
{
|
||||
if (!params->enabled)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
float feedback = 0.28f + params->room_size * 0.7f;
|
||||
float damp1 = params->damping * 0.4f;
|
||||
float damp2 = 1.0f - damp1;
|
||||
|
||||
float out = 0.0f;
|
||||
for (uint32_t i = 0; i < FX_REVERB_NUM_COMBS; i++)
|
||||
{
|
||||
out += FxComb_Process(&state->combs[i], input, feedback, damp1, damp2);
|
||||
}
|
||||
out /= (float)FX_REVERB_NUM_COMBS;
|
||||
|
||||
for (uint32_t i = 0; i < FX_REVERB_NUM_ALLPASS; i++)
|
||||
{
|
||||
out = FxAllpass_Process(&state->allpass[i], out, 0.5f);
|
||||
}
|
||||
|
||||
return input * (1.0f - params->mix) + out * params->mix;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "fx_saturation.h"
|
||||
#include <math.h>
|
||||
|
||||
#define FX_SATURATION_DC_BLOCK_R 0.995f
|
||||
|
||||
void FxSaturation_Init(FxSaturationState *state, FxSaturationParams *params)
|
||||
{
|
||||
state->dc_block_x1 = 0.0f;
|
||||
state->dc_block_y1 = 0.0f;
|
||||
|
||||
params->enabled = false;
|
||||
params->drive = 0.3f;
|
||||
params->level = 0.8f;
|
||||
}
|
||||
|
||||
float FxSaturation_Process(FxSaturationState *state, const FxSaturationParams *params, float input)
|
||||
{
|
||||
if (!params->enabled)
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
float driven = input * (1.0f + params->drive * 12.0f);
|
||||
float shaped = tanhf(driven);
|
||||
|
||||
/* Le tanh sur un signal non symetrique introduit un leger DC : filtre bloqueur de DC. */
|
||||
float y = shaped - state->dc_block_x1 + FX_SATURATION_DC_BLOCK_R * state->dc_block_y1;
|
||||
state->dc_block_x1 = shaped;
|
||||
state->dc_block_y1 = y;
|
||||
|
||||
return y * params->level;
|
||||
}
|
||||
+16
-5
@@ -25,6 +25,7 @@
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include "stm32h7s78_discovery_audio.h"
|
||||
#include "audio_effects.h"
|
||||
#include <string.h>
|
||||
/* USER CODE END Includes */
|
||||
|
||||
@@ -186,6 +187,8 @@ int main(void)
|
||||
fifo_write_idx = FIFO_SIZE / 2;
|
||||
fifo_read_idx = 0;
|
||||
|
||||
AudioEffects_Init();
|
||||
|
||||
sDmaConfig.Address = (uint32_t)adf_buf;
|
||||
sDmaConfig.DataLength = AUDIO_SAMPLES * sizeof(int32_t); /* OCTETS */
|
||||
sDmaConfig.MsbOnly = DISABLE; /* 32-bit/sample ; ENABLE si buffer int16 */
|
||||
@@ -768,11 +771,17 @@ static void MX_GPIO_Init(void)
|
||||
|
||||
/* USER CODE BEGIN 4 */
|
||||
|
||||
static inline int16_t adf_sample_to_pcm16(int32_t raw)
|
||||
static inline float adf_sample_to_float(int32_t raw)
|
||||
{
|
||||
int32_t v = raw >> 8; // 24 bits -> 16 bits (comme le fait le BSP)
|
||||
if (v > 32767) v = 32767;
|
||||
if (v < -32768) v = -32768;
|
||||
int32_t v = raw >> 8; // 24 bits -> valeur signee sur 24 bits
|
||||
return (float)v / 8388608.0f; // normalisation en [-1.0, 1.0]
|
||||
}
|
||||
|
||||
static inline int16_t float_to_pcm16(float x)
|
||||
{
|
||||
float v = x * 32767.0f;
|
||||
if (v > 32767.0f) v = 32767.0f;
|
||||
if (v < -32768.0f) v = -32768.0f;
|
||||
return (int16_t)v;
|
||||
}
|
||||
|
||||
@@ -782,7 +791,9 @@ static void push_to_fifo(int32_t raw)
|
||||
{
|
||||
return; // FIFO pleine : on jette l'échantillon plutôt que d'écraser du non-lu
|
||||
}
|
||||
int16_t s = adf_sample_to_pcm16(raw);
|
||||
float sample = adf_sample_to_float(raw);
|
||||
sample = AudioEffects_Process(sample);
|
||||
int16_t s = float_to_pcm16(sample);
|
||||
uint32_t idx = fifo_write_idx & (FIFO_SIZE - 1);
|
||||
audio_fifo[idx * 2] = s;
|
||||
audio_fifo[idx * 2 + 1] = s;
|
||||
|
||||
+7
-1
@@ -298,7 +298,13 @@ board_c_files += \
|
||||
Appli/Core/Src/stm32h7rsxx_it.c \
|
||||
Appli/Core/Src/stm32h7rsxx_hal_msp.c \
|
||||
Appli/Core/Src/stm32h7rsxx_hal_timebase_tim.c \
|
||||
Appli/Core/Src/system_stm32h7rsxx.c
|
||||
Appli/Core/Src/system_stm32h7rsxx.c \
|
||||
Appli/Core/Src/audio_effects.c \
|
||||
Appli/Core/Src/fx_equalizer.c \
|
||||
Appli/Core/Src/fx_overdrive.c \
|
||||
Appli/Core/Src/fx_saturation.c \
|
||||
Appli/Core/Src/fx_echo.c \
|
||||
Appli/Core/Src/fx_reverb.c
|
||||
|
||||
# Drivers
|
||||
board_include_paths := \
|
||||
|
||||
Reference in new issue
Block a user