electro-music.com   Dedicated to experimental electro-acoustic
and electronic music
 
    Front Page  |  Radio
 |  Media  |  Forum  |  Wiki  |  Links
Forum with support of Syndicator RSS
 FAQFAQ   CalendarCalendar   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   LinksLinks
 RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in  Chat RoomChat Room 
 Forum index » DIY Hardware and Software » Developers' Corner
Midi to CV design -- Soliciting advice
Post new topic   Reply to topic Moderators: DrJustice
Page 2 of 3 [59 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
Goto page: Previous 1, 2, 3 Next
Author Message
elkayem



Joined: Jul 04, 2017
Posts: 33
Location: Santa Clara, CA

PostPosted: Mon Apr 08, 2019 6:03 am    Post subject: Reply with quote  Mark this post and the followings unread

I realize now that you were probably asking about my midi2cv code rather than my usbMidi2cv code. Meaning I probably answered a question you didn’t ask.

Yes, pitch bend can be added to midi2cv. I probably need to hear more about what you want the code to do before jumping in with advice.
Back to top
View user's profile Send private message
hububalli



Joined: Feb 15, 2014
Posts: 41
Location: UK

PostPosted: Mon Apr 08, 2019 7:07 am    Post subject: Reply with quote  Mark this post and the followings unread

Thanks for the quick reply!

I am talking about your original Midi2CV, which does already have a pitch output. This one on github:

https://github.com/elkayem/midi2cv

You are correct in what I was trying to achieve. I tired what you suggested anyway and am getting a little under 1 octave with

Code:

// Pitch bend output from 0 to 1023 mV.  Left shift d2 by 4 to scale from 0 to 2047.
// With DAC gain = 1X, this will yield a range from 0 to 1023 mV.
SetVoltage(DAC2, 0, 0, d2<<5);  // DAC2, channel 0, gain = 1X


Using
Code:
setVoltage(DAC2, 0, 0, d2<<2);

I achieve about 1 3/4 semitones. That is where I got stuck in my experiments.
Back to top
View user's profile Send private message
elkayem



Joined: Jul 04, 2017
Posts: 33
Location: Santa Clara, CA

PostPosted: Tue Apr 09, 2019 8:15 am    Post subject: Reply with quote  Mark this post and the followings unread

Then I wasn’t too far off in my original reply. Try replacing d2<<4 with (unsigned int)(5.208f * d2). I haven’t tried it, but believe it should accomplish what you want.
Back to top
View user's profile Send private message
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue Apr 09, 2019 8:35 am    Post subject: Reply with quote  Mark this post and the followings unread

NO

DO NOT DO FLOATING POINT MATH IN AN MCU.

There was at least one open source MIDI project out there that would skip notes because the overhead of putting the FP math into their code slowed it down/bloated the code because there was no native FP support.

Do the math as equivalent fractions.

(unsigned int)((d2 * 5208) / 1000)

The compiler will know that it doesn't need to worry about decimals in this case and won't try to add in all the FP overhead.
Back to top
View user's profile Send private message
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue Apr 09, 2019 8:37 am    Post subject: Reply with quote  Mark this post and the followings unread

Even better, get rid of all the extraneous common factors between 5208 and 1000, and use 651 / 125. Less risk of overflow.
Back to top
View user's profile Send private message
JovianPyx



Joined: Nov 20, 2007
Posts: 1988
Location: West Red Spot, Jupiter
Audio files: 224

PostPosted: Tue Apr 09, 2019 9:22 am    Post subject: Reply with quote  Mark this post and the followings unread

elmegil wrote:
NO

DO NOT DO FLOATING POINT MATH IN AN MCU.

There was at least one open source MIDI project out there that would skip notes because the overhead of putting the FP math into their code slowed it down/bloated the code because there was no native FP support.

Do the math as equivalent fractions.

(unsigned int)((d2 * 5208) / 1000)

The compiler will know that it doesn't need to worry about decimals in this case and won't try to add in all the FP overhead.


I would add a caveat here. Believe it or not, STM32 devices are called MCU (micro controller unit). It may seem untrue for 32 bit processors that can run as fast as 400 MHz, but that's what it is. In the case of many STM32 processors, there is a hardware floating point FPU which does add, subtract and multiply in a single CPU cycle. In those processors, it makes sense to use floating point instead of say 16 bit fixed point or integer math because integer arithmetic is no faster than floating point. In fact, the leading edge STM32 processors also include a double precision mode for double types. I don't believe those execute arithmetic in one CPU cycle because double is 64 bits wide so the CPU needs to do 2 memory fetches, the calculation and then 2 memory stores for at least 5 CPU cycles - still quite fast though.

Of course, on a 16 MHz arduino I do agree that it's folly to try to code up arithmetic processes using floats. But the Arduino (or AVR) is an 8 bit CPU so it takes a collection of instructions to do even 16 bit integer arithmetic.

STM32 and other ARM type processors are so cheap now that not only can fancy stuff be done with things like MIDI controllers, you can also bury a whole MIDI synthesizer using DSP methods in one.

So my caveat would boil down to "don't do floats in an 8 bit low speed MCU".

Last edited by JovianPyx on Tue Apr 09, 2019 9:26 am; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue Apr 09, 2019 9:23 am    Post subject: Reply with quote  Mark this post and the followings unread

fair enough Smile
Back to top
View user's profile Send private message
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue Apr 09, 2019 9:39 am    Post subject: Reply with quote  Mark this post and the followings unread

BTW using an STM32 for MIDI seems like MAJOR overkill Wink
Back to top
View user's profile Send private message
JovianPyx



Joined: Nov 20, 2007
Posts: 1988
Location: West Red Spot, Jupiter
Audio files: 224

PostPosted: Tue Apr 09, 2019 10:59 am    Post subject: Reply with quote  Mark this post and the followings unread

My main point was that when one starts doing stuff that uses wider bit width (any integer larger than 255 needs more than one instruction to do even an add in an 8 bit MCU) it becomes an advantage to move to a wider bit CPU. Certainly, many MIDI controllers can work using an 8 bit chip - depending on everything required of them. Since there really is no "archetype" MIDI to CV unit, there can be a desire for fancier stuff than just a few outs/ins and there are other things the MCU could do to enhance the MIDI to CV - which is when floating point can become more than just convenient (again, depending on the individual user's desires).

So it boils down to the right chip for the job. Surely a few outputs are handled well by an AVR, but as a (long time) developer, I know what the term "feature creep" means. You say "Ah! it works!" and then in a little while you think "Gee, what if I could add..." and then it starts. So I like to have processing headroom rather than try to cram code into a small slow CPU that can disappoint when you try to add one more feature. Planning can help here by trying to think of the features that you must have as well as those that would be nice extras.

Yes, a 400 MHz STM32H7 *might* be overkill, but that depends on what it is doing. Perhaps it's controlling more than one set of hardware attached to it's pins. Perhaps it's outputting 32 CVs gathered from 2 or 4 MIDI channels. Each person's idea of what MIDI to CV does is going to be unique.

STM32 CPU chips can have a large number of pins. Many have built in DACs and ADCs with the later chips doing as many as 16 bits of analog in and out - at really high speeds.

So I could counter that an AVR is a rather weak IC to use to save a couple of dollars - and it may not do even that when you start adding muxes and other logic to it. My start in MCU work began at the 8 bit MC6800 which ran at a whopping slow 1 MHz, so I know a whole lot about writing kinky weird assembly language stuff to make up for it's lack of registers, lack of speed, lack of bit width and lack of RAM. Why suffer?

Of course, if you're not *designing* a MIDI to CV and you are instead building someone else's already finished unit, I'd use what was specified since the code is already there. And I know that a lot of those are AVR based.

Main point here being: Choose the right chip for the job - and that can be a 8 bit AVR - but that can also be an STM32. We live in a wonderful time filled with kick-ass choices Smile

_________________
FPGA, dsPIC and Fatman Synth Stuff

Time flies like a banana.
Fruit flies when you're having fun.
BTW, Do these genes make my ass look fat?
corruptio optimi pessima
Back to top
View user's profile Send private message Visit poster's website
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue Apr 09, 2019 11:07 am    Post subject: Reply with quote  Mark this post and the followings unread

All good points. Smile

You're assuming AVR; the project in question is actually PIC16F based but that's still 8-bit math, so same difference, ultimately.

It's so much EEEEEASIER to just do it the way someone else did with slight tweaks though! Wink
Back to top
View user's profile Send private message
JovianPyx



Joined: Nov 20, 2007
Posts: 1988
Location: West Red Spot, Jupiter
Audio files: 224

PostPosted: Tue Apr 09, 2019 11:57 am    Post subject:   Reply with quote  Mark this post and the followings unread

I used AVR only as an example of a typical chip often used for things like MIDI controllers or MIDI to CV. Certainly PICs of all different shades can be used and some are more than 8 bits and some are quite fast.

However, all devices have their limits including STM32 high end MCUs.

I agree that when someone else has published as open source an already designed and debugged project and you want to have a clone, that's the easiest route. No sense in reinventing the wheel. It's just good to know how close to the wall the project had come for the original developer before you start to modify it - and then the fun starts when you look at the designer's coding style and go WTH did they do?. Been there...

The most important thing is to have fun and it looks like the people in this thread are doing that. I make these comments not to denigrate this or any other project, only to ensure that people are aware of choices they might not have realized are available. In my first days with MCUs, the only MCUs were 8 bit and they were all horribly slow. These days the choices we have are pretty crazy and something seemingly low key and simple like a MIDI to CV converter can easily bear the fruit of many new ideas that in my first days were not even possible.

_________________
FPGA, dsPIC and Fatman Synth Stuff

Time flies like a banana.
Fruit flies when you're having fun.
BTW, Do these genes make my ass look fat?
corruptio optimi pessima
Back to top
View user's profile Send private message Visit poster's website
elkayem



Joined: Jul 04, 2017
Posts: 33
Location: Santa Clara, CA

PostPosted: Tue Apr 09, 2019 10:03 pm    Post subject: Reply with quote  Mark this post and the followings unread

elmegil wrote:
NO

DO NOT DO FLOATING POINT MATH IN AN MCU.



No need to yell, I'm a reasonable guy Cool
Back to top
View user's profile Send private message
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue Apr 09, 2019 10:05 pm    Post subject: Reply with quote  Mark this post and the followings unread

Sorry about that Very Happy
Back to top
View user's profile Send private message
elkayem



Joined: Jul 04, 2017
Posts: 33
Location: Santa Clara, CA

PostPosted: Tue Apr 09, 2019 10:11 pm    Post subject: Reply with quote  Mark this post and the followings unread

elmegil wrote:


Do the math as equivalent fractions.

(unsigned int)((d2 * 5208) / 1000)



Are you suggesting I replace the floating point multiply in my "bloated" code with an even more expensive division operator?

My benchmark tests suggest that an integer divide takes 14 microseconds vs 8 usec for the dreaded floating point multiply.
Back to top
View user's profile Send private message
elkayem



Joined: Jul 04, 2017
Posts: 33
Location: Santa Clara, CA

PostPosted: Tue Apr 09, 2019 10:15 pm    Post subject: Reply with quote  Mark this post and the followings unread

elmegil wrote:
Even better, get rid of all the extraneous common factors between 5208 and 1000, and use 651 / 125. Less risk of overflow.


How about (d2 * 5332) >> 10. Even more efficient.
Back to top
View user's profile Send private message
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue Apr 09, 2019 10:17 pm    Post subject: Reply with quote  Mark this post and the followings unread

What's your processor, I have lost track of that.

I have assumed being a MIDI project that it was something smaller, closer to the AVR/PIC I was discussing with Pyx than the STM32.

Integer operations will ALWAYS be faster than FP operations unless theres some kind of FP coprocessor etc.

So my suspicion based on your result is that you're using something more capable than I was assuming, in which case feel free to disregard me. Smile

Also, use the simplified fraction, if you weren't testing with that already. a factor of 8 in numerator and denominator, and the fact that's likely to overflow, won't do you any favors.

.... or the multiply and shift, sure. That definitely would be faster.


PS I don't recall saying your code was bloated Wink I was referring to the PIC code for the MIDI project I was referring to. Size was significantly larger when the FP routines were added to the image.
Back to top
View user's profile Send private message
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue Apr 09, 2019 10:23 pm    Post subject: Reply with quote  Mark this post and the followings unread

Is your benchmark running on the hardware directly, or in some emulation on your computer that, perhaps, takes advantage of the computer's FP coprocessor? Smile
Back to top
View user's profile Send private message
elkayem



Joined: Jul 04, 2017
Posts: 33
Location: Santa Clara, CA

PostPosted: Tue Apr 09, 2019 10:47 pm    Post subject: Reply with quote  Mark this post and the followings unread

Sorry for getting a bit touchy. I'm just running on an Arduino Nano, featuring an AVR 328P. 8-bit math, no FPU, 16 MHz, nothing fancy. Those numbers were benchmarked on my chip, not emulated.

Incidentally, I don't agree at all that integer operations are "ALWAYS" faster than FP. Integer division is notoriously slow.
Back to top
View user's profile Send private message
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue Apr 09, 2019 11:14 pm    Post subject: Reply with quote  Mark this post and the followings unread

elkayem wrote:
Integer division is notoriously slow.


We can agree to disagree, but while integer division is definitely much slower that multiplication and shifting, FP operations without FP support in the hardware is also notoriously slow. I don't know how the AVR libraries differ from PIC stuff, but the ACXNet Lite was doing the exact same multiply (5.208) and it would drop notes like nobody's business if it was being driven by a fast MIDI sequencer. Going to the integer operations fixed it.

That is interesting that the division is so much slower in this case; how does the multiply then shift benchmark? (BTW could do multiply by 1333 and >>8 instead ... )
Back to top
View user's profile Send private message
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue Apr 09, 2019 11:31 pm    Post subject: Reply with quote  Mark this post and the followings unread

Actually found the code, I was wrong it wasn't 5.208...

switch (MIDI_Byte1) {
case 0x90: // Note On
if (MIDI_Byte3 == 0) FinNote();
else {
Note_VAL = MIDI_Byte2 - 24; //Le do grave a la valeur 24 et pas 0
//Note_VAL = Note_VAL * 83.3333; //83.3333 = 1 V/oct /12
// use integer math instead; the slowdown causes dropped notes and hanging gates
// with some MIDI sources
Note_VAL = Note_VAL * 250;
Note_VAL = (int) (Note_VAL / 3);
PlayNote(); //on joue la note
Gate();
}
Back to top
View user's profile Send private message
hububalli



Joined: Feb 15, 2014
Posts: 41
Location: UK

PostPosted: Wed Apr 10, 2019 2:19 am    Post subject: Reply with quote  Mark this post and the followings unread

I have had a chance to try out the new code and got the following results.

'(unsigned int)(5.208f * d2)' Worked perfectly.

'(d2 * 5332) >> 10', '(unsigned int)((d2 * 5208) / 1000)', and '(unsigned int)((d2 * 651) / 125)', all gave strange results. '(d2 * 5332) >> 10' was my favourite, it gave a weird 8bit kind of effect, had flashbacks of playing my Atari. Smile

'(unsigned int)((d2 * 651) / 125)' had a pitch bend of about an octave for the first 5th of the wheel then for the rest it dropped a couple of octaves to a fixed tone.

Although far beyond me I enjoyed the discussion, working with microcontrollers has been on my to do list for some time.
Back to top
View user's profile Send private message
elkayem



Joined: Jul 04, 2017
Posts: 33
Location: Santa Clara, CA

PostPosted: Wed Apr 10, 2019 6:57 am    Post subject: Reply with quote  Mark this post and the followings unread

Glad it works hububalli! The problem with posting untested code is that it can lead to unpredictable results. It sounds like you stumbled on some new cool audio effects. I'm not certain, but I suspect the reason the other options didn't work is due to integer overflow. For example, d2 is a 7 bit integer (0-127) and 5208 is 13-bits, and we're trying to stuff the product into a 16-bit integer. The product is probably wrapping.
Back to top
View user's profile Send private message
elkayem



Joined: Jul 04, 2017
Posts: 33
Location: Santa Clara, CA

PostPosted: Wed Apr 10, 2019 7:22 am    Post subject: Reply with quote  Mark this post and the followings unread

Regarding speed of math operations on AVR MCUs, I was curious so I poked around a bit to see what others found. There are plenty of results out there, but I found this thread to be fairly interesting:

https://www.avrfreaks.net/forum/speed-maths-operations-especially-floating-point

It is a different chip than I'm using (1284P vs 328P, though very similar). Also a different compiler (Codevision), which probably has most to do with the results.

Post #3 shows a bar chart of some results. 32-bit integer division is the slowest, at 39 usec, followed by 8-bit division at 5.5 usec. Float multiplication is on par with 32-bit integer multiplication and faster than 8-bit int division, which clearly befuddled many people on the thread.

Further down the list on post #20, another person shares their own benchmark results. This one uses the same chip I'm using (328P @ 16 MHz) and same compiler (gcc-avr). His results show 16-bit int multiply in 1.06 usec, 32-bit int multiply in 5.3 usec, float multiply in 8.3 usec, 16-bit int divide in 13.8 usec, and 32-bit int divide in 37.2 usec. These results are similar to what I observed.

Anyway, I just post this out of idle curiosity. I've never really worried much about optimizing my code for the fastest math operations probably because I haven't been burned as others have with using floating point operations on MCUs. Maybe the compiler algorithms are improving?
Back to top
View user's profile Send private message
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Wed Apr 10, 2019 7:29 am    Post subject: Reply with quote  Mark this post and the followings unread

Huh. That's interesting.

I didn't go through any significant amount of optimizing with the ACXLite code, I just made the one change noted and the dropped notes stopped happening. I wonder if perhaps there was more context to this than my simple interpretation of FP vs INT.

And obviously since I mis-remembered, and was working with much smaller numbers (250 vs 5000) I didn't hit any overflow issues.

I can't argue with working code Very Happy

Make sure you take a MIDI sequencer and drive your converter as fast as you can, it's a good stress test.
Back to top
View user's profile Send private message
elkayem



Joined: Jul 04, 2017
Posts: 33
Location: Santa Clara, CA

PostPosted: Wed Apr 10, 2019 7:45 am    Post subject: Reply with quote  Mark this post and the followings unread

Good tip about testing it out on a sequencer.

Of course all of these discussions will become a thing of the past when we all move to 32-bit chips. I've been using the Blue Pill 72 MHz STM32 board for a lot of projects lately. No hardware floating point operations, but at less than $2 on Aliexpress, it outperforms the 8-bit Nano by miles for the same price.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic Moderators: DrJustice
Page 2 of 3 [59 Posts]
View unread posts
View new posts in the last week
Goto page: Previous 1, 2, 3 Next
Mark the topic unread :: View previous topic :: View next topic
 Forum index » DIY Hardware and Software » Developers' Corner
Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Forum with support of Syndicator RSS
Powered by phpBB © 2001, 2005 phpBB Group
Copyright © 2003 through 2009 by electro-music.com - Conditions Of Use