2026-01-07 17:45:46 -06:00
|
|
|
#pragma once
|
|
|
|
|
|
2026-01-08 01:19:25 -06:00
|
|
|
#include "pxl8_hal.h"
|
2026-01-07 17:45:46 -06:00
|
|
|
#include "pxl8_types.h"
|
|
|
|
|
|
|
|
|
|
#define PXL8_SFX_BUFFER_SIZE 1024
|
|
|
|
|
#define PXL8_SFX_MAX_CONTEXTS 8
|
|
|
|
|
#define PXL8_SFX_MAX_DELAY_SAMPLES 44100
|
|
|
|
|
#define PXL8_SFX_MAX_VOICES 16
|
|
|
|
|
#define PXL8_SFX_SAMPLE_RATE 44100
|
|
|
|
|
|
|
|
|
|
typedef struct pxl8_sfx_context pxl8_sfx_context;
|
|
|
|
|
typedef struct pxl8_sfx_mixer pxl8_sfx_mixer;
|
|
|
|
|
typedef struct pxl8_sfx_node pxl8_sfx_node;
|
|
|
|
|
|
|
|
|
|
typedef enum pxl8_sfx_filter_type {
|
|
|
|
|
PXL8_SFX_FILTER_BANDPASS = 0,
|
|
|
|
|
PXL8_SFX_FILTER_HIGHPASS,
|
|
|
|
|
PXL8_SFX_FILTER_LOWPASS,
|
|
|
|
|
PXL8_SFX_FILTER_NONE
|
|
|
|
|
} pxl8_sfx_filter_type;
|
|
|
|
|
|
|
|
|
|
typedef enum pxl8_sfx_lfo_target {
|
|
|
|
|
PXL8_SFX_LFO_AMPLITUDE = 0,
|
|
|
|
|
PXL8_SFX_LFO_FILTER,
|
|
|
|
|
PXL8_SFX_LFO_PITCH
|
|
|
|
|
} pxl8_sfx_lfo_target;
|
|
|
|
|
|
|
|
|
|
typedef enum pxl8_sfx_node_type {
|
|
|
|
|
PXL8_SFX_NODE_COMPRESSOR,
|
|
|
|
|
PXL8_SFX_NODE_DELAY,
|
|
|
|
|
PXL8_SFX_NODE_REVERB
|
|
|
|
|
} pxl8_sfx_node_type;
|
|
|
|
|
|
|
|
|
|
typedef enum pxl8_sfx_waveform {
|
|
|
|
|
PXL8_SFX_WAVE_NOISE = 0,
|
|
|
|
|
PXL8_SFX_WAVE_PULSE,
|
|
|
|
|
PXL8_SFX_WAVE_SAW,
|
|
|
|
|
PXL8_SFX_WAVE_SINE,
|
|
|
|
|
PXL8_SFX_WAVE_SQUARE,
|
|
|
|
|
PXL8_SFX_WAVE_TRIANGLE
|
|
|
|
|
} pxl8_sfx_waveform;
|
|
|
|
|
|
|
|
|
|
typedef struct pxl8_sfx_adsr {
|
|
|
|
|
f32 attack;
|
|
|
|
|
f32 decay;
|
|
|
|
|
f32 sustain;
|
|
|
|
|
f32 release;
|
|
|
|
|
} pxl8_sfx_adsr;
|
|
|
|
|
|
|
|
|
|
typedef struct pxl8_sfx_compressor_config {
|
|
|
|
|
f32 attack;
|
|
|
|
|
f32 ratio;
|
|
|
|
|
f32 release;
|
|
|
|
|
f32 threshold;
|
|
|
|
|
} pxl8_sfx_compressor_config;
|
|
|
|
|
|
|
|
|
|
typedef struct pxl8_sfx_delay_config {
|
|
|
|
|
f32 feedback;
|
|
|
|
|
f32 mix;
|
|
|
|
|
u32 time_l;
|
|
|
|
|
u32 time_r;
|
|
|
|
|
} pxl8_sfx_delay_config;
|
|
|
|
|
|
|
|
|
|
typedef struct pxl8_sfx_reverb_config {
|
|
|
|
|
f32 damping;
|
|
|
|
|
f32 mix;
|
|
|
|
|
f32 room;
|
|
|
|
|
} pxl8_sfx_reverb_config;
|
|
|
|
|
|
|
|
|
|
typedef struct pxl8_sfx_voice_params {
|
|
|
|
|
pxl8_sfx_adsr amp_env;
|
|
|
|
|
pxl8_sfx_adsr filter_env;
|
|
|
|
|
pxl8_sfx_filter_type filter_type;
|
|
|
|
|
pxl8_sfx_lfo_target lfo_target;
|
|
|
|
|
pxl8_sfx_waveform lfo_waveform;
|
|
|
|
|
pxl8_sfx_waveform waveform;
|
|
|
|
|
f32 filter_cutoff;
|
|
|
|
|
f32 filter_env_depth;
|
|
|
|
|
f32 filter_resonance;
|
|
|
|
|
f32 fx_send;
|
|
|
|
|
f32 lfo_depth;
|
|
|
|
|
f32 lfo_rate;
|
|
|
|
|
f32 pulse_width;
|
|
|
|
|
} pxl8_sfx_voice_params;
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
pxl8_sfx_node* pxl8_sfx_compressor_create(pxl8_sfx_compressor_config cfg);
|
|
|
|
|
void pxl8_sfx_compressor_set_attack(pxl8_sfx_node* node, f32 attack);
|
|
|
|
|
void pxl8_sfx_compressor_set_ratio(pxl8_sfx_node* node, f32 ratio);
|
|
|
|
|
void pxl8_sfx_compressor_set_release(pxl8_sfx_node* node, f32 release);
|
|
|
|
|
void pxl8_sfx_compressor_set_threshold(pxl8_sfx_node* node, f32 threshold);
|
|
|
|
|
|
|
|
|
|
void pxl8_sfx_context_append_node(pxl8_sfx_context* ctx, pxl8_sfx_node* node);
|
|
|
|
|
pxl8_sfx_context* pxl8_sfx_context_create(void);
|
|
|
|
|
void pxl8_sfx_context_destroy(pxl8_sfx_context* ctx);
|
|
|
|
|
pxl8_sfx_node* pxl8_sfx_context_get_head(pxl8_sfx_context* ctx);
|
|
|
|
|
f32 pxl8_sfx_context_get_volume(const pxl8_sfx_context* ctx);
|
|
|
|
|
void pxl8_sfx_context_insert_node(pxl8_sfx_context* ctx, pxl8_sfx_node* after, pxl8_sfx_node* node);
|
|
|
|
|
void pxl8_sfx_context_remove_node(pxl8_sfx_context* ctx, pxl8_sfx_node* node);
|
|
|
|
|
void pxl8_sfx_context_set_volume(pxl8_sfx_context* ctx, f32 volume);
|
|
|
|
|
|
|
|
|
|
pxl8_sfx_node* pxl8_sfx_delay_create(pxl8_sfx_delay_config cfg);
|
|
|
|
|
void pxl8_sfx_delay_set_feedback(pxl8_sfx_node* node, f32 feedback);
|
|
|
|
|
void pxl8_sfx_delay_set_mix(pxl8_sfx_node* node, f32 mix);
|
|
|
|
|
void pxl8_sfx_delay_set_time(pxl8_sfx_node* node, u32 time_l, u32 time_r);
|
|
|
|
|
|
2026-01-08 01:19:25 -06:00
|
|
|
#define PXL8_SFX_EVENT_NOTE_ON 1
|
|
|
|
|
#define PXL8_SFX_EVENT_NOTE_OFF 2
|
|
|
|
|
|
|
|
|
|
typedef void (*pxl8_sfx_event_callback)(u8 event_type, u8 context_id, u8 note, f32 volume, void* userdata);
|
|
|
|
|
|
2026-01-07 17:45:46 -06:00
|
|
|
void pxl8_sfx_mixer_attach(pxl8_sfx_mixer* mixer, pxl8_sfx_context* ctx);
|
|
|
|
|
void pxl8_sfx_mixer_clear(pxl8_sfx_mixer* mixer);
|
2026-01-08 01:19:25 -06:00
|
|
|
pxl8_sfx_mixer* pxl8_sfx_mixer_create(const pxl8_hal* hal);
|
2026-01-07 17:45:46 -06:00
|
|
|
void pxl8_sfx_mixer_destroy(pxl8_sfx_mixer* mixer);
|
|
|
|
|
void pxl8_sfx_mixer_detach(pxl8_sfx_mixer* mixer, pxl8_sfx_context* ctx);
|
|
|
|
|
f32 pxl8_sfx_mixer_get_master_volume(const pxl8_sfx_mixer* mixer);
|
2026-01-08 01:19:25 -06:00
|
|
|
void pxl8_sfx_mixer_process(pxl8_sfx_mixer* mixer);
|
|
|
|
|
void pxl8_sfx_mixer_set_event_callback(pxl8_sfx_mixer* mixer, pxl8_sfx_event_callback cb, void* userdata);
|
2026-01-07 17:45:46 -06:00
|
|
|
void pxl8_sfx_mixer_set_master_volume(pxl8_sfx_mixer* mixer, f32 volume);
|
|
|
|
|
|
|
|
|
|
void pxl8_sfx_node_destroy(pxl8_sfx_node* node);
|
|
|
|
|
f32 pxl8_sfx_note_to_freq(u8 note);
|
2026-01-08 01:19:25 -06:00
|
|
|
u16 pxl8_sfx_play_note(pxl8_sfx_context* ctx, u8 note, const pxl8_sfx_voice_params* params, f32 volume, f32 duration);
|
2026-01-07 17:45:46 -06:00
|
|
|
void pxl8_sfx_release_voice(pxl8_sfx_context* ctx, u16 voice_id);
|
|
|
|
|
|
|
|
|
|
pxl8_sfx_node* pxl8_sfx_reverb_create(pxl8_sfx_reverb_config cfg);
|
|
|
|
|
void pxl8_sfx_reverb_set_damping(pxl8_sfx_node* node, f32 damping);
|
|
|
|
|
void pxl8_sfx_reverb_set_mix(pxl8_sfx_node* node, f32 mix);
|
|
|
|
|
void pxl8_sfx_reverb_set_room(pxl8_sfx_node* node, f32 room);
|
|
|
|
|
|
|
|
|
|
void pxl8_sfx_stop_all(pxl8_sfx_context* ctx);
|
|
|
|
|
void pxl8_sfx_stop_voice(pxl8_sfx_context* ctx, u16 voice_id);
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
#endif
|