FFT code in C (or not in assembly language) anyone?

Hello

I'm new to this forum. I'm working on a Christmas project to drive some APA 102 LEDs from the frequencies found in the live music playing.

I know how to drive my APA 102 form the FastLED library - that works fine
I've downloaded and installed the Open Music Labs library for FFT and can run simple FFT input from a microphone input

Challenge is when I try to use some of the FastLED library HSV functions such as setHSV(hue, 255,255) where hue would come from the value of a given frequency bin for example I'm getting a compile time error


TEST_FHT.ino: In function 'void loop()':
TEST_FHT:70: error: r28 cannot be used in asm here
TEST_FHT:70: error: r29 cannot be used in asm here
TEST_FHT:70: error: r28 cannot be used in asm here
TEST_FHT:70: error: r29 cannot be used in asm here
r28 cannot be used in asm here

if I remove the HSV function, then I don't run into an issue.

2 questions:

1/ are there known incompatibilities between those libraries.
2/ is there an easy fix (I googled around but could not find anything obvious)
3/ I've seen there is a simpler fix_fft floating around the internet which would work for what I want to do but I can't seem to find a suitable version for the latest arduino IDE version. Anyone would have a pointer to something that works?

thx

I'm looking for some FFT code that would work fine in 1.6.6 and would not use any ASM language (I'm using various libraries in my project that seems to conflict).

I've seen fix_fft in different places all over the internet but nothing recent. This would meet my needs but there seems to be lots of challenges (code I've seen dates from 2011)

Any pointer on where I could start to get a "modern" FFT code?

thx

http://wiki.openmusiclabs.com/wiki/ArduinoFHT

J-M-L:
Any pointer on where I could start to get a "modern" FFT code?

You didn't mention which board you're using, or which ones you'd be willing to consider, if such code existed for them.

I'm going to guess you're only willing to use 8 bit AVR? As you might imagine, your FFT options open up considerably if you step up to 32 bit ARM chips.

I would suggest the Openmusiclabs FFT rather than the FHT suggested in reply #1. On the Arduino, there is no significant advantage in using the FHT. Both are limited to 256 points. With a less efficient FFT, such as the standard Numerical Recipes code, you can have larger, floating point arrays. Download at http://ronispc.chem.mcgill.ca/ronis/chem593/sinfft.c.html

I think we have here a classic XY problem
http://xyproblem.info/
X-Y Problem

J-M-L:
I'm looking for some FFT code that would work fine in 1.6.6 and would not use any ASM language (I'm using various libraries in my project that seems to conflict).

What makes you think that assembler language in a library causes any conflict? Quite simply it does not.

What causes conflict is when each library uses the same hardware resource like a timer. Therefore your real problem is that the FFT you have tried is using some resource that some other unspecified libraries need. It could be as simple as it is just using up all the memory, we don't know because there is so much missing from the original post.

J-M-L:
(code I've seen dates from 2011)

Any pointer on where I could start to get a "modern" FFT code?

Bless. You must be terribly young if you think 2011 is old. This is not an operating system you know being made redundant just to sell more stuff. The year 2011 is just like yesterday for code like this, nothing has changed in "all those long years" to make the code obsolete in any way.

Maybe this video tutorial will help? The FFT info begins at 34:56.

Internally, this library is mostly C++ with some small bits of assembly, and the FFT portion is built on top of ARM's DSP math library, which is mostly written in C but also uses some assembly.

Hopefully you can see in the video how the library makes processing audio pretty easy, so you don't have to do painful assembly code in your sketch. That's what libraries are all about. They package up the difficult parts for you.

Of course FFT involves a lot of computation, which needs to happen while you're also rapidly acquiring the data and trying to actually do something with the FFT results. Different libraries will have different ease of use, especially regarding the need to balance all 3 of these activities.

Hi

thanks for the answers. let me give you a bit more context

I'm planing to use an arduino mega for my project which is about driving ~2500 APA 102 LEDs based on live audio analysis so i need more RAM than the UNO would offer.

I can drive the APA 102 LEDS from the FastLED library - that works fine

I've downloaded and installed the Open Music Labs library for FFT and can run simple FFT input from a microphone input. from what I gather they use assembly code there

My challenge comes when I try to use some of the FastLED library HSV functions such as setHSV(hue, 255,255) where hue would come from the value of a given frequency bin for example I'm getting a compile time error


TEST_FHT.ino: In function 'void loop()':
TEST_FHT:70: error: r28 cannot be used in asm here
TEST_FHT:70: error: r29 cannot be used in asm here
TEST_FHT:70: error: r28 cannot be used in asm here
TEST_FHT:70: error: r29 cannot be used in asm here
r28 cannot be used in asm here

if I remove the HSV function, then I don't run into an issue. if I don't have the FFT library then all the FastLED library examples just run fine. (hence my impression there is some sort of conflicts somewhere).

I've googled around for "r28 cannot be used in asm here" but this did not lead me anywhere.

My thoughts were that if I could find a C based FFT library then it would be easier for me to understand what's going on.

any thoughts on where I could start exploring this would be appreciated!

thanks

thanks - I'll give it a try

You should really step up to faster 32 bit chip. Then you can have higher FFT resolution (a 1024 point FFT analysis), which really help after you consider the loss of resolution from using a window function which prevents spectral leakage problems.

A fast 32 bit chip will also really help with acquiring incoming audio while you do all the other computationally intensive work and transmit the LED data. Otherwise, you'll be only analyzing the music in small chunks with large blind spots, which can cause you to miss important short-duration but musically meaningful events.

if I remove the HSV function, then I don't run into an issue. if I don't have the FFT library then all the FastLED library examples just run fine. (hence my impression there is some sort of conflicts somewhere).

You might be running out of memory but I can't find any reference to r28 in the FastLED library so I doubt it it the library per-say that is giving you trouble.

Any chance of posting the code that gives that error as an attachment?
Plus a link to any libraries you are using so I can try and reproduce what you are seeing.

Hi "Grumpy_Mike"

I'm fine on memory side I believe, I reduced memory footprint to a min (40 LEDS FHT size 32) for testing and the error is at compile time anyway, not at runtime.

here is what a failing example of the code looks like

#define LOG_OUT 1 // use the log output function
#define FHT_N 32  // set to 32 point fht
#include <FHT.h>  // include the library

#include <FastLED.h>


#define DATA_PIN    51
#define CLK_PIN     52
#define LED_TYPE    APA102
#define COLOR_ORDER BGR
#define NUM_LEDS    40
CRGB leds[NUM_LEDS];

#define BRIGHTNESSMAX 16

void setup() {
  FastLED.addLeds<LED_TYPE, DATA_PIN, CLK_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);

  // all red
  fill_solid( leds, NUM_LEDS, CRGB::Red);
  FastLED.show();
  delay(1000); // wait a bit (debug)

  ADCSRA = 0xe7;  // set the adc to free running mode, scaler 7 --> 128
  ADMUX = 0x40;   // use adc0
  DIDR0 = 0x01;   // turn off the digital input for adc0
}




void loop() {


  cli();  // globally disable interrupts — UDRE interrupt slows this way down on arduino1.0
  for (int i = 0 ; i < FHT_N ; i++) { // save FHT_N samples. the loop is faster than adc gets ready so max speed
    while (!(ADCSRA & 0x10)); // wait for adc to be ready
    ADCSRA = 0xf5; // restart adc
    byte m = ADCL; // fetch adc data
    byte j = ADCH;
    int k = (j << 8) | m; // form into an int
    k -= 0x0200; // form into a signed int
    k <<= 6; // form into a 16b signed int
    fht_input[i] = k; // put real data into bins
  }
  fht_window(); // window the data for better frequency response
  fht_reorder(); // reorder the data before doing the fht
  fht_run(); // process the data in the fht
  fht_mag_log(); // take the output of the fht
  sei();

  for (int i = 0; i < FHT_N / 2; i++) {
    /* compiling with those 2 lines works fine and code executes OK */
    if ((2 * i) < NUM_LEDS)     leds[2 * i].setRGB( fht_log_out[i], 0, 0);
    if ((2 * i) + 1 < NUM_LEDS) leds[(2 * i) + 1].setRGB( fht_log_out[i], 0, 0);
    /* commenting out the 2 previous lines and uncommenting the 2 below = compiling error APA102_TEST_FHT:61: error: r29 cannot be used in asm here*/
//    if ((2 * i) < NUM_LEDS)     leds[2 * i] = CHSV( fht_log_out[i], 255, 255);
//    if ((2 * i) + 1 < NUM_LEDS) leds[(2 * i) + 1] = CHSV( fht_log_out[i], 255, 255);
  }
  FastLED.show();
}

I've an Arduino Mega 2560 with microphone input on analog 0 and an APA102 LED strip connected to pin 51 for data and pin 52 for the clock.

when you compile the code as provided above, all runs fine. I get 32 LEDS blinking with various shades of Red depending on sound input which is not really visual but works.

if you comment out the lines where I used the setRGB call and use instead the ones where I use the CHSV call then I can't compile and get


*/path/on/my/computer/*APA102_TEST_FHT.ino: In function 'void loop()':
APA102_TEST_FHT:62: error: r28 cannot be used in asm here
}
^
APA102_TEST_FHT:62: error: r29 cannot be used in asm here
APA102_TEST_FHT:62: error: r28 cannot be used in asm here
APA102_TEST_FHT:62: error: r29 cannot be used in asm here
exit status 1
r28 cannot be used in asm here


the compiler points at the closing bracket of the loop()

I'd be curious if you can compile the same code and see if you get the compile error. No need to have the same APA LEDS equipment as the error happens at compile time.

Source of libraries:

Thanks for the cooperation.

Your problem is that CHSV is not a function that you call to set values it is a strut data structure. It is defined in the library file as this:-

struct CHSV {
    union {
		struct {
		    union {
		        uint8_t hue;
		        uint8_t h; };
		    union {
		        uint8_t saturation;
		        uint8_t sat;
		        uint8_t s; };
		    union {
		        uint8_t value;
		        uint8_t val;
		        uint8_t v; };
		};
		uint8_t raw[3];
	};

Therefore you problems have nothing to do with the FFT library only the way you are using this structure.

Look at the ColorPalette examples for how it is used. You will see the variable that CHSV loads has previously been declared as:-

CRGBPalette16 currentPalette;

What is the problem with fix_fft and what version of the IDE are you using?

thanks for spending time to explore this and for the suggestion

yes indeed they have a struct but also some helper functions

if you look in the Controlling-leds documentation in the "Set HSV Color " section, you can see that they have 2 legit way to set the hue, saturation and brightness:

    // Simplest, preferred way: assignment from a CHSV color
    leds[i] = CHSV( 224, 187, 255);

    // Alternate syntax
    leds[i].setHSV( 224, 187, 255);

I did try also with the other form

if ((2 * i) < NUM_LEDS)     leds[2 * i].setHSV( fht_log_out[i], 255, 255);
if ((2 * i) + 1 < NUM_LEDS) leds[(2 * i) + 1].setHSV( fht_log_out[i], 255, 255);

but it fails in the same way at compile time.

any other idea welcome

Solved it.. thanks for helping me look in the right direction.

actually after looking a bit closer at what I thought were helper functions I realized indeed I was wrong.

I created a global variable

CHSV spectrumcolor;

and modified the code to read

spectrumcolor.hue = fht_log_out[i];
spectrumcolor.saturation = 255;
spectrumcolor.value = 255;
if ((2 * i) < NUM_LEDS)     hsv2rgb_spectrum( spectrumcolor, leds[2 * i] );
if ((2 * i) + 1 < NUM_LEDS) hsv2rgb_spectrum( spectrumcolor, leds[(2 * i) + 1] );

then it just compiles fine.

Thanks

Basically FastLED + Open Music Labs library is reported to work fine together.

The HSV stuff expects unsigned 8 bit value. Is that what the FFT gives you?

Also make sure to use the latest version of FastLED.

In case you don't find the problem yourself, just come over to the FastLED community and discuss your issue with people who have FFT up and running.

Problem is solved.
Cross post with here:-
http://forum.arduino.cc/index.php?topic=364808.0

Grumpy_Mike:
Problem is solved.
Cross post with here:-
http://forum.arduino.cc/index.php?topic=364808.0

Link died. Could you explain how to solve it?