Forums > Dev

Ambisonics – Will I need a buffer for real time?

July 11, 2010 | 8:07 pm

Hey,

I am attempting to create an ambisonic encoder and decoder object set for MaxMSP5. Although I seem to have been able to create the objects I cannot get them to function correctly.

The main processing has been built into a DSP chain using the standard ‘svec’ process. The result however is distorted audio, which is apparently quite a difficult issue to resolve. The formulas used are:

*out1 = *in1 * 1 / sqrt2
*out2 = *in1 * cos(A) * sin(E)
*out3 = *in1 * sin(A) * cos(E)
*out4 = *in1 * sin(E)

As this is the most simple (first order, non velocity orientated) encoder I cannot seem to find an issue.
The decoder process is then set for ‘n’ speakers as:

*Speaker = 1 / n * (*in1 / sqrt2 + *in2 *cos(A) * *cos(E) + *in3 * sin(A) * cos(E) + *in4 * sin(E))

Where A is azimuth, E is elevation and n is number of speakers.

In order to do the encoding/decoding in real time will I need to implement a buffer system that is more advanced than svec?

Many thanks in advance, it is something I am really struggling with, any suggestions are extremely appreciated.

Thanks!!


July 11, 2010 | 10:54 pm

One possible problem is pointer aliasing.

Any of the out pointers could be the same as your in1 vector, so when you write to them you may overwrite the input sample, then when you read from the input pointer again you get a different value. To solve this, read your input into a local variable before calculating .Like this:

float input_sample = *in1++;

*out1++ = input_sample * 1 / sqrt2;
*out2++ = input_sample * cos(A) * sin(E);
*out3++ = input_sample * sin(A) * cos(E);
*out4++ = input_sample * sin(E);

Likewise for the decoder example. What you’ve posted isn’t proper or full code though, so there could be other errors. I am assuming you are incrementing your pointers elsewhere correctly, and looping over the block/vector and that the other variables are valid and correct.

YOu should not need to implement your own buffer.

Hope this helps

Alex


July 12, 2010 | 12:25 am

Thank you so much for your reply! I do think that this is the issue now that you have pointed it out, as the distorted output of the sound is almost granular.

After implementing it into the code the ins/outs do seem to be more stable and more responsive in the MaxMSP environment, but unfortunately my decoder does not like having the ‘++’ units added to it’s equations.

Thanks again, you’re help is extremely appreciated, hopefully this will sort it, I’ll post again as soon as I’ve got a result.

:D


July 12, 2010 | 10:00 am

Are you looping around the whole sample block? If you post all of your code here it will probably be much easier to help. The ++ is an operator that increments the pointer to point to the next sample – you should be doing this in a loop that loops once-per-sample.

Alex


July 13, 2010 | 5:48 pm

Thank you so much for your help so far. Unfortunately however I still seem to get strange output results. Focusing on the encoder for example – when testing the outputs of the ICST ambisonic encoder each channel sounded clean after the encoding process. Unfortunately I do think, as you say I am overwriting. Below is the dsp and perform section of the code so far (sorry for the obscure object name), I cannot see an error internally at the moment. I have implemented the ‘float signal = in’ idea and this has the channels working correctly e.g. mono sounds are producing outputs of W, X and D.

The equation used is the W,X,Y,Z,D to implement distance, but even with this removed I am receiving noise.

I have also attached the full C file in case I have left a strange error inside it, but other than some currently dormant ‘set’ messages there is little more to do with the actual encode process there.

Again I thank any suggestions or comments as I would simply love to get this working.

Thanks again for your help :D

void aambiencoderd_dsp(t_aambiencoderd *x, t_signal **sp, short *count)
{
dsp_add(aambiencoderd_perform, 7, sp[0]->s_vec, sp[1]->s_vec,
sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec, sp[0]->s_n);
}

/// 8.2 Actual Perform Funtion

t_int *aambiencoderd_perform(t_int *w)
{
t_float *in1 = (t_float *)(w[1]); //// Defining Inputs
t_float *out1 = (t_float *)(w[2]); //// Defining Outputs
t_float *out2 = (t_float *)(w[3]);
t_float *out3 = (t_float *)(w[4]);
t_float *out4 = (t_float *)(w[5]);
t_float *out5 = (t_float *)(w[6]);

int n = (int)w[7];

float input_1 = *in1++;

while (n–) //// Function is Active With DSP

*out1++ = input_1 * 1 / sqrt(2); //// Equation 1

*out2++ = input_1 * cos(0.0) * cos(0.0) * sin(1.0); //// Equation 2

*out3++ = input_1 * sin(0.0) * cos(0.0) * sin(1.0); //// Equation 3

*out4++ = input_1 * sin(0.0) * sin(1.0); //// Equation 4

*out5++ = input_1 * cos(0.0); //// Equation 5

return w + 8; //// Return Value is One Above DSP Links to Prevent Crashes
}

Attachments:
  1. aambiencoderd~.c

July 13, 2010 | 8:43 pm

This line:

input_1 = *in1++

is not inside your while loop. So that means it is only assigned/incremented once per vector rather than for every single sample. Is this the problem?

HTH,
Tim


July 13, 2010 | 9:09 pm

Hey Tim, thanks for your response. I had a look and updated the section (as seen below) and it has helped to dramatically clean up the audio, and has given a fantastic result. I am unfortunately however still left with a static granular effect. The positive thing is that it was clearly an overwriting of the buffer, thank you so much for your help with it, I think between you and Alex the main problem has been revealed, there is just some slight distortion issue, leaving artefacts on the audio output.

Does anyone know if there are ways of actually splitting the input from one channel into four to process it separately, rather than use a store and recall system, or would this be likely to result in the same issue?

Thanks again for your help with this.

int n = (int)w[7];

float input_1 = *in1++;

while (n–) //// Function is Active With DSP

input_1 = *in1++;

*out1++ = input_1 * 1 / sqrt(2); //// Equation 1

*out2++ = input_1 * cos(0.0) * cos(0.0) * sin(1.0); //// Equation 2

*out3++ = input_1 * sin(0.0) * cos(0.0) * sin(1.0); //// Equation 3

*out4++ = input_1 * sin(0.0) * sin(1.0); //// Equation 4

*out5++ = input_1 * cos(0.0); //// Equation 5

return w + 8; //// Return Value is One Above DSP Links to Prevent Crashes
}


July 13, 2010 | 10:44 pm

there were brackets missing around the main loop and in1 was already incremented once before the while loop.

try this:

int n = (int)w[7];

float input_1; ///< --- no need to assign a value yet

while (n–) //// Function is Active With DSP
{ /// < ------------- dsp loop begin

input_1 = *in1++;

*out1++ = input_1 * 1 / sqrt(2); //// Equation 1

*out2++ = input_1 * cos(0.0) * cos(0.0) * sin(1.0); //// Equation 2

*out3++ = input_1 * sin(0.0) * cos(0.0) * sin(1.0); //// Equation 3

*out4++ = input_1 * sin(0.0) * sin(1.0); //// Equation 4

*out5++ = input_1 * cos(0.0); //// Equation 5
} /// < -------- dsp loop end

return w + 8; //// Return Value is One Above DSP Links to Prevent Crashes
}


July 13, 2010 | 11:30 pm

I am practically speechless. The encoder works perfectly with no noise, and it’s now fully functional. Thank you so much for your time with this guys, all three of you (Alex, Tim and Mudang) have fixed my perform function. I am extremely grateful for your time and help with this as it is something strongly enjoy working with.

I will update my decoder with my new gained knowledge and and just drop a post in when it is finished, but I have every confidence now that the encoder is performing correctly. Thanks again. I can simply not express my gratitude enough.


July 13, 2010 | 11:34 pm

smotyn, you’re very welcome :)


July 14, 2010 | 12:04 am

The decoder is functioning 100% as well, so thanks again! This help has really proved invaluable, now I can start adding more features and playing around. Really impressed so thank you.


Viewing 11 posts - 1 through 11 (of 11 total)