Skip to content

Commit 7fd8e6e

Browse files
committed
Calculate CC/PBmodulation amplitudes from the full/half range
1 parent e573513 commit 7fd8e6e

37 files changed

+394
-279
lines changed

src/application/application.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,12 @@ Application::Application(int & argc, char ** argv)
7272
, m_applicationService { std::make_shared<ApplicationService>() }
7373
, m_settingsService { std::make_shared<SettingsService>() }
7474
, m_selectionService { std::make_shared<SelectionService>() }
75-
, m_editorService { std::make_shared<EditorService>(m_selectionService, m_settingsService) }
75+
, m_utilService { std::make_shared<UtilService>() }
76+
, m_propertyService { std::make_shared<PropertyService>() }
77+
, m_automationService { std::make_shared<AutomationService>(m_propertyService) }
78+
, m_editorService { std::make_shared<EditorService>(m_selectionService, m_settingsService, m_automationService) }
7679
, m_jackService { std::make_shared<JackService>(m_settingsService) }
7780
, m_audioService { std::make_shared<AudioService>(m_settingsService, m_jackService) }
78-
, m_automationService { std::make_shared<AutomationService>() }
7981
, m_eventSelectionModel { std::make_shared<EventSelectionModel>() }
8082
, m_midiService { std::make_shared<MidiService>() }
8183
, m_mixerService { std::make_shared<MixerService>() }
@@ -93,15 +95,12 @@ Application::Application(int & argc, char ** argv)
9395
, m_trackSettingsModel { std::make_unique<TrackSettingsModel>() }
9496
, m_midiSettingsModel { std::make_unique<MidiSettingsModel>(m_settingsService) }
9597
, m_audioSettingsModel { std::make_unique<AudioSettingsModel>(m_audioService, m_settingsService) }
96-
, m_utilService { std::make_shared<UtilService>() }
97-
, m_propertyService { std::make_shared<PropertyService>() }
9898
, m_noteColumnLineContainerHelper { std::make_shared<NoteColumnLineContainerHelper>(
9999
m_automationService, m_editorService, m_selectionService, m_utilService) }
100100
, m_noteColumnModelHandler { std::make_unique<NoteColumnModelHandler>(m_editorService, m_selectionService, m_automationService, m_settingsService) }
101101
, m_engine { std::make_unique<QQmlApplicationEngine>() }
102102
{
103103
m_editorService->setMixerService(m_mixerService);
104-
m_editorService->setAutomationService(m_automationService);
105104
registerTypes();
106105

107106
handleCommandLineArguments(argc, argv); // Handle command-line arguments at initialization

src/application/application.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,17 @@ class Application : public QObject
126126
std::shared_ptr<SettingsService> m_settingsService;
127127

128128
std::shared_ptr<SelectionService> m_selectionService;
129+
130+
std::shared_ptr<UtilService> m_utilService;
131+
std::shared_ptr<PropertyService> m_propertyService;
132+
std::shared_ptr<AutomationService> m_automationService;
133+
129134
std::shared_ptr<EditorService> m_editorService;
130135

131136
std::shared_ptr<JackService> m_jackService;
132137

133138
std::shared_ptr<AudioService> m_audioService;
134139

135-
std::shared_ptr<AutomationService> m_automationService;
136-
137140
std::shared_ptr<EventSelectionModel> m_eventSelectionModel;
138141

139142
std::shared_ptr<MidiService> m_midiService;
@@ -157,9 +160,6 @@ class Application : public QObject
157160
std::unique_ptr<MidiSettingsModel> m_midiSettingsModel;
158161
std::unique_ptr<AudioSettingsModel> m_audioSettingsModel;
159162

160-
std::shared_ptr<UtilService> m_utilService;
161-
std::shared_ptr<PropertyService> m_propertyService;
162-
163163
std::shared_ptr<NoteColumnLineContainerHelper> m_noteColumnLineContainerHelper;
164164
std::unique_ptr<NoteColumnModelHandler> m_noteColumnModelHandler;
165165

src/application/service/automation_service.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "../../domain/midi_cc_data.hpp"
2222
#include "../../domain/pitch_bend_data.hpp"
2323
#include "../position.hpp"
24+
#include "property_service.hpp"
2425

2526
#include <algorithm>
2627
#include <cmath> // For std::sin and M_PI
@@ -34,7 +35,8 @@ namespace noteahead {
3435

3536
static const auto TAG = "AutomationService";
3637

37-
AutomationService::AutomationService()
38+
AutomationService::AutomationService(std::shared_ptr<PropertyService> propertyService) :
39+
m_propertyService { propertyService }
3840
{
3941
}
4042

@@ -416,9 +418,9 @@ AutomationService::EventList AutomationService::renderMidiCcToEventsByLine(size_
416418
totalModulation = modulationValue * modulation.amplitude / 100.0; // Amplitude is a percentage
417419
}
418420
totalModulation += modulation.offset / 100.0;
419-
interpolatedValue += interpolatedValue * totalModulation;
421+
interpolatedValue += totalModulation * m_propertyService->maxValue(automation.controller());
420422

421-
const auto clampedValue = std::clamp(static_cast<int>(std::round(interpolatedValue)), 0, 127); // MIDI CC value range
423+
const auto clampedValue = std::clamp(static_cast<int>(std::round(interpolatedValue)), 0, m_propertyService->maxValue(automation.controller())); // MIDI CC value range
422424
events.push_back(std::make_shared<Event>(tick, MidiCcData { track, column, automation.controller(), static_cast<uint8_t>(clampedValue) }));
423425
}
424426
}
@@ -473,7 +475,7 @@ AutomationService::EventList AutomationService::renderPitchBendToEventsByLine(si
473475
totalModulation = modulationValue * modulation.amplitude / 100.0; // Amplitude is a percentage
474476
}
475477
totalModulation += modulation.offset / 100.0;
476-
interpolatedValue += interpolatedValue * totalModulation;
478+
interpolatedValue += totalModulation * 100.0;
477479

478480
const auto percentage = std::clamp(static_cast<int>(std::round(interpolatedValue)), -100, 100);
479481
events.push_back(std::make_shared<Event>(tick, PitchBendData { track, column, static_cast<double>(percentage) }));
@@ -548,9 +550,9 @@ AutomationService::EventList AutomationService::renderMidiCcToEventsByColumn(siz
548550
totalModulation = modulationValue * modulation.amplitude / 100.0;
549551
}
550552
totalModulation += modulation.offset / 100.0;
551-
interpolatedValue += interpolatedValue * totalModulation;
553+
interpolatedValue += totalModulation * m_propertyService->maxValue(automation.controller());
552554

553-
const auto clampedValue = std::clamp(static_cast<int>(std::round(interpolatedValue)), 0, 127); // MIDI CC value range
555+
const auto clampedValue = std::clamp(static_cast<int>(std::round(interpolatedValue)), 0, m_propertyService->maxValue(automation.controller())); // MIDI CC value range
554556
if (!prevValue || *prevValue != clampedValue) {
555557
events.push_back(std::make_shared<Event>(tick + line * ticksPerLine, MidiCcData { track, column, automation.controller(), static_cast<uint8_t>(clampedValue) }));
556558
prevValue = clampedValue;
@@ -595,7 +597,7 @@ AutomationService::EventList AutomationService::renderPitchBendToEventsByColumn(
595597
totalModulation = modulationValue * modulation.amplitude / 100.0;
596598
}
597599
totalModulation += modulation.offset / 100.0;
598-
interpolatedValue += interpolatedValue * totalModulation;
600+
interpolatedValue += totalModulation * 100.0;
599601

600602
const auto percentage = std::clamp(static_cast<int>(std::round(interpolatedValue)), -100, 100);
601603
const double minDiff = 200.0 / 16383;

src/application/service/automation_service.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ namespace noteahead {
3333

3434
struct Position;
3535

36+
class PropertyService;
37+
3638
class AutomationService : public QObject
3739
{
3840
Q_OBJECT
3941

4042
public:
41-
AutomationService();
43+
AutomationService(std::shared_ptr<PropertyService> propertyService);
4244

4345
void clear();
4446

@@ -122,6 +124,7 @@ public slots:
122124
};
123125

124126
Automations m_automations;
127+
std::shared_ptr<PropertyService> m_propertyService;
125128
};
126129

127130
} // namespace noteahead

src/application/service/editor_service.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
// You should have received a copy of the GNU General Public License
1414
// along with Noteahead. If not, see <http://www.gnu.org/licenses/>.
1515

16-
#include "automation_service.hpp"
1716
#include "../../domain/pattern.hpp"
1817
#include "editor_service.hpp"
1918

@@ -28,8 +27,10 @@
2827
#include "../command/composite_command.hpp"
2928
#include "../instrument_request.hpp"
3029
#include "../note_converter.hpp"
30+
#include "automation_service.hpp"
3131
#include "copy_manager.hpp"
3232
#include "mixer_service.hpp"
33+
#include "property_service.hpp"
3334
#include "selection_service.hpp"
3435
#include "settings_service.hpp"
3536

@@ -45,15 +46,15 @@ using namespace std::chrono_literals;
4546
static const auto TAG = "EditorService";
4647

4748
EditorService::EditorService()
48-
: EditorService { std::make_shared<SelectionService>(), std::make_shared<SettingsService>() }
49+
: EditorService { std::make_shared<SelectionService>(), std::make_shared<SettingsService>(), std::make_shared<AutomationService>(std::make_shared<PropertyService>()) }
4950
{
5051
}
5152

52-
EditorService::EditorService(SelectionServiceS selectionService, SettingsServiceS settingsService)
53+
EditorService::EditorService(SelectionServiceS selectionService, SettingsServiceS settingsService, AutomationServiceS automationService)
5354
: m_undoStack { std::make_unique<UndoStack>() }
5455
, m_selectionService { selectionService }
5556
, m_settingsService { settingsService }
56-
, m_automationService { std::make_shared<AutomationService>() }
57+
, m_automationService { automationService }
5758
{
5859
initialize();
5960
m_undoStack->setCanUndoChangedCallback([this] { emit canUndoChanged(); });

src/application/service/editor_service.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class EditorService : public QObject
8080
using SettingsServiceS = std::shared_ptr<SettingsService>;
8181
using MixerServiceS = std::shared_ptr<MixerService>;
8282
using AutomationServiceS = std::shared_ptr<AutomationService>;
83-
EditorService(SelectionServiceS selectionService, SettingsServiceS settingsService);
83+
EditorService(SelectionServiceS selectionService, SettingsServiceS settingsService, AutomationServiceS automationService);
8484
~EditorService() override;
8585

8686
void initialize();

src/domain/pitch_bend_data.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
#include "pitch_bend_data.hpp"
1717

18+
#include <cmath>
19+
1820
namespace noteahead {
1921

2022
PitchBendData::PitchBendData(size_t track, size_t column, uint8_t msb, uint8_t lsb)
@@ -30,7 +32,7 @@ PitchBendData::PitchBendData(size_t track, size_t column, uint16_t value)
3032
}
3133

3234
PitchBendData::PitchBendData(size_t track, size_t column, double percentage)
33-
: PitchBendData { track, column, static_cast<uint16_t>((percentage + 100.0) * (16383.0 / 200.0)) }
35+
: PitchBendData { track, column, static_cast<uint16_t>(std::round((percentage + 100.0) * (16383.0 / 200.0))) }
3436
{
3537
}
3638

src/infra/video/video_generator.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "video_generator.hpp"
1717

1818
#include "../../application/service/automation_service.hpp"
19+
#include "../../application/service/property_service.hpp"
1920
#include "../../application/service/side_chain_service.hpp"
2021
#include "../../common/utils.hpp"
2122
#include "../../contrib/SimpleLogger/src/simple_logger.hpp"
@@ -56,7 +57,7 @@ void VideoGenerator::initialize(const VideoConfig & config, SongS song)
5657
m_config.logo = !config.logoPath.empty() ? QImage { QString::fromStdString(config.logoPath) } : QImage {};
5758

5859
m_eventMap.clear();
59-
for (auto && event : m_song->renderToEvents(std::make_shared<AutomationService>(), std::make_shared<SideChainService>(), config.startPosition)) {
60+
for (auto && event : m_song->renderToEvents(std::make_shared<AutomationService>(std::make_shared<PropertyService>()), std::make_shared<SideChainService>(), config.startPosition)) {
6061
m_eventMap[event->tick()].push_back(event);
6162
}
6263
const double tickDurationMs = 60'000 / (static_cast<double>(m_song->beatsPerMinute() * m_song->linesPerBeat() * m_song->ticksPerLine()));

src/unit_tests/application_service_test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ set(SRC
55
${NAME}.hpp
66
../../application/service/application_service.cpp
77
../../application/service/editor_service.cpp
8+
../../application/service/property_service.cpp
89
../../application/service/player_service.cpp
910
../../application/service/recent_files_manager.cpp
1011
../../application/service/automation_service.cpp

src/unit_tests/automation_service_test/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ set(SRC
55
${NAME}.hpp
66
../../application/position.hpp
77
../../application/service/automation_service.cpp
8+
../../application/service/property_service.cpp
89
../../application/service/random_service.cpp
910
../../common/constants.cpp
1011
../../common/utils.cpp
@@ -18,6 +19,7 @@ set(SRC
1819
../../domain/note_data.cpp
1920
../../domain/pitch_bend_automation.cpp
2021
../../domain/pitch_bend_data.cpp
22+
../../infra/midi/midi_cc_mapping.cpp
2123
)
2224
qt_add_executable(${NAME} ${SRC})
2325
set_target_properties(${NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${UNIT_TEST_BASE_DIR})

0 commit comments

Comments
 (0)