QtFM::Patch Class
The Patch class holds one complete, self-describing sound. More…
| Header | #include <QtFM> |
|---|---|
| CMake | target_link_libraries(app PRIVATE Nt::FM) |
| Module | Nt FM C++ Classes |
List of all members, including inherited members
Public Functions
| Patch() | |
| Patch(const Patch &other) | |
| Patch(Patch &&other) | |
| Patch & | operator=(const Patch &other) |
| Patch & | operator=(Patch &&other) |
| ~Patch() | |
| QByteArray | toJson() const |
| QByteArray | toCbor() const |
| QByteArray | toChipInstrument(InstrumentFormat format, QString *error = nullptr) const |
| Patch | mutated(float amount, quint32 seed) const |
| bool | fitsChip(ChipType chip, QStringList *violations = nullptr) const |
| bool | isValid() const |
| QString | name() const |
| QString | category() const |
| ChipType | chip() const |
| int | operatorCount() const |
| bool | isLoop() const |
| float | duration() const |
| bool | operator==(const Patch &other) const |
| bool | operator!=(const Patch &other) const |
Static Public Members
| Patch | fromJson(const QByteArray &json, QString *error = nullptr) |
| Patch | fromCbor(const QByteArray &cbor, QString *error = nullptr) |
| Patch | fromChipInstrument(const QByteArray &data, InstrumentFormat format, QString *error = nullptr) |
| Patch | generate(Category category, quint32 seed, ChipType target = ChipType::None) |
Detailed Description
A patch describes four operators and their routing, envelopes, pitch movement, an LFO, noise, a filter, a bit crusher and a block of random variance. It plays at any pitch and length, and is stored as JSON of a few hundred bytes:
const char *laserJson = R"({
"format": "qtfm-patch", "version": 1, "name": "laser-small", "category": "laser",
"algorithm": 5, "feedback": 3,
"operators": [
{ "ratio": 1.0, "level": 1.0, "env": { "a": 0, "d": 0.12, "s": 0, "r": 0.05 } },
{ "ratio": 3.5, "level": 0.6, "env": { "a": 0, "d": 0.08, "s": 0, "r": 0.02 } },
{ "ratio": 1.0, "level": 0.8, "env": { "a": 0, "d": 0.15, "s": 0, "r": 0.05 } },
{ "ratio": 7.0, "level": 0.3, "env": { "a": 0, "d": 0.05, "s": 0, "r": 0.02 } }
],
"pitch": { "base": "A5", "env": { "start": 12, "end": -24, "time": 0.18, "curve": -2 } },
"filter": { "type": "lowpass", "cutoff": 8000, "resonance": 0.2 },
"random": { "pitch.base": 2, "operators.1.ratio": 0.25 },
"gain": -6
})";
Patch is a value type and implicitly shared. A default-constructed patch is invalid; make one with fromJson(), fromCbor(), fromChipInstrument() or generate(). Unknown JSON keys are ignored, missing keys take their defaults, and out-of-range values are clamped, so isValid() is false only for a document that is not a patch at all.
See also QtFM::Engine and Using Nt FM.
Differences from Qt
A patch cannot yet be edited field by field from C++: edit its JSON. Only the SBI instrument format is imported, and patches are not yet exported to chip formats.
Member Function Documentation
QtFM::Patch::Patch()
Constructs an invalid patch.
QtFM::Patch::Patch(const Patch &other)
Constructs a copy of other.
QtFM::Patch::Patch(Patch &&other)
Move-constructs a patch from other.
QtFM::Patch::~Patch()
Destroys the patch.
QString QtFM::Patch::category() const
Returns the category of the patch, such as laser, as written in its category field.
ChipType QtFM::Patch::chip() const
Returns the chip that the patch targets, or ChipType::None.
float QtFM::Patch::duration() const
Returns the length of a note in seconds before it is released, or -1 if the patch has no fixed length: it then runs through its envelopes once, or sustains if isLoop().
bool QtFM::Patch::fitsChip(ChipType chip, QStringList *violations = nullptr) const
Returns true if the patch can be played by chip as it is: its operator count, waveforms, multipliers, feedback and envelopes are within the chip's limits, and it uses no noise, filter, crusher or modulation-index envelope. The fields that are not are appended to violations. Every patch fits ChipType::None.
Patch QtFM::Patch::fromCbor(const QByteArray &cbor, QString *error = nullptr)
Returns the patch in the CBOR encoding cbor, as toCbor() writes it, or an invalid patch, with the reason in error.
Patch QtFM::Patch::fromChipInstrument(const QByteArray &data, InstrumentFormat format, QString *error = nullptr)
Returns the native patch of a chip instrument in data, stored in format, or an invalid patch, with the reason in error. The parameters map onto the native engine: an OPL2 instrument becomes a two-operator patch with the same multipliers, waveforms, feedback, connection and envelopes. The result sounds close to the chip, without its quantisation.
Patch QtFM::Patch::fromJson(const QByteArray &json, QString *error = nullptr)
Returns the patch in the JSON document json, or an invalid patch, with the reason in error, if it is not a patch.
See also toJson().
Patch QtFM::Patch::generate(Category category, quint32 seed, ChipType target = ChipType::None)
Returns a random but plausible patch of category, drawn from seed: the same seed always gives the same patch. If target is a chip, the patch keeps to that chip's limits (two operators and the OPL waveforms for ChipType::OPL2, no noise or filter), for authentic chip sounds.
const Patch blip = Patch::generate(Category::Blip, 8);
bool QtFM::Patch::isLoop() const
Returns true if the patch sustains until it is stopped.
bool QtFM::Patch::isValid() const
Returns true if the patch holds a sound.
Patch QtFM::Patch::mutated(float amount, quint32 seed) const
Returns a variation of the patch: its times, ratios, levels, pitch movement and cutoff are each scaled by a random factor of up to amount (0.1 for 10%), drawn from seed. A patch for a chip keeps its ratios on the chip's multipliers.
QString QtFM::Patch::name() const
Returns the name of the patch.
bool QtFM::Patch::operator!=(const Patch &other) const
Returns true if this patch and other differ.
Patch & QtFM::Patch::operator=(const Patch &other)
Assigns other to this patch and returns a reference to it.
Patch & QtFM::Patch::operator=(Patch &&other)
Move-assigns other to this patch and returns a reference to it.
bool QtFM::Patch::operator==(const Patch &other) const
Returns true if this patch and other hold the same sound.
int QtFM::Patch::operatorCount() const
Returns the number of operators of the patch: 2 or 4.
QByteArray QtFM::Patch::toCbor() const
Returns the patch encoded as CBOR, a smaller form for embedded targets.
See also fromCbor().
QByteArray QtFM::Patch::toChipInstrument(InstrumentFormat format, QString *error = nullptr) const
Returns the patch as a chip instrument in format, or an empty array, with the reason in error, if the patch cannot be expressed in it. Only InstrumentFormat::Sbi is a single instrument; it needs a patch of two operators, and maps it to the nearest OPL2 values.
See also fitsChip() and QtFM::PatchBank::toChipBank().
QByteArray QtFM::Patch::toJson() const
Returns the JSON document of the patch, with every field written, so that fromJson() gives back an equal patch. Returns an empty array for an invalid patch.