|
View:
New views
13 Messages
—
Rating Filter:
Alert me
|
|
|
new panning algorithmDear OpenAL developers,
as someone who is interested in virtual acoustics I started reading the openal-soft source code. While doing so, I thought it might be interesting to write a more sophisticated panning algorithm. The current implementation is great in terms of computational complexity, but a little bit simple. My new implementation is energy-preserving and should result in smoother movements of sound sources. It takes the positions of the speakers for different speaker setups into account and uses a look-up-table to reduce the computational complexity. As this look-up-table contains pre-calculated panning values, other panning algorithms could be implemented at no additional runtime costs, too (e.g., Gerzon's 3-channel panning algorithm). If you are interested in the code, you can find my patch against openal-soft version 1.5.304 on our web server: http://www2.ika.rub.de/borss/openal_panning_borss.diff Ciao, Christian -- Christian Borß, Dipl.-Ing. || Institut für Kommunikationsakustik http://www.ika.ruhr-uni-bochum.de || Ruhr-Universität Bochum Tel.: +49-(0)234-32-22470 || Universitätsstr. 150, IC1/33 Fax.: +49-(0)234-32-14165 || D-44780 Bochum (Germany) _______________________________________________ Openal-devel mailing list Openal-devel@... http://opensource.creative.com/mailman/listinfo/openal-devel |
|
|
Re: new panning algorithmOn Saturday 18 October 2008 09:23:49 am Christian Borss wrote:
> as someone who is interested in virtual acoustics I started reading the > openal-soft source code. While doing so, I thought it might be > interesting to write a more sophisticated panning algorithm. The current > implementation is great in terms of computational complexity, but a > little bit simple. My new implementation is energy-preserving and should > result in smoother movements of sound sources. Hi Christian, Thanks for taking the time to work on this code. Unfortunately the patch won't apply because of some changes I've done to the mixer since 1.5 was released. I don't want to try to push in such changes before OpenAL Soft 1.6 is released (which I'd like to do in about a week or so), so I probably won't be able to try it out before then. It does look interesting though, and I'll try to remember to look into it later. Thanks again, - Chris _______________________________________________ Openal-devel mailing list Openal-devel@... http://opensource.creative.com/mailman/listinfo/openal-devel |
|
|
Re: new panning algorithmDear OpenAL hackers,
Am 24. Okt. 2008 um 18:38 Uhr schrieb Chris Robinson: >> [patch for new panning algorithm] > >Thanks for taking the time to work on this code. Unfortunately the patch won't >apply because of some changes I've done to the mixer since 1.5 was released. >I don't want to try to push in such changes before OpenAL Soft 1.6 is >released (which I'd like to do in about a week or so), so I probably won't be >able to try it out before then. > >It does look interesting though, and I'll try to remember to look into it As a nice task for a rainy sunday I took the time to port my panning algorithm to OpenAL Soft 1.6. You can find my patch against the current GIT version of openal-soft on the web server of our institute: http://www2.ika.rub.de/borss/openal_panning_borss_git20090118.diff Maybe I should add some notes about what this patch does and why I propose to include it in the repository: My panning algorithm is intended for multi-speaker setups like a 5.1 or 7.1 surround setup. The current implementation uses only 4 of these speakers, i.e. the front and the rear speakers, for spatial rendering. The center and the back surround speakers are not used. What the current implementation does is linear panning between the left and the right speakers and in addition linear panning between the front and the rear speakers. This may be a proper panning method for a quadrophony setup where you have 4 speakers at +/-45° and +/-135° but for a up to date surround system with 5 and more speakers this is a clear limitation. Besides the limitation of the reduced number of involved speakers, the current implementation results in displaced auditory events. A speaker setup which conforms with the ITU-R BS.775 recommendation, has its front speakers at +/-30° and its rear speaker at +/-110°. This is the typical 5.1 surround setup. Now, if one uses the currunt panning implementation in combination with a typical 5.1 speaker setup, the space between the front speakers is compressed and the space between the rear speakers is expanded. Why does this matter? Imagine a sound source which circles around the listener with constant speed. Due to the compression/ expansion, the auditory event (the perceived sound source) moves no longer with constant velocity - it's slower in the frontal region and faster in the back region. My panning algorithm takes the speaker arrangement into account to cope with this issue. In my implementation, the directional part of panning values are pre-calculated and stored in a look-up-table (LUT). For speed optimization, the resolution of this LUT is not constant. Instead of using atanf() to determine the source direction from which the LUT index is derived, I derive the index from the ratio |x| / ( |x| + |z| ) which is faster to compute than atanf(). I tested my algorithm with ioquake3 in combination with the openarena data files and it worked pretty well. The localization of the sound sources is clearly improved. As I'm not a gamer I can't provide information about how well it works with other games. Please give it a try and let me know if it works for you! Ciao, Christian -- Christian Borß, Dipl.-Ing. || Institut für Kommunikationsakustik http://www.ika.ruhr-uni-bochum.de || Ruhr-Universität Bochum Tel.: +49-(0)234-32-22470 || Universitätsstr. 150, IC1/33 Fax.: +49-(0)234-32-14165 || D-44780 Bochum (Germany) _______________________________________________ Openal-devel mailing list Openal-devel@... http://opensource.creative.com/mailman/listinfo/openal-devel |
|
|
Re: new panning algorithmOn Sunday 18 January 2009 7:29:22 am Christian Borss wrote:
> As a nice task for a rainy sunday I took the time to port my panning > algorithm to OpenAL Soft 1.6. You can find my patch against the current > GIT version of openal-soft on the web server of our institute: > > http://www2.ika.rub.de/borss/openal_panning_borss_git20090118.diff Thanks for updating it. :) > My panning algorithm is intended for multi-speaker setups like a 5.1 or > 7.1 surround setup. The current implementation uses only 4 of these > speakers, i.e. the front and the rear speakers, for spatial rendering. > The center and the back surround speakers are not used. The center channel isn't used in spatial calculations because it's a bit ambiguous as to where it should be. The absolute center? Or between the front speakers? Often times in movies, the center speaker is left out for sound effects and used specifically as a voice track and/or some "special" sounds to draw the viewer's attention to. For 7.1 surround-sound setups, it should use 6 speakers (2 front, 2 side, 2 rear). > What the current > implementation does is linear panning between the left and the right > speakers and in addition linear panning between the front and the rear > speakers. This may be a proper panning method for a quadrophony setup > where you have 4 speakers at +/-45° and +/-135° but for a up to date > surround system with 5 and more speakers this is a clear limitation. > Besides the limitation of the reduced number of involved speakers, the > current implementation results in displaced auditory events. A speaker > setup which conforms with the ITU-R BS.775 recommendation, has its front > speakers at +/-30° and its rear speaker at +/-110°. This is the typical > 5.1 surround setup. Now, if one uses the currunt panning implementation > in combination with a typical 5.1 speaker setup, the space between the > front speakers is compressed and the space between the rear speakers is > expanded. Why does this matter? Imagine a sound source which circles > around the listener with constant speed. Due to the compression/ > expansion, the auditory event (the perceived sound source) moves no > longer with constant velocity - it's slower in the frontal region and > faster in the back region. This, however, was a concern. I had planned on fixing this by making the scalars used configurable, though it would've added some complexity to the calculations. > My panning algorithm takes the speaker arrangement into account to cope > with this issue. In my implementation, the directional part of panning > values are pre-calculated and stored in a look-up-table (LUT). For > speed optimization, the resolution of this LUT is not constant. Instead > of using atanf() to determine the source direction from which the LUT > index is derived, I derive the index from the ratio |x| / ( |x| + |z| ) > which is faster to compute than atanf(). I tested my algorithm with > ioquake3 in combination with the openarena data files and it worked > pretty well. The localization of the sound sources is clearly improved. > As I'm not a gamer I can't provide information about how well it works > with other games. Please give it a try and let me know if it works for > you! A quick test showed it seem to work well. I have question, though.. with this: pos = round(QUADRANT_NUM * aluFabs(im) / (aluFabs(re) + aluFabs(im))); what is supposed to happen if re and im are 0? Since they're the -Z and X coords, this is quite possible for head-relative sources that are left at 0,0,0, and given the code, it would cause a 0/0 which wouldn't be very good. _______________________________________________ Openal-devel mailing list Openal-devel@... http://opensource.creative.com/mailman/listinfo/openal-devel |
|
|
Re: new panning algorithmAm 18. Jan. 2009 um 18:05 Uhr schrieb Chris Robinson:
>The center channel isn't used in spatial calculations because it's a bit >ambiguous as to where it should be. The absolute center? Or between the front >speakers? The center speaker is typically placed between the front speakers as recommended by "ITU-R BS.775": http://en.wikipedia.org/wiki/Surround_sound#5.1_Channel_Surround_.283-2_Stereo.29_.28digital_discrete:_Dolby_Digital.2C_DTS.2C_SDDS.29 http://www.sengpielaudio.com/Surround-ITU-Wiedergabe.pdf The second web site contains documents for German "Tonmeister" (sound engineers). >Often times in movies, the center speaker is left out for sound >effects and used specifically as a voice track and/or some "special" >sounds to draw the viewer's attention to. I think, a rocket fired by an opponent in the front in a computer game should definitely draw the gamers attention to the front. :-) >For 7.1 surround-sound setups, it should use 6 speakers (2 front, 2 side, 2 >rear). The center speaker was introduced to improve the localization in the frontal region. So, why not make use of it? I saw in the source code that you use this arrangement for 6.1 surround setups. Thats why I used the front/side/rear-back speaker setup also in my code. But normaly I would expect a 1 center 2 front 2 side 1 rear-back speaker arrangement: http://en.wikipedia.org/wiki/Surround_sound#6.1_Channel_Surround_.28digital_discrete:_DTS-ES.29 Would you agree to change the configuration to a DTS-ES arrangement? >A quick test showed it seem to work well. Great. >I have question, though.. with this: > >pos = round(QUADRANT_NUM * aluFabs(im) / (aluFabs(re) + aluFabs(im))); > >what is supposed to happen if re and im are 0? Since they're the -Z and X >coords, this is quite possible for head-relative sources that are left at >0,0,0, and given the code, it would cause a 0/0 which wouldn't be very good. In this case, DirGain is set to zero DirGain = aluSqrt(Position[0] * Position[0] + Position[2] * Position[2]); and AmbientGain is set to MaxAmbientGain: AmbientGain = MaxAmbientGain * (1.0 - DirGain); Thus, there is no directional sound and the sound is played back over all speakers instead. In ioquake3 you can hear this effect, e.g., when you fire your own weapons. But you are right, it would be a more clean implementation to avoid a division by zero. Ciao, Christian P.S.: For those of you who will attend it: See you at the 35th international AES convention "Audio for Games" in London! -- Christian Borß, Dipl.-Ing. || Institut für Kommunikationsakustik http://www.ika.ruhr-uni-bochum.de || Ruhr-Universität Bochum Tel.: +49-(0)234-32-22470 || Universitätsstr. 150, IC1/33 Fax.: +49-(0)234-32-14165 || D-44780 Bochum (Germany) _______________________________________________ Openal-devel mailing list Openal-devel@... http://opensource.creative.com/mailman/listinfo/openal-devel |
|
|
Re: new panning algorithmAm 19. Jan. 2009 um 10:39 Uhr schrieb Christian Borss:
>But you are right, it would be a more clean implementation to avoid a >division by zero. How about: static __inline ALint aluCart2LUTpos(ALfloat re, ALfloat im) { ALint pos; ALfloat denum; denum = aluFabs(re) + aluFabs(im); if (denum == 0.0) return 0; pos = round(QUADRANT_NUM * aluFabs(im) / denum); if (re < 0.0) pos = 2 * QUADRANT_NUM - pos; if (im < 0.0) pos = LUT_NUM - pos; return pos % LUT_NUM; } Ciao, Christian -- Christian Borß, Dipl.-Ing. || Institut für Kommunikationsakustik http://www.ika.ruhr-uni-bochum.de || Ruhr-Universität Bochum Tel.: +49-(0)234-32-22470 || Universitätsstr. 150, IC1/33 Fax.: +49-(0)234-32-14165 || D-44780 Bochum (Germany) _______________________________________________ Openal-devel mailing list Openal-devel@... http://opensource.creative.com/mailman/listinfo/openal-devel |
|
|
Re: new panning algorithmOn Monday 19 January 2009 1:39:24 am Christian Borss wrote:
> The center speaker is typically placed between the front speakers as > recommended by "ITU-R BS.775": > > > http://en.wikipedia.org/wiki/Surround_sound#5.1_Channel_Surround_.283-2_Ste >reo.29_.28digital_discrete:_Dolby_Digital.2C_DTS.2C_SDDS.29 > http://www.sengpielaudio.com/Surround-ITU-Wiedergabe.pdf > > The second web site contains documents for German "Tonmeister" (sound > engineers). I see. > >Often times in movies, the center speaker is left out for sound > >effects and used specifically as a voice track and/or some "special" > >sounds to draw the viewer's attention to. > > I think, a rocket fired by an opponent in the front in a computer game > should definitely draw the gamers attention to the front. :-) True enough. Though there's not much saying the rocket fire in front of the player is any more important than the one to his side.. > >For 7.1 surround-sound setups, it should use 6 speakers (2 front, 2 side, > > 2 rear). > > The center speaker was introduced to improve the localization in the > frontal region. So, why not make use of it? Code complexity mostly. It's easier to pan around in a symmetrical "grid" using physically-correct math (ie. centering using a gain of sqrt(0.5)) than an imbalanced grid with 3 sections in front and 2 in back. It was something I was eventually going to look into, but it wasn't a high priority. > I saw in the source code that you use this arrangement for 6.1 surround > setups. Thats why I used the front/side/rear-back speaker setup also in > my code. But normaly I would expect a > > 1 center > 2 front > 2 side > 1 rear-back > > speaker arrangement: > > > http://en.wikipedia.org/wiki/Surround_sound#6.1_Channel_Surround_.28digital >_discrete:_DTS-ES.29 > > Would you agree to change the configuration to a DTS-ES arrangement? Looking over that wikipedia page, it does seem that's the intended arrangement, yes. I suppose that affects the AL_FORMAT_61CHN* formats as well. I really need to clean up the mixer loop to properly remix multichannel buffers.. > >I have question, though.. with this: > > > >pos = round(QUADRANT_NUM * aluFabs(im) / (aluFabs(re) + aluFabs(im))); > > > >what is supposed to happen if re and im are 0? Since they're the -Z and X > >coords, this is quite possible for head-relative sources that are left at > >0,0,0, and given the code, it would cause a 0/0 which wouldn't be very > > good. > > In this case, DirGain is set to zero > > DirGain = aluSqrt(Position[0] * Position[0] + Position[2] * Position[2]); Ah, right. Yeah, it shouldn't be too difficult to handle that, then. Just a simple if > 0 check. Though as "luck" would have it, I started implementing a Phonon backend just before this patch was brought up, and I've been fighting with it trying to get it not to crash. Unfortunately this means I can't (really shouldn't) go about applying/tweaking this while I have other changes being worked on, and I don't want to split my attention between the two and accidentally overlook something. If I can't get the Phonon backend working I'll just set it aside for another day, but whether I get it in or drop it, I'll dig deeper into this patch right after. _______________________________________________ Openal-devel mailing list Openal-devel@... http://opensource.creative.com/mailman/listinfo/openal-devel |
|
|
Re: new panning algorithmAm 20. Jan. 2009 um 7:09 Uhr schrieb Chris Robinson:
>> The center speaker was introduced to improve the localization in the >> frontal region. So, why not make use of it? > >Code complexity mostly. Yeah, the quadrophony panpot mixer is indeed compelling in terms of simplicity. >It's easier to pan around in a symmetrical "grid" using >physically-correct math [...] This "physically-correct math" is a little bit tricky anyway. Exactly at the sweet spot where all speakers have the same distance to the listener, the sound pressure is added. So for this case, a "pressure preserving" panning law would be correct. A random position within the sound field would result in a random phase difference of the signals radiated from the speakers which results in added sound energy (by neglecting the distance dependent attenuation, occlusion/diffraction effects, and reverberation). The latter case is taken into account by "energy preserving" panning laws. Aproaches for energy preserving panning functions are a dime a dozen, starting from the "sine law" proposed by Bauer [1], the "tan law" proposed by Bennet et al. [2], multi-speaker approaches as the one proposed by Gerzon and Barton [3], vector base amplitude panning for 3D arrangements as proposed by Pullki [4], or perceptual approaches as, e.g., proposed by Lee et al. [5]. To make it short: don't worry too much about "physically-correct math". :-) In my implementation I simply expand/compress the angle between the involved loudspeaker pairs to 90° and use a sin() and cos() function to obtain energy preserving gain factors (which results in 1/sqrt(2) for an angle in between). But anyway, exchanging the panning function by any of the above mentioned approaches would be trivial. >Though as "luck" would have it, I started implementing a Phonon backend just >before this patch was brought up, and I've been fighting with it trying to get >it not to crash. Good luck. ;-) Ciao, Christian [1] B. B. Bauer, "Phasor Analysis of Some Stereophonic Phenomena," J. Acoust. Soc. Am., vol. 33, no. 2, pp. 1536-1539, 1961. [2] J. C. Bennett and K. Barker and F. O. Edeko, "A New Approach to the Assessment of Stereophonic Sound System Performance," J. Audio Eng. Soc., vol. 33, no. 5, pp. 314-321, 1985. [3] M. A. Gerzon and G. J. Barton, "Panpot Laws for Multispeaker Stereo," in 92nd AES Convention, (Vienna, Austria), Mar. 1992. [4] V. Pulkki, "Virtual Sound Source Positioning Using Vector Base Amplitude Panning," J. Audio Eng. Soc., vol. 45, no. 6, pp. 456-466, 1997. [5] S.-L. Lee et al., "Reduction of Sound Localization Error for Surround Sound System Using Enhanced Constant Power Panning Law," IEEE Transactions on Consumer Electronics, vol. 50, no. 3, pp. 941-944, 2004. -- Christian Borß, Dipl.-Ing. || Institut für Kommunikationsakustik http://www.ika.ruhr-uni-bochum.de || Ruhr-Universität Bochum Tel.: +49-(0)234-32-22470 || Universitätsstr. 150, IC1/33 Fax.: +49-(0)234-32-14165 || D-44780 Bochum (Germany) _______________________________________________ Openal-devel mailing list Openal-devel@... http://opensource.creative.com/mailman/listinfo/openal-devel |
|
|
Re: new panning algorithmOn Wednesday 21 January 2009 1:02:02 am Christian Borss wrote:
> >Though as "luck" would have it, I started implementing a Phonon backend > > just before this patch was brought up, and I've been fighting with it > > trying to get it not to crash. > > Good luck. ;-) Well, the Phonon backend didn't work out as I hoped. Doesn't seem as though I'll be able to use it for ALURE to load files either, for the time being. Oh well. In either case, I've been playing around with this code. I've simplified the code setting the drysends a bit, but it should be functionally the same. I've also made it so stereo will use it too, since it's possible they may not be at the sides (like with quad+, they could be at 30~45 degree angles.. or they could be at +/-90, eg. with headphones; this allows them to be configurable as such). I didn't change the positioning of the speakers yet, but I'll do that after the initial change is committed. Attached is a patch that I have now.. does it work good for you? [new-pan-algo.diff] diff --git a/Alc/ALc.c b/Alc/ALc.c index 7f393c7..7290229 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -37,6 +37,7 @@ #include "alExtension.h" #include "alAuxEffectSlot.h" #include "bs2b.h" +#include "alu.h" /////////////////////////////////////////////////////// // DEBUG INFORMATION @@ -487,6 +488,8 @@ static ALvoid InitContext(ALCcontext *pContext) bs2b_set_srate(pContext->bs2b, pContext->Frequency); bs2b_set_level(pContext->bs2b, level); } + + aluInitPanning(pContext); } diff --git a/Alc/ALu.c b/Alc/ALu.c index a6be6ae..1ffdc0c 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -23,6 +23,8 @@ #include "config.h" #include <math.h> +#include <stdlib.h> +#include <string.h> #include "alMain.h" #include "AL/al.h" #include "AL/alc.h" @@ -62,6 +64,18 @@ typedef long long ALint64; #define aluAcos(x) ((ALfloat)acos((double)(x))) #endif +#ifdef HAVE_ATANF +#define aluAtan(x) ((ALfloat)atanf((float)(x))) +#else +#define aluAtan(x) ((ALfloat)atan((double)(x))) +#endif + +#ifdef HAVE_FABSF +#define aluFabs(x) ((ALfloat)fabsf((float)(x))) +#else +#define aluFabs(x) ((ALfloat)fabs((double)(x))) +#endif + // fixes for mingw32. #if defined(max) && !defined(__max) #define __max max @@ -240,17 +254,158 @@ static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat matrix[3][3]) memcpy(vector, result, sizeof(result)); } +static __inline ALfloat aluLUTpos2Angle(ALint pos) +{ + if(pos < QUADRANT_NUM) + return aluAtan((ALfloat)pos / (ALfloat)(QUADRANT_NUM - pos)); + if(pos < 2 * QUADRANT_NUM) + return M_PI_2 + aluAtan((ALfloat)(pos - QUADRANT_NUM) / (ALfloat)(2 * QUADRANT_NUM - pos)); + if(pos < 3 * QUADRANT_NUM) + return aluAtan((ALfloat)(pos - 2 * QUADRANT_NUM) / (ALfloat)(3 * QUADRANT_NUM - pos)) - M_PI; + return aluAtan((ALfloat)(pos - 3 * QUADRANT_NUM) / (ALfloat)(4 * QUADRANT_NUM - pos)) - M_PI_2; +} + +ALvoid aluInitPanning(ALCcontext *Context) +{ + ALint pos, offset, s; + ALfloat Alpha, Theta; + ALfloat SpeakerAngle[OUTPUTCHANNELS]; + ALint Speaker2Chan[OUTPUTCHANNELS]; + + // Shall the user configure this in alsoft.conf ?! + switch(Context->Device->Format) + { + case AL_FORMAT_QUAD8: + case AL_FORMAT_QUAD16: + case AL_FORMAT_QUAD32: + Context->NumChan = 4; + Speaker2Chan[0] = BACK_LEFT; + Speaker2Chan[1] = FRONT_LEFT; + Speaker2Chan[2] = FRONT_RIGHT; + Speaker2Chan[3] = BACK_RIGHT; + SpeakerAngle[0] = -135.0f * M_PI/180.0f; + SpeakerAngle[1] = -45.0f * M_PI/180.0f; + SpeakerAngle[2] = 45.0f * M_PI/180.0f; + SpeakerAngle[3] = 135.0f * M_PI/180.0f; + break; + + case AL_FORMAT_51CHN8: + case AL_FORMAT_51CHN16: + case AL_FORMAT_51CHN32: + Context->NumChan = 5; + Speaker2Chan[0] = BACK_LEFT; + Speaker2Chan[1] = FRONT_LEFT; + Speaker2Chan[2] = CENTER; + Speaker2Chan[3] = FRONT_RIGHT; + Speaker2Chan[4] = BACK_RIGHT; + SpeakerAngle[0] = -110.0f * M_PI/180.0f; + SpeakerAngle[1] = -30.0f * M_PI/180.0f; + SpeakerAngle[2] = 0.0f * M_PI/180.0f; + SpeakerAngle[3] = 30.0f * M_PI/180.0f; + SpeakerAngle[4] = 110.0f * M_PI/180.0f; + break; + + case AL_FORMAT_61CHN8: + case AL_FORMAT_61CHN16: + case AL_FORMAT_61CHN32: + Context->NumChan = 6; + Speaker2Chan[0] = BACK_LEFT; + Speaker2Chan[1] = SIDE_LEFT; + Speaker2Chan[2] = FRONT_LEFT; + Speaker2Chan[3] = FRONT_RIGHT; + Speaker2Chan[4] = SIDE_RIGHT; + Speaker2Chan[5] = BACK_RIGHT; + SpeakerAngle[0] = -150.0f * M_PI/180.0f; + SpeakerAngle[1] = -90.0f * M_PI/180.0f; + SpeakerAngle[2] = -30.0f * M_PI/180.0f; + SpeakerAngle[3] = 30.0f * M_PI/180.0f; + SpeakerAngle[4] = 90.0f * M_PI/180.0f; + SpeakerAngle[5] = 150.0f * M_PI/180.0f; + break; + + case AL_FORMAT_71CHN8: + case AL_FORMAT_71CHN16: + case AL_FORMAT_71CHN32: + Context->NumChan = 7; + Speaker2Chan[0] = BACK_LEFT; + Speaker2Chan[1] = SIDE_LEFT; + Speaker2Chan[2] = FRONT_LEFT; + Speaker2Chan[3] = CENTER; + Speaker2Chan[4] = FRONT_RIGHT; + Speaker2Chan[5] = SIDE_RIGHT; + Speaker2Chan[6] = BACK_RIGHT; + SpeakerAngle[0] = -150.0f * M_PI/180.0f; + SpeakerAngle[1] = -90.0f * M_PI/180.0f; + SpeakerAngle[2] = -30.0f * M_PI/180.0f; + SpeakerAngle[3] = 0.0f * M_PI/180.0f; + SpeakerAngle[4] = 30.0f * M_PI/180.0f; + SpeakerAngle[5] = 90.0f * M_PI/180.0f; + SpeakerAngle[6] = 150.0f * M_PI/180.0f; + break; + + default: + Context->NumChan = 2; + Speaker2Chan[0] = FRONT_LEFT; + Speaker2Chan[1] = FRONT_RIGHT; + SpeakerAngle[0] = -90.0f * M_PI/180.0f; + SpeakerAngle[1] = 90.0f * M_PI/180.0f; + } + + for(pos = 0; pos < LUT_NUM; pos++) + { + // source angle + Theta = aluLUTpos2Angle(pos); + + // clear all values + offset = OUTPUTCHANNELS * pos; + for(s = 0; s < OUTPUTCHANNELS; s++) + Context->PanningLUT[offset+s] = 0.0f; + + // set panning values + for(s = 0; s < Context->NumChan - 1; s++) + { + if(Theta >= SpeakerAngle[s] && Theta < SpeakerAngle[s+1]) + { // source between speaker s and speaker s+1 + Alpha = M_PI_2 * (Theta - SpeakerAngle[s]) / (SpeakerAngle[s+1]-SpeakerAngle[s]); + Context->PanningLUT[offset + Speaker2Chan[s]] = cos(Alpha); + Context->PanningLUT[offset + Speaker2Chan[s+1]] = sin(Alpha); + break; + } + } + if(s == Context->NumChan - 1) // source between last and first speaker + { + if(Theta < SpeakerAngle[0]) + Theta += 2.0f * M_PI; + Alpha = M_PI_2 * (Theta - SpeakerAngle[s]) / (2.0f * M_PI + SpeakerAngle[0]-SpeakerAngle[s]); + Context->PanningLUT[offset + Speaker2Chan[s]] = cos(Alpha); + Context->PanningLUT[offset + Speaker2Chan[0]] = sin(Alpha); + } + } +} + +static __inline ALint aluCart2LUTpos(ALfloat re, ALfloat im) +{ + ALint pos = 0; + ALfloat denom = aluFabs(re) + aluFabs(im); + if(denom > 0.0f) + pos = (ALint)(QUADRANT_NUM*aluFabs(im) / denom + 0.5); + + if(re < 0.0) + pos = 2 * QUADRANT_NUM - pos; + if(im < 0.0) + pos = LUT_NUM - pos; + return pos%LUT_NUM; +} static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, - ALenum isMono, ALenum OutputFormat, - ALfloat *drysend, ALfloat *wetsend, - ALfloat *pitch, ALfloat *drygainhf, - ALfloat *wetgainhf) + ALenum isMono, ALfloat *drysend, + ALfloat *wetsend, ALfloat *pitch, + ALfloat *drygainhf, ALfloat *wetgainhf) { ALfloat InnerAngle,OuterAngle,Angle,Distance,DryMix,WetMix=0.0f; ALfloat Direction[3],Position[3],SourceToListener[3]; ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff,OuterGainHF; - ALfloat ConeVolume,SourceVolume,PanningFB,PanningLR,ListenerGain; + ALfloat ConeVolume,SourceVolume,ListenerGain; ALfloat U[3],V[3],N[3]; ALfloat DopplerFactor, DopplerVelocity, flSpeedOfSound, flMaxVelocity; ALfloat Matrix[3][3]; @@ -260,6 +415,9 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, ALfloat RoomRolloff; ALfloat DryGainHF = 1.0f; ALfloat WetGainHF = 1.0f; + ALfloat DirGain, AmbientGain; + const ALfloat *SpeakerGain; + ALint pos, s; ALfloat cw, a, g; //Get context properties @@ -519,65 +677,20 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, DryMix *= ListenerGain; WetMix *= ListenerGain; - //6. Convert normalized position into pannings, then into channel volumes + // Use energy-preserving panning algorithm for multi-speaker playback aluNormalize(Position); - switch(aluChannelsFromFormat(OutputFormat)) + + pos = aluCart2LUTpos(-Position[2], Position[0]); + SpeakerGain = &ALContext->PanningLUT[OUTPUTCHANNELS * pos]; + + DirGain = aluSqrt(Position[0] * Position[0] + Position[2] * Position[2]); + // elevation adjustment for directional gain. this sucks, but + // has low complexity + AmbientGain = 1.0/aluSqrt(ALContext->NumChan) * (1.0-DirGain); + for (s = 0; s < OUTPUTCHANNELS; s++) { - case 1: - case 2: - PanningLR = 0.5f + 0.5f*Position[0]; - drysend[FRONT_LEFT] = DryMix * aluSqrt(1.0f-PanningLR); //L Direct - drysend[FRONT_RIGHT] = DryMix * aluSqrt( PanningLR); //R Direct - drysend[BACK_LEFT] = 0.0f; - drysend[BACK_RIGHT] = 0.0f; - drysend[SIDE_LEFT] = 0.0f; - drysend[SIDE_RIGHT] = 0.0f; - break; - case 4: - /* TODO: Add center/lfe channel in spatial calculations? */ - case 6: - // Apply a scalar so each individual speaker has more weight - PanningLR = 0.5f + (0.5f*Position[0]*1.41421356f); - PanningLR = __min(1.0f, PanningLR); - PanningLR = __max(0.0f, PanningLR); - PanningFB = 0.5f + (0.5f*Position[2]*1.41421356f); - PanningFB = __min(1.0f, PanningFB); - PanningFB = __max(0.0f, PanningFB); - drysend[FRONT_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); - drysend[FRONT_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); - drysend[BACK_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); - drysend[BACK_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB)); - drysend[SIDE_LEFT] = 0.0f; - drysend[SIDE_RIGHT] = 0.0f; - break; - case 7: - case 8: - PanningFB = 1.0f - fabs(Position[2]*1.15470054f); - PanningFB = __min(1.0f, PanningFB); - PanningFB = __max(0.0f, PanningFB); - PanningLR = 0.5f + (0.5*Position[0]*((1.0f-PanningFB)*2.0f)); - PanningLR = __min(1.0f, PanningLR); - PanningLR = __max(0.0f, PanningLR); - if(Position[2] > 0.0f) - { - drysend[BACK_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); - drysend[BACK_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); - drysend[SIDE_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); - drysend[SIDE_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB)); - drysend[FRONT_LEFT] = 0.0f; - drysend[FRONT_RIGHT] = 0.0f; - } - else - { - drysend[FRONT_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); - drysend[FRONT_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); - drysend[SIDE_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); - drysend[SIDE_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB)); - drysend[BACK_LEFT] = 0.0f; - drysend[BACK_RIGHT] = 0.0f; - } - default: - break; + ALfloat gain = SpeakerGain[s]*DirGain + AmbientGain; + drysend[s] = DryMix * gain; } *wetsend = WetMix; @@ -748,7 +861,7 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma CalcSourceParams(ALContext, ALSource, (Channels==1) ? AL_TRUE : AL_FALSE, - format, newDrySend, &newWetSend, &Pitch, + newDrySend, &newWetSend, &Pitch, &DryGainHF, &WetGainHF); Pitch = (Pitch*Frequency) / ALContext->Frequency; @@ -847,6 +960,7 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma DryBuffer[j][SIDE_RIGHT] += outsamp*DrySend[SIDE_RIGHT]; DryBuffer[j][BACK_LEFT] += outsamp*DrySend[BACK_LEFT]; DryBuffer[j][BACK_RIGHT] += outsamp*DrySend[BACK_RIGHT]; + DryBuffer[j][CENTER] += outsamp*DrySend[CENTER]; //Room path final mix buffer and panning outsamp = lpFilter(WetFilter, sample); WetBuffer[j] += outsamp*(*WetSend); diff --git a/CMakeLists.txt b/CMakeLists.txt index 2862217..845442c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,10 +122,12 @@ CHECK_INCLUDE_FILE(float.h HAVE_FLOAT_H) CHECK_LIBRARY_EXISTS(m sqrtf "" HAVE_SQRTF) CHECK_LIBRARY_EXISTS(m acosf "" HAVE_ACOSF) +CHECK_LIBRARY_EXISTS(m atanf "" HAVE_ATANF) +CHECK_LIBRARY_EXISTS(m fabsf "" HAVE_FABSF) IF(HAVE_FENV_H) CHECK_LIBRARY_EXISTS(m fesetround "" HAVE_FESETROUND) ENDIF() -IF(HAVE_SQRTF OR HAVE_ACOSF OR HAVE_FESETROUND) +IF(HAVE_SQRTF OR HAVE_ACOSF OR HAVE_ATANF OR HAVE_FABSF OR HAVE_FESETROUND) SET(EXTRA_LIBS m ${EXTRA_LIBS}) ENDIF() CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF) diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 042ab77..de53b07 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -129,6 +129,9 @@ extern char _alDebug[256]; #define LOWPASSFREQCUTOFF (5000) +#define QUADRANT_NUM 128 +#define LUT_NUM (4 * QUADRANT_NUM) + typedef struct { ALCboolean (*OpenPlayback)(ALCdevice*, const ALCchar*); @@ -206,6 +209,9 @@ struct ALCcontext_struct ALint lNumMonoSources; ALint lNumStereoSources; + ALfloat PanningLUT[OUTPUTCHANNELS * LUT_NUM]; + ALint NumChan; + ALCdevice *Device; const ALCchar *ExtensionList; diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h index b14180b..f307ea0 100644 --- a/OpenAL32/Include/alu.h +++ b/OpenAL32/Include/alu.h @@ -25,6 +25,7 @@ extern ALboolean DuplicateStereo; __inline ALuint aluBytesFromFormat(ALenum format); __inline ALuint aluChannelsFromFormat(ALenum format); +ALvoid aluInitPanning(ALCcontext *Context); ALvoid aluMixData(ALCcontext *context,ALvoid *buffer,ALsizei size,ALenum format); #ifdef __cplusplus diff --git a/config.h.in b/config.h.in index 45df515..0c8ef40 100644 --- a/config.h.in +++ b/config.h.in @@ -31,6 +31,12 @@ /* Define if we have the acosf function */ #cmakedefine HAVE_ACOSF +/* Define if we have the atanf function */ +#cmakedefine HAVE_ATANF + +/* Define if we have the fabsf function */ +#cmakedefine HAVE_FABSF + /* Define if we have the strtof function */ #cmakedefine HAVE_STRTOF _______________________________________________ Openal-devel mailing list Openal-devel@... http://opensource.creative.com/mailman/listinfo/openal-devel |
|
|
Re: new panning algorithmI am resending this as looking at another post, this may not have gone
through a few days ago - sorry! Not sure if this is any help in working out what your final effect should achieve: http://www.dolby.com/uploadedFiles/zz-_Shared_Assets/English_PDFs/Professional/44_SuroundMixing.pdf This is the manual for one of the pro dolby studio units. It discusses true speaker placement as well as use. One of the problems in games I have noticed from a sound engineers perspective is that there is often little or no allowance for the narrowing of the front stereo image that is inherent in LCRSS configurations. I think this comes sometimes from a misunderstanding of the role of the centre speaker in cinema and the possible misuse of it when sitting at a computer. In theory, in a cinema, if everyone in the audience could sit in the precise middle of the screen, then there would be no need for a centre speaker, as the combined left and right pairing would give the correct balance. However, sitting left or right means that the voice would be imbalanced. So a centre channel is added to a dedicated speaker to fix the voice to the centre of the screen. The down side of this is that because a stereo sound (music for instance) also contains a lot of mono L+R information, this will also use this channel and result in a narrowing of the stereo field. Consequently, we often produced stereo tracks that were "wider" than would be mixed for normal stereo to compensate, or occasionally add a very small delay to the right channel (not good on music). The other problem with games, (and I think this is especially affecting MMOs now) is panning through centre which is a little too fast. In real life, though we may turn our head slightly from left to right when talking to someone, we perceive the sound as still being in front of us until we move our head to either the extreme left or right. This is something that the brain sorts out for us in some way. However, with the artificial movement of sound created in a surround field in respect to an avatar the brain does not have the same information as it would in a real life situation and does not do this. In consequence the sound seems to move very quickly from centre to left or right. I would be interested to hear what would happen if the sound moved slightly too slowly from centre to, say, left and then caught up as it moved round the pan. This is not a problem we have in cinema since we are mostly showing a static image and the audience can move their heads in the normal way and get the normal live feel. There is another problem in games which is the binaural or dummy-head effect (or lack of it). Sounds behind your avatar should be duller than the sounds ahead. There is an argument that says that since the two main SS speakers are placed behind the listener then this real life positioning should do the job. However, since it is common for the rear speakers to be not directly behind but very nearly to the side of the listener then I am not convinced this is happening appropriately. It was actually easier with the older true dolby stereo (LCRS). With only one mono surround channel (even if split over several speakers) the sound was naturally duller. But with a true stereo pair, the sound is normally as fresh sounding as the front speakers. I am not sure anything really could, or should be done in that situation during the mix as we have no knowledge of the users speaker set up (and the better quality it is, the worse it often sounds. Spending a fortune on a system is a waste in most domestic environment - smaller is actually probably better and more accurate). However, it would be interesting if a switch could be added to the output of the mix that perhaps is called something like "enhanced binaural positioning" where is reduces the bandwidth of the SS tracks and changed the way the front panning worked. Something like that. Anyway - it was the manual that was the important bit! Sorry! Joss Christian Borss wrote: > Am 18. Jan. 2009 um 18:05 Uhr schrieb Chris Robinson: > > >> The center channel isn't used in spatial calculations because it's a bit >> ambiguous as to where it should be. The absolute center? Or between the front >> speakers? >> > > The center speaker is typically placed between the front speakers as > recommended by "ITU-R BS.775": > > http://en.wikipedia.org/wiki/Surround_sound#5.1_Channel_Surround_.283-2_Stereo.29_.28digital_discrete:_Dolby_Digital.2C_DTS.2C_SDDS.29 > http://www.sengpielaudio.com/Surround-ITU-Wiedergabe.pdf > > The second web site contains documents for German "Tonmeister" (sound > engineers). > > >> Often times in movies, the center speaker is left out for sound >> effects and used specifically as a voice track and/or some "special" >> sounds to draw the viewer's attention to. >> > > I think, a rocket fired by an opponent in the front in a computer game > should definitely draw the gamers attention to the front. :-) > > >> For 7.1 surround-sound setups, it should use 6 speakers (2 front, 2 side, 2 >> rear). >> > > The center speaker was introduced to improve the localization in the > frontal region. So, why not make use of it? > > I saw in the source code that you use this arrangement for 6.1 surround > setups. Thats why I used the front/side/rear-back speaker setup also in > my code. But normaly I would expect a > > 1 center > 2 front > 2 side > 1 rear-back > > speaker arrangement: > > http://en.wikipedia.org/wiki/Surround_sound#6.1_Channel_Surround_.28digital_discrete:_DTS-ES.29 > > Would you agree to change the configuration to a DTS-ES arrangement? > > >> A quick test showed it seem to work well. >> > > Great. > > >> I have question, though.. with this: >> >> pos = round(QUADRANT_NUM * aluFabs(im) / (aluFabs(re) + aluFabs(im))); >> >> what is supposed to happen if re and im are 0? Since they're the -Z and X >> coords, this is quite possible for head-relative sources that are left at >> 0,0,0, and given the code, it would cause a 0/0 which wouldn't be very good. >> > > In this case, DirGain is set to zero > > DirGain = aluSqrt(Position[0] * Position[0] + Position[2] * Position[2]); > > and AmbientGain is set to MaxAmbientGain: > > AmbientGain = MaxAmbientGain * (1.0 - DirGain); > > Thus, there is no directional sound and the sound is played back over > all speakers instead. In ioquake3 you can hear this effect, e.g., when > you fire your own weapons. > > But you are right, it would be a more clean implementation to avoid a > division by zero. > > > Ciao, > Christian > > P.S.: For those of you who will attend it: See you at the 35th > international AES convention "Audio for Games" in London! > -- ------------------------------------------------------------------------ *Wurm Online* /The truly original and independent MMO from OneTooFree AB/ *Official Website:* *http://www.wurmonline.com* For press and other information please email press@... This e-mail contains information which may be legally privileged, proprietary in nature, or otherwise protected by law from disclosure, and is intended only for the use of the Addressee(s) named above for their private information or for use as a press release if marked as such. If you are not the intended recipient, you are hereby notified that any dissemination or copying of this e-mail may be strictly prohibited. If you have received the e-mail in error, please immediately notify by e-mail press@... and forward the original e-mail. _______________________________________________ Openal-devel mailing list Openal-devel@... http://opensource.creative.com/mailman/listinfo/openal-devel |
|
|
Re: new panning algorithmOn Sunday 25 January 2009 12:04:44 pm Joss Sanglier wrote:
> I am resending this as looking at another post, this may not have gone > through a few days ago - sorry! > > Not sure if this is any help in working out what your final effect > should achieve: > > http://www.dolby.com/uploadedFiles/zz-_Shared_Assets/English_PDFs/Professio >nal/44_SuroundMixing.pdf > > This is the manual for one of the pro dolby studio units. It discusses > true speaker placement as well as use. It's an interesting read, regardless. Thanks. :) > In theory, in a cinema, if everyone in the audience could sit in the > precise middle of the screen, then there would be no need for a centre > speaker, as the combined left and right pairing would give the correct > balance. However, sitting left or right means that the voice would be > imbalanced. So a centre channel is added to a dedicated speaker to fix > the voice to the centre of the screen. > > The down side of this is that because a stereo sound (music for > instance) also contains a lot of mono L+R information, this will also > use this channel and result in a narrowing of the stereo field. > Consequently, we often produced stereo tracks that were "wider" than > would be mixed for normal stereo to compensate, or occasionally add a > very small delay to the right channel (not good on music). So does that mean stereo sounds should mix into the center channel? Or is that mainly for 5.1-mixed tracks? I ask because at least some in rendered music (like MIDI-to-wave, or module formats, that are played in real-time), mixing the left and right channels into the center would dull the perceived stereo effect, causing notes that are panned left to become panned halfway between center and left. > The other problem with games, (and I think this is especially affecting > MMOs now) is panning through centre which is a little too fast. In real > life, though we may turn our head slightly from left to right when > talking to someone, we perceive the sound as still being in front of us > until we move our head to either the extreme left or right. This is > something that the brain sorts out for us in some way. However, with the > artificial movement of sound created in a surround field in respect to > an avatar the brain does not have the same information as it would in a > real life situation and does not do this. In consequence the sound seems > to move very quickly from centre to left or right. I think this could be mostly resolved on the application side. For example, keeping the listener orientation facing auditory points of interest (eg. someone talking) even if the camera moves around a bit. Then reorient it when you look far enough away. > There is another problem in games which is the binaural or dummy-head > effect (or lack of it). Sounds behind your avatar should be duller than > the sounds ahead. There is an argument that says that since the two main > SS speakers are placed behind the listener then this real life > positioning should do the job. However, since it is common for the rear > speakers to be not directly behind but very nearly to the side of the > listener then I am not convinced this is happening appropriately. It > was actually easier with the older true dolby stereo (LCRS). With only > one mono surround channel (even if split over several speakers) the > sound was naturally duller. But with a true stereo pair, the sound is > normally as fresh sounding as the front speakers. I've thought about the idea of a listener cone before for a similar reason. But I also somewhat dismissed it for the similar thought, "a real surround sound setup would naturally dull the sound anyway". I don't think it would actually be too difficult to add listener cones to OpenAL.. but it may not interact well since as you say, you can't know the user's speaker setup (enabling it for stereo may produce good results, but perhaps not as good for surround sound setups). > However, it would be interesting if a switch could be added to the > output of the mix that perhaps is called something like "enhanced > binaural positioning" where is reduces the bandwidth of the SS tracks > and changed the way the front panning worked. Something like that. Not sure changing the way panning works is a good idea, as a game designer can have proper control over it and they would know best what to focus on. Though, I probably could add a config option that applies the cone logic to the listener->source position (similar to the logic there for source->listener) that's left for the user, not the app. It can modulate the gain and high frequencies with the low-pass filter that's already being used. > Anyway - it was the manual that was the important bit! Sorry! No need to apologize. You brought up some interesting points. :) _______________________________________________ Openal-devel mailing list Openal-devel@... http://opensource.creative.com/mailman/listinfo/openal-devel |
|
|
Re: new panning algorithmOn the panning - basically if you send a stereo signal to the front
pair, the LR, then the C will contain any mono information from that sound (I think I may have mistyped about that somewhere) The problem with that is that is does have some narrowing effect on the sound. Now, I have to say this is how it works in DOlby and THX. I am assuming it is the same in computer systems since it is described as 5:1. Obviously, if the listener does not have a centre speaker (not the effects channel - the sub woofer), then there is not an issue. If they do, then there is. In Dolby we get round this confusion with flags. The system understands that certain things are not required and switch them off depending on the playback set up. Computers definitely do not do that. I think there is a major confusion. Surround is NOT quadraphonic. In Quad (which I used to use in the 70s) the signals between speakers was equal, and the panning between them was also equal. It was assumed that the 4 speakers would be matching and the listener would be in the centre. With surround, it is assumed that the quality speakers are the LCR speakers and the surround speakers are support, and normally smaller and of lesser frequency range. Consequently, you mix to that formula. The reason for this is that the point of focus should always be infront of the listener, and the listener is always static to the screen. In quad it is often the case that the listener moves and turns in the space - for instance an installation - and so you want it balanced all round. Now, this is the point that I get it all wrong as I am not up enough on game technology! It seems to me that games treat the sound as Quadraphonic. However, the player (the listener) is listening on a surround system. This is awkward, to say the least and would also explain why a friend of mine keeps blowing out his rear speakers! hehe We also have the problem that in the majority of home spaces the speakers are really badly set up (the players think they are wonderful, but trust me, they are not). So mixing for them is a real pain. With cinema both the studio and the theatre have to have a very expensive Dolby Licence, and Dolby come and tweak the set up to their standard. Thus, if it sounds good in the studio it sounds good in the theatre. We almost need a test system for each game where the player is told to put a microphone where they sit, pointing straight up, then we run a little application to work out what the player is hearing and optimising the output of the specific sound engine. Chris Robinson wrote: > On Sunday 25 January 2009 12:04:44 pm Joss Sanglier wrote: > >> I am resending this as looking at another post, this may not have gone >> through a few days ago - sorry! >> >> Not sure if this is any help in working out what your final effect >> should achieve: >> >> http://www.dolby.com/uploadedFiles/zz-_Shared_Assets/English_PDFs/Professio >> nal/44_SuroundMixing.pdf >> >> This is the manual for one of the pro dolby studio units. It discusses >> true speaker placement as well as use. >> > > It's an interesting read, regardless. Thanks. :) > > >> In theory, in a cinema, if everyone in the audience could sit in the >> precise middle of the screen, then there would be no need for a centre >> speaker, as the combined left and right pairing would give the correct >> balance. However, sitting left or right means that the voice would be >> imbalanced. So a centre channel is added to a dedicated speaker to fix >> the voice to the centre of the screen. >> >> The down side of this is that because a stereo sound (music for >> instance) also contains a lot of mono L+R information, this will also >> use this channel and result in a narrowing of the stereo field. >> Consequently, we often produced stereo tracks that were "wider" than >> would be mixed for normal stereo to compensate, or occasionally add a >> very small delay to the right channel (not good on music). >> > > So does that mean stereo sounds should mix into the center channel? Or is that > mainly for 5.1-mixed tracks? I ask because at least some in rendered music > (like MIDI-to-wave, or module formats, that are played in real-time), mixing > the left and right channels into the center would dull the perceived stereo > effect, causing notes that are panned left to become panned halfway between > center and left. > > >> The other problem with games, (and I think this is especially affecting >> MMOs now) is panning through centre which is a little too fast. In real >> life, though we may turn our head slightly from left to right when >> talking to someone, we perceive the sound as still being in front of us >> until we move our head to either the extreme left or right. This is >> something that the brain sorts out for us in some way. However, with the >> artificial movement of sound created in a surround field in respect to >> an avatar the brain does not have the same information as it would in a >> real life situation and does not do this. In consequence the sound seems >> to move very quickly from centre to left or right. >> > > I think this could be mostly resolved on the application side. For example, > keeping the listener orientation facing auditory points of interest (eg. > someone talking) even if the camera moves around a bit. Then reorient it when > you look far enough away. > > >> There is another problem in games which is the binaural or dummy-head >> effect (or lack of it). Sounds behind your avatar should be duller than >> the sounds ahead. There is an argument that says that since the two main >> SS speakers are placed behind the listener then this real life >> positioning should do the job. However, since it is common for the rear >> speakers to be not directly behind but very nearly to the side of the >> listener then I am not convinced this is happening appropriately. It >> was actually easier with the older true dolby stereo (LCRS). With only >> one mono surround channel (even if split over several speakers) the >> sound was naturally duller. But with a true stereo pair, the sound is >> normally as fresh sounding as the front speakers. >> > > I've thought about the idea of a listener cone before for a similar reason. > But I also somewhat dismissed it for the similar thought, "a real surround > sound setup would naturally dull the sound anyway". I don't think it would > actually be too difficult to add listener cones to OpenAL.. but it may not > interact well since as you say, you can't know the user's speaker setup > (enabling it for stereo may produce good results, but perhaps not as good for > surround sound setups). > > >> However, it would be interesting if a switch could be added to the >> output of the mix that perhaps is called something like "enhanced >> binaural positioning" where is reduces the bandwidth of the SS tracks >> and changed the way the front panning worked. Something like that. >> > > Not sure changing the way panning works is a good idea, as a game designer can > have proper control over it and they would know best what to focus on. Though, > I probably could add a config option that applies the cone logic to the > listener->source position (similar to the logic there for > source->listener) that's left for the user, not the app. It can modulate the > gain and high frequencies with the low-pass filter that's already being used. > > >> Anyway - it was the manual that was the important bit! Sorry! >> > > No need to apologize. You brought up some interesting points. :) > _______________________________________________ > Openal-devel mailing list > Openal-devel@... > http://opensource.creative.com/mailman/listinfo/openal-devel > -- ------------------------------------------------------------------------ *Wurm Online* /The truly original and independent MMO from OneTooFree AB/ *Official Website:* *http://www.wurmonline.com* For press and other information please email press@... This e-mail contains information which may be legally privileged, proprietary in nature, or otherwise protected by law from disclosure, and is intended only for the use of the Addressee(s) named above for their private information or for use as a press release if marked as such. If you are not the intended recipient, you are hereby notified that any dissemination or copying of this e-mail may be strictly prohibited. If you have received the e-mail in error, please immediately notify by e-mail press@... and forward the original e-mail. _______________________________________________ Openal-devel mailing list Openal-devel@... http://opensource.creative.com/mailman/listinfo/openal-devel |
|
|
Re: new panning algorithmAm 21. Jan. 2009 um 10:02 Uhr schrieb Christian Borss:
>In my implementation I simply expand/compress the angle between the >involved loudspeaker pairs to 90° and use a sin() and cos() function to >obtain energy preserving gain factors (which results in 1/sqrt(2) for an >angle in between). But anyway, exchanging the panning function by any of >the above mentioned approaches would be trivial. If you like to try another panning function, the attached patch against the current git repository implements Vector Base Intensity Panning (VBIP), a variant of Vector Base Amplitude Panning (VBAP) which uses the energy vector instead of the velocity vector. For frequencies > 700Hz this should result in auditory events that are closer to the intended source position (the effect that the sound source "jumps" from speaker to speaker instead of moving smoothly is reduced). Which panning function do you prefer? Ciao, Christian -- Christian Borß, Dipl.-Ing. || Institut für Kommunikationsakustik http://www.ika.ruhr-uni-bochum.de || Ruhr-Universität Bochum Tel.: +49-(0)234-32-22470 || Universitätsstr. 150, IC1/33 Fax.: +49-(0)234-32-14165 || D-44780 Bochum (Germany) --- Alc.orig/ALu.c 2009-02-24 21:48:35.077008402 +0100 +++ Alc/ALu.c 2009-02-24 23:38:32.911859982 +0100 @@ -356,14 +356,13 @@ static __inline ALfloat aluLUTpos2Angle( ALvoid aluInitPanning(ALCcontext *Context) { - ALint pos, offset, s; - ALfloat Alpha, Theta; + ALint pos, offset, s, s2; + ALfloat Alpha, Theta, norm, g1, g2, xp, yp, xl, yl, xr, yr; ALfloat SpeakerAngle[OUTPUTCHANNELS]; ALint Speaker2Chan[OUTPUTCHANNELS]; for(s = 0;s < OUTPUTCHANNELS;s++) { - int s2; for(s2 = 0;s2 < OUTPUTCHANNELS;s2++) Context->ChannelMatrix[s][s2] = ((s==s2) ? 1.0f : 0.0f); } @@ -514,29 +513,49 @@ ALvoid aluInitPanning(ALCcontext *Contex for(s = 0; s < OUTPUTCHANNELS; s++) Context->PanningLUT[offset+s] = 0.0f; - /* set panning values */ + /* determine involved speakers */ for(s = 0; s < Context->NumChan - 1; s++) { if(Theta >= SpeakerAngle[s] && Theta < SpeakerAngle[s+1]) + break; // source between speaker s and speaker s+1 + } + s2 = ((s==Context->NumChan-1) ? 0 : s+1); + + if(Context->NumChan == 2) + { + /* simple panning for stereo */ + if (s2==s+1) { - /* source between speaker s and speaker s+1 */ Alpha = M_PI_2 * (Theta-SpeakerAngle[s]) / - (SpeakerAngle[s+1]-SpeakerAngle[s]); - Context->PanningLUT[offset + Speaker2Chan[s]] = cos(Alpha); - Context->PanningLUT[offset + Speaker2Chan[s+1]] = sin(Alpha); - break; + (SpeakerAngle[s2]-SpeakerAngle[s]); + } + else + { + if(Theta < SpeakerAngle[0]) + Theta += 2.0f * M_PI; + Alpha = M_PI_2 * (Theta-SpeakerAngle[s]) / + (2.0f * M_PI + SpeakerAngle[s2]-SpeakerAngle[s]); } + g1 = cos(Alpha); + g2 = sin(Alpha); } - if(s == Context->NumChan - 1) + else { - /* source between last and first speaker */ - if(Theta < SpeakerAngle[0]) - Theta += 2.0f * M_PI; - Alpha = M_PI_2 * (Theta-SpeakerAngle[s]) / - (2.0f * M_PI + SpeakerAngle[0]-SpeakerAngle[s]); - Context->PanningLUT[offset + Speaker2Chan[s]] = cos(Alpha); - Context->PanningLUT[offset + Speaker2Chan[0]] = sin(Alpha); + /* vector base intensity panning [Pernaux et al., 1998] */ + xp = sin(Theta); + yp = cos(Theta); + xl = sin(SpeakerAngle[s]); + yl = cos(SpeakerAngle[s]); + xr = sin(SpeakerAngle[s2]); + yr = cos(SpeakerAngle[s2]); + g1 = aluSqrt(aluFabs((xp * yr - xr * yp) / (xl * yr - xr * yl))); + g2 = aluSqrt(aluFabs((xl * yp - xp * yl) / (xl * yr - xr * yl))); } + + // energy normalization + norm = 1.0 / sqrt(g1 * g1 + g2 * g2); + Context->PanningLUT[offset + Speaker2Chan[s]] = g1 * norm; + Context->PanningLUT[offset + Speaker2Chan[s2]] = g2 * norm; } } _______________________________________________ Openal-devel mailing list Openal-devel@... http://opensource.creative.com/mailman/listinfo/openal-devel |
| Free embeddable forum powered by Nabble | Forum Help |