Help - Search - Members - Calendar
Full Version: Help using get_data()
Hydrogenaudio Forums > Hosted Forums > foobar2000 > Development - (fb2k)
Esben84
Dear foobar experts,

I'm trying to implement an IIR filter, using the excellent dsp_tutorial by foosion. So far I've found out the chunks contain 1152 samples, and the command to find the samplerate, in the on_chunk part of the code.

My next question is how do I access those 1152 samples? For example, what is the command to get the value of channel 1 sample 1?

I've looked up the typedef audio_chunk_impl, but I don't understand the class defined below, other than I can see different functions returning different integers. It looks like get_data returns a pointer to an audio_sample type, but I don't know how to use that crying.gif

This is my first programming project in C++, so far I've only programmed Java, C and Matlab. unsure.gif
Yirkha
audio_chunk::get_data() returns pointer to audio_sample, which is typedef'd to some basic float type. At the returned address, there are audio_chunk::get_sample_count() * audio_chunk::get_channel_count() values.
E.g. for one second of "CD audio" 44100 Hz stereo data, there would be 44100 * 2 = 88200 values.
CODE
const audio_sample *pData = chunk.get_data();
float l0 = pData[0]; // 1st sample of left channel
float r0 = pData[1]; // 1st sample of right channel
float l1 = pData[2]; // 2nd sample of left channel
...


(BTW, don't assume you'll always get 1152 samples, that depends on many variables ranging from filetype/decoder to DSPs before yours in the chain.)
lvqcl
QUOTE
So far I've found out the chunks contain 1152 samples

Not necessary. A chunk contains chunk->get_sample_count() samples.

QUOTE
It looks like get_data returns a pointer to an audio_sample type, but I don't know how to use that

In foo_dsp_tutorial.cpp you can find an example:
CODE
        unsigned channel_count = chunk->get_channels();
        t_size sample_count = chunk->get_sample_count();
        audio_sample * current = chunk->get_data();
        //...
        for (t_size sample = 0; sample < sample_count; sample++) {
            for (unsigned channel = 0; channel < channel_count; channel++) {
                audio_sample temp = current[0];
                //...
                current[0] = /*something*/;
                current++;
            }
        }
Esben84
Thanks guys, your help is appreciated! biggrin.gif The IIR filter is now working and sounds great. Next step is making a configuration window instead of having the parameters hardcoded in the constructor.

I've discovered the resource file which I can see contains parameters of how the configuration window looks. To edit the window setup I've found a program called Resedit. But how the parameters are passed between the GUI and dsp_tutorial is still a puzzle to me.
lvqcl
QUOTE
I've discovered the resource file which I can see contains parameters of how the configuration window looks. To edit the window setup I've found a program called Resedit. But how the parameters are passed between the GUI and dsp_tutorial is still a puzzle to me.

Look at dialog_dsp_tutorial::on_message() and dsp_tutorial::g_show_config_popup()
BTW, you can edit configuration window layout in MS Visual Studio, there's no need to use Resedit.

Added: How to use WTL: http://www.hydrogenaudio.org/forums/index....st&p=625925
Esben84
Thanks alot for the answer. For some strange reason Visual Studio gives me an error RC2247 : SYMBOL name too long, but with Resedit I've made a preliminary UI, with sliders for adjusting frequencies. In the update_display() function, the values of the sliders are acquired and stored in m_params.m_fc and m_params.m_fcnew. m_dirty makes the four lines execute:
CODE
            dsp_preset_impl data;
            m_params.get_data(data);
            console::printf("m_dirty fc: %d, fcnew: %d", m_params.m_fc, m_params.m_fcnew);
            m_callback.on_preset_changed(data);

When the get_data(data) function runs, I can also see the adjusted values of fc and fcnew.

Then (I don't know why) the set_data function runs, but the values are back to the default values crying.gif
This is where I'd planned to recalculate filter coefficients, but with default values no changes are made.

I've compared it to the foosion tutorial with presets, and it uses the params.m_percent, where I use params.m_fcnew and params.m_fcnew, so why I don't get modified values is a puzzle.

I cannot figure out how p_data stores data, but I've tried saving the new sliders by adding the code to get_data(dsp_preset & p_data):
CODE
        t_int32 temp2 = m_fc;
        t_int32 temp3 = m_fcnew;
        console::printf("Running get_data function, fc: %d, fcnew: %d", temp2, temp3);
        byte_order::order_native_to_le_t(temp2);
        byte_order::order_native_to_le_t(temp3);
        p_data.set_data(&temp2, sizeof(temp2));
        p_data.set_data(&temp2, sizeof(temp3));

Maybe I'm not storing it properly?

Regarding WTL and ATL, I'm not sure how to use it (or what it is). I always get compiling errors in some way related to atlapp.h, and a message that dialog_helper::dialog_modal::run is deprecated. It still works though smile.gif
lvqcl
I think you should call p_data.set_data only once. I use this code:
CODE
    t_int32 temp[5];
    temp[0] = ...
    temp[1] = ...
    temp[2] = ...
    temp[3] = ...
    temp[4] = ...

    p_data.set_owner(g_get_guid());
    for(int i=0; i<5; i++)
        byte_order::order_native_to_le_t(temp[i]);
    p_data.set_data(temp, sizeof(temp));
Yirkha
I'm a bit confused, on_preset_changed() should create another instance of your DSP and pass the new preset to its constructor. Do you set correct owner GUID?

And what lvqcl said. Also there is very nice class called dsp_preset_builder with stream-like interface.
Esben84
Thanks for explaining how values are stored in the presets. Now it's working with realtime adjustments of filter coefficients, through the two sliders biggrin.gif

I would like to implement three extra sliders for Q-values and a scaling factor. All three values are doubles. Is it possible to make a slider with floats? Is there a way to store both integers and doubles in the preset?

I assume the other way to do it is to make the program with Q-values and scaling factor as integers by multiplying it with some large number. Would you recommend to do it that way?
Esben84
QUOTE (Yirkha @ Apr 30 2009, 16:26) *
I'm a bit confused, on_preset_changed() should create another instance of your DSP and pass the new preset to its constructor. Do you set correct owner GUID?
I've made a new GUID with guidgen.exe, so it should have a unique id. I think it was because I didn't understand how to properly read/write presets. unsure.gif
QUOTE (Yirkha @ Apr 30 2009, 16:26) *
And what lvqcl said. Also there is very nice class called dsp_preset_builder with stream-like interface.
Thanks, it looks like it could be used as a replacement in the set_data() and get_data() functions, if I knew how to use it. I'm happy the other two functions could be modified so that I could use them.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2009 Invision Power Services, Inc.