11#ifndef __AUDIO_ENGINE_H__
12#define __AUDIO_ENGINE_H__
14#include "zrythm-config.h"
17#include "dsp/exporter.h"
29# include "weak_libjack.h"
33# include <pulse/pulseaudio.h>
37# include <portaudio.h>
41# include <alsa/asoundlib.h>
45# include <SDL2/SDL_audio.h>
49# include <rtaudio_c.h>
59typedef struct WindowsMmeDevice WindowsMmeDevice;
73#define BLOCK_LENGTH 4096
74#define MIDI_BUF_SIZE 1024
76#define MIDI_IN_NUM_EVENTS AUDIO_ENGINE->midi_in->midi_events->num_events
78#define AUDIO_ENGINE (PROJECT->audio_engine)
79#define MANUAL_PRESS_EVENTS \
80 (AUDIO_ENGINE->midi_editor_manual_press->midi_events)
82#define DENORMAL_PREVENTION_VAL (AUDIO_ENGINE->denormal_prevention_val)
84#define engine_is_in_active_project(self) (self->project == PROJECT)
88#define engine_set_run(engine, _run) g_atomic_int_set (&(engine)->run, _run)
89#define engine_get_run(engine) g_atomic_int_get (&(engine)->run)
91#define engine_has_handled_buffer_size_change(engine) \
92 ((engine)->audio_backend != AUDIO_BACKEND_JACK || \
93 ((engine)->audio_backend == AUDIO_BACKEND_JACK && \
94 g_atomic_int_get (&(engine)->handled_jack_buffer_size_change) == 1))
96#define ENGINE_MAX_EVENTS 100
98#define engine_queue_push_back_event(q, x) mpmc_queue_push_back (q, (void *) x)
100#define engine_queue_dequeue_event(q, x) mpmc_queue_dequeue (q, (void *) x)
105#define ENGINE_EVENTS_PUSH(et, _arg, _uint_arg, _float_arg) \
108 AudioEngineEvent * _ev = \
109 (AudioEngineEvent *) object_pool_get (AUDIO_ENGINE->ev_pool); \
110 _ev->file = __FILE__; \
111 _ev->func = __func__; \
112 _ev->lineno = __LINE__; \
114 _ev->arg = (void *) _arg; \
115 _ev->uint_arg = _uint_arg; \
116 _ev->float_arg = _float_arg; \
117 if (zrythm_app->gtk_thread == g_thread_self ()) \
119 _ev->backtrace = backtrace_get ("", 40, false); \
121 "pushing engine event " #et " (%s:%d) uint: %u | float: %f", \
122 __func__, __LINE__, _uint_arg, _float_arg); \
124 engine_queue_push_back_event (AUDIO_ENGINE->ev_queue, _ev); \
132 AUDIO_ENGINE_EVENT_BUFFER_SIZE_CHANGE,
133 AUDIO_ENGINE_EVENT_SAMPLE_RATE_CHANGE,
156 AUDIO_ENGINE_BUFFER_SIZE_16,
157 AUDIO_ENGINE_BUFFER_SIZE_32,
158 AUDIO_ENGINE_BUFFER_SIZE_64,
159 AUDIO_ENGINE_BUFFER_SIZE_128,
160 AUDIO_ENGINE_BUFFER_SIZE_256,
161 AUDIO_ENGINE_BUFFER_SIZE_512,
162 AUDIO_ENGINE_BUFFER_SIZE_1024,
163 AUDIO_ENGINE_BUFFER_SIZE_2048,
164 AUDIO_ENGINE_BUFFER_SIZE_4096,
165 NUM_AUDIO_ENGINE_BUFFER_SIZES,
168static const char * buffer_size_str[] = {
169 "16",
"32",
"64",
"128",
"256",
170 "512", N_ (
"1,024"), N_ (
"2,048"), N_ (
"4,096"),
173static inline const char *
176 return buffer_size_str[buf_size];
184 AUDIO_ENGINE_SAMPLERATE_22050,
185 AUDIO_ENGINE_SAMPLERATE_32000,
186 AUDIO_ENGINE_SAMPLERATE_44100,
187 AUDIO_ENGINE_SAMPLERATE_48000,
188 AUDIO_ENGINE_SAMPLERATE_88200,
189 AUDIO_ENGINE_SAMPLERATE_96000,
190 AUDIO_ENGINE_SAMPLERATE_192000,
191 NUM_AUDIO_ENGINE_SAMPLERATES,
194static const char * sample_rate_str[] = {
195 N_ (
"22,050"), N_ (
"32,000"), N_ (
"44,100"), N_ (
"48,000"),
196 N_ (
"88,200"), N_ (
"96,000"), N_ (
"192,000"),
199static inline const char *
202 return sample_rate_str[sample_rate];
205typedef enum AudioBackend
208 AUDIO_BACKEND_DUMMY_LIBSOUNDIO,
210 AUDIO_BACKEND_ALSA_LIBSOUNDIO,
211 AUDIO_BACKEND_ALSA_RTAUDIO,
213 AUDIO_BACKEND_JACK_LIBSOUNDIO,
214 AUDIO_BACKEND_JACK_RTAUDIO,
215 AUDIO_BACKEND_PULSEAUDIO,
216 AUDIO_BACKEND_PULSEAUDIO_LIBSOUNDIO,
217 AUDIO_BACKEND_PULSEAUDIO_RTAUDIO,
218 AUDIO_BACKEND_COREAUDIO_LIBSOUNDIO,
219 AUDIO_BACKEND_COREAUDIO_RTAUDIO,
221 AUDIO_BACKEND_WASAPI_LIBSOUNDIO,
222 AUDIO_BACKEND_WASAPI_RTAUDIO,
223 AUDIO_BACKEND_ASIO_RTAUDIO,
228audio_backend_is_rtaudio (AudioBackend backend)
230 return backend == AUDIO_BACKEND_ALSA_RTAUDIO
231 || backend == AUDIO_BACKEND_JACK_RTAUDIO
232 || backend == AUDIO_BACKEND_PULSEAUDIO_RTAUDIO
233 || backend == AUDIO_BACKEND_COREAUDIO_RTAUDIO
234 || backend == AUDIO_BACKEND_WASAPI_RTAUDIO
235 || backend == AUDIO_BACKEND_ASIO_RTAUDIO;
238__attribute__ ((unused))
static const char * audio_backend_str[] = {
240 N_ (
"Dummy"), N_ (
"Dummy (libsoundio)"),
241 "ALSA (not working)",
"ALSA (libsoundio)",
242 "ALSA (rtaudio)",
"JACK",
243 "JACK (libsoundio)",
"JACK (rtaudio)",
244 "PulseAudio",
"PulseAudio (libsoundio)",
245 "PulseAudio (rtaudio)",
"CoreAudio (libsoundio)",
246 "CoreAudio (rtaudio)",
"SDL",
247 "WASAPI (libsoundio)",
"WASAPI (rtaudio)",
272typedef enum MidiBackend
276 MIDI_BACKEND_ALSA_RTMIDI,
278 MIDI_BACKEND_JACK_RTMIDI,
279 MIDI_BACKEND_WINDOWS_MME,
280 MIDI_BACKEND_WINDOWS_MME_RTMIDI,
281 MIDI_BACKEND_COREMIDI_RTMIDI,
282 MIDI_BACKEND_WINDOWS_UWP_RTMIDI,
287midi_backend_is_rtmidi (MidiBackend backend)
289 return backend == MIDI_BACKEND_ALSA_RTMIDI || backend == MIDI_BACKEND_JACK_RTMIDI
290 || backend == MIDI_BACKEND_WINDOWS_MME_RTMIDI
291 || backend == MIDI_BACKEND_COREMIDI_RTMIDI
292 || backend == MIDI_BACKEND_WINDOWS_UWP_RTMIDI;
295static const char * midi_backend_str[] = {
298 N_ (
"ALSA Sequencer (not working)"),
299 N_ (
"ALSA Sequencer (rtmidi)"),
301 "JACK MIDI (rtmidi)",
303 "Windows MME (rtmidi)",
305 "Windows UWP (rtmidi)",
308typedef enum AudioEngineJackTransportType
310 AUDIO_ENGINE_JACK_TIMEBASE_MASTER,
311 AUDIO_ENGINE_JACK_TRANSPORT_CLIENT,
312 AUDIO_ENGINE_NO_JACK_TRANSPORT,
313} AudioEngineJackTransportType;
368 jack_client_t * client;
474 gint64 last_midi_activity;
529 snd_pcm_t * playback_handle;
530 snd_seq_t * seq_handle;
531 snd_pcm_hw_params_t * hw_params;
532 snd_pcm_sw_params_t * sw_params;
548 void * playback_handle;
566#ifdef HAVE_PORT_AUDIO
567 PaStream * pa_stream;
583 WindowsMmeDevice * mme_in_devs[1024];
585 WindowsMmeDevice * mme_out_devs[1024];
586 int num_mme_out_devs;
588 void * mme_in_devs[1024];
590 void * mme_out_devs[1024];
591 int num_mme_out_devs;
595 SDL_AudioDeviceID dev;
606#ifdef HAVE_PULSEAUDIO
607 pa_threaded_mainloop * pulse_mainloop;
608 pa_context * pulse_context;
609 pa_stream * pulse_stream;
611 void * pulse_mainloop;
612 void * pulse_context;
615 gboolean pulse_notified_underflow;
691 float denormal_prevention_val;
850engine_append_ports (
AudioEngine * self, GPtrArray * ports);
889 const int beats_per_bar,
893 bool update_from_ticks,
974#define engine_is_port_own(self, port) \
975 (port == MONITOR_FADER->stereo_in->l || port == MONITOR_FADER->stereo_in->r \
976 || port == MONITOR_FADER->stereo_out->l \
977 || port == MONITOR_FADER->stereo_out->r)
986engine_audio_backend_from_string (
const char * str);
991static inline const char *
992engine_midi_backend_to_string (MidiBackend backend)
994 return midi_backend_str[backend];
998engine_midi_backend_from_string (
const char * str);
The control room backend.
NONNULL_ARGS(1) int undo_manager_undo(UndoManager *self
Undo last action.
AudioEngineSamplerate
Samplerates to be used in comboboxes.
AudioEngineEventType
Audio engine event type.
void engine_set_default_backends(bool reset_to_dummy)
Detects the best backends on the system and sets them to GSettings.
void engine_setup(AudioEngine *self)
Sets up the audio engine after the project is initialized/loaded.
void engine_wait_for_pause(AudioEngine *self, EngineState *state, bool force_pause, bool with_fadeout)
AudioEngineBufferSize
Buffer sizes to be used in combo boxes.
const char * engine_audio_backend_to_string(AudioBackend backend)
Returns the audio backend as a string.
COLD WARN_UNUSED_RESULT AudioEngine * engine_new(Project *project)
Create a new audio engine.
int engine_samplerate_enum_to_int(AudioEngineSamplerate samplerate)
Returns the int value corresponding to the given AudioEngineSamplerate.
void engine_pre_setup(AudioEngine *self)
Sets up the audio engine before the project is initialized/loaded.
void engine_wait_n_cycles(AudioEngine *self, int n)
Waits for n processing cycles to finish.
NONNULL HOT void engine_post_process(AudioEngine *self, const nframes_t roll_nframes, const nframes_t nframes)
To be called after processing for common logic.
NONNULL HOT bool engine_process_prepare(AudioEngine *self, nframes_t nframes)
To be called by each implementation to prepare the structures before processing.
COLD NONNULL void engine_free(AudioEngine *self)
Closes any connections and free's data.
void engine_reset_bounce_mode(AudioEngine *self)
Reset the bounce mode on the engine, all tracks and regions to OFF.
NONNULL void engine_fill_out_bufs(AudioEngine *self, const nframes_t nframes)
Called to fill in the external buffers at the end of the processing cycle.
BounceMode
Mode used when bouncing, either during exporting or when bouncing tracks or regions to audio.
COLD void engine_activate(AudioEngine *self, bool activate)
Activates the audio engine to start processing and receiving events.
void engine_update_frames_per_tick(AudioEngine *self, const int beats_per_bar, const bpm_t bpm, const sample_rate_t sample_rate, bool thread_check, bool update_from_ticks, bool bpm_change)
Updates frames per tick based on the time sig, the BPM, and the sample rate.
COLD NONNULL AudioEngine * engine_clone(const AudioEngine *src)
Clones the audio engine.
void engine_set_buffer_size(AudioEngine *self, uint32_t buf_size)
Request the backend to set the buffer size.
int engine_process_events(AudioEngine *self)
GSourceFunc to be added using idle add.
NONNULL HOT int engine_process(AudioEngine *self, const nframes_t total_frames_to_process)
Processes current cycle.
int engine_buffer_size_enum_to_int(AudioEngineBufferSize buffer_size)
Returns the int value corresponding to the given AudioEngineBufferSize.
@ BOUNCE_OFF
Don't bounce.
@ BOUNCE_INHERIT
Bounce if parent is bouncing.
uint32_t sample_rate_t
Sample rate.
uint32_t nframes_t
Frame count.
uint8_t midi_byte_t
MIDI byte.
Hardware processor for the routing graph.
PanAlgorithm
See https://www.harmonycentral.com/articles/the-truth-about-panning-laws.
PanLaw
These are only useful when changing mono to stereo.
int32_t beat
Current beat (within bar).
double tick_within_beat
Current tick-within-beat.
int32_t sixteenth_within_bar
Current sixteenth (within bar).
double tick_within_bar
Current tick (within bar).
int32_t ninetysixth_notes
Total 1/96th notes completed up to current pos.
int32_t sixteenth_within_song
Current sixteenth (within song, ie, total sixteenths).
bool is_rolling
Transport is rolling.
double playhead_ticks
Exact playhead position (in ticks).
int32_t sixteenth
Current sixteenth (within beat).
HardwareProcessor * hw_in_processor
Input device processor.
AudioEnginePositionInfo pos_nfo_at_end
Expected position info at the end of the current cycle.
double ticks_per_frame
Reciprocal of AudioEngine::frames_per_tick.
double frames_per_tick
Number of frames/samples per tick.
bool bounce_with_parents
Whether currently bouncing with parents (cache).
nframes_t remaining_latency_preroll
When first set, it is equal to the max playback latency of all initial trigger nodes.
nframes_t nframes
Number of frames/samples in the current cycle, per channel.
size_t midi_buf_size
Size of MIDI port buffers in bytes.
ControlRoom * control_room
The ControlRoom.
Port * midi_editor_manual_press
Manual note press events from the piano roll.
gint64 last_timestamp_start
Timestamp at start of previous cycle.
int capture_cc
To be set to 1 when the CC from the Midi in port should be captured.
bool setup
Whether the engine is already set up.
gint cycle_running
Whether the cycle is currently running.
gint64 last_events_process_started
Time last event processing started.
gint64 zrythm_start_time
Time at start to keep track if trial limit is reached.
gint handled_jack_buffer_size_change
Whether pending jack buffer change was handled (buffers reallocated).
gint64 timestamp_start
Timestamp at the start of the current cycle.
AudioEnginePositionInfo pos_nfo_before
Position info at the end of the previous cycle before moving the transport.
int processing_events
Whether currently processing events.
StereoPorts * dummy_input
Used during tests to pass input data for recording.
Port * midi_in
Port used for receiving MIDI in messages for binding CC and other non-recording purposes.
AudioBackend audio_backend
Current audio backend.
sample_rate_t sample_rate
Sample rate.
nframes_t block_length
Audio buffer size (block length), per channel.
AudioPool * pool
Audio file pool.
AudioEngineJackTransportType transport_type
Whether transport master/client or no connection with jack transport.
Metronome * metronome
The metronome.
int limit_reached
Flag to keep track of the first time the limit is reached.
MPMCQueue * ev_queue
Event queue.
bool updating_frames_per_tick
True while updating frames per tick.
gint exporting
1 if currently exporting.
gint filled_stereo_out_bufs
Flag used when processing in some backends.
MidiBackend midi_backend
Current MIDI backend.
bool preparing_to_export
To be set to true when preparing to export.
gint64 last_xrun_notification
Last time an XRUN notification was shown.
StereoPorts * monitor_out
Monitor - these should be the last ports in the signal chain.
gint panic
Send note off MIDI everywhere.
Router * router
The processing graph router.
gint preparing_for_process
Flag used to check if we are inside engine_process_prepare().
gint64 last_events_processed
Time last event processing completed.
BounceMode bounce_mode
If this is on, only tracks/regions marked as "for bounce" will be allowed to make sound.
guint process_source_id
ID of the event processing source func.
BounceStep bounce_step
Bounce step cache.
ObjectPool * ev_pool
Object pool of event structs to avoid allocation.
ZixSem port_operation_lock
Semaphore for blocking DSP while a plugin and its ports are deleted.
AudioEnginePositionInfo pos_nfo_current
Position info at the start of the current cycle.
Project * project
Pointer to owner project, if any.
float * pa_out_buf
Port Audio output buffer.
gint64 max_time_taken
Max time taken to process in the last few cycles.
float * alsa_out_buf
ALSA audio buffer.
Transport * transport
Timeline metadata like BPM, time signature, etc.
gint64 last_timestamp_end
Timestamp at end of previous cycle.
bool denormal_prevention_val_positive
Whether the denormal prevention value (1e-12 ~ 1e-20) is positive.
Port * midi_clock_out
MIDI Clock output.
GThread * dummy_audio_thread
Dummy audio DSP processing thread.
uint_fast64_t cycle
Cycle count to know which cycle we are in.
gint64 last_time_taken
Time taken to process in the last cycle.
PanAlgorithm pan_algo
Pan algorithm.
bool pre_setup
Whether the engine is already pre-set up.
Port * midi_clock_in
MIDI Clock input TODO.
midi_byte_t last_cc[3]
Last MIDI CC captured.
gint64 timestamp_end
Expected timestamp at the end of the current cycle.
int stop_dummy_audio_thread
Set to 1 to stop the dummy audio thread.
HardwareProcessor * hw_out_processor
Output device processor.
int trigger_midi_activity
Flag to tell the UI that this channel had MIDI activity.
int buf_size_set
True iff buffer size callback fired.
gint run
Ok to process or not.
bool activated
Whether the engine is currently activated.
An audio pool is a pool of audio files and their corresponding float arrays in memory that are refere...
A Channel is part of a Track (excluding Tracks that don't have Channels) and contains information rel...
The control room allows to specify how Listen will work on each Channel and to set overall volume aft...
bool looping
Transport loop.
int running
Engine running.
Multiple Producer Multiple Consumer lock-free queue.
All MIDI mappings in Zrythm.
The base plugin Inheriting plugins must have this as a child.
Must ONLY be created via port_new()
Contains all of the info that will be serialized into a project file.
A processor to be used in the routing graph for playing samples independent of the timeline.
L & R port, for convenience.
The Tracklist contains all the tracks in the Project.