Author Topic: midi offset and EDIT: globaltune...  (Read 8644 times)

lokki

  • Sr. Member
  • ****
  • Posts: 383
    • View Profile
midi offset and EDIT: globaltune...
« on: December 22, 2017, 12:54:31 PM »
hi xavier, i know i brought this up before in different contexts. do you see any chance of including a midi offset to a specific timbre?

it would be super useful for live playing, since one can then centre the patches in the right octave instantly on program change, without the need to fiddle with the octave switch on a keyboard or similar. it would also allow to play multiple timbres with one controller by simply changing midi channel without touching the octave button.

the ideal way would be an offset that is adjustable by +-48 semitones, but even just the possibility to change octaves (say +-3) would be great.

i don't see a way to add this without changing the preset files. if it would be added to the combo files, that would be perfect, but adding another page in the instrument menu seems out of the question for you.

thanks for considering,

have a great christmas time

« Last Edit: January 02, 2018, 09:43:18 PM by lokki »

Xavier

  • Administrator
  • Hero Member
  • *
  • Posts: 2256
    • View Profile
Re: midi offset
« Reply #1 on: December 22, 2017, 01:42:10 PM »
Hi Lokki,

Yes i thought about that, and i think I have a workaround for what you want, so that you don't have to wait for a real midi offset to be implemented  ;)

Ideally we would need a constant value in the source matrix. We don't have one but we can simulate one.
Set LFO1to :
SIN 0.00 1.00 0.00
LFO1 phase : 0.00
That makes the LFO1 start at 1.00 and remains at 1.00.
You can use this in the matrix to modify the frequency of all operators :

Formula is here :
https://github.com/Ixox/preenfm2/blob/master/src/synth/Osc.h#L57?ts=4

So you have freq = freq * ( 1 + matrixDest * .1)

Which means if you add a line in the matrix such as :
LFO1 -5.0 o*fq => freq = .5 * freq :  instruments sounds 1 octave lower
LFO1 -7.5 o*fq => freq = .25 * freq : instruments sounds 2 octaves lower
LFO1 10 o*fq => freq = 2 * freq : instruments sounds 1 octave higher

Save a different preset for each frequency shift you need and you're done :)

Xavier
« Last Edit: December 22, 2017, 01:46:46 PM by Xavier »

lokki

  • Sr. Member
  • ****
  • Posts: 383
    • View Profile
Re: midi offset
« Reply #2 on: December 22, 2017, 08:39:21 PM »
thanks xavier, that works!

i'm losing lfo1 of course but it should be easy enough to code in a constant as matrix source, will give this a go. might even be useful for other things.
thanks for the idea, obvious now that i think about it :-)


lokki

  • Sr. Member
  • ****
  • Posts: 383
    • View Profile
Re: midi offset
« Reply #3 on: December 23, 2017, 12:08:15 AM »
hi xavier,

ok almost there. i added a cnst menu entry and it is showed in the matrix source menu. can you tell me where and how i should declare the constant value? i cannot set it in the enum directly it seems.


Xavier

  • Administrator
  • Hero Member
  • *
  • Posts: 2256
    • View Profile
Re: midi offset
« Reply #4 on: December 23, 2017, 11:49:50 AM »
hi xavier,
ok almost there. i added a cnst menu entry and it is showed in the matrix source menu. can you tell me where and how i should declare the constant value? i cannot set it in the enum directly it seems.

Constant value ?  I'm not sure i understand.
What i would do is to set the source value to 1.0 here, after the loop :
https://github.com/Ixox/preenfm2/blob/298f859bf8a42da5a998c9021a0eaef728ec8f47/src/synth/Matrix.h?ts=4#L36
Then it think (not sure) it will remains 1.0 and you don't have to worry about it.

Edited : constant value ? you want to be able to modify this 1.0 right ? Just make a few of them : 1.0, 2.0, 4.0, 8.0 ;)

lokki

  • Sr. Member
  • ****
  • Posts: 383
    • View Profile
Re: midi offset
« Reply #5 on: December 23, 2017, 04:39:42 PM »
thanks for that. will try it after christmas :-)

i think 1 2 4 8 makes no sense, since you add 1 in the formula for the freq calc.
so better to just use 10.0 for example. gives a big range and some undocumented behaviour below -1.0 :) let's see what happens.


lokki

  • Sr. Member
  • ****
  • Posts: 383
    • View Profile
Re: midi offset
« Reply #6 on: December 23, 2017, 04:55:11 PM »
ok, i couldn't resist and had a spare two minutes :-)

it works very well with a value of 10.0. this gives me three octaves higher at 7.0 and at -8.0 :-) so yes negative values just get mirrored after -1.0... and one or two octaves lower are still possible with -0.5 and -0.75. three octaves lower is not precise anymore but that is ok for me. (i don't need it)

nice and thanks for your idea and support, really appreciated.

Xavier

  • Administrator
  • Hero Member
  • *
  • Posts: 2256
    • View Profile
Re: midi offset
« Reply #7 on: December 25, 2017, 09:19:25 AM »

Great to see custom development !!  :)

lokki

  • Sr. Member
  • ****
  • Posts: 383
    • View Profile
Re: midi offset
« Reply #8 on: December 26, 2017, 10:29:14 PM »
ok, globaltune is next :-)

i thought i could do it in the same place in osc.h where the matrix stuff is done and tried this:

(line 57)
Code: [Select]
oscState->mainFrequencyPlusMatrix +=  (oscState->mainFrequency  * (matrix->getDestination(destFreq) + matrix->getDestination(ALL_OSC_FREQ)) * .1f) * ((435.0 + (this->synthState->fullState.midiConfigValue[MIDICONFIG_GLOBAL_TUNE] / 2.0)) / 440.0);
    }

this->synthState->fullState.midiConfigValue[MIDICONFIG_GLOBAL_TUNE] is a value i added in the global menu ranging from 435 to 444 in 0.5 steps. so this makes 19 possible values with 440.0 represented by value 10.

this is the code in menu.cpp

Code: [Select]
const char* tuneSteps[] = {"435.0", "435.5", "436.0", "436.5", "437.0", "437.5", "438.0", "438.5", "439.0", "439.5", "440.0", "440.5", "441.0", "441.5", "442.0","442.5", "443.0", "443.5", "444.0", };

the code compiles fine, modulating the pitch with the matrix still works as expected but adjusting the value in the global menu has no effect. do you see any obvious errors? why does  "this->synthState->fullState.midiConfigValue[MIDICONFIG_GLOBAL_TUNE] "  not get updated?
« Last Edit: December 26, 2017, 10:32:37 PM by lokki »

Xavier

  • Administrator
  • Hero Member
  • *
  • Posts: 2256
    • View Profile
Re: midi offset
« Reply #9 on: December 27, 2017, 11:15:27 AM »

You put the modificaiton at a wrong place, your global tuning is only apply to the matrix destintion part of the frequency.
And we should not add this modificaiton here because it's called all the time, the global tuning should be caluclated only once.

I think you should try to modify float*frequency which contains the frequency for each note (if not in scala mode) :
https://github.com/Ixox/preenfm2/blob/master/waveforms/waves.c#L1

frequencyToUse is initialise to frequency here :
https://github.com/Ixox/preenfm2/blob/5868bb37c0e76c68a504400fb91bffd3c5007a37/src/synth/Osc.cpp?ts=4#L165
And when we disable the scala scale.

You should try to modify frequency with your globaltune at boot time + when we modify the global tune in the settings.

Xavier

lokki

  • Sr. Member
  • ****
  • Posts: 383
    • View Profile
Re: midi offset
« Reply #10 on: December 27, 2017, 04:53:41 PM »
thanks xavier,

yeah i see now, why it does not work :-) i was tired yesterday...
you make good points of course and most of them i though about as well, but:

unfortunately i don't know enough about the preenfm source to make this happen only at boot time or when the settings are changed...
also i remember trying to change the frequency array in osc.cpp in an earlier attempt but i will try again. i don't know enough about floats and their precision, but wouldn't manipulating the array back and forth (changing tuning from 438 to 442 repeatedly for example)  introduce errors over time?  would the value also be updated before i save the config? i ask because it is much easier to tune when you can play a note and immediately hear the change.

lokki

  • Sr. Member
  • ****
  • Posts: 383
    • View Profile
Re: midi offset
« Reply #11 on: December 27, 2017, 09:50:24 PM »
ok,  i tried this in osc.cpp just before frequencyToUse = frequency:

Code: [Select]
float currentA = frequency[81];
 for (int k=0; k<127; k++) {
frequency[k] = frequency[k] * ((870.0 + this->synthState->fullState.midiConfigValue[MIDICONFIG_GLOBAL_TUNE])/currentA);
}

everything still works but changing the global_tune value has no effect :-(

even a reboot of the preenfm does not change the tuning.

as i said i don't know any further than this...sorry for all the questions.
« Last Edit: December 27, 2017, 09:55:47 PM by lokki »

Xavier

  • Administrator
  • Hero Member
  • *
  • Posts: 2256
    • View Profile
Re: midi offset
« Reply #12 on: December 28, 2017, 08:44:02 AM »
i don't know enough about floats and their precision, but wouldn't manipulating the array back and forth (changing tuning from 438 to 442 repeatedly for example)  introduce errors over time? 

Yes i think so.
You should keep the original frequency. Copy it in another array and point to this array.

For the calcul i would do something like
Code: [Select]
float tunedFrequencies= {  435.0, 435.5, 436....<put the list of frequencies here>.. };
float fAdjust = tunedFrequencies[ this->synthState->fullState.midiConfigValue[MIDICONFIG_GLOBAL_TUNE] / 440.0f;
for (int k=0; k<127; k++) {
    midiNoteTunedFrequency[k] = frequency[k] * fAdjust;
}
frequencyToUse = midiNoteTunedFrequency;

where midiNoteTunedFrequency is a new array to prevent error accumulation when many modifications defined globaly.
Code: [Select]
float midiNoteTunedFrequency[128];

I had a look and i think you can intercept when a new value is changed here :
https://github.com/Ixox/preenfm2/blob/master/src/synth/SynthState.cpp?ts=4#L1029
with a
Code: [Select]
if (fullState.midiConfigValue[fullState.menuSelect] == <YOUR MIDI GLOBAL TUNING CONSTANT>) {

}

Don't hesitate to post any other question you have
« Last Edit: December 28, 2017, 09:07:03 AM by Xavier »

lokki

  • Sr. Member
  • ****
  • Posts: 383
    • View Profile
Re: midi offset
« Reply #13 on: December 28, 2017, 10:52:57 PM »
xavier, thanks for this indepth answer.

i implemented it as per your suggestion:

Code: [Select]
float  tuneFactor[] = {435.0,435.5,436.0,436.5,437.0,437.5,438.0,438.5,439.0,439.5,440.0,440.5,441.0,441.5,442.0,442.5,443.0,443.5,444.0} ;
float frecAdjust = tuneFactor[this->synthState->fullState.midiConfigValue[MIDICONFIG_GLOBAL_TUNE]] / 440.0f;
 for (int k=0; k<127; k++) {
midiNoteTunedFrequency[k]= frequency[k] * frecAdjust;
 }
        // Set frequencyToUse  to frequency (no Scala scale defined)
        frequencyToUse = midiNoteTunedFrequency;

but the problem persists, no change in tuning even after a reboot.

i did not yet do the part in SynthState.cpp, but that would only be to have immediate change when i adjust the value, right? or is this the crucial step i'm missing and the reason why the tuning does not change  ??? EDIT: calling Osc Init from there?
(i do not fully get that part, would i have to do the same calculation in the brackets there as well? or do i leave just empty brackets? or have a propagateNewParamValue in there?)

also on a related note: is there any reason why the frequency array in waves2.c is not declared as a const? if a scala file is used that array is not manipulated i think. would that not be more efficient? (my tuneFactor should also be const :-))
« Last Edit: December 29, 2017, 06:29:52 AM by lokki »

Xavier

  • Administrator
  • Hero Member
  • *
  • Posts: 2256
    • View Profile
Re: midi offset
« Reply #14 on: December 29, 2017, 09:34:07 AM »
I see.
Osc objects are created before the midi config values are read from the USB drive.

Osc are initialized from this line :
https://github.com/Ixox/preenfm2/blob/master/src/PreenFM.cpp?ts=4#L107

And the USB configuration file is read just bellow :
https://github.com/Ixox/preenfm2/blob/master/src/PreenFM.cpp?ts=4#L138

You can try to move up the UsbKey block (line 133 to 139). Moving init block often lead to freeze because of null pointer exception ;)

Or move you frequency adjust code from init() to a Osc static method and call it from PreenFM.cpp bellow UsbKey init... line 145 for exemple.