#ifndef CHANNEL_H #define CHANNEL_H // cppcheck-suppress missingIncludeSystem #include #include #define MAX_SCENES 8 #define LOOP_BUF_SIZE (5 * 48000) #define MAX_MIDI_EVENTS 1024 #define MAX_CHANNELS 16 #include "ringbuffer.h" typedef enum { CHANNEL_AUDIO, CHANNEL_MIDI } channel_type_t; typedef enum { STATE_IDLE, STATE_RECORD, STATE_LOOPING, STATE_PAUSED } looper_state; /* Structure for a recorded or playing MIDI event */ typedef struct { jack_nframes_t timestamp; unsigned char status; unsigned char note; unsigned char velocity; } midi_event_t; /* Loop data for a scene */ typedef struct { float audio_buffer[LOOP_BUF_SIZE]; midi_event_t midi_events[MAX_MIDI_EVENTS]; } loop_data_t; /* A single scene within a channel */ typedef struct { atomic_int state; atomic_int prev_state; atomic_int loop_count; atomic_int record_pos; atomic_int playback_pos; loop_data_t loop; } scene_t; struct channel_t { channel_type_t type; /* AUDIO or MIDI */ atomic_int active; jack_port_t *audio_in; jack_port_t *audio_out; jack_port_t *midi_in; /* NULL for audio channels */ jack_port_t *midi_out; int scene_count; /* number of scenes (max MAX_SCENES) */ int current_scene; /* index of currently active scene */ scene_t scenes[MAX_SCENES]; _Atomic RingBuf *save_ring; atomic_int save_complete; /* 1 when writer is done; RT thread must stop writing */ }; /* Globals declared in looper.c */ extern struct channel_t channels[MAX_CHANNELS]; extern atomic_int channel_count; extern atomic_int channel_capacity; extern int next_channel_id; extern atomic_int cmd_add; extern atomic_int cmd_remove; extern atomic_int cmd_load; extern atomic_int cmd_save; void init_scene(scene_t *sc); void channel_add(jack_client_t *client, int idx); void channel_remove(jack_client_t *client, int idx); void channel_add_scene(jack_client_t *client, int idx); void channel_remove_scene(jack_client_t *client, int idx); void channel_next_scene(jack_client_t *client, int idx); void channel_prev_scene(jack_client_t *client, int idx); #endif