2022-03-25 05:00:26 -04:00
|
|
|
|
|
|
|
[![Arduino CI](https://github.com/RobTillaart/WaveMix/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
|
|
|
|
[![Arduino-lint](https://github.com/RobTillaart/WaveMix/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/WaveMix/actions/workflows/arduino-lint.yml)
|
|
|
|
[![JSON check](https://github.com/RobTillaart/WaveMix/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/WaveMix/actions/workflows/jsoncheck.yml)
|
|
|
|
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/WaveMix/blob/master/LICENSE)
|
|
|
|
[![GitHub release](https://img.shields.io/github/release/RobTillaart/WaveMix.svg?maxAge=3600)](https://github.com/RobTillaart/WaveMix/releases)
|
|
|
|
|
|
|
|
|
|
|
|
# WaveMix
|
|
|
|
|
|
|
|
WaveMix is an Arduino library to mix two signals (A and B) with an adaptive weight.
|
|
|
|
|
|
|
|
|
|
|
|
## Description
|
|
|
|
|
|
|
|
WaveMix is a very simple library to mix two signals (A and B) with an adaptive weight.
|
|
|
|
|
2022-03-26 06:33:27 -04:00
|
|
|
Depending on the weights applied the output signal (O) looks more on signal A or on signal B.
|
|
|
|
A gain can be applied to amplify weak signals or to be used for modulation.
|
|
|
|
|
2022-03-25 05:00:26 -04:00
|
|
|
|
|
|
|
Inspired by - https://www.codeproject.com/Articles/5323200/On-how-to-mix-two-signals-by-using-Spectral-Foreca
|
|
|
|
|
|
|
|
Differences
|
|
|
|
- simpler algorithm
|
|
|
|
- WaveMix works on streams of measurements too.
|
|
|
|
|
|
|
|
|
|
|
|
## Interface
|
|
|
|
|
2022-03-26 06:33:27 -04:00
|
|
|
The main functions of the WaveMix:
|
|
|
|
|
|
|
|
- **explicit WaveMix()** Constructor
|
2022-11-27 04:36:01 -05:00
|
|
|
- **bool setWeight(float weight1, float weight2)** set the weight of the channels A and B.
|
2022-03-26 06:33:27 -04:00
|
|
|
The weights do not need to be normalized, so one can use e.g **setWeight(7, 13)** See below.
|
2022-11-27 04:36:01 -05:00
|
|
|
The function returns false if the weights sum up to 0. (no changes will be made)
|
2022-03-26 06:33:27 -04:00
|
|
|
- **float getW1()** return the normalized weight for channel A.
|
|
|
|
- **float getW2()** return the normalized weight for channel B.
|
2022-11-27 04:36:01 -05:00
|
|
|
- **bool setPercentage(float percentage)** sets the weight for channel A to percentage.
|
2022-03-26 06:33:27 -04:00
|
|
|
Channel B will have 100 - percentage.
|
2022-11-27 04:36:01 -05:00
|
|
|
Returns false if percentage < 0 or percentage > 100. (no changes will be made)
|
2022-03-26 06:33:27 -04:00
|
|
|
- **void setGain(float gain)** sets the gain factor.
|
2022-03-27 04:26:59 -04:00
|
|
|
An important use of gain is to amplify weak signals but one can also use it as a modulator of a signal.
|
2022-03-26 06:33:27 -04:00
|
|
|
See examples.
|
|
|
|
- **float getGain()** return the gain set.
|
2022-03-27 04:26:59 -04:00
|
|
|
- **void setOffset(float offset)** sets the offset for the output signal.
|
|
|
|
Typical used to align the zero level.
|
|
|
|
- **float getOffset()** return the current offset used.
|
2022-03-26 06:33:27 -04:00
|
|
|
- **float mix(float s1, float s2 = 0)** returns the weighted average of signal1 and signal2.
|
|
|
|
Signal2 is made optional to allow single signal processes e.g. modulation by **setGain()**.
|
2022-03-25 05:00:26 -04:00
|
|
|
|
|
|
|
|
|
|
|
## Operation
|
|
|
|
|
2022-03-26 06:33:27 -04:00
|
|
|
See examples.
|
|
|
|
|
|
|
|
|
|
|
|
#### Weights
|
|
|
|
|
|
|
|
**setWeight()** typically uses positive weights, e.g. **setWeight(7, 13)**
|
|
|
|
counts A for 7/20 part and B for 13/20 part.
|
|
|
|
It is also possible to use one or two negative weights.
|
|
|
|
Using negative weights means effectively the input value is inverted before it is added.
|
|
|
|
E.g. **setWeight(-1, 0)** would effectively invert signal A.
|
|
|
|
Only restriction to the weights is that the sum of the weights may not be zero.
|
|
|
|
|
|
|
|
|
|
|
|
#### Amplification
|
|
|
|
|
|
|
|
Weights cannot be used to amplify the signal in absolute sense, use **setGain()** for that.
|
|
|
|
By constantly updating the gain (0..max) one can implement **Amplitude Modulation**.
|
|
|
|
|
|
|
|
When the gain is negative, the output is effectively inverted.
|
2022-03-25 05:00:26 -04:00
|
|
|
|
|
|
|
|
|
|
|
## Future ideas
|
|
|
|
|
2022-03-26 06:33:27 -04:00
|
|
|
|
2022-03-27 04:26:59 -04:00
|
|
|
#### N channel variant.
|
2022-03-26 06:33:27 -04:00
|
|
|
|
2022-03-27 04:26:59 -04:00
|
|
|
- add **setValue(uint8_t channel, float value)** allow update of channels at a different frequency.
|
|
|
|
- add **getValue()**, read the current output given the value of the channels. OR
|
|
|
|
- add **getValue(uint8_t mask = 0xFF)**, read the current output given the value of selected channels.
|
|
|
|
- add **setMask(uint8_t mask = 0xFF)**, select channels. ease of use? **getValue(mask)** still needed?
|
|
|
|
- add **getMask()**, read back \_mask;
|
|
|
|
- note that **mix()** can be implemented with the above functions.
|
|
|
|
- add **setWeight(uint8_t channel, float weight)** need internal array of weights and \_sum
|
|
|
|
- add **float getWeight(uint8_t channel)** Normalized or not?
|
|
|
|
Not normalized allows easier increment per channel. Needs a **float getTotalWeight()**.
|
|
|
|
- add constructor **WaveMix(uint8_t channels = 8)** with parameter to set the number of channels? \[NO\]
|
|
|
|
- or do we need **WaveMix2()**, **WaveMix4()**, **WaveMix8()**, or even **WaveMix16()**, **WaveMix24()**, **WaveMix32()** class?
|
2022-03-26 06:33:27 -04:00
|
|
|
|
|
|
|
**WaveMix4()** and **WaveMix8()** seems to be realistic in terms of performance.
|
|
|
|
**WaveMix8()** can be used for 2-8 channels, using a uint8_t mask.
|
2022-03-27 04:26:59 -04:00
|
|
|
More channels will be much slower, so upon request the 16 and 32 variant? other variants can be obtained by masking.
|
2022-03-26 06:33:27 -04:00
|
|
|
|
|
|
|
|
|
|
|
#### Medium
|
|
|
|
|
|
|
|
- performance test.
|
|
|
|
|
|
|
|
|
|
|
|
#### Low
|
|
|
|
|
|
|
|
- think of integer version
|
|
|
|
- performance
|
|
|
|
- integer weights
|
|
|
|
- math in **int32_t** with last moment float conversion
|
|
|
|
- Templated version
|
|
|
|
- float vs double vs int
|
|
|
|
- maybe upon request.
|
|
|
|
- dynamic weights
|
|
|
|
- add **increment(float)**
|
|
|
|
- add **decrement(float)**
|
|
|
|
- percentages? hard for multichannel?
|
2022-03-27 04:26:59 -04:00
|
|
|
- default parameters
|
|
|
|
- gain = 1.0
|
|
|
|
- percentage 50%
|
|
|
|
- offset = 0.0
|
|
|
|
- **reset()** needed?
|
2022-03-25 05:00:26 -04:00
|
|
|
|
|
|
|
|
2022-03-27 04:26:59 -04:00
|
|
|
#### wont
|
|
|
|
- add top clipping
|
|
|
|
- add **setMaximum(float)**
|
|
|
|
- add **setMinimum(float)**
|
|
|
|
- needs an enable/disable per limit.
|
|
|
|
becomes more complex than let the user constrain the output.
|