diff options
| author | spl3g <spleefer6@yandex.ru> | 2025-09-28 17:57:42 +0300 |
|---|---|---|
| committer | spl3g <spleefer6@yandex.ru> | 2025-09-28 18:01:33 +0300 |
| commit | 706f6b01c0f5e44c18171b0c803ca5bbffcdb652 (patch) | |
| tree | 31fef516830ad11d475cfe9e4200609712bad5d6 /src/sounds.h | |
| parent | dfdfb4c52b843425b751567cf945cc8c2b34af94 (diff) | |
Revamp the architecture
Diffstat (limited to 'src/sounds.h')
| -rw-r--r-- | src/sounds.h | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/src/sounds.h b/src/sounds.h new file mode 100644 index 0000000..e58ae4f --- /dev/null +++ b/src/sounds.h @@ -0,0 +1,137 @@ +#ifndef SOUNDS_H_ +#define SOUNDS_H_ + +#include <alsa/asoundlib.h> +#include <math.h> +#include <pthread.h> +#include <stdbool.h> +#include <limits.h> + +#define check(ret) \ + do { \ + int res = (ret); \ + if (res < 0) { \ + fprintf(stderr, "%s:%d ERROR: %s (%d)\n", \ + __FILE__, __LINE__, snd_strerror(res), res); \ + exit(1); \ + } \ + } while (0) + +#define MESSAGE_QUEUE_SIZE 128 +#define SAMPLE_RATE 48000 +#define PERIOD_SIZE 480 + +typedef enum { + PARAM_OSC, + PARAM_VOLUME, +} param_type; + +typedef enum { + OSC_SINE, + OSC_SAW, + OSC_SQUARE, + OSC_TRIANGLE, +} oscilator_type; + +typedef enum { + MSG_NOTE_ON, + MSG_NOTE_OFF, + MSG_ALL_NOTES_OFF, + MSG_PARAM_CHANGE, + MSG_STOP, +} synth_message_type; + +typedef struct { + synth_message_type type; + + union { + // NOTE_ON / NOTE_OFF + struct { + size_t note_id; + } note; + + // SET_PARAM; + struct { + param_type param_type; + float value; + } param_change; + }; +} synth_message; + + +typedef struct { + synth_message buffer[MESSAGE_QUEUE_SIZE]; + size_t head; + size_t tail; + pthread_mutex_t lock; +} message_queue; + +typedef struct { + snd_pcm_t *pcm; + message_queue *queue; +} sound_thread_meta; + +typedef struct { + bool active; + float freq; + float phase; + float phase_inc; +} synth_voice; + +typedef struct { + synth_voice *buffer; + size_t size; +} synth_voices; + +typedef struct { + oscilator_type oscilator_type; + float master_volume; +} synth_params; + +typedef void (*oscilator_func)(float *buffer, size_t sample_count, float *phase, float phase_inc); + +#define mqueue_init(q) \ + do { \ + (q)->head = (q)->tail = 0; \ + pthread_mutex_init(&(q)->lock, NULL); \ + } while (0) + + +#define mqueue_push(q, msg) \ + do { \ + pthread_mutex_lock(&(q)->lock); \ + size_t next = ((q)->head + 1) % MESSAGE_QUEUE_SIZE; \ + \ + if ((q)->tail == next) { \ + pthread_mutex_unlock(&(q)->lock); \ + return 1; \ + } \ + \ + (q)->buffer[(q)->head] = msg; \ + (q)->head = next; \ + \ + pthread_mutex_unlock(&(q)->lock); \ + } while (0) \ + +/* #define mqueue_get(q, msg, ok) \ */ +/* do { \ */ +/* pthread_mutex_lock(&(q)->lock); \ */ +/* if ((q)->tail == (q)->head) { \ */ +/* pthread_mutex_unlock(&(q)->lock); \ */ +/* *(ok) = false;\ */ +/* break; \ */ +/* } \ */ +/* \ */ +/* *(msg) = (q)->buffer[(q)->tail]; \ */ +/* (q)->tail = ((q)->tail + 1) % MESSAGE_QUEUE_SIZE; \ */ +/* \ */ +/* pthread_mutex_unlock(&(q)->lock); \ */ +/* *(ok) = true; \ */ +/* } while (0) */ + +#define mqueue_empty(q) (q)->head == (q)->tail + +void *sound_thread_start(void *ptr); +int set_hw_params(snd_pcm_t *pcm); + +#endif // SOUNDS_H_ |
