electro-smith / libDaisy

Hardware Library for the Daisy Audio Platform
https://www.electro-smith.com/daisy
MIT License
336 stars 144 forks source link

Port Mincer #40

Closed PaulBatchelor closed 4 years ago

PaulBatchelor commented 4 years ago

Hey @andrewikenberry, hope you don't mind me making a separate issue for porting mincer in #39. I think it warrants it. Mincer is going to be a multi-step process. Mincer is one of the few modules that uses all the built-in soundpipe-y utilites: FFT, ftables, and aux data.

You're going to need to port the FFT routine that it uses (a public domain one by John Green, which is the same internal FFT routine used by Csound): https://github.com/PaulBatchelor/Soundpipe/tree/master/lib/fft

I built a custom FFT wrapper for it which is what you see used in the soundpipe mincer implementation.

Mincer also uses soundpipe ftables, but you really don't need all the baggage that comes with that. A floating point array + size should do the trick. With some work, you should be able to factor that out.

Glancing at the source again, the allocated memory chunks via sp_alloc seem to be derived from window size. If you make the window size fixed via a macro or something (2048 or 4096 tend to be good values), these probably can go away as well. (And damn, looking at this, they really need to. Blech.)

andrewikenberry commented 4 years ago

Cool sounds great!

The extra utilities will be good to have anyways. I know Stephen has been looking at quite a few different FFT options lately.

stephenhensley commented 4 years ago

I have done minimal testing with ARMs CMSIS DSP library which has real fft transforms

https://github.com/ARM-software/CMSIS_5/tree/develop/CMSIS/DSP/Source/TransformFunctions

performs fairly well

static void test_stuff(float *in, float *out, size_t size)
{
    dsy_gpio_write(&gateout, 0);
    for (uint16_t i = 0; i < 32; i++)
    {
        test_in[i] = 2.5f * in[i * 2];
        sine_copy[i] = in[i * 2];
    }
    arm_rfft_fast_f32(&fft, test_in, test_out, 0);
    arm_cmplx_mag_squared_f32(test_out, test_mag, 16); 
    for (size_t i = 0; i < size; i+=2)
    {
        out[i] = sine_copy[i / 2];
        out[i + 1] = sine_copy[i / 2];
    }
    dsy_gpio_write(&gateout, 1);
}

this callback took roughly:

The source for this library is in the libdaisy/Drivers/CMSIS/DSP folder.

There are a lot of other cool things in there, too.

PaulBatchelor commented 4 years ago

@stephenhensley yeah, that is definitely going to be the the way moving forward. it would be so cool to get mincer working with hyper-optimized FFT routines. I'd first want to see how well the software implementation works first though.

stephenhensley commented 4 years ago

@PaulBatchelor fastest way to get this started (without porting the 3k lines of fft routines) would probably just be to make a wrapper similar to sp_fft that calls the CMSIS routines for now.

It'd be a good test of using them on something real as well. If we wanted to try a different software implementation we could always swap it out later.

PaulBatchelor commented 4 years ago

@stephenhensley it might be faster, but it could also be another component that can go wrong during the port. Using the software FFT first makes for less moving parts and makes the porting process more incremental.

If you're worried about introducing 3k lines (which is a great concern to have, btw!), we can always just begin the initial mincer port as an example that is never actually added to git. Once we know we have that code working, we can drop swap it out for hardware FFTs and introduce it all to the repo then. That would be my process at least. What do you think about that?

andrewikenberry commented 4 years ago

closing as this should be in daisysp