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(engine_) (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 != AudioBackend::AUDIO_BACKEND_JACK || ((engine)->audio_backend == AudioBackend::AUDIO_BACKEND_JACK && g_atomic_int_get (&(engine)->handled_jack_buffer_size_change) == 1))
94#define ENGINE_MAX_EVENTS 100
96#define engine_queue_push_back_event(q, x) mpmc_queue_push_back (q, (void *) x)
98#define engine_queue_dequeue_event(q, x) mpmc_queue_dequeue (q, (void **) x)
103#define ENGINE_EVENTS_PUSH(et, _arg, _uint_arg, _float_arg) \
106 AudioEngineEvent * _ev = \
107 (AudioEngineEvent *) object_pool_get (AUDIO_ENGINE->ev_pool); \
108 _ev->file = __FILE__; \
109 _ev->func = __func__; \
110 _ev->lineno = __LINE__; \
112 _ev->arg = (void *) _arg; \
113 _ev->uint_arg = _uint_arg; \
114 _ev->float_arg = _float_arg; \
115 if (zrythm_app->gtk_thread == g_thread_self ()) \
117 _ev->backtrace = backtrace_get ("", 40, false); \
119 "pushing engine event " #et " (%s:%d) uint: %u | float: %f", \
120 __func__, __LINE__, _uint_arg, _float_arg); \
122 engine_queue_push_back_event (AUDIO_ENGINE->ev_queue, _ev); \
130 AUDIO_ENGINE_EVENT_BUFFER_SIZE_CHANGE,
131 AUDIO_ENGINE_EVENT_SAMPLE_RATE_CHANGE,
154 AUDIO_ENGINE_BUFFER_SIZE_16,
155 AUDIO_ENGINE_BUFFER_SIZE_32,
156 AUDIO_ENGINE_BUFFER_SIZE_64,
157 AUDIO_ENGINE_BUFFER_SIZE_128,
158 AUDIO_ENGINE_BUFFER_SIZE_256,
159 AUDIO_ENGINE_BUFFER_SIZE_512,
160 AUDIO_ENGINE_BUFFER_SIZE_1024,
161 AUDIO_ENGINE_BUFFER_SIZE_2048,
162 AUDIO_ENGINE_BUFFER_SIZE_4096,
165static const char * buffer_size_str[] = {
166 "16",
"32",
"64",
"128",
"256",
167 "512", N_ (
"1,024"), N_ (
"2,048"), N_ (
"4,096"),
170static inline const char *
173 return buffer_size_str[
static_cast<int> (buf_size)];
181 AUDIO_ENGINE_SAMPLERATE_22050,
182 AUDIO_ENGINE_SAMPLERATE_32000,
183 AUDIO_ENGINE_SAMPLERATE_44100,
184 AUDIO_ENGINE_SAMPLERATE_48000,
185 AUDIO_ENGINE_SAMPLERATE_88200,
186 AUDIO_ENGINE_SAMPLERATE_96000,
187 AUDIO_ENGINE_SAMPLERATE_192000,
190static const char * sample_rate_str[] = {
191 N_ (
"22,050"), N_ (
"32,000"), N_ (
"44,100"), N_ (
"48,000"),
192 N_ (
"88,200"), N_ (
"96,000"), N_ (
"192,000"),
195static inline const char *
198 return sample_rate_str[
static_cast<int> (sample_rate)];
201enum class AudioBackend
204 AUDIO_BACKEND_DUMMY_LIBSOUNDIO,
206 AUDIO_BACKEND_ALSA_LIBSOUNDIO,
207 AUDIO_BACKEND_ALSA_RTAUDIO,
209 AUDIO_BACKEND_JACK_LIBSOUNDIO,
210 AUDIO_BACKEND_JACK_RTAUDIO,
211 AUDIO_BACKEND_PULSEAUDIO,
212 AUDIO_BACKEND_PULSEAUDIO_LIBSOUNDIO,
213 AUDIO_BACKEND_PULSEAUDIO_RTAUDIO,
214 AUDIO_BACKEND_COREAUDIO_LIBSOUNDIO,
215 AUDIO_BACKEND_COREAUDIO_RTAUDIO,
217 AUDIO_BACKEND_WASAPI_LIBSOUNDIO,
218 AUDIO_BACKEND_WASAPI_RTAUDIO,
219 AUDIO_BACKEND_ASIO_RTAUDIO,
223audio_backend_is_rtaudio (AudioBackend backend)
225 return backend == AudioBackend::AUDIO_BACKEND_ALSA_RTAUDIO
226 || backend == AudioBackend::AUDIO_BACKEND_JACK_RTAUDIO
227 || backend == AudioBackend::AUDIO_BACKEND_PULSEAUDIO_RTAUDIO
228 || backend == AudioBackend::AUDIO_BACKEND_COREAUDIO_RTAUDIO
229 || backend == AudioBackend::AUDIO_BACKEND_WASAPI_RTAUDIO
230 || backend == AudioBackend::AUDIO_BACKEND_ASIO_RTAUDIO;
233__attribute__ ((unused))
static const char * audio_backend_str[] = {
235 N_ (
"Dummy"), N_ (
"Dummy (libsoundio)"),
236 "ALSA (not working)",
"ALSA (libsoundio)",
237 "ALSA (rtaudio)",
"JACK",
238 "JACK (libsoundio)",
"JACK (rtaudio)",
239 "PulseAudio",
"PulseAudio (libsoundio)",
240 "PulseAudio (rtaudio)",
"CoreAudio (libsoundio)",
241 "CoreAudio (rtaudio)",
"SDL",
242 "WASAPI (libsoundio)",
"WASAPI (rtaudio)",
267enum class MidiBackend
271 MIDI_BACKEND_ALSA_RTMIDI,
273 MIDI_BACKEND_JACK_RTMIDI,
274 MIDI_BACKEND_WINDOWS_MME,
275 MIDI_BACKEND_WINDOWS_MME_RTMIDI,
276 MIDI_BACKEND_COREMIDI_RTMIDI,
277 MIDI_BACKEND_WINDOWS_UWP_RTMIDI,
281midi_backend_is_rtmidi (MidiBackend backend)
283 return backend == MidiBackend::MIDI_BACKEND_ALSA_RTMIDI
284 || backend == MidiBackend::MIDI_BACKEND_JACK_RTMIDI
285 || backend == MidiBackend::MIDI_BACKEND_WINDOWS_MME_RTMIDI
286 || backend == MidiBackend::MIDI_BACKEND_COREMIDI_RTMIDI
287 || backend == MidiBackend::MIDI_BACKEND_WINDOWS_UWP_RTMIDI;
290static const char * midi_backend_str[] = {
293 N_ (
"ALSA Sequencer (not working)"),
294 N_ (
"ALSA Sequencer (rtmidi)"),
296 "JACK MIDI (rtmidi)",
298 "Windows MME (rtmidi)",
300 "Windows UWP (rtmidi)",
303enum class AudioEngineJackTransportType
305 AUDIO_ENGINE_JACK_TIMEBASE_MASTER,
306 AUDIO_ENGINE_JACK_TRANSPORT_CLIENT,
307 AUDIO_ENGINE_NO_JACK_TRANSPORT,
363 jack_client_t * client;
469 gint64 last_midi_activity;
524 snd_pcm_t * playback_handle;
525 snd_seq_t * seq_handle;
526 snd_pcm_hw_params_t * hw_params;
527 snd_pcm_sw_params_t * sw_params;
543 void * playback_handle;
561#ifdef HAVE_PORT_AUDIO
562 PaStream * port_audio_stream;
564 void * port_audio_stream;
578 WindowsMmeDevice * mme_in_devs[1024];
580 WindowsMmeDevice * mme_out_devs[1024];
581 int num_mme_out_devs;
583 void * mme_in_devs[1024];
585 void * mme_out_devs[1024];
586 int num_mme_out_devs;
590 SDL_AudioDeviceID dev;
601#ifdef HAVE_PULSEAUDIO
602 pa_threaded_mainloop * pulse_mainloop;
603 pa_context * pulse_context;
604 pa_stream * pulse_stream;
606 void * pulse_mainloop;
607 void * pulse_context;
610 gboolean pulse_notified_underflow;
686 float denormal_prevention_val;
843engine_append_ports (
AudioEngine * self, GPtrArray * ports);
882 const int beats_per_bar,
886 bool update_from_ticks,
967#define engine_is_port_own(self, port) \
968 (port == MONITOR_FADER->stereo_in->l || port == MONITOR_FADER->stereo_in->r \
969 || port == MONITOR_FADER->stereo_out->l \
970 || port == MONITOR_FADER->stereo_out->r)
979engine_audio_backend_from_string (
const char * str);
984static inline const char *
985engine_midi_backend_to_string (MidiBackend backend)
987 return midi_backend_str[
static_cast<int> (backend)];
991engine_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_INHERIT
Bounce if parent is bouncing.
@ BOUNCE_OFF
Don't bounce.
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.
float * port_audio_out_buf
Port Audio output buffer.
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.
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.