24 May '13 - 08:43 *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
 
   Home   Help Search Login Register  
Pages: [1]
  Reply  |  Print  
Author Topic: [Solved] FFT with live ASIO data  (Read 664 times)
valyard
Posts: 15


« on: 4 Jul '12 - 17:45 »
Reply with quoteQuote

Hi.

I'm trying to visualize audio data from a live source with BASS .NET.
I wanted to modify "livefx" demo, it's playing fine right now.
But I can't figure out how to get FFT data from BASS_ChannelGetData.
With ASIO I don't really have any streams. Audio data seems to be magically coming and going somewhere else.

This is the delegate called by ASIO.

       private static int AsioCallback(bool input, int channel, IntPtr buffer, int length, IntPtr user)
        {
            if (input) {
                Marshal.Copy(buffer, data, 0, length/4);
                return 0;
            } else {
                Marshal.Copy(data, 0, buffer, length/4);
                Bass.BASS_ChannelGetData(channel, buffer, length);
                return length;
            }
        }

I even have all the data in the buffer. Where do I get a channel to put it to? o.O
Can anyone point me the way how to get FFT data here?
« Last Edit: 11 Jul '12 - 11:28 by valyard » Logged
valyard
Posts: 15


« Reply #1 on: 5 Jul '12 - 12:56 »
Reply with quoteQuote

Anyone?
I got this data in the buffer, I just want to use some channel where I can get FFT data from.
Logged
Ian @ un4seen
Administrator
Posts: 15270


« Reply #2 on: 5 Jul '12 - 13:54 »
Reply with quoteQuote

You can get FFT data from the buffered sample data via a custom stream, by having the stream feed on the buffered data. It might look something like this...

bufstream=BASS_StreamCreate(freq, chans, BASS_SAMPLE_FLOAT|BASS_STREAM_DECODE, BufStreamProc, NULL); // create a custom stream with same format as the ASIO input/output

...

DWORD CALLBACK BufStreamProc(HSTREAM handle, void *buffer, DWORD length, void *user)
{
if (length>asiodatalen) length=asiodatalen; // limit it to the amount of data in the ASIO buffer
memcpy(buffer, asiodata, length); // copy the data from the ASIO buffer
return length;
}

...

float fft[512];
BASS_ChannelGetData(bufstream, fft, BASS_DATA_FFT1024); // get FFT data from the buffer stream

"asiodata" is the buffer containing the ASIO sample data, and "asiodatalen" is the amount of data (set that in the ASIOPROC). Note the refresh rate will be limited by the ASIO buffer length specified in the BASS_ASIO_Start call, ie. that determines how often the ASIOPROC is called and new data placed in the buffer.
Logged
valyard
Posts: 15


« Reply #3 on: 6 Jul '12 - 10:30 »
Reply with quoteQuote

Thank you, I did the following:
stream = Bass.BASS_StreamCreate((int)BassAsio.BASS_ASIO_GetRate(), 2, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE, StreamCallback, IntPtr.Zero);
private static int StreamCallback(int handle, IntPtr buffer, int length, IntPtr user) {
  Console.WriteLine(length);
  return length;
}

But the callback is never called. Should I start the stream or something?

Also, where do I call BASS_ChannelGetData(bufstream, fft, BASS_DATA_FFT1024)? In some kind of a timer callback?
Logged
radio42
Posts: 4012


« Reply #4 on: 6 Jul '12 - 11:33 »
Reply with quoteQuote

That doesn't look quite right - you need to create a delegate for your StreamCallback (see docs for an example), like this:
private STREAMPROC _myStreamCreate;
...
_myStreamCreate = new STREAMPROC(StreamCallback);
stream = Bass.BASS_StreamCreate((int)BassAsio.BASS_ASIO_GetRate(), 2, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_DECODE, _myStreamCreate, IntPtr.Zero);

private static int StreamCallback(int handle, IntPtr buffer, int length, IntPtr user) {
  Console.WriteLine(length);
  return length;
}
Logged
valyard
Posts: 15


« Reply #5 on: 6 Jul '12 - 11:43 »
Reply with quoteQuote

That doesn't look quite right - you need to create a delegate for your StreamCallback (see docs for an example), like this:

I believe starting from some c# version you can pass delegates like this. My code for asio stream works fine. I'm getting audio data in the very same code.
Logged
Ian @ un4seen
Administrator
Posts: 15270


« Reply #6 on: 6 Jul '12 - 16:00 »
Reply with quoteQuote

But the callback is never called. Should I start the stream or something?

Also, where do I call BASS_ChannelGetData(bufstream, fft, BASS_DATA_FFT1024)? In some kind of a timer callback?

Yes, you could make the BASS_ChannelGetData call in a timer, eg. to update a spectrum display. Basically, whenever you want FFT data. The stream is a "decoding channel" (using the BASS_STREAM_DECODE flag), which means that its STREAMPROC function will be called to get the data within the BASS_ChannelGetData call; you don't need to "start" it, eg. by calling BASS_ChannelPlay.
Logged
valyard
Posts: 15


« Reply #7 on: 6 Jul '12 - 19:43 »
Reply with quoteQuote

EDIT: as in this post http://www.un4seen.com/forum/?topic=13433.0 I had issues with garbage collector. Crashes solved. Thanks again!

Thanks, I think I understand now how this library works.
I am getting some non-zero data and I was going to check what was there but I started getting weird crashes.
« Last Edit: 6 Jul '12 - 19:56 by valyard » Logged
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.18 | SMF © 2013, Simple Machines