Jump to content

note to frequency calculation (core32) -SOLVED


Phatline
 Share

Recommended Posts

the calculation from midi notes to frequency, is based on

tuning of note Number A3: eg. 430-450hz

 

the formular on the internet give me this:

freq = 440 * 2^((n-69)/12) where 'n' is the MIDI note number (2)
//Calculate Frequencys 4 notes...   
for (notecount = 0; notecount < 127; ++notecount)   
    { midi[notecount] = tuning * pow(2, (float)(notecount - 69)/12); }

it should fill an 127 wide array with Frequencys corresponding to its note numbers.

 

the formular make something wrong:  --- SOLVED - i updetate the working code > THX to Peter

when i put in Note Nr 33, i get -14hz (A0)

when i put in Note Nr 45, i get -17hz (A1)

when i put in Note Nr 57, i get -12hz (A2)

when i put in Note Nr 69, i get 866hz (A3)

when i put in Note Nr 61, i get 129hz (A4)

when i put in Note Nr 93, i get 0hz     (A5)

I put in:
actualnote: 69 (which is A3 &gt;&gt;&gt; Kammerton A)
tuning: 431 (A3 = 431hz)

it should put out: midi[actualnote]=431    

but on the LCD i prints out:1079427072 --- and this is not right >> SOLVED: write (float) in front of a Variable if you want to print it >>> thx to TK
 

WORKING CODE:

#include <mios32.h>
#include <FreeRTOS.h>
#include <task.h>
#include "tasks.h"
#include "file.h"
#include "app.h"
#include <portmacro.h>
#include <queue.h>
#include <semphr.h>
#include <string.h>
#include "mios32_timer.h"
#include "float.h"  
#include <stdio.h>
#include <math.h>
//#include "dmx.h"
 
//DMX:
typedef struct {
    int normal_access : 3;
    int single_bit_bb : 1;
} __attribute__((bitband)) my_struct;
my_struct phil;
 
#define NUM_ENCODERS 9 //5 Menue Encoders are connectet
const mios32_enc_config_t encoders[NUM_ENCODERS] = {//(SR begin with 1, ENC with 0) // setup the Pinout of that Encoders
    { .cfg.type=DETENTED2, .cfg.speed=FAST, .cfg.speed_par=4, .cfg.sr=1, .cfg.pos=0 },        //Menue Encoder 0     - only virtual, since they are mapped to differnt Variables...  
    { .cfg.type=DETENTED2, .cfg.speed=FAST, .cfg.speed_par=4, .cfg.sr=1, .cfg.pos=2 },        //Menue Encoder 1    - ...if "Menue Page Encoder" has changed
    { .cfg.type=DETENTED2, .cfg.speed=FAST, .cfg.speed_par=4, .cfg.sr=1, .cfg.pos=4 },        //Menue Encoder 2
    { .cfg.type=DETENTED2, .cfg.speed=FAST, .cfg.speed_par=4, .cfg.sr=1, .cfg.pos=6 },        //Menue Encoder 3
    { .cfg.type=DETENTED2, .cfg.speed=FAST, .cfg.speed_par=4, .cfg.sr=2, .cfg.pos=0 },        //Menue Encoder 4  
    { .cfg.type=DETENTED2, .cfg.speed=FAST, .cfg.speed_par=4, .cfg.sr=2, .cfg.pos=2 },        //Menue Encoder 5
    { .cfg.type=DETENTED2, .cfg.speed=FAST, .cfg.speed_par=4, .cfg.sr=2, .cfg.pos=4 },        //Menue Encoder 6
    { .cfg.type=DETENTED2, .cfg.speed=FAST, .cfg.speed_par=4, .cfg.sr=2, .cfg.pos=6 },        //Menue Encoder 7    
    { .cfg.type=DETENTED2, .cfg.speed=FAST, .cfg.speed_par=4, .cfg.sr=3, .cfg.pos=0 },};    //Menue Page Encoder
xSemaphoreHandle xLCDSemaphore;        // take and give access to LCD
 
    u32 MenueUpdateCount = 0; //to calculate the LCD-Menue-Update-Rate
    float value = 0; //Encoder calculation...
    u32 i = 0; //Encoder calcualtion
 
//DMX
u8 RGBWdmx[4]={0, 0, 0, 250}; //RGBW values
u8 RGBWenc[4]={0, 0, 0, 250}; //RGBW values
u8 count = 0; //to count thru the rgbw-channels while sending DMX...
 
//note2sound
  u32 nm = 10;
  u32 rpm = 25680;
  u32 time = 2161; //setup timer time
  u32 timecount = 0;
  u32 hzcount = 0;
  u32 decaytime = 128;
  float tuning = 431; //represent the tuning of "Kammerton A3"   
  float finetuning = 0.95; //represent the floating point of tuning (eg.: 431,095hz)
  u32 finetuningLCD = 95; //float of tuning - to calculate to show on display
  float midi[127] = {}; //represent Midinote 0-127 - and its value is a Frequency in [hz]
  u32 actualnote = 69; // where 69 is A3 named A (which is tuned with "tuning" Variable above)
  s32 notecount = 0; // only a counter variable to calculate the note frequencys.
   
//MidiSetup
u8 midich = Chn9;
u8 midiport= 32; //Midi-Melody Input, [32=UART0=Midi1, 33=UART1=Midi2 on LPC17core]
 
//Task Prioritys    
#define MUTEX_LCD_TAKE { while( xSemaphoreTakeRecursive(xLCDSemaphore, (portTickType)0) != pdTRUE ); }  //a Mutex reserve a Resoure (LCD or SD-Card) for a task, until it is given away...
#define MUTEX_LCD_GIVE { xSemaphoreGiveRecursive(xLCDSemaphore); }
#define PRIORITY_StoreLoad   ( tskIDLE_PRIORITY + 2 ) //3:Mios standart
 
static void StoreLoad(u8 tick, u16 order);        
 
void APP_Init(void){
    MIOS32_BOARD_LED_Init(0xffffffff);                                  //initialize all LEDs
    xLCDSemaphore         = xSemaphoreCreateRecursiveMutex();                //create Mutex for LCD access                                                                                                    //initialize encoders   i = counter
    for(i=0; i<NUM_ENCODERS; ++i) MIOS32_ENC_ConfigSet(i, encoders[i]); //initialize encoders
    //DMX_Init(0);
}
 
 
void APP_Background(void){  
//DMX:
  // endless loop
/*  while(1) { for (count=0;count<4;count++)
             { if (RGBWdmx[count]!=RGBWenc[count]) //if something has changed - send the value via DMX!
               {   RGBWdmx[count]=RGBWenc[count];
                   DMX_SetChannel(count,(u8)RGBWdmx[count]);}
             }
           } */
}
 
void APP_Tick(void) {  //1ms Event Triggering
MenueUpdateCount = MenueUpdateCount + 1;  
     if(MenueUpdateCount > 650){MenueUpdateCount = 0; StoreLoad(0, 0);}} //update the Menue
 
void APP_MIDI_Tick(void){}
 
void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package){
  if(port==midiport && midi_package.chn == midich && midi_package.type == NoteOn)
    {actualnote=midi_package.note;}}
    
void APP_SRIO_ServicePrepare(void){}
void APP_SRIO_ServiceFinish(void){}
void APP_DIN_NotifyToggle(u32 pin, u32 pin_value){}
 
void APP_ENC_NotifyChange(u32 encoder, s32 incrementer){    
    if(encoder == 1){ value = tuning + incrementer; //tuning of note A-3  
       if(value < 430)   {value = 450;}
       if(value > 450)   {value = 430;}
       tuning = value;
       //Calculate Frequencys 4 notes...   
       for (notecount = 0; notecount < 127; ++notecount)   
         {midi[notecount] = tuning * pow(2, (float)(notecount - 69)/12);}
       //{midi[notecount] = tuning * (2 ^ ((notecount-69) / 12));}  
    }    
    
    if(encoder == 2){ value = finetuning + ((float)incrementer/1000); // finetune
                      if(value < 0.001)   {value = 0;}
                      if(value > 1)       {value = 1;}
                      finetuning = value;
                      tuning=tuning + finetuning;      
                      if(tuning < 430)   {tuning = 430;}
                      if(tuning > 450)   {tuning = 450;}
                      finetuningLCD = finetuning*1000;    }
                          
    if(encoder == 3){ value = RGBWenc[0] + incrementer; //RED
                      if(value < 0)   {value = 255;}
                      if(value > 255)   {value = 0;}
                      RGBWenc[0] = value;               }
 
    if(encoder == 4){ value = RGBWenc[1] + incrementer; //GREEN
                      if(value < 0)   {value = 255;}
                      if(value > 255)   {value = 0;}
                      RGBWenc[1] = value;               }                       
    if(encoder == 5){ value = RGBWenc[2] + incrementer; //BLUE
                      if(value < 0)   {value = 255;}
                      if(value > 255)   {value = 0;}
                      RGBWenc[2] = value;               }
                       
    if(encoder == 6){ value = RGBWenc[3] + incrementer; //White
                      if(value < 0)   {value = 255;}
                      if(value > 255)   {value = 0;}
                      RGBWenc[3] = value;               }                      
}
 
void APP_AIN_NotifyChange(u32 pin, u32 pin_value){}
 
static void StoreLoad(u8 tick, u16 order){         //Display MENUE
    if(tick == 0){//Menue tick
         MUTEX_LCD_TAKE;        //request LCD access
            MIOS32_LCD_Clear(); //clear screen
          //1st Line = Encoder Variables....change something!
            MIOS32_LCD_CursorSet(0,  0);  MIOS32_LCD_PrintFormattedString("%u", actualnote);
            MIOS32_LCD_CursorSet(4,  0);  MIOS32_LCD_PrintFormattedString("%d", (int)tuning);
            MIOS32_LCD_CursorSet(7,  0);   
            if (finetuningLCD>=100)                      {MIOS32_LCD_PrintFormattedString("%s" "%d", ".",   finetuningLCD);}
            if (finetuningLCD< 100 && finetuningLCD>=10) {MIOS32_LCD_PrintFormattedString("%s" "%d", ".0",  finetuningLCD);}
            if (finetuningLCD< 10)                       {MIOS32_LCD_PrintFormattedString("%s" "%d", ".00", finetuningLCD);}     
                   
            MIOS32_LCD_CursorSet(16, 0);  MIOS32_LCD_PrintFormattedString("%d", RGBWenc[0]);
            MIOS32_LCD_CursorSet(21, 0);  MIOS32_LCD_PrintFormattedString("%d", RGBWenc[1]);
            MIOS32_LCD_CursorSet(27, 0);  MIOS32_LCD_PrintFormattedString("%d", RGBWenc[2]);
            MIOS32_LCD_CursorSet(32, 0);  MIOS32_LCD_PrintFormattedString("%d", RGBWenc[3]);
            MIOS32_LCD_CursorSet(37, 0);  MIOS32_LCD_PrintFormattedString("%d", (int)midi[actualnote]);
             
          //2nd Line = Menue Describtio
            MIOS32_LCD_CursorSet(0,  1);  MIOS32_LCD_PrintFormattedString("%s", "nte ");
            MIOS32_LCD_CursorSet(4,  1);  MIOS32_LCD_PrintFormattedString("%s", "tune");             
            MIOS32_LCD_CursorSet(16, 1);  MIOS32_LCD_PrintFormattedString("%s", "red  ");
            MIOS32_LCD_CursorSet(21, 1);  MIOS32_LCD_PrintFormattedString("%s", "gren  ");             
            MIOS32_LCD_CursorSet(27, 1);  MIOS32_LCD_PrintFormattedString("%s", "blue ");
            MIOS32_LCD_CursorSet(32, 1);  MIOS32_LCD_PrintFormattedString("%s", "whit ");                                    
            MIOS32_LCD_CursorSet(37, 1);  MIOS32_LCD_PrintFormattedString("%s", "frq");             
          MUTEX_LCD_GIVE;}}                    // release LCD access for other tasks

 

&

 

replace:
LIBS =

with

LIBS = -lm

in the makefile...

 

 
Edited by Phatline
Link to comment
Share on other sites

THX TK!  - worked! - have updatet the code above...i think there are better way to show floating in LCD, but thats the workaround i can do (which much code lines extra.)

 

now i see what the code does... and it does not right:

 

the calculation from midi notes to frequency, is based on

tuning of note Number 69 (A3): for example @ 432hz

 

the formular on the internet give me this:

freq = 430 * 2^((n-69)/12) where 'n' is the MIDI note number (2)

 

i progrommed this:

for (notecount = 0; notecount < 127; ++notecount)  
       {midi[notecount] = tuning * (2 ^ ((notecount-69) / 12));} 

 

it should fill a 127 wide array with Frequencys corresponding to its note numbers.

 

the formular make something wrong because the outputs are wrong:

when i put in Note Nr 33, i get -14hz (A0)  should be 54

when i put in Note Nr 45, i get -17hz (A1)  should be 107

when i put in Note Nr 57, i get -12hz (A2)  should be 215

when i put in Note Nr 69, i get 866hz (A3)  should be 431

when i put in Note Nr 61, i get 129hz (A4)  should be 862

when i put in Note Nr 93, i get 0hz     (A5)  should be 1724

Edited by Phatline
Link to comment
Share on other sites

Hm, lemme say the calculation seems at least a bit dubious :-)

 

 

(notecount-69) / 12

 

 

this is a note offset, divided by 12 (octave), which kind of shifts the input note around the origin (69), than scales it by octaves. Good thinking, so far...

But it performs on an s32, which is a signed 32 bit integer. The C compiler will not use floating point math here (source variable datatype defines the division method), so it is very lossy after the division by 12.

 

Then, the "^" operator - the original author probably wanted a "2 to the power of x" operation, but in C, the "^" operator is executed as a bitwise XOR calculation. So, this seems very strange.

 

Why not try it with this line:

 

 

midi[notecount] = tuning * pow(2, (float)(notecount - 69)/12);

 

 

Many greets,

Peter

Edited by Hawkeye
Link to comment
Share on other sites

hi peter, thank you for watching in.

 

for POW i had to add first:

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

 

i got then following compiling error with your line:

(app.c:21:1: was there bevore and has something to do what that dmx stuff...that i "//" out  @ the moment)

 

make (im Verzeichnis: /home/tekkstar/c/note2light)
rm -f project.hex
Creating object file for app.c
app.c:21:1: warning: 'bitband' attribute directive ignored [-Wattributes]
 } __attribute__((bitband)) my_struct;
 ^
/usr/lib/gcc/arm-none-eabi/4.8/../../../arm-none-eabi/lib/armv7-m/libm.a(lib_a-w_pow.o): In function `pow':
/build/buildd/newlib-2.1.0+git20140818.1a8323b/build/arm-none-eabi/armv7-m/newlib/libm/math/../../../../../../newlib/libm/math/w_pow.c:210: undefined reference to `__errno'
/build/buildd/newlib-2.1.0+git20140818.1a8323b/build/arm-none-eabi/armv7-m/newlib/libm/math/../../../../../../newlib/libm/math/w_pow.c:164: undefined reference to `__errno'
/build/buildd/newlib-2.1.0+git20140818.1a8323b/build/arm-none-eabi/armv7-m/newlib/libm/math/../../../../../../newlib/libm/math/w_pow.c:120: undefined reference to `__errno'
/build/buildd/newlib-2.1.0+git20140818.1a8323b/build/arm-none-eabi/armv7-m/newlib/libm/math/../../../../../../newlib/libm/math/w_pow.c:207: undefined reference to `__errno'
collect2: error: ld returned 1 exit status
Kompilierung fehlgeschlagen.
/home/tekkstar/mios32/trunk/include/makefile/common.mk:139: recipe for target 'project_build/project.elf' failed
make: *** [project_build/project.elf] Error 1
 
Link to comment
Share on other sites

Very interesting - do you have the lastest compiler toolchain in use?

 

I just tried injecting a pow() statement in the source code of "Tutorial 1" and it compiles and links without a problem for either LPC1769 or STM32F4...

Omitting the #include <math.h> only produced a warning, but no linker error. But of course, it makes sense to include math.h! :-)

 

Can you update the toolchain?

 

Many greets,

Peter

Link to comment
Share on other sites

hi,

no - i setuped this linux pc 2015, the actual toolchain is 2013

 

I also opened Tutorial 1 and  i made a simple operation:

#include <mios32.h>
#include "app.h"
#include <math.h>

  float midi[127] = {}; //represent Midinote 0-127 - and its value is a Frequency in [hz]
  u32 actualnote = 69; // where 69 is A3 named A (which is tuned with "tuning" Variable above)
  s32 notecount = 0; // only a counter variable to calculate the note frequencys.
  float tuning = 431; //represent the tuning of "Kammerton A3"  
  float finetuning = 0.95; //represent the floating point of tuning (eg.: 431,095hz)
  
void APP_Init(void){}
void APP_Background(void){}
void APP_Tick(void){}
void APP_MIDI_Tick(void){}

void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package)
{ 
	       notecount = tuning * pow(2, 2);
         //for (notecount = 0; notecount < 127; ++notecount)  
         //{midi[notecount] = tuning * pow(2, (float)(notecount - 69)/12);}
}

void APP_SRIO_ServicePrepare(void){}
void APP_SRIO_ServiceFinish(void){}
void APP_DIN_NotifyToggle(u32 pin, u32 pin_value){}
void APP_ENC_NotifyChange(u32 encoder, s32 incrementer){}
void APP_AIN_NotifyChange(u32 pin, u32 pin_value){}

which is compiling without problems

 

but by using again your code line:

#include <mios32.h>
#include "app.h"
#include <math.h>

  float midi[127] = {}; //represent Midinote 0-127 - and its value is a Frequency in [hz]
  u32 actualnote = 69; // where 69 is A3 named A (which is tuned with "tuning" Variable above)
  s32 notecount = 0; // only a counter variable to calculate the note frequencys.
  float tuning = 431; //represent the tuning of "Kammerton A3"  
  float finetuning = 0.95; //represent the floating point of tuning (eg.: 431,095hz)
  
void APP_Init(void){}
void APP_Background(void){}
void APP_Tick(void){}
void APP_MIDI_Tick(void){}

void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package)
{ 
	       //notecount = tuning * pow(2, 2);
         for (notecount = 0; notecount < 127; ++notecount)  
         {midi[notecount] = tuning * pow(2, (float)(notecount - 69)/12);}
}

void APP_SRIO_ServicePrepare(void){}
void APP_SRIO_ServiceFinish(void){}
void APP_DIN_NotifyToggle(u32 pin, u32 pin_value){}
void APP_ENC_NotifyChange(u32 encoder, s32 incrementer){}
void APP_AIN_NotifyChange(u32 pin, u32 pin_value){}

i got the known error message:

make (im Verzeichnis: /home/tekkstar/mios32/trunk/apps/tutorials/001_forwarding_midi)
rm -f project.hex
Creating object file for app.c
/usr/lib/gcc/arm-none-eabi/4.8/../../../arm-none-eabi/lib/armv7-m/libm.a(lib_a-w_pow.o): In function `pow':
/build/buildd/newlib-2.1.0+git20140818.1a8323b/build/arm-none-eabi/armv7-m/newlib/libm/math/../../../../../../newlib/libm/math/w_pow.c:210: undefined reference to `__errno'
/build/buildd/newlib-2.1.0+git20140818.1a8323b/build/arm-none-eabi/armv7-m/newlib/libm/math/../../../../../../newlib/libm/math/w_pow.c:164: undefined reference to `__errno'
/build/buildd/newlib-2.1.0+git20140818.1a8323b/build/arm-none-eabi/armv7-m/newlib/libm/math/../../../../../../newlib/libm/math/w_pow.c:120: undefined reference to `__errno'
Kompilierung fehlgeschlagen.
/home/tekkstar/mios32/trunk/include/makefile/common.mk:139: recipe for target 'project_build/project.elf' failed
/build/buildd/newlib-2.1.0+git20140818.1a8323b/build/arm-none-eabi/armv7-m/newlib/libm/math/../../../../../../newlib/libm/math/w_pow.c:207: undefined reference to `__errno'
collect2: error: ld returned 1 exit status
make: *** [project_build/project.elf] Error 1

strange.

Link to comment
Share on other sites

Oh yes,

you are right! :-)

 

Somehow my test line was probably eliminated by the optimizer.

Compiling your code, i got the same error.

But it is easy to be solved :-)

 

Replace

 

 

LIBS =

 

 

with

 

 

LIBS = -lm

 


 

in your Makefile and it should work. We need to link with the math library, and all will be fine :-)

 

Have a great evening!

Peter

Link to comment
Share on other sites

THANKZ @ TK and

THANKZ @ Peter - you made my day - [note]2[hz] is up and running!

----so the first conversions from the first part of [sound]2[light] is done... and i learned a bit math - what a day.

---I updated the first postt and the code >>> SOLVED!

Edited by Phatline
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

×
×
  • Create New...