0
$\begingroup$

I attempted to implement a real-time audio filtering in a callback function using the simplest moving-average filter with coefficients [0.5 0.5] :

void process(void* in_, void* out_, DWORD length, void* user) {

    //data is float, mono
    int n = length/sizeof(float);
    float* in = (float*)in_;
    float* out = (float*)out_;
    float* buff = (float*)user;

    //buff holds the last input sample from the previous block
    //if this is a first block, it is 0
    out[0] = 0.5*in[0] + 0.5*buff;

    for (int i = 1; i < n; ++i)
    {
         out[i] = 0.5*in[i] + 0.5*in[i - 1];
    }

    buff[0] = in[n-1];
}

however, i get a distortion in the output, like an aliasing of some sort or clipping. But, to my knowledge none of this is possible to occur in this case. I've implemented the same code in Matlab ( although not in real-time ) and everything was fine.

I am using a BASS library.

I would like to know if i am missing something obvious here, cause i am running out of ideas. Thanks in advance!

EDIT: Thanks everyone for the answers. The above function is in the form for simplicity, but in actual from it looks like below (there is no output buffer, filtering must be done in-place) but it does exact same thing, although I will write it for convenience:

void CALLBACK filterDSPMono(HDSP handle, DWORD channel, void* buffer, DWORD length, void* user)
{
    float* x = (float*) buffer;
    int n = length / sizeof(float);
    float* buff = (float*) user;
    float temp;


    int i = 0;
    for (; i < n; ++i)
    {
        temp = x[i];
        x[i] = 0.5*x[i] + 0.5*buff[0];
        buff[0] = temp;
    }
}

EDIT2: Ok, so it turns out the problem was with the buffer size set in the library that my sound card drivers didn't like for some reason. After I changed that, everything is fine. Thank you for all the answers unfortunately I cant mark any as The Answer due to the fault being on my part. This question now can be considered as resolved.

$\endgroup$
  • $\begingroup$ Are in and out monophonic streams? If not, they will contain interleaved Left and Right samples. $\endgroup$ – pichenettes Jun 1 '14 at 12:44
  • 1
    $\begingroup$ Can you share the input test signal with us. $\endgroup$ – learner Jun 1 '14 at 12:44
  • $\begingroup$ I am testing it with different wave files. I doubt it has something to do with the input itself, the library opens the file and this processing function receives raw data, in this case values between -1 and +1. If I, for example, change whole this code to something like out[i] = in[i]*0.5 the output is clean. $\endgroup$ – tomi.lee.jones Jun 1 '14 at 15:02
  • $\begingroup$ Yes, both in and out are mono. $\endgroup$ – tomi.lee.jones Jun 1 '14 at 15:10
  • $\begingroup$ This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. $\endgroup$ – Jason R Jun 3 '14 at 13:22
1
$\begingroup$

I suspect that most likely the audio coming in is integer, and not floating point. Depending on your device, operating system and type of file input, you can get one or the other. Read documentation for audio input API you're using to see which format the audio is in. Also, if it's integer, it's likely to be 16 bit rather than 32 bit. In any case, again, read the documentation.

EDIT: BASS library has a flag you can set to get floating point values everywhere:

BASS_SetConfig(
    BASS_CONFIG_FLOATDSP,
    BOOL floatdsp
);
$\endgroup$
  • $\begingroup$ I should've mentioned it that I had done it already. I made sure in every possible way the audio is float. I've red the documentation extensively. $\endgroup$ – tomi.lee.jones Jun 7 '14 at 10:03
0
$\begingroup$

okay, i am not sure how the function process() must be set up. i am going to suggest that process() assumes floats going in and out and rather than pass length, let's call it nSamples and instead of user, we'll call it state. i'm doing this to simplify it. this is portable and doesn't give a rat's ass about BASS or any library.

void process(float* in, float* out, int nSamples, float* state) {

    //data is float, mono

    // *state holds the last input sample from the previous block
    // if this is a first block, it is 0

    out[0] = 0.5*in[0] + 0.5*(*state); 
    for (int n=1; n<nSamples; n++)
    {
         out[n] = 0.5*in[n] + 0.5*in[n-1];
    }
    *state = in[nSamples-1];
 }

that should work. if there is any casting needed from void* to float*, i would suggest it is done by whoever calls process(). looks like you have it as a callback function, but i still don't see why the casting need be done in process(). if you do this as simply and cleanly as possible, there is less room for funky bugs to slip it.

$\endgroup$
  • $\begingroup$ Thanks, but You have just rewritten my code in a simpler form. I know how to filter data, i have basics in DSP, what i'm having problem is that exactly this causes little distortions in the output audio when the processing is done in blocks. Maybe it's some little detail with implementation in this particular library (BASS) , maybe something else, but it's not like i am trying to make things harder and doing unnecessary casting...it's just how the callback function is defined in BASS. Only buffer to process, length is in bytes, its up to programmer to know what the data type is. $\endgroup$ – tomi.lee.jones Jun 8 '14 at 7:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.