I2c issues & amplitude modulation

Status
Not open for further replies.

synthj

Member
Hey Folks,
I have a pretty big project: a complete standalone synth unit with recycled old cheap keyboard keys and a ton of potis and switches all hooked up on a teensy 3.5.
Since i am running out of pins i am relying on muxes and gpio expanders. Whereas the first are easy to handle the latter (using 2 mcp23017s) are wired up via i2c to do keyboard mapping and various other stuff. I really need (probably a very generic statement :D ) my loop() to go as quick as possible. Due to the size of the project and my own hardware pcb designs etc it is not quite easy to give MWEs for this forum. But i am having 2 quite general and non-related questions, i hope this is the right way of posting this:

First - I2C communication rates:
- I have a teensy 3.5 with audio shield hooked up on a self designed pcb. The i2c (scl0 sda0) is shared for both mcp23017s and pulled up via external resistors (do the resistor sizes limit speed?) the wires aka pcb lines are basically as short as it gets. I am using the i2c_t3 library and the datasheet of the mcps states i2c rates 100k 400k, 1.7M Hz. But it doesnt matter what i change in the code (ie rate on the teensy) the loop that involves the i2c communications always takes up the same amount of time, i somehow have the feeling that any rate change in code does not do any difference...

---> HINT: For all just flying over the text and might be looking for something related to their problem: i got rid of the MCP23017 adafruit library, it produces massive latency. Just reading out my keybed with the i2c_t3 library wire commands takes ~4.5 ms in total (independent for some reason on i2c rate) but took ~80 ms with the adafruit MCP library!!

Can anyone give me a hint what i need to do in order to achieve quicker i2c rates for the mcp communications or experienced something similar? just setting and reading out a couple of digital pins shouldnt introduce ~ 5ms latency per loop. It would probably be alright for the project since overall i am running with ~9 ms per loop for all control stuff (i.e. keys and changing pots and switches) which is not noticeable in the use case. But even my adc mux reads only take about 40 us in total each go. So i would really like to up the digital IO game :)

Code:
Wire.begin(I2C_MASTER, MCP_KEYS_ADDR, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000);
Wire.begin(I2C_MASTER, MCP_DIO_ADDR, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000);
I thought this is what does the trick i'nit?


Second:
- I am looking for proper amplitude modulation of my waves (running with 3 oscillators + 1 noise object through a hell of a lot of stuff) and i would look into coding it myself into the waveform objects but wanted to ask here first before maybe reinventing the wheel:
I have not found a way of just creating a simple LFO to control my output volume.
I used an amp object and updated the gain with a ~20 - 40 sample wavetable for OKish results but cant update quick enough due to my overall loop() function timing. So i get glitches on really low (due to limited sample number) and very high (due to limited update rate) LFO rates.
The multiply object doesnt do either (even though the documentation pretends) since it basically is a ring modulator: multiplying two waves does not simply create a wave with an envelope but due to trigonometrics (for the simple case of sine waves):

sin(x)sin(y)= 1/ 2 [cos(x−y)−cos(x+y)],

inputting an 10 Hz LFO and my previously (through a lot of steps) modulated multi wave object (say playing a note A = 440 Hz) i get a 450Hz and 430Hz split output, i.e. i am detuning the note up and down rather than modulating its amplitude. This is a separate feature of my synth but not what i want when trying to copy analog VCA.
Can someone help or hint me on how to do this?! I want the LFO to control the output amplitude of the sound!

Apart from that: I have built a case now, holding it all together, i am constantly trying to optimize the code , still with multiple branches on my git open :D. I will redo the schematics and pcb files (for the teensy with a power circuit, MIDI IO, gpio expanders and all necessary plugs and separately some basic "modules" with a 8 ch multiplexer each, holding pots and various other stuff, for "easy" modular "build your own" design :D), and it will all be up and available on github in the near future. For now i have a monophonic unit but with the power of the later teensys it shouldnt be impossible to do a polyphonic version. I am really excited and will let you all know (in case you want to :) ),
since i profitted a lot from the audio tool and from the forum!
Thanks in advance and all the best!
Jochen
 
You could use a simple timer driven Phase Accumulator and a Huuuuge Lookup Table for your LFOs and have these modulate an AudioAmplifier Object. At least its what i do.

And: Yes, im Interested what you did there.....
 
multiply.jpg

The more i think of it the less i know why i am suspecting something else than what is happening. My lfo creates a periodically changing envelope, once this is morphing into the audible range it will create detune. I was thinking all the time "if i would just turn my volume poti up and down all the time i would not get detune". But after all, if i would be able to turn it with say 50 Hz, it would probably be the exactly the same situation, at least i dont see why mathematically it shouldnt. So i suspect my second question was stupid after all....

Do you get the same effect doing it your way? How quick are your lfo rates?
 
synthj said:
The more i think of it the less i know why i am suspecting something else than what is happening. My lfo creates a periodically changing envelope, once this is morphing into the audible range it will create detune. I was thinking all the time "if i would just turn my volume poti up and down all the time i would not get detune". But after all, if i would be able to turn it with say 50 Hz, it would probably be the exactly the same situation, at least i dont see why mathematically it shouldnt. So i suspect my second question was stupid after all....

Do you get the same effect doing it your way? How quick are your lfo rates?

Two points about modulating volume: firstly the modulation value should be ranging between 0 and 1, ie not going negative,
so using a simple sinusoid centred on 0 isn't right.

Secondly the modulation is ideally logarithmic in nature, so the actual modulation value would be calculated as exp(volume),
with volume in this case being negative. If you work in dB that would be pow(10, volume/20), with 0dB being maximum
volume.

If wanting to use a sinusoid to derive the volume, it might be like:

pow (10, depth * (1 - sin(LFOfreq*time)/2 / 20)

where depth is the volume modulation depth in dB, and (1 - sin)/2 gives a modulation signal in the -1 to 0 range.
 
View attachment 22878

Do you get the same effect doing it your way? How quick are your lfo rates?

Nope, i get the effect of a classic VCA modulated by a LFO : change the Amplitude according to the LFOs Signal.

As staded above, you should feed the AudioAmplifer Object with Values from 0-1.0 do miin the VCAs behavior, otherwise you will invert the Signal with negative Values, this will result in weired wavefolding like Effects.

How fast the LFO can go depends on the Size of the Phase Accumulator, the Phase Increment and Update Rate and the Lookuptable Size. I get fine results with 1kHz Update Rate, 16 Bit Phase Accumulator ("unsigned short" ) and 512 values ( "short" using 12 Bit as Teensys PWM is 12Bit at max) Lookup table for LFOs of 1/8Hz up to 50 Hz. Big Advantage is you can use any Waveform you like as LookupTable and you have a constant CPU load, independent of the LFOs frequency.

https://electricdruid.net/wavetable-oscillators/ is a nice introduction to this approach, https://www.manfreda.org/prophet-vs/birth-of-the-prophet-vs may be also of interest.
 
Thanks for the replies.
I did not use negative values (that img was mainly for visualization, its the same with positive waves, see below). I used the first half of a sine cycle or triangle.
However, I wanted to get exactly what you wrote that you get:
a classic VCA modulated by a LFO : change the Amplitude according to the LFOs Signal.
But when looking at the math side of things i am confused as of what this actually means.
when my wave is something like: wave(t) = amplitude(t) * somewave(t), and the amplitude itself has some periodic dependence i will get sidebands in the fourier transform, aka the frequency spectrum and hear some detuned notes. Still my main note is apparent but i will get some shifted frequencies. So i am somewhere lost with what should be the difference between multiplying (multiply object) the LFO onto my stream and doing the lookup table way of updating an amplifier object (as i tried both). Mathematically it should be the same?!

I will have a second look into the phase accumulator and change in lookup table size. And if it is working and i get exactly what i want to then thats perfect. I still dont understand why there should be a difference between the two.

As for the logarithm. I am aware of how the volume works with perception and i will take into consideration working with the exponential. Nonetheless i dont think this is core of my problem.
Thank you all!

Does someone know about the I2c communication thing?
multiply.jpg
 
I guess the trick is an LFO means LOW frequency oscillator. Low as in "much lower than the modulated Signal". Your Pic above reminds me more of FM, as the modulating Oscillators frequency is roughly the same as the modulated Oscillator, right? Try simulating with a way lower LFO frequency and the Sidebands will next to disappear. Or just try with your modulars OSC, VCA ans LFO.

Your Problems do not derive from the kind of generating that LFO signal, btw.
 
Yes, i was using LFO rates of 0-40 or 60Hz. It is kinda low but obviously going into the audible range. And especially noticeable as detune for the lower octaves of notes. I had to restrain the VCA LFO i am using to 10 Hz and it works. So i guess the sidebands are part of AM. I was probably not thinking about it enough beforehand. Since i wanted something different than what a ring modulator does :)

Thanks for the help!
 
Status
Not open for further replies.
Back
Top