#pragma once #include "common.hpp" #include "engine/Light.hpp" namespace rack { namespace engine { static const int PORT_MAX_CHANNELS = 16; struct alignas(32) Port { /** Voltage of the port. */ union { /** Unstable API. Use getVoltage() and setVoltage() instead. */ float voltages[PORT_MAX_CHANNELS] = {}; /** DEPRECATED. Unstable API. Use getVoltage() and setVoltage() instead. */ float value; }; /** Number of polyphonic channels Unstable API. Use set/getChannels() instead. May be 0 to PORT_MAX_CHANNELS. */ uint8_t channels = 0; /** Unstable API. Use isConnected() instead. */ bool active = false; /** For rendering plug lights on cables. Green for positive, red for negative, and blue for polyphonic. */ Light plugLights[3]; void setVoltage(float voltage, int channel = 0) { voltages[channel] = voltage; } /** Returns the voltage of the given channel. Because of proper bookkeeping, all channels higher than the input port's number of channels should be 0V. */ float getVoltage(int channel = 0) { return voltages[channel]; } /** Returns the given channel's voltage if the port is polyphonic, otherwise returns the first voltage (channel 0). */ float getPolyVoltage(int channel) { return (channels == 1) ? getVoltage(channel) : getVoltage(0); } /** Returns the voltage if a cable is connected, otherwise returns the given normal voltage. */ float getNormalVoltage(float normalVoltage, int channel = 0) { return isConnected() ? getVoltage(channel) : normalVoltage; } float getNormalPolyVoltage(float normalVoltage, int channel) { return isConnected() ? getPolyVoltage(channel) : normalVoltage; } /** Reads all voltage values from an array of size `channels` */ void setVoltages(const float *voltages) { for (int c = 0; c < channels; c++) { this->voltages[c] = voltages[c]; } } /** Writes all voltage values to an array of size `channels` */ void getVoltages(float *voltages) { for (int c = 0; c < channels; c++) { voltages[c] = this->voltages[c]; } } /** Sets the number of polyphony channels. */ void setChannels(int channels) { // Set higher channel voltages to 0 for (int c = channels; c < this->channels; c++) { voltages[c] = 0.f; } this->channels = channels; } int getChannels() { return channels; } /** Returns if a cable is connected to the Port. You can use this for skipping code that generates output voltages. */ bool isConnected() { return active; } void process(float deltaTime); /** Use getNormalVoltage() instead. */ DEPRECATED float normalize(float normalVoltage) { return getNormalVoltage(normalVoltage); } }; struct Output : Port { Output() { channels = 1; } }; struct Input : Port {}; } // namespace engine } // namespace rack