Skip to content

Commit 5ae1cab

Browse files
committed
Replace RtAudio with a custom ALSA backend
1 parent 781fb63 commit 5ae1cab

33 files changed

Lines changed: 1177 additions & 876 deletions

Agents.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ The project follows a layered architecture to ensure separation of concerns:
1313
- **`command/`**: Implementation of the Command Pattern for Undo/Redo functionality.
1414
- **`src/infra`**: The "Hands". Handles external systems:
1515
- **`midi/`**: RtMidi backend and MIDI file export/import.
16-
- **`audio/`**: RtAudio backend and audio recording.
16+
- **`audio/`**: ALSA/JACK backend for audio recording and playback.
1717
- **`video/`**: ffmpeg-based video generation.
1818
- **`settings/`**: Persistent configuration management.
1919
- **`src/view`**: The "Face". Pure QML-based UI, communicating with the application layer via models and services.
@@ -27,7 +27,7 @@ The project follows a layered architecture to ensure separation of concerns:
2727
- **Build System**: CMake with Ninja.
2828
- **Backend**:
2929
- **MIDI**: RtMidi.
30-
- **Audio**: RtAudio / JACK.
30+
- **Audio**: ALSA / JACK.
3131
- **File IO**: libsndfile, Qt XML.
3232
- **Testing**: CTest + Qt Test.
3333

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Bug fixes:
1111

1212
Other:
1313

14+
* Replace RtAudio with a custom ALSA backend
15+
1416
2.1.0
1517
=====
1618

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ find_package(PkgConfig REQUIRED)
4646
# Use pkg-config to find RtMidi
4747
pkg_check_modules(RTMIDI REQUIRED rtmidi)
4848

49-
# Use pkg-config to find RtAudio
50-
pkg_check_modules(RTAUDIO REQUIRED rtaudio)
49+
# Use pkg-config to find ALSA
50+
pkg_check_modules(ALSA REQUIRED alsa)
5151

5252
# Use pkg-config to find JACK
5353
if(ENABLE_JACK_SUPPORT)

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Noteahead is a "simple" MIDI tracker and sequencer for Linux focusing on ease of
66

77
Noteahead is designed to be especially a MIDI tracker, so it has/will have features that make MIDI sequencing as easy as possible.
88

9-
Noteahead is written in Qt/QML/C++20 on top of RtMidi back-end + RtAudio for the audio recorder. It builds with CMake and uses CTest + Qt Test framework for unit tests.
9+
Noteahead is written in Qt/QML/C++20 on top of RtMidi back-end + native ALSA/JACK for audio recording and playback. It builds with CMake and uses CTest + Qt Test framework for unit tests.
1010

1111
<table>
1212
<tr><td colspan="3"><img src="/screenshots/1.8.0/1.png" width="100%"></td></tr>
@@ -197,7 +197,7 @@ Noteahead is currently being developed on Ubuntu 24.04 LTS and on Ubuntu 25.10 w
197197

198198
Packages needed for building:
199199

200-
$ sudo apt install build-essential cmake pkg-config ninja-build qt6-base-dev qt6-declarative-dev qt6-tools-dev librtmidi-dev librtaudio-dev libsndfile-dev libjack-jackd2-dev
200+
$ sudo apt install build-essential cmake pkg-config ninja-build qt6-base-dev qt6-declarative-dev qt6-tools-dev librtmidi-dev libasound2-dev libsndfile-dev libjack-jackd2-dev
201201

202202
**Note**: As we are in the middle of the PipeWire transition, the Jack development files might not be needed.
203203

io.github.juzzlin.Noteahead.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,6 @@ modules:
2222
sha256: ef7bcda27fee6936b651c29ebe9544c74959d0b1583b716ce80a1c6fea7617f0
2323
builddir: true
2424

25-
- name: rtaudio
26-
buildsystem: cmake-ninja
27-
sources:
28-
- type: archive
29-
url: https://github.com/thestk/rtaudio/archive/refs/tags/6.0.1.tar.gz
30-
sha256: 7206c8b6cee43b474f43d64988fefaadfdcfc4264ed38d8de5f5d0e6ddb0a123
31-
builddir: true
32-
3325
- name: libsndfile
3426
buildsystem: cmake-ninja
3527
config-opts:

src/CMakeLists.txt

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
77
# These are needed only for the IDE
88
set(HEADER_FILES
99
application/application.hpp
10-
application/instrument_request.hpp
11-
application/command/note_edit_command.hpp
1210
application/command/automation_command.hpp
1311
application/command/composite_command.hpp
12+
application/command/note_edit_command.hpp
1413
application/command/undo_stack.hpp
15-
view/qml/Editor/line_number_renderer.hpp
14+
application/instrument_request.hpp
1615
application/models/audio_settings_model.hpp
1716
application/models/column_settings_model.hpp
1817
application/models/event_selection_model.hpp
@@ -24,10 +23,9 @@ set(HEADER_FILES
2423
application/models/note_column_model_handler.hpp
2524
application/models/pitch_bend_automations_model.hpp
2625
application/models/recent_files_model.hpp
27-
application/models/track_settings_model.hpp
2826
application/models/sampler/sampler_pad_model.hpp
27+
application/models/track_settings_model.hpp
2928
application/note_converter.hpp
30-
view/qml/Editor/note_column_renderer.hpp
3129
application/position.hpp
3230
application/service/application_service.hpp
3331
application/service/audio_service.hpp
@@ -58,9 +56,9 @@ set(HEADER_FILES
5856
common/constants.hpp
5957
common/utils.hpp
6058
common/waveform_generator.hpp
59+
domain/arpeggiator.hpp
6160
domain/automation.hpp
6261
domain/automation_location.hpp
63-
domain/arpeggiator.hpp
6462
domain/column.hpp
6563
domain/column_settings.hpp
6664
domain/devices/device.hpp
@@ -88,12 +86,17 @@ set(HEADER_FILES
8886
domain/side_chain_settings.hpp
8987
domain/song.hpp
9088
domain/track.hpp
89+
infra/audio/async_audio_file_reader.hpp
90+
infra/audio/async_audio_file_writer.hpp
9191
infra/audio/audio_engine.hpp
92+
infra/audio/audio_player.hpp
9293
infra/audio/audio_recorder.hpp
9394
infra/audio/backend/audio_file_reader.hpp
9495
infra/audio/backend/sndfile_reader.hpp
96+
infra/audio/implementation/alsa/audio_player_alsa.hpp
97+
infra/audio/implementation/alsa/audio_recorder_alsa.hpp
98+
infra/audio/implementation/jack/audio_player_jack.hpp
9599
infra/audio/implementation/jack/audio_recorder_jack.hpp
96-
infra/audio/implementation/librtaudio/audio_recorder_rt_audio.hpp
97100
infra/audio/ring_buffer.hpp
98101
infra/midi/export/midi_exporter.hpp
99102
infra/midi/import/midi_importer.hpp
@@ -110,16 +113,17 @@ set(HEADER_FILES
110113
infra/video/default_animation.hpp
111114
infra/video/video_config.hpp
112115
infra/video/video_generator.hpp
116+
view/qml/Editor/line_number_renderer.hpp
117+
view/qml/Editor/note_column_renderer.hpp
113118
)
114119

115120
set(SOURCE_FILES
116121
application/application.cpp
117-
application/instrument_request.cpp
118-
application/command/note_edit_command.cpp
119122
application/command/automation_command.cpp
120123
application/command/composite_command.cpp
124+
application/command/note_edit_command.cpp
121125
application/command/undo_stack.cpp
122-
view/qml/Editor/line_number_renderer.cpp
126+
application/instrument_request.cpp
123127
application/models/audio_settings_model.cpp
124128
application/models/column_settings_model.cpp
125129
application/models/event_selection_model.cpp
@@ -131,11 +135,10 @@ set(SOURCE_FILES
131135
application/models/note_column_model_handler.cpp
132136
application/models/pitch_bend_automations_model.cpp
133137
application/models/recent_files_model.cpp
134-
application/models/track_settings_model.cpp
135138
application/models/sampler/sampler_model.cpp
136139
application/models/sampler/sampler_pad_model.cpp
140+
application/models/track_settings_model.cpp
137141
application/note_converter.cpp
138-
view/qml/Editor/note_column_renderer.cpp
139142
application/service/application_service.cpp
140143
application/service/audio_service.cpp
141144
application/service/audio_worker.cpp
@@ -166,11 +169,13 @@ set(SOURCE_FILES
166169
common/constants.cpp
167170
common/utils.cpp
168171
common/waveform_generator.cpp
172+
domain/arpeggiator.cpp
169173
domain/automation.cpp
170174
domain/automation_location.cpp
171-
domain/arpeggiator.cpp
172175
domain/column.cpp
173176
domain/column_settings.cpp
177+
domain/devices/device.cpp
178+
domain/devices/sampler_device.cpp
174179
domain/event.cpp
175180
domain/event_data.cpp
176181
domain/instrument.cpp
@@ -192,16 +197,16 @@ set(SOURCE_FILES
192197
domain/play_order.cpp
193198
domain/song.cpp
194199
domain/track.cpp
195-
domain/devices/device.cpp
196-
domain/devices/sampler_device.cpp
200+
infra/audio/async_audio_file_reader.cpp
201+
infra/audio/async_audio_file_writer.cpp
197202
infra/audio/audio_engine.cpp
198-
infra/audio/audio_recorder.cpp
199203
infra/audio/audio_player.cpp
204+
infra/audio/audio_recorder.cpp
200205
infra/audio/backend/sndfile_reader.cpp
201-
infra/audio/implementation/jack/audio_recorder_jack.cpp
206+
infra/audio/implementation/alsa/audio_player_alsa.cpp
207+
infra/audio/implementation/alsa/audio_recorder_alsa.cpp
202208
infra/audio/implementation/jack/audio_player_jack.cpp
203-
infra/audio/implementation/librtaudio/audio_recorder_rt_audio.cpp
204-
infra/audio/implementation/librtaudio/audio_player_rt_audio.cpp
209+
infra/audio/implementation/jack/audio_recorder_jack.cpp
205210
infra/midi/export/midi_exporter.cpp
206211
infra/midi/import/midi_importer.cpp
207212
infra/midi/implementation/librtmidi/midi_in_rt_midi.cpp
@@ -217,6 +222,8 @@ set(SOURCE_FILES
217222
infra/video/default_animation.cpp
218223
infra/video/video_generator.cpp
219224
main.cpp
225+
view/qml/Editor/line_number_renderer.cpp
226+
view/qml/Editor/note_column_renderer.cpp
220227
)
221228

222229
qt_add_executable(${BINARY_NAME} ${HEADER_FILES} ${SOURCE_FILES})
@@ -354,7 +361,7 @@ qt_add_qml_module(${BINARY_NAME}
354361

355362
target_include_directories(${BINARY_NAME} PRIVATE contrib/SimpleLogger/src)
356363
target_include_directories(${BINARY_NAME} PRIVATE contrib/Argengine/src)
357-
target_include_directories(${BINARY_NAME} PRIVATE ${RTAUDIO_INCLUDE_DIRS})
364+
target_include_directories(${BINARY_NAME} PRIVATE ${ALSA_INCLUDE_DIRS})
358365
target_include_directories(${BINARY_NAME} PRIVATE ${SNDFILE_INCLUDE_DIRS})
359366

360367
target_compile_definitions(${BINARY_NAME} PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
@@ -365,7 +372,7 @@ if(ENABLE_MIDI_DEBUG)
365372
target_compile_definitions(${BINARY_NAME} PRIVATE ENABLE_MIDI_DEBUG)
366373
endif()
367374

368-
target_link_libraries(${BINARY_NAME} PRIVATE Qt6::Core Qt6::Quick ${RTMIDI_LIBRARIES} ${RTAUDIO_LIBRARIES} ${SNDFILE_LIBRARIES} SimpleLogger_static Argengine_static)
375+
target_link_libraries(${BINARY_NAME} PRIVATE Qt6::Core Qt6::Quick ${RTMIDI_LIBRARIES} ${ALSA_LIBRARIES} ${SNDFILE_LIBRARIES} SimpleLogger_static Argengine_static)
369376

370377
if(JACK_FOUND)
371378
target_include_directories(${BINARY_NAME} PRIVATE ${JACK_INCLUDE_DIRS})

src/application/service/audio_service.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,11 @@
2020
#include "../../contrib/SimpleLogger/src/simple_logger.hpp"
2121
#include "../../infra/audio/implementation/jack/audio_recorder_jack.hpp"
2222
#include "../../infra/audio/implementation/jack/audio_player_jack.hpp"
23-
#include "../../infra/audio/implementation/librtaudio/audio_recorder_rt_audio.hpp"
24-
#include "../../infra/audio/implementation/librtaudio/audio_player_rt_audio.hpp"
23+
#include "../../infra/audio/implementation/alsa/audio_recorder_alsa.hpp"
24+
#include "../../infra/audio/implementation/alsa/audio_player_alsa.hpp"
2525
#include "audio_worker.hpp"
2626
#include "settings_service.hpp"
2727

28-
#include <RtAudio.h>
2928
#include <sndfile.h>
3029
#include <QFile>
3130
#include <QTimer>
@@ -42,6 +41,9 @@ AudioService::AudioService(SettingsServiceS settingsService, JackServiceS jackSe
4241
, m_audioEngine { std::move(audioEngine) }
4342
{
4443
connect(m_settingsService.get(), &SettingsService::jackSyncEnabledChanged, this, &AudioService::reinitialize);
44+
connect(m_settingsService.get(), &SettingsService::audioBufferSizeChanged, this, &AudioService::reinitialize);
45+
connect(m_settingsService.get(), &SettingsService::audioInputDeviceIdChanged, this, &AudioService::reinitialize);
46+
connect(m_settingsService.get(), &SettingsService::audioOutputDeviceIdChanged, this, &AudioService::reinitialize);
4547

4648
if (autoInitialize) {
4749
reinitialize();
@@ -73,8 +75,8 @@ void AudioService::reinitialize()
7375
audioRecorder = std::make_unique<AudioRecorderJack>(m_jackService);
7476
audioPlayer = std::make_unique<AudioPlayerJack>(m_jackService);
7577
} else {
76-
audioRecorder = std::make_unique<AudioRecorderRtAudio>(m_audioEngine, RtAudio::UNSPECIFIED);
77-
audioPlayer = std::make_unique<AudioPlayerRtAudio>(m_audioEngine, RtAudio::UNSPECIFIED);
78+
audioRecorder = std::make_unique<AudioRecorderAlsa>(m_audioEngine);
79+
audioPlayer = std::make_unique<AudioPlayerAlsa>(m_audioEngine);
7880
}
7981

8082
m_audioWorker = std::make_unique<AudioWorker>(std::move(audioRecorder), std::move(audioPlayer), m_audioEngine);

src/application/service/audio_worker.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#include <QTimer>
2121
#include <QVariantList>
2222

23-
#include <RtAudio.h>
2423
#include <memory>
2524

2625
namespace noteahead {

0 commit comments

Comments
 (0)