Phatline

changable logartimic (curve of LFO or ENVELOPE)

18 posts in this topic

Problems Solution is:

were we have to add this to the lokal makefile:

Quote

first point after adding Math lib, it seems the loading sequence of libraries is wrong. the `__errno' compilation error.
To resolve it we have to set the loading sequence, just change this line in your Makefile:


LIBS=
to
LIBS = -lm -lgcc -lc

 

ORGINAL PROBLEM POST

 Hei.

I have made now, a LFO (UP/DOWN Ramp & Triangle), now i need to add a logaritmic ammount to get CURVES/SINEs on the LFO Straight Lines, i want to do this with a Encoder.

My LFO Values going from 0-65535 (16bit, AOUT-Ready)

My Curve CC also goes from 0-65535  (Curve means Logaritmic)

I have to execute this code every milli seconds, to change the AOUT, and every 75ms to update the SCOPE-Display

 

I tryd around and this is code is working with stdi0 and math.h, outside of mios: (Working)

#include <stdio.h> 
#include <math.h>

double cc = 32000;
double curve = 64000;
int endresult;


int main (void)
{
printf("exponential_input 0-65535: ");
    scanf("%lf", &curve);
    
endresult = cc * (log(curve) / log(cc));

printf (" %d \n", endresult  );

  return 0;
}

 

now in mios my code it is also working when i fill in fixed values:   (WORKING)

//calculate Exponential
double lfo   = 65000;
double curve = 32000;
double lfo_result;
lfo_result = lfo * (log(curve) / log(lfo));
if(lfo_result > 65535) { lfo_result = 65535;}
if(lfo_result < 1)     { lfo_result = 0;}  

 

but when i use my arrays instead of this fixed values, i become a error (NOT WORKING)

//calculate Exponential
double lfo   = aout[channel_strip].lfo[y];
double curve = aout[channel_strip].v_cc[26+(y*8)];
double lfo_result;
lfo_result = lfo * (log(curve) / log(lfo));

i also tryed: (NOT WORKING)

double lfo_result = aout[channel_strip].lfo[y] * ( log(aout[channel_strip].v_cc[26+(y*8)]) / log(aout[channel_strip].lfo[y]) );

error is: (errno)

Quote

make (im Verzeichnis: /home/triggermatrix/c/Filterbox-V1)
rm -f project.hex
Creating object file for app.c
app.c: In function 'APP_Init':
app.c:218:5: warning: pointer targets in passing argument 2 of 'xTaskCreate' differ in signedness [-Wpointer-sign]
In file included from app.c:11:0:
/home/triggermatrix/mios32/trunk/FreeRTOS/Source/include/task.h:360:13: note: expected 'const char * const' but argument is of type 'signed char *'
/home/triggermatrix/mios32_toolchain/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/armv7e-m/libm.a(lib_a-w_log.o): In function `log':
w_log.c:(.text.log+0xb8): undefined reference to `__errno'
w_log.c:(.text.log+0xc2): undefined reference to `__errno'
w_log.c:(.text.log+0xcc): undefined reference to `__errno'
collect2: error: ld returned 1 exit status
Kompilierung fehlgeschlagen.
make: *** [project_build/project.elf] Fehler 1

 

dont know how to handle this, i need a cc-controlled logaritmic  - any ideas?

 

 

here a goodie:

 

Edited by Phatline

Share this post


Link to post
Share on other sites

It may be better to prepare a log and antilog table then just use multiply, instead of heavy math processing.

Best
Bruno

Share this post


Link to post
Share on other sites

hei.

@ table, na

a life-changeable log? table?

or a table holds all 16bit possibilitys?

[65536][65536] while [lfo_value][curve] - that ram i cant see :cry: in a µC (dont say i dont should use 16 bit values, the program doing it well,  i have other reasons for that...)

such  table could calculate in a a background task - with the give CURVE-Parameter,, endlessly, and could be used then live... but in the end i have to ask which value should be which tablecell anyway.

 

@ least i want to try do the math, - and i will see timing then. if there is a way for log with this compiler(gcc?) gcc and frtos/mios?

what did i wrong. i tryd double floats...

-mike

Edited by Phatline

Share this post


Link to post
Share on other sites

POST NOT WORKING

hmm a workaround, that comes in my mind , while sitting here trinking vodka, set with collected raspberrys in it-  :rolleyes:

i could (if there is no other solution):

i could set my CURVE-Encoder (log setting encoder) to count from 0-20 ----curve= 0-19 (instead of 0-65525)

then make a switch, not very nice, not very small

switch (curve) {

case 0: lfo_log = lfo_lin * log(0.1);  break;

case 1: lfo_log = lfo_lin * log(0.2); break;

case 2: lfo_log = lfo_lin * log(0.3); break;

case 3: lfo_log = lfo_lin * log(0.4); break;

case 4: lfo_log = lfo_lin * log(0.5); break;

case 5: lfo_log = lfo_lin * log(0.6); break;

case 6: lfo_log = lfo_lin * log(0.7); break;

case 7: lfo_log = lfo_lin * log(0.8); break;

case 8: lfo_log = lfo_lin * log(0.9); break;

case 9: lfo_log = lfo_lin * log(1.0); break;

case 10: lfo_log = lfo_lin * log(1.1); break;

case 11: lfo_log = lfo_lin * log(1.2); break;

case 12: lfo_log = lfo_lin * log(1.3); break;

case 13: lfo_log = lfo_lin * log(1.4); break;

case 14: lfo_log = lfo_lin * log(1.5); break;

case 15: lfo_log = lfo_lin * log(1.6); break;

case 16: lfo_log = lfo_lin * log(1.7); break;

case 17: lfo_log = lfo_lin * log(1.8); break;

case 18: lfo_log = lfo_lin * log(1.9); break;

case 19: lfo_log = lfo_lin * log(2.0); break;

}

(not testet yet, cause the lack of hardware here) - maybe there has to be that log(x)/log(y) thing... but somekind like this

so  i have this constants what the compiler crying out. for

Edited by Phatline

Share this post


Link to post
Share on other sites


I did the same thing in MIOS32, applied to a 16bit linear function y=x:


Is this what you want?
Will explain tomorrow... have to get some sleep...

 

 

1 person likes this

Share this post


Link to post
Share on other sites

Good morning,

First thing: the bitmap manipulation

Declaration:

/////////////////////////////////////////////////////////////////////////////
// Local variables
/////////////////////////////////////////////////////////////////////////////
// You need 128*64 pixel, for SSD1306 a pixel is one bit
// we will declare an u8 array, size is 128*64/8 = 1024
static u8 bitmap_array[1024];
// the bitmap
mios32_lcd_bitmap_t bitmap;
// some other variables for the example
u32 line, column; 
const float a=1.0;

Init:

/////////////////////////////////////////////////////////////////////////////
// This hook is called after startup to initialize the application
/////////////////////////////////////////////////////////////////////////////
void APP_Init(void)
{
  MIOS32_BOARD_LED_Init(0xffffffff); // initialize all LEDs
  // initialize bitmap width=128, height=64, offset=128(!) and depth=1 bit
  bitmap = MIOS32_LCD_BitmapInit(bitmap_array,128,64,128,1);
  ...
}

Linear function exemple:
I used the SRIO_ServicePrepare as 1ms timer

/////////////////////////////////////////////////////////////////////////////
// This hook is called before the shift register chain is scanned
/////////////////////////////////////////////////////////////////////////////
void APP_SRIO_ServicePrepare(void)
{
	column +=128; //column increment(x axis)
	if( column > 0xffff){ // 65535 max
    	column = 0;
		// this will clear/reset the bitmap !
		memset(bitmap_array, 0, sizeof bitmap_array);
    }
	// this is just a linear function y=ax
	line = (u32)(a*column);
  	u8 x= (u8)(column>>9); //reducing 16 bit to 128pixels(7bits)
  	u8 y= (u8)(line>>10); //reducing 16 bit to 64pixels(6bits)
	// set the pixel
  	MIOS32_LCD_BitmapPixelSet(bitmap, x, 63-y, 1); // 63-y is to invert the y axis
}

now we send it:
 

/////////////////////////////////////////////////////////////////////////////
// This task is running endless in background
/////////////////////////////////////////////////////////////////////////////
void APP_Background(void)
{
  column = 0;
  line = 0;
  // clear LCD
  MIOS32_LCD_Clear();
  // endless loop
  while( 1 ) {
    int i;
    MIOS32_LCD_GCursorSet(0, 0);
    MIOS32_LCD_BitmapPrint(bitmap);
	// done!
  }
}

result:

 

Edited by Antichambre
1 person likes this

Share this post


Link to post
Share on other sites

For a partial bitmap(not full screen) e.g. 32x32 centered

change declare

// You need 32*32 pixel, for SSD1306 a pixel is one bit
// we will declare an u8 array, size is 32*32/8 = 128
//static u8 bitmap_array[128]; //I don't know why this not work
static u8 bitmap_array[1024]; //this is fine

init:
 

// initialize bitmap width=32, height=32, offset=128(!) and depth=1 bit
  bitmap = MIOS32_LCD_BitmapInit(bitmap_array,32,32,128,1);

calc:
 

  	u8 x= (u8)(column>>11); //reducing 16 bit to 32pixels(5bits)
  	u8 y= (u8)(line>>11); //reducing 16 bit to 32pixels(5bits)
	// set the pixel
  	MIOS32_LCD_BitmapPixelSet(bitmap, x, 31-y, 1); // 31-y is to invert the y axis

positionning:

MIOS32_LCD_GCursorSet(48, 16);
MIOS32_LCD_BitmapPrint(bitmap);


result:

 

1 person likes this

Share this post


Link to post
Share on other sites

Adding curve response Log and Antilog:

first point after adding Math lib, it seems the loading sequence of libraries is wrong. the `__errno' compilation error.
To resolve it we have to set the loading sequence, just change this line in your Makefile:

LIBS=
to
LIBS = -lm -lgcc -lc

works for me ;)

Now the curve:
in declaration add the curve variable, I use MIOS Studio to control it

u8 curve = 64;

in MIDI_Notify CC#1 is curve parameter

/////////////////////////////////////////////////////////////////////////////
// This hook is called when a MIDI package has been received
/////////////////////////////////////////////////////////////////////////////
void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package)
{
  // store incoming ModWheel values to curve
  if( midi_package.type == CC && midi_package.cc_number == 1 )
    curve = (u8)midi_package.value;
}

Ok now we will change the function to:

/////////////////////////////////////////////////////////////////////////////
// This hook is called before the shift register chain is scanned
/////////////////////////////////////////////////////////////////////////////
void APP_SRIO_ServicePrepare(void)
{
	column +=128; //column increment(x axis)
	if( column > 0xffff){ // 65535 max
    	column = 0;
		// this will clear/reset the bitmap !
		memset(bitmap_array, 0, sizeof bitmap_array);
    }
  	// log/antilog function
  	if(curve<64){
    		// reducing curve to a float between 0 and 1
    		float curv_f=(float)(64-curve)/64.0;
    		// reducing column to a float between 0 and 1
    		float column_f = (1.0-((float)(column/65536.0)));
    		// line value is
    		line = (u32)(column + ((log(column_f)*curv_f*column_f)*65536));
  	}else{
    		// reducing curve to a float between 0 and 1
    		float curv_f=(float)(curve-64)/64.0;
    		// reducing column to a float between 0 and 1
    		float column_f = (float)(column/65536.0);
    		// line value is
    		line = (u32)(column - ((log(column_f)*curv_f*column_f)*65536));
  	}
  	u8 x= (u8)(column>>9); //reducing 16 bit to 128pixels(7bits)
  	u8 y= (u8)(line>>11); //reducing 16 bit to 64pixels(6bits)
	// set the pixel
  	MIOS32_LCD_BitmapPixelSet(bitmap, x, 63-y, 1); // 63-y is to invert the y axis
}

result:

Voilà!
I hope it will help you ;)

have a good sunday!
Bruno

2 people like this

Share this post


Link to post
Share on other sites

cool device, for programing on the field? yes that curve behavior is what i  was looking for... thx will try that @ evening  --- special that library thing

 

Quote

LIBS=
to
LIBS = -lm -lgcc -lc

yes also works me thx!!!!! --- i add this to the top of article! this solve allmost everything

 

 

in the night i was thinking of a solution, how to DIY a log function special for this task, but it endet up to be exponential... my idea was:

1. make a linear LFO like bevore, call it LFO_LIN, this is only for calculations

2. calculate LFO_LOG, this will be mixed with other LFOs and will be sent out to AOUT_Channels

2a: calculate LFO_LOG:

for example:

LFO_length: 500ms,    LFO_actual time Position: 250ms,   LFO_LIN: 32768, cc_curve: variable from 0-65535 as example below

calculation:

LFO_LOG  =  LFO_LIN  +  LFO_LIN_ADD

 

LFO_LIN_ADD   =   LFO_LIN  *  ( %time * %cc_curve)   - - - - [0-65535] = [0-65535] * [%] * [%] )

3750 = 15000     *     ( (   (1/500ms) * 250ms))  *  (1/65536) * 32768))  )

3750 = 15000 * 0,5time * 0,5cc     @ cc_curve: 32768

18750  =  150003750

 

example calculation of the LFO_LIN_ADD

15000  =  150000   = 15000 * 0,5time * 0,0cc     @ cc_curve: 0

15000,2  =  150000,22   = 15000 * 0,5time * 0,00003cc     @ cc_curve: 2

15000,4  =  150000,45   = 15000 * 0,5time * 0,00006cc     @ cc_curve: 4

....

15234  =  15000234   = 15000 * 0,5time * 0,03125cc     @ cc_curve: 2048

15468  =  15000468   = 15000 * 0,5time * 0,06250cc     @ cc_curve: 4096

15937  =  15000937   = 15000 * 0,5time * 0,12500cc     @ cc_curve: 8192

16875  =  150001875 = 15000 * 0,5time * 0,25000cc     @ cc_curve:16384

18750  =  150003750 = 15000 * 0,5time * 0,50000cc     @ cc_curve:32768

22250  =  150007500 = 15000 * 0,5time * 1.0000cc       @ cc_curve:65536

 

now try half time and half lfo_lin to proof that this is not linear...:

7968,75  =  7500 + 468 =  7500 * 0,25time * 0,25000cc     @ cc_curve:16384

15937,5 = 7968,75 * 2

where we had:

16875  =  150001875 = 15000 * 0,5time * 0,25000cc     @ cc_curve:16384

15937,5 vs 16875   @ 1/4time @ 1/4curve_cc   (positive log)

so if that result is not a comma-loos result, then this is now not linear, have to proof if that make sense on the machine

 

what happens when try a full cc_curve effect @ 65536 :

22250  =  150007500 = 15000 * 0,5time * 1.0000cc       @ cc_curve:65536

vs half time

9375  =  7500 + 1875 = 7500 * 0,25time * 1.0000cc       @ cc_curve:65536

18750 = 9375 * 2

18750 vs 22250

 

what happens @ end of time ( i guis it clips over 65536):

1310720  =  65536+ 65536 = 65536 * 1.0 time * 1.0000cc       @ cc_curve:65536

oh that we have to clip

if ( lfo_log > 65536 )  {lfo_log = 65536)

so we have more a exponential then a logarithmic, depending on the cc_curve parameter i have a clipping

expanding cc_curve to -65536 to + 65536 makes it +-(time)exponential, i just cant wait, to try my and brunos codes.

Edited by Phatline

Share this post


Link to post
Share on other sites

Ahah. Mine is a true log/antilog, this is math!

see the function applied to a triangle LFO
with variable speed and amplitude


 

2 people like this

Share this post


Link to post
Share on other sites
2 hours ago, Phatline said:

cool device, for programing on the field?

This is something I made for a customer, it can convert all serial connection and a lot of protocol, RS232, 422, 485 MIDI LANC and some specials others...
It's based on 2 SP338 IC around an LPC1769, so I can use it for MIOS32 too.
When I did the boxes I made one for me too and I use it as a tool on field, it 'saved my life' 2 times already.

IMG_1823.jpg?raw=1IMG_1836.jpg?raw=1
IMG_1846.jpg?raw=1

Share this post


Link to post
Share on other sites

how get you the tri-angle > sine conversion done,

when i do, i get in the bottum part a arrowhead, and in the top i round (see video first display...3rd encoder sets curve parameter

    // T R I A N G L E
    if( aout[x].v_cc[24 + (8*y)] == 2 ) {

           if( (counter[x][y] * 2)  > lfo_cycle[x][y] ) {  lfo_lin[x][y]  =  lfo_lin[x][y]  -  ( 131072  /  lfo_cycle[x][y] ) ;}
             else                                       {  lfo_lin[x][y]  =  lfo_lin[x][y]  +  ( 131072  /  lfo_cycle[x][y] ) ;}

            // Reset - ms - Counter
            if( lfo_loop_step_pos[x][y] == 0  &&  flag.step0once[x][y] == 1)
                                {   flag.step0once[x][y] = 0;
                                    counter[x][y] = 0;
                                    lfo_lin[x][y] = 0;    // init lfo internal
                                    lfo_log[x][y] = 1;    // init CV Value
                                    update_lfo_scope[x][y]   = 1;    // wait for next 16th step of seq to restart LFO Cycle
                               }            
    } // end triangle

i do the lin-log calculation right after the Waveform calculation, and save the result --- result will then printed on Screen, and dumped out to AOUT.

for lin-log i used your code - mine have not done that, what i want... did you changed anything? i dont get the sinus you have in your video

 

  	// L I N  >  L O G  /  A N T I  L O G
  	// lin > log
  	if (curve < 32767){
    		// reducing curve to a float between 0 and 1
    		curv_f=(float)(32768-curve)/32768.0;
    		// reducing column to a float between 0 and 1
    		lfo_f = (1.0-((float)(lfo_lin[x][y]/65536.0)));
            // lin > log
    		lfo_log[x][y] = (u32)(lfo_lin[x][y] + ((log(lfo_f)*curv_f*lfo_f)*65536));
            }
    // lin > antilog
    else{
    		// reducing curve to a float between 0 and 1
    		curv_f=(float)(aout[x].v_cc[26+(y*8)] - 32768) / 32768.0;
    		// reducing column to a float between 0 and 1
    		lfo_f = (float)(lfo_lin[x][y]/65536.0);
            // lin > log
            lfo_log[x][y] = (u32)(lfo_lin[x][y] - ((log(lfo_f)*curv_f*lfo_f)*65536));
            }
    
    }}// end x y loop

 

Share this post


Link to post
Share on other sites

Yes I just adapt it to a signed value, normally a lfo is bipolar.

declare 2 new static function

/////////////////////////////////////////////////////////////////////////////
// Local variables
/////////////////////////////////////////////////////////////////////////////
u16 phase =0;
u16 curve =32768;
u16 amp_cc =65535:
/////////////////////////////////////////////////////////////////////////////
// Local Prototypes
/////////////////////////////////////////////////////////////////////////////
static s16 XXX_hlp_log_signed(u16 curv, s16 signed_amp);
static u16 XXX_hlp_log_unsigned(u16 curv, u16 abs_amp);

Add the function

/////////////////////////////////////////////////////////////////////////////
// help func: return the Log/Antilog of a given signed value
/////////////////////////////////////////////////////////////////////////////
static s16 XXX_hlp_log_signed(u16 curv, s16 signed_amp){
  s16 log_amp;
  if(signed_amp<-32767)signed_amp=-32767; // limit signed to -32767 to -32767
  if(signed_amp<0){
    u16 abs_amp = (u16)((0-signed_amp) << 1);
    log_amp = (s16)(0-(XXX_hlp_log_unsigned(curv, abs_amp)>>1));
  }else{
    log_amp = (s16)(XXX_hlp_log_unsigned(curv, (u16)(signed_amp<<1))>>1);
  }
  return log_amp;
}
/////////////////////////////////////////////////////////////////////////////
// help func: return the Log/Antilog of a given unsugned value
// note: math.h must be included
/////////////////////////////////////////////////////////////////////////////
static u16 XXX_hlp_log_unsigned(u16 curv, u16 abs_amp){
  u16 log_amp;
  float curv_f, amp_f;
  if (curv < 32768){
    // reducing curve to a float between 0 and 1
    curv_f=(float)(32767-curv)/32767.0;
    // reducing column to a float between 0 and 1
    amp_f = (1.0-((float)(abs_amp/65535.0)));
    // lin > log
    log_amp = (u16)(abs_amp + ((log(amp_f)*curv_f*amp_f)*65535));
  }else{
    // reducing curve to a float between 0 and 1
    curv_f=(float)(curv-32767)/32767.0;
    // reducing column to a float between 0 and 1
    amp_f = (float)(abs_amp/65535.0);
    // lin > log
    log_amp = (u16)(abs_amp - ((log(amp_f)*curv_f*amp_f)*65535));
  }
  return log_amp;
}

now you will be able to use it everywhere with signed or unsigned 16bit value


A TRIANGLE LFO with amplitude, phase and curve parameters:

	// calc an unipolar triangle(0 to 65535) depending on x(time) between 0 and 65355 and phase between 0 and 65355
 	u16 time = (u16)(x + phase + 16384) ; // apply the phase
	u16 tri = (time < 32768) ? time << 1 : ((65535 - time) << 1));

	// now we shift down the unipolar to get a bipolar one
	s16 signed_tri = (s16)(tri - 32768);

	// call log function, curve is unsigned 16bit value!
	signed_tri = XXX_hlp_log_signed(curve, signed_tri);

	// apply amplitude parameter, amp_cc between 0 and 65355
	signed_tri = (s16)(signed_tri*amp_cc/65535); 

	// we shift back the triangle to unsigned 16 bit value, for use with lcd and aout
	tri = (u16)(signed_tri + 32768);
                                                                 
                                                       

Result:

More? ;)

Edited by Antichambre
some correction shifting is 32768 not 32758 ;) --- added amp_cc and phase parameter
1 person likes this

Share this post


Link to post
Share on other sites

... Always More! ;)

Width modulation added, with it you can achieve ramp down/up, pseudo sine(this is not true sine) and many more from a single triangle waveform:

 

// calc an unipolar triangle(0 to 65535) depending on x(time) between 0 and 65355 and phase between 0 and 65355
// set the phase
u16 time = (u16)(x + phase + (u16)(wide_mod/2)) ; 

// apply pos/neg width modulation, wide_mod is an unsigned 16bit ;)
float wide_pos = 65535.0/wide_mod;
float wide_neg = 65535.0/(65535-wide_mod);
u16 tri = (time < wide_mod) ? ((u16)(time*wide_pos)) : ((u16)((65535 - time)*wide_neg));

// now we shift down the unipolar to get a bipolar one
s16 signed_tri = (s16)(tri - 32768);

// call log function, curve is unsigned 16bit value!
signed_tri = XXX_hlp_log_signed(curve, signed_tri);

// apply amplitude parameter, amp_cc between 0 and 65355
signed_tri = (s16)(signed_tri*amp_cc/65535); 

// we shift back the triangle to unsigned 16 bit value, for use with lcd and aout
tri = (u16)(signed_tri + 32768);

 

Share this post


Link to post
Share on other sites

thX great inspiration!

special the bithshift to 128 und 64 > genial... or to scale time to u16, and then make more simple any offset possible (automation-assignment of this paremters is now also easy), also the log antilog logic..

i used your code as inspiration source to optimize code... not only because of you, because of RAM, i looked what happens when i let calculate all 4Channel-Strips & all 8 Scopes (8x4 OSCs, 88xVelo-, 88xOSC-,88xMotionSeuencer-Assignments...) had blackscreens, and ram debugger warnings usw, now i am a bit faster here :cheers: - no problem with + - operation, and like you said, -heavy division and multiplication- the programm then is working ok with one screen, 8 with log and all that stuff just dont have a function... it will take me more time to experience that.

i combine now ENV + LFO und let them share the same controlls, ENV is just a nother OSC/WAVEFORM, with Bendable paremeters.

I addet 0: retrigger und 1: sustain to my RATE CC, the rest are typical LFO cycle rates encreasing... so i can use a envelope as LFO and a typical LFO-Wave as Envelope, so i am also more flexible, not every track needs 4 envelopse

most of them only 2 or even 1, haveing on the other side more LFOs... and so on.

 

Share this post


Link to post
Share on other sites

You're welcome!

I already planned to do something like that for the PIXI, then not a waste of time you just pushed me to do it now ;)
But I will come back to this because it needs an accurate frequency too, exponential range something from 0.002Hz to 20Hz.

I've already got the math just have to translate it in code:
if note < note_Ref then
freq = Freq_Ref / (2^((note_Ref/note)/12)
else
freq = Freq_Ref * (2^((note/note_Ref)/12)

something like this

#define LFO_FREQ_REF  1.0 	//1Hz
#define LFO_FREQ_REF_NOTE  0x45  // 69, A3 midi note //7bit
#define LFO_FREQ_REF_VALUE (LFO_FREQ_REF_NOTE<<9)	//16bit
#define LFO_FREQ_TICK_RESO 1.0	//ms
u8 coarse = LFO_REF_NOTE;  // LFO Coarse Tune (7bit)
u8 fine = 64; // LFO Fine Tune +/- 6bit(7bit)
float target_period, last_period; // in millisecond
float accumulator, accum_step; // in millisecond
//with
freq_val = (u16)(coase<<9 + (fine-64)<<2);
if(freq_val<LFO_FREQ_REF_VALUE)
target_period = (float)(1000.0 / (REF_FREQ / (2^(((LFO_FREQ_REF_VALUE-freq_val)/512.0)/12);
else
target_period = (float)(1000.0 / (REF_FREQ * (2^(((freq_val-LFO_FREQ_REF_VALUE)/512.0)/12);

accum_step = target_period / LFO_FREQ_TICK_RESO;

like a VCO is centered around 440Hz on A3 note, the LFO will be centered around 1Hz on A3 note
which will give 0.01858Hz for the lowest note and 28.50876Hz for the higher one.
ToDo! And I didn't check in the SVN if something like this was done before

Best
Bruno
 

Edited by Antichambre

Share this post


Link to post
Share on other sites
9 hours ago, Phatline said:

no problem with + - operation, and like you said, -heavy division and multiplication- the programm then is working ok with one screen, 8 with log and all that stuff just dont have a function... it will take me more time to experience that.

For process time, remember, by decreasing the parameters resolution to 7bit (CC resolution) you can prepare some tables at startup(RAM) OR write it in program memory(FLASH) and finally remove some calculation.
e.g. this can be replaced by an array if curve is a 7bit

On 30/04/2018 at 1:19 PM, Antichambre said:

curv_f=(float)(32767-curv)/32767.0;

We can also try to use the FPU of the STM32 for hardware floating point calculation, but I read in the forum people have some troubles to get it.

 

Edited by Antichambre

Share this post


Link to post
Share on other sites
18 hours ago, Antichambre said:

For process time, remember, by decreasing the parameters resolution to 7bit (CC resolution) you can prepare some tables at startup(RAM) OR write it in program memory(FLASH) and finally remove some calculation.
e.g. this can be replaced by an array if curve is a 7bit

We can also try to use the FPU of the STM32 for hardware floating point calculation, but I read in the forum people have some troubles to get it.

 

i have tryed, but with the result, that i could use FPU, but not for my program because in order to use FPU i have to turn off optimize and frame pointer (as workaround), but i a am not expirienced enough to rewrite my code good enough to not need optimize and other stuff...

 

@7bit, i want to automate  everything possible (so all except Wave-Form, RATE and Programchange), because they are combined with Clock, resync...)

The Automations are:

MotionSequencer

Velocity from trigger

OSC (LFO)

and they all get summed/combined together on each CC/aout/parameter ... i dont want to mix here, its better to leaf it u16, the program is already big, and it would lead to problems and headpain in the future.

Edited by Phatline

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now