34class Type final :
public Selection,
public FormattedTitle {
36 Type(l10n::String name, l10n::String title_format_str, uint8_t source_id)
37 :
Selection(name), FormattedTitle(title_format_str, source_id + 1), sourceId_{source_id} {};
40 bool mayUseDx()
const {
return !soundEditor.editingKit() && sourceId_ == 0; }
43 int32_t rawVal =
static_cast<int32_t
>(soundEditor.currentSound->sources[sourceId_].oscType);
44 if (!mayUseDx() && rawVal >
static_cast<int32_t
>(OscType::DX7)) {
49 void writeCurrentValue()
override {
50 OscType oldValue = soundEditor.currentSound->sources[sourceId_].oscType;
51 auto newValue = getValue<OscType>();
52 if (!mayUseDx() &&
static_cast<int32_t
>(newValue) >=
static_cast<int32_t
>(OscType::DX7)) {
53 newValue =
static_cast<OscType
>(
static_cast<int32_t
>(newValue) + 1);
56 const auto needs_unassignment = {
59 OscType::INPUT_STEREO,
67 if (util::one_of(oldValue, needs_unassignment) || util::one_of(newValue, needs_unassignment)) {
68 soundEditor.currentSound->killAllVoices();
71 soundEditor.currentSound->sources[sourceId_].setOscType(newValue);
73 if (oldValue == OscType::SQUARE || newValue == OscType::SQUARE) {
74 soundEditor.currentSound->setupPatchingForAllParamManagers(currentSong);
78 [[nodiscard]] std::string_view
getTitle()
const override {
return FormattedTitle::title(); }
80 deluge::vector<std::string_view> getOptions(OptType optType)
override {
82 using enum l10n::String;
83 deluge::vector options = {
84 l10n::getView(STRING_FOR_SINE),
85 l10n::getView(STRING_FOR_TRIANGLE),
86 l10n::getView(STRING_FOR_SQUARE),
87 l10n::getView(STRING_FOR_ANALOG_SQUARE),
88 l10n::getView(STRING_FOR_SAW),
89 l10n::getView(STRING_FOR_ANALOG_SAW),
90 l10n::getView(STRING_FOR_WAVETABLE),
93 if (soundEditor.currentSound->getSynthMode() == SynthMode::RINGMOD) {
97 options.emplace_back(l10n::getView(STRING_FOR_SAMPLE));
100 options.emplace_back(l10n::getView(STRING_FOR_DX7));
103 if (AudioEngine::micPluggedIn || AudioEngine::lineInPluggedIn) {
104 options.emplace_back(l10n::getView(STRING_FOR_INPUT_LEFT));
105 options.emplace_back(l10n::getView(STRING_FOR_INPUT_RIGHT));
106 options.emplace_back(l10n::getView(STRING_FOR_INPUT_STEREO));
109 options.emplace_back(l10n::getView(STRING_FOR_INPUT));
116 Sound* sound =
static_cast<Sound*
>(modControllable);
117 return (sound->getSynthMode() != SynthMode::FM);
121 if (soundEditor.currentSound->sources[sourceId_].oscType != OscType::DX7) {
129 void renderInHorizontalMenu(int32_t startX, int32_t width, int32_t startY, int32_t height)
override {
132 const OscType oscType = soundEditor.currentSound->sources[sourceId_].oscType;
133 if (oscType == OscType::DX7) {
134 const auto option = getOptions(OptType::FULL)[getValue()].data();
135 return image.drawStringCentered(option, startX, startY + 8, kTextTitleSpacingX, kTextTitleSizeY, width);
138 const Icon& icon = [&] {
141 return OLED::sineIcon;
142 case OscType::TRIANGLE:
143 return OLED::triangleIcon;
144 case OscType::SQUARE:
145 case OscType::ANALOG_SQUARE:
146 return OLED::squareIcon;
148 case OscType::ANALOG_SAW_2:
149 return OLED::sawIcon;
150 case OscType::SAMPLE:
151 return OLED::sampleIcon;
152 case OscType::INPUT_STEREO:
153 case OscType::INPUT_L:
154 case OscType::INPUT_R:
155 return OLED::inputIcon;
156 case OscType::WAVETABLE:
157 return OLED::wavetableIcon;
159 return OLED::sineIcon;
163 image.drawIconCentered(icon, startX, width, startY + 4);
165 if (oscType == OscType::ANALOG_SQUARE || oscType == OscType::ANALOG_SAW_2) {
166 const int32_t x = startX + 4;
167 constexpr int32_t y = OLED_MAIN_HEIGHT_PIXELS - kTextSpacingY - 8;
168 image.clearAreaExact(x - 1, y - 1, x + kTextSpacingX + 1, y + kTextSpacingY + 1);
169 image.drawChar(
'A', x, y, kTextSpacingX, kTextSpacingY);