You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
3.1KB

  1. #pragma once
  2. #include <common.hpp>
  3. #include <engine/Light.hpp>
  4. namespace rack {
  5. namespace engine {
  6. static const int PORT_MAX_CHANNELS = 16;
  7. struct alignas(32) Port {
  8. /** Voltage of the port. */
  9. union {
  10. /** Unstable API. Use getVoltage() and setVoltage() instead. */
  11. float voltages[PORT_MAX_CHANNELS] = {};
  12. /** DEPRECATED. Unstable API. Use getVoltage() and setVoltage() instead. */
  13. float value;
  14. };
  15. /** Number of polyphonic channels
  16. Unstable API. Use set/getChannels() instead.
  17. May be 0 to PORT_MAX_CHANNELS.
  18. */
  19. uint8_t channels = 1;
  20. /** Unstable API. Use isConnected() instead. */
  21. bool active = false;
  22. /** For rendering plug lights on cables.
  23. Green for positive, red for negative, and blue for polyphonic.
  24. */
  25. Light plugLights[3];
  26. void setVoltage(float voltage, int channel = 0) {
  27. voltages[channel] = voltage;
  28. }
  29. /** Returns the voltage of the given channel.
  30. Because of proper bookkeeping, all channels higher than the input port's number of channels should be 0V.
  31. */
  32. float getVoltage(int channel = 0) {
  33. return voltages[channel];
  34. }
  35. /** Returns the given channel's voltage if the port is polyphonic, otherwise returns the first voltage (channel 0). */
  36. float getPolyVoltage(int channel) {
  37. return (channels == 1) ? getVoltage(0) : getVoltage(channel);
  38. }
  39. /** Returns the voltage if a cable is connected, otherwise returns the given normal voltage. */
  40. float getNormalVoltage(float normalVoltage, int channel = 0) {
  41. return isConnected() ? getVoltage(channel) : normalVoltage;
  42. }
  43. float getNormalPolyVoltage(float normalVoltage, int channel) {
  44. return isConnected() ? getPolyVoltage(channel) : normalVoltage;
  45. }
  46. /** Returns a pointer to the array of voltages beginning with firstChannel.
  47. The pointer can be used for reading and writing.
  48. Useful for SIMD.
  49. */
  50. float *getVoltages(int firstChannel = 0) {
  51. return &voltages[firstChannel];
  52. }
  53. /** Copies the port's voltages to an array of size at least `channels`. */
  54. void readVoltages(float *v) {
  55. for (int c = 0; c < channels; c++) {
  56. v[c] = voltages[c];
  57. }
  58. }
  59. /** Copies an array of size at least `channels` to the port's voltages.
  60. Remember to set the number of channels *before* calling this method.
  61. */
  62. void writeVoltages(const float *v) {
  63. for (int c = 0; c < channels; c++) {
  64. voltages[c] = v[c];
  65. }
  66. }
  67. /** Returns the sum of all voltages. */
  68. float getVoltageSum() {
  69. float sum = 0.f;
  70. for (int c = 0; c < channels; c++) {
  71. sum += voltages[c];
  72. }
  73. return sum;
  74. }
  75. /** Sets the number of polyphony channels. */
  76. void setChannels(int channels) {
  77. // Set higher channel voltages to 0
  78. for (int c = channels; c < this->channels; c++) {
  79. voltages[c] = 0.f;
  80. }
  81. this->channels = channels;
  82. }
  83. int getChannels() {
  84. return channels;
  85. }
  86. /** Returns if a cable is connected to the Port.
  87. You can use this for skipping code that generates output voltages.
  88. */
  89. bool isConnected() {
  90. return active;
  91. }
  92. void process(float deltaTime);
  93. /** Use getNormalVoltage() instead. */
  94. DEPRECATED float normalize(float normalVoltage) {
  95. return getNormalVoltage(normalVoltage);
  96. }
  97. };
  98. struct Output : Port {};
  99. struct Input : Port {};
  100. } // namespace engine
  101. } // namespace rack