Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions manual/src/dev/control-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ A `press` acts like a thumb piston: it does what the object does, once.
| 21 | Wind sway | tenths of a cent, 0 (off) to 100 | yes |
| 22 | Sparse loading | 1 every note, 2 every second, 3 every third | yes |
| 23 | Pedal combinations coupled | 0, 1 | yes |
| 24 | Attack emphasis | tenths of a dB, -120 to +120, 0 off | yes |
| 25 | Attack length | milliseconds, 5 to 300 | yes |

New properties are added at the end; an index is never reused.

Expand Down
2 changes: 2 additions & 0 deletions manual/src/guide/organ-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ A correction for the room and the speakers, applied to the whole organ. The orga
| **Save for this organ** | Keeps the EQ as it is now with this organ, whatever it is, the **On** box included, for its next load. Reads **Saved** or **Could not save** afterwards, and returns to its label at the next change. | | | At once |
| Ten band sliders, labelled **31.5**, **63**, **125**, **250**, **500**, **1k**, **2k**, **4k**, **8k**, **16k** | One slider for each octave band, in Hz. The lowest and highest bands are shelves; the other eight are peaks (Q 1.4). A double-click returns a slider to 0. | 0 dB | -12 to +12 dB in steps of 0.5 | At once |
| **Gain** | The output gain, to make up for what the bands add or take. | 0 dB | -12 to +12 dB in steps of 0.5 | At once |
| **Attack** and **over** | The attack's emphasis: each pipe begins this much louder, or softer when negative, and comes to its own level in a straight line over the time given. More or less chiff, on the pipes' own speech; noises and releases start as recorded. Applies whether the EQ is on or off. | 0 dB (off), 40 ms | -12 to +12 dB in steps of 0.5; 5 to 300 ms | From the next note |

Every organ starts from the default EQ, which is off and flat until **Save as default** keeps another. An organ gets an EQ of its own only from **Save for this organ**; other saves of the organ file leave it on the default. Changes on the tab are live and are kept only by these buttons. A preset changes the live EQ the same way: **Save for this organ** or **Save as default** keeps it.

Expand Down Expand Up @@ -229,6 +230,7 @@ The organ file is `organs/<organ key>.mporgan` in the data folder (see [General
| `buses`, `busir`, `groups` | The mixer's pairs, per-pair rooms and groups | The **Mixer** tab |
| `route <rank> bus <n>` | The pair of one rank | The **Mixer** tab |
| `voicingadj`, `voicingslot` | The voicing sets A and B and the live slot | The **Voicing** tab |
| `attack` | The attack's emphasis in dB and its length in ms, as `attack 4.0 60`; absent while it is off | Any write of the organ file after it is set |
| `eq` | The organ's own equaliser, written whatever it is, off and flat included; absent while the organ plays the default EQ (`defaulteq` in the [global file](general-settings.md#the-global-file)) | **Save for this organ** on the **Voicing EQ** tab |
| `skipstop`, `skipperspective`, `skiprank` | One item left out | The **Stops and perspectives** tab |
| `portable` | `1` | **Keep this organ playable without its installation files** |
Expand Down
2 changes: 2 additions & 0 deletions protocol/control.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ program:
- {index: 21, name: windSway, min: 0, max: 100, access: set, doc: The wind's slow pitch sway in tenths of a cent - 0 off}
- {index: 22, name: sparseLoading, min: 1, max: 3, access: set, doc: "How many notes of a rank are loaded: 1 every note, 2 every second, 3 every third"}
- {index: 23, name: pedalCombinationsCoupled, min: 0, max: 1, access: set, doc: The first manual's divisionals also recall the Pedal's of the same number}
- {index: 24, name: attackDb, min: -120, max: 120, access: set, doc: "The attack's emphasis in tenths of a dB: each pipe begins this much louder, or softer, and comes to its own level over attackMs. 0 is off"}
- {index: 25, name: attackMs, min: 5, max: 300, access: set, doc: How long the attack's emphasis lasts, in milliseconds}

# Commands (type 9), pressed.
commands:
Expand Down
4 changes: 4 additions & 0 deletions resources/translations/cs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -992,3 +992,7 @@ countries: cz
"Learn a knob or a pedal for this level" = "Naučit otočný ovladač nebo pedál pro tuto úroveň"
"Learn: move the knob or pedal" = "Učení: pohněte ovladačem nebo pedálem"
"Move it..." = "Pohněte jím..."
"Attack" = "Nasazení"
"over" = "během"
"Each pipe begins this much louder, or softer, and comes to its own level: more or less chiff. 0 dB is off. Heard from the next note; saved with the organ." = "Každá píšťala začne o tolik hlasitěji nebo tišeji a pak dojde na svou vlastní úroveň: více nebo méně chiffu. 0 dB je vypnuto. Slyšet od další noty; ukládá se s varhanami."
"How long the attack's emphasis lasts" = "Jak dlouho trvá zdůraznění nasazení"
4 changes: 4 additions & 0 deletions resources/translations/de.txt
Original file line number Diff line number Diff line change
Expand Up @@ -992,3 +992,7 @@ countries: de at ch li lu
"Learn a knob or a pedal for this level" = "Einen Drehregler oder ein Pedal für diesen Pegel anlernen"
"Learn: move the knob or pedal" = "Anlernen: Drehregler oder Pedal bewegen"
"Move it..." = "Jetzt bewegen..."
"Attack" = "Ansprache"
"over" = "über"
"Each pipe begins this much louder, or softer, and comes to its own level: more or less chiff. 0 dB is off. Heard from the next note; saved with the organ." = "Jede Pfeife setzt um so viel lauter oder leiser ein und kommt dann auf ihren eigenen Pegel: mehr oder weniger Vorläuferton. 0 dB ist aus. Ab dem nächsten Ton zu hören; mit der Orgel gespeichert."
"How long the attack's emphasis lasts" = "Wie lange die Betonung der Ansprache dauert"
4 changes: 4 additions & 0 deletions resources/translations/es.txt
Original file line number Diff line number Diff line change
Expand Up @@ -992,3 +992,7 @@ countries: es ar bo cl co cr cu do ec gt hn mx ni pa pe pr py sv uy ve
"Learn a knob or a pedal for this level" = "Aprender una perilla o un pedal para este nivel"
"Learn: move the knob or pedal" = "Aprender: mueva la perilla o el pedal"
"Move it..." = "Muévalo..."
"Attack" = "Ataque"
"over" = "durante"
"Each pipe begins this much louder, or softer, and comes to its own level: more or less chiff. 0 dB is off. Heard from the next note; saved with the organ." = "Cada tubo empieza así de más fuerte, o más suave, y llega a su propio nivel: más o menos chiff. 0 dB es apagado. Se oye desde la próxima nota; se guarda con el órgano."
"How long the attack's emphasis lasts" = "Cuánto dura el énfasis del ataque"
4 changes: 4 additions & 0 deletions resources/translations/fr.txt
Original file line number Diff line number Diff line change
Expand Up @@ -992,3 +992,7 @@ countries: fr be ca ch lu mc
"Learn a knob or a pedal for this level" = "Apprendre un bouton ou une pédale pour ce niveau"
"Learn: move the knob or pedal" = "Apprendre : bougez le bouton ou la pédale"
"Move it..." = "Bougez-le..."
"Attack" = "Attaque"
"over" = "sur"
"Each pipe begins this much louder, or softer, and comes to its own level: more or less chiff. 0 dB is off. Heard from the next note; saved with the organ." = "Chaque tuyau commence d'autant plus fort, ou plus doux, puis rejoint son propre niveau : plus ou moins de chiff. 0 dB, c'est désactivé. Entendu dès la note suivante ; enregistré avec l'orgue."
"How long the attack's emphasis lasts" = "Durée de l'accentuation de l'attaque"
4 changes: 4 additions & 0 deletions resources/translations/it.txt
Original file line number Diff line number Diff line change
Expand Up @@ -992,3 +992,7 @@ countries: it ch sm va
"Learn a knob or a pedal for this level" = "Apprendere una manopola o un pedale per questo livello"
"Learn: move the knob or pedal" = "Apprendi: muovi la manopola o il pedale"
"Move it..." = "Muovilo..."
"Attack" = "Attacco"
"over" = "in"
"Each pipe begins this much louder, or softer, and comes to its own level: more or less chiff. 0 dB is off. Heard from the next note; saved with the organ." = "Ogni canna inizia di tanto più forte, o più piano, e poi torna al suo livello: più o meno chiff. 0 dB è spento. Udito dalla nota successiva; salvato con l'organo."
"How long the attack's emphasis lasts" = "Quanto dura l'enfasi dell'attacco"
4 changes: 4 additions & 0 deletions resources/translations/nl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -992,3 +992,7 @@ countries: nl be sr
"Learn a knob or a pedal for this level" = "Een draaiknop of pedaal voor dit niveau leren"
"Learn: move the knob or pedal" = "Leren: beweeg de draaiknop of het pedaal"
"Move it..." = "Beweeg hem..."
"Attack" = "Aanspraak"
"over" = "over"
"Each pipe begins this much louder, or softer, and comes to its own level: more or less chiff. 0 dB is off. Heard from the next note; saved with the organ." = "Elke pijp begint zoveel luider of zachter en komt dan op zijn eigen niveau: meer of minder chiff. 0 dB is uit. Te horen vanaf de volgende noot; opgeslagen met het orgel."
"How long the attack's emphasis lasts" = "Hoe lang de nadruk op de aanspraak duurt"
4 changes: 4 additions & 0 deletions resources/translations/pl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -992,3 +992,7 @@ countries: pl
"Learn a knob or a pedal for this level" = "Naucz pokrętło lub pedał dla tego poziomu"
"Learn: move the knob or pedal" = "Nauka: porusz pokrętłem lub pedałem"
"Move it..." = "Porusz nim..."
"Attack" = "Atak"
"over" = "przez"
"Each pipe begins this much louder, or softer, and comes to its own level: more or less chiff. 0 dB is off. Heard from the next note; saved with the organ." = "Każda piszczałka zaczyna o tyle głośniej lub ciszej i dochodzi do własnego poziomu: więcej lub mniej chiffu. 0 dB to wyłączone. Słychać od następnej nuty; zapisywane z organami."
"How long the attack's emphasis lasts" = "Jak długo trwa podkreślenie ataku"
4 changes: 4 additions & 0 deletions resources/translations/strings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ countries: gb us
"Back to the default EQ, and forget the one saved for this organ" = "Back to the default EQ, and forget the one saved for this organ"
"A correction for the room and the speakers, on the whole organ. Off unless turned on here; the organ as recorded is the reference." = "A correction for the room and the speakers, on the whole organ. Off unless turned on here; the organ as recorded is the reference."
"Gain" = "Gain"
"Attack" = "Attack"
"over" = "over"
"Each pipe begins this much louder, or softer, and comes to its own level: more or less chiff. 0 dB is off. Heard from the next note; saved with the organ." = "Each pipe begins this much louder, or softer, and comes to its own level: more or less chiff. 0 dB is off. Heard from the next note; saved with the organ."
"How long the attack's emphasis lasts" = "How long the attack's emphasis lasts"
"Presets" = "Presets"
"Your presets" = "Your presets"
"Edited" = "Edited"
Expand Down
4 changes: 3 additions & 1 deletion resources/web/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@
"pipeDetune",
"windSway",
"sparseLoading",
"pedalCombinationsCoupled"
"pedalCombinationsCoupled",
"attackDb",
"attackMs"
]
}
},
Expand Down
4 changes: 4 additions & 0 deletions src/mp_api/ControlModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ int ControlModel::programValue(ProgramProp prop) {
case ProgramProp::WindSway: return juce::roundToInt(proc_.windSwayCents() * 10.0f);
case ProgramProp::SparseLoading: return proc_.sparseEvery();
case ProgramProp::PedalCombinationsCoupled: return proc_.pedalCombinationsCoupled() ? 1 : 0;
case ProgramProp::AttackDb: return juce::roundToInt(proc_.attackDb() * 10.0f);
case ProgramProp::AttackMs: return proc_.attackMs();
}
return 0;
}
Expand Down Expand Up @@ -778,6 +780,8 @@ Error ControlModel::setProgram(ProgramProp prop, int value) {
case ProgramProp::WindSway: proc_.setWindSwayCents(static_cast<float>(value) / 10.0f); break;
case ProgramProp::SparseLoading: proc_.setSparseEvery(value); break;
case ProgramProp::PedalCombinationsCoupled: proc_.setPedalCombinationsCoupled(value == 1); break;
case ProgramProp::AttackDb: proc_.setAttack(static_cast<float>(value) / 10.0f, proc_.attackMs()); break;
case ProgramProp::AttackMs: proc_.setAttack(proc_.attackDb(), value); break;
default: return Error::ReadOnly;
}
return Error::None;
Expand Down
6 changes: 5 additions & 1 deletion src/mp_api/ControlProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ enum class ProgramProp : uint8_t {
WindSway = 21,
SparseLoading = 22,
PedalCombinationsCoupled = 23,
AttackDb = 24,
AttackMs = 25,
};

struct ProgramPropInfo {
Expand Down Expand Up @@ -178,8 +180,10 @@ constexpr ProgramPropInfo kProgram[] = {
{ProgramProp::WindSway, "windSway", 0, 100, true, "The wind's slow pitch sway in tenths of a cent - 0 off"},
{ProgramProp::SparseLoading, "sparseLoading", 1, 3, true, "How many notes of a rank are loaded: 1 every note, 2 every second, 3 every third"},
{ProgramProp::PedalCombinationsCoupled, "pedalCombinationsCoupled", 0, 1, true, "The first manual's divisionals also recall the Pedal's of the same number"},
{ProgramProp::AttackDb, "attackDb", -120, 120, true, "The attack's emphasis in tenths of a dB: each pipe begins this much louder, or softer, and comes to its own level over attackMs. 0 is off"},
{ProgramProp::AttackMs, "attackMs", 5, 300, true, "How long the attack's emphasis lasts"},
};
constexpr int kProgramCount = 24;
constexpr int kProgramCount = 26;

enum class Command : uint8_t {
Panic = 0,
Expand Down
17 changes: 17 additions & 0 deletions src/mp_audio/MasterpieceProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2096,6 +2096,7 @@ bool MasterpieceProcessor::saveSettings() const {
// Written whatever it is, off and flat too: an organ with a line keeps
// it, and one without plays the default EQ.
if (organOwnsEq_) text << "eq " << juce::String(voicingEqSettings_.toLine()) << "\n";
if (attackDb() != 0.0f) text << "attack " << juce::String(attackDb(), 1) << " " << attackMs() << "\n";
}

return f.replaceWithText(text);
Expand Down Expand Up @@ -2123,6 +2124,8 @@ bool MasterpieceProcessor::loadSettingsFor(const juce::File& odf) {
// note, and this one's own file says which notes it keeps.
sparseEvery_ = 1;
samples_.setSparseEvery(1);
attackDb_.store(0.0f, std::memory_order_relaxed);
attackMs_.store(40, std::memory_order_relaxed);
excludedStops_.clear();
excludedPerspectives_.clear();
excludedRanks_.clear();
Expand Down Expand Up @@ -2258,6 +2261,14 @@ bool MasterpieceProcessor::loadSettingsFor(const juce::File& odf) {
windSwayCents_.store(juce::jlimit(0.0f, kMaxUnevennessCents, val.getFloatValue()), std::memory_order_relaxed);
continue;
}
if (key == "attack") {
const auto tok = juce::StringArray::fromTokens(val, " ", "");
if (tok.size() >= 2) {
attackDb_.store(juce::jlimit(-12.0f, 12.0f, tok[0].getFloatValue()), std::memory_order_relaxed);
attackMs_.store(juce::jlimit(5, 300, tok[1].getIntValue()), std::memory_order_relaxed);
}
continue;
}
if (key == "skipstop") {
excludedStops_.insert(static_cast<Id>(val.getLargeIntValue()));
continue;
Expand Down Expand Up @@ -3792,6 +3803,12 @@ bool MasterpieceProcessor::startPipeLayers(const Pipe& pipe, Id rankId,
}
vs.mixBus = mixBusForPipe(rankId, midiNote);
vs.rankIndex = liveRankIndexOf(rankId);
// The attack's emphasis, for a pipe's own speech only: a noise and a
// release start as they were recorded.
if (const float db = attackDb(); db != 0.0f) {
vs.attackBoost = juce::Decibels::decibelsToGain(db) - 1.0f;
vs.attackFrames = static_cast<int>(attackMs() * 0.001 * sampleRate_);
}
{
const auto wIt = pipeWindIndex_.find(pipe.pipeId);
vs.windIndex = wIt == pipeWindIndex_.end() ? -1 : wIt->second;
Expand Down
14 changes: 14 additions & 0 deletions src/mp_audio/MasterpieceProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1506,6 +1506,18 @@ class MasterpieceProcessor : public juce::AudioProcessor {
const VoicingEqSettings& defaultVoicingEq() const { return defaultEq_; }
bool organHasOwnVoicingEq() const { return organOwnsEq_; }

// The attack's emphasis (Organ settings, Voicing EQ): each pipe begins
// `db` louder, or softer when negative, and comes to its own level in a
// straight line over `ms`. 0 dB is off, and then no voice does anything
// for it. Saved with the organ; heard from the next note.
float attackDb() const { return attackDb_.load(std::memory_order_relaxed); }
int attackMs() const { return attackMs_.load(std::memory_order_relaxed); }
void setAttack(float db, int ms) {
attackDb_.store(juce::jlimit(-12.0f, 12.0f, db), std::memory_order_relaxed);
attackMs_.store(juce::jlimit(5, 300, ms), std::memory_order_relaxed);
markSettingsDirty();
}

// The EQ's presets, program-wide: ten of the program's and the player's own
// (VoicingEqPresets.h). Recalling one sets the EQ at once and turns it on,
// as moving the sliders does; Save for this organ and Save as default keep
Expand Down Expand Up @@ -2162,6 +2174,8 @@ class MasterpieceProcessor : public juce::AudioProcessor {
int voicingEqChanges_ = 0; // message thread only
std::atomic<int> pendingEqPreset_{0};
bool organOwnsEq_ = false; // the organ's file has an `eq` line
std::atomic<float> attackDb_{0.0f};
std::atomic<int> attackMs_{40};
VoicingEq voicingEq_;
Favourites favourites_;
// Empty means the organ's default set.
Expand Down
Loading
Loading