flibitijibibo / flibitBounties

Pile of programming bounties for things flibit can't do right now
27 stars 0 forks source link

Implement X3DAUDIO_CALCULATE_MATRIX for FAudio #2

Closed flibitijibibo closed 6 years ago

flibitijibibo commented 6 years ago

Introductory Information:

X3DAudio is Microsoft's library to calculate output matrices for XAudio2 voices to create various 3D audio effects including positional audio, doppler pitch scaling, and reverb/filter coefficient calculation.

FAudio is FNA's upcoming replacement for the Audio subsystem. It was originally designed as just an XACT reimplementation, but was eventually expanded to act as an DirectX Audio implementation with support for XAudio2, XACT3, X3DAudio, and XAPO. The repository is currently here.

The Project:

For FAudio's X3DAudioCalculate function, we need to implement the calculations requested by X3DAUDIO_CALCULATE_MATRIX. The short version: It takes the emitter/listener data and calculates what the volume levels for each input channel should be for each output channel. For example, an emitter playing a sound to the right of the listener would have higher volumes for the right speaker(s) and lower volumes for the left speaker(s). It is of course more complicated than that, but that's the short version.

You'll notice that both input and output have a channel count. At most we'll be dealing with 2-channel input (referenced in pEmitter->ChannelCount), and output can be based on your usual speaker counts/layouts (referenced in the "instance"). For 2-channel input you can just assume that the levels/positions are exactly the same, so stuff like emitter channel radii/azimuths can be ignored. We're effectively discarding the stereo data and treating it as monaural input, but with more busy work.

X3DAudioInitialize has been implemented and all the other bitflags we care about have been implemented, and the rest are extra glitter we likely won't need for a very long time.

Prerequisites:

FAudio is written in C99, so having the ability to build/test C programs is required, but I don't expect the code to be so complicated that it would be hard to translate to C from another language if you're more comfortable prototyping/drafting in a different language.

Experience with X3DAudio and/or audio programming is a plus but is not really required, considering how tiny the API is and how isolated it is from XAudio2.

This project isn't so much a programming project as much as it is a 3D math project. If you want to do this it's because you love trigonometry and 3D math. I don't expect all that much code to come out of this. As an example, here is some code we already have for X3DAUDIO_CALCULATE_DOPPLER.

Having a Windows development environment will also be helpful as it could be useful to take Microsoft's X3DAudio and spam input values at it to see what comes out, for reference and comparison.

Example Games:

XNA/FNA games use this extensively for 3D support; if it uses SoundEffectInstance or XACT this is almost certainly being used. The example list is absolutely ginormous, but popular examples include FEZ, Rogue Legacy, Dust: An Elysian Tail, Capsized/Apotheon/Cryptark, and Murder Miners. A more recent example is Staxel.

How Much Can flibit Help?

I am absolutely terrible at 3D math, so you're pretty much on your own when it comes to the implementation. If you have questions about the X3DAudio/XAudio2 spec, however, I can probably clear that up pretty easily.

Budget/Timeline:

Measuring in weekends, I expect this to take about 2 weekends. The first weekend would be spent on reading/research and the second weekend would be spend on implementation and testing. In total there is currently $1000 USD allocated for this project; I have $500 USD allocated and Bart van der Werf has an additional $500 USD allocated for accuracy with Staxel specifically.

lamarqua commented 6 years ago

I've started working on this; I did some extensive reading on the docs and did a little black box testing.

I'm going to set up a more practical tool to do the reverse engineering next. I'll also take some time to gather some of the questions I have with regards to both the spec and the code style (and a few tooling issues), and send them your way. (Will try to do that by tomorrow.) (I was busy with other stuff last week, but this project now has my almost undivided attention!)

flibitijibibo commented 6 years ago

Excellent! For the F3DAUDIO_HANDLE I did end up parsing that since it was only a few bytes and I had a feeling it was just a few 4-byte values:

https://github.com/flibitijibibo/FACT/commit/60e249f648208a1e80316fe271687a3bd607d76b

Sadly not too helpful with the Calculate func but maybe I’ll be wrong on that.

flibitijibibo commented 6 years ago

Just doing a weekly checkup on this - @lamarqua, find anything out of the ordinary?

lamarqua commented 6 years ago

I didn't get as much time as I wanted last week to make progress. (I also lost some time yak-shaving.) I've been getting back to it since Friday. I'm still reverse-engineering the matrix calculation (which is by far the most complex bit); the docs are a bit underspecced and some stuff still eludes me. I just found that the headers actually mentioned a debug version of X3DAudio1_7.dll, which has proven very useful since it helps me validate when I feed bad input to X3DAudioCalculate. (It will also be useful to implement a similar kind of check to validate inputs in our code. I've been taking quite a few notes to that effect.) I've gathered questions in a text file, so once I'm done with (or temporarily tired of) the reverse engineering part I'll clean them up and ask all of it in batch, if that's OK with you. (As I mentioned earlier, these are roughly 3 kinds of questions: clarifications on the API, random build/tooling issues, and code style.) The parameter space is really big, but once I solve a few puzzling results I can't figure out right now, I'll roughly proceed that way: handle non-cone listener, single-channel emitters, first with no distance curve, then with. Afterwards, multi channel emitters, then cone listeners, then cone emitters, and finally InnerRadius / InnerRadiusAngle. (The docs are really unclear on those two...) It corresponds roughly to order of difficulty, I think.

Since there's already code for the emitter angle and doppler calculation, and these are largely orthogonal to the matrix code, I'll defer validation/improvements to after getting the matrix right.

lamarqua commented 6 years ago

Precision: I'll be testing all cases (non-cone, cone, ...) for all configurations, starting with mono, stereo, 2.1, etc. Basically this should boil down to handling regular speaker configurations, then handling those with LFE speakers, but this adds up to the size of the parameter space...

flibitijibibo commented 6 years ago

Doing the weekly checkup! Anything new happen this week?

flibitijibibo commented 6 years ago

Another week, another check.

This time however I do need to open this back up to the public since it's past-due and there don't seem to be any new commits since mid-March. If new commits happen we can mark this as in-progress again!

lamarqua commented 6 years ago

Hi! Apologies for the lack of communication on my part. I was busy with something else (I was giving a talk at a conference last week and spent way too much time preparing my slides among others) and had to leave my work in a messy state. To top it off I forgot to update you after seeing the GH notification. (Doubly my fault because I also receive emails but I don't check them because of the noise...)

My progress so far:

While I'm there I might as well recap some of the issues I've faced and sollicitate your feedback.

Build issues:

Code style (discussion can wait though as all my code is still very much in draft form):

I have a bunch more questions down the road, but I'll stick with those remarks for now, as some of my interrogations might just solve themselves while I work on the code.

flibitijibibo commented 6 years ago

I'd be up for making a couple changes for VS2010 support - 2010 is the target mostly because that's my minimum spec for FNA builds. isnan() I'll have to figure out how to deal with, and those const variables should probably just be at the top of the function (making it a bit more C90ish). Not too big of a deal, just the occasional annoyance from old Visual Studio days.

For macOS, I just build from source since it doesn't install a whole lot and it lets me use the latest (which is common for me since I contribute to it):

CC="./build-scripts/gcc-fat.sh" CXX="./build-scripts/g++-fat.sh" ./configure
make
make install

Grab the latest and see which uninitialized variables it pulls up - I did a handful of Valgrind validation so maybe that fixed it.

For Git commits/branches, feel free to commit early and often and however works best; we can clean up the final patch when it's done. As you can see in the mainline history, I'm not too fussy about clean logs :P

And definitely write it however is best - I think even in X3DAudio it's split up into a bunch of static functions, so if that makes it easier to understand, great!

lamarqua commented 6 years ago

Sent you a PR for the build issues.

The warnings I mentioned are:

src/FACT.c:1241:12: warning: variable 'wave' is used uninitialized whenever function
      'FACTWaveBank_Stop' is called [-Wsometimes-uninitialized]

Probably you forgot to initialize it with (FACTWave*) list->entry?

Then there's numerous complaints to comparison with an enum type:

src/FAudio_internal.c:311:29: warning: comparison of constant 255 with expression of type
      'const FAudioFilterType' (aka 'const enum FAudioFilterType') is always true
      [-Wtautological-constant-out-of-range-compare]

Windows build also uncovered this:

 >e:\home\dev\fact\src\fact.c(1836): warning C4244: '=' : conversion from 'float' to 'uint8_t', possible loss of data
lamarqua commented 6 years ago

Also you were right w.r.t C-style declarations; they were introduced in VS2013, so essentially we'll need to be sticking to C90 style declarations.

(Surely they could've given better error messages than just "syntax error" though...)

flibitijibibo commented 6 years ago

Merged the PR and fixed that FACTWave* typo, thanks for both! For the FAudioFilterType warning I'm not entirely sure what to do there other than maybe change the variable declarations; in XACT they store 0xFF for waves that don't use a filter so we do need that constant for accuracy.

The float->uint8_t is me not doing proper XACT packed volume conversion, will have to deal with that at some point... but that'll only affect XACT, the XAudio stuff should be safe from that.

lamarqua commented 6 years ago

For the FAudioFilterType I would just declare an enum case in FAudio.h, perhaps marking it as "internal" or "reserved" if you don't want people to think it is part of the public API. (and perhaps using a #define in the code that uses it to make it clearer what the intent was)

flibitijibibo commented 6 years ago

What I really should do is implement the Flags parameter for CreateSourceVoice, to keep the magic number mess in FACT and not FAudio...

https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.ixaudio2.ixaudio2.createsourcevoice(v=vs.85).aspx

I just need to make 0xFF skip USEFILTER, and then the FAudio spec can just treat this as it should without any special numbers. I’ll take care of that this week.

flibitijibibo commented 6 years ago

This should deal with the 0xFF cast:

https://github.com/flibitijibibo/FACT/commit/978afab623856ab09eed6bb913330ac746dbae39

flibitijibibo commented 6 years ago

Also silenced that uint8_t conversion issue, this function is largely unused so it's not critical but I'll have to figure out what this actually means at another time: https://github.com/flibitijibibo/FACT/commit/4f0909cbdae0740265f9b94dfecaee25e4b73664

flibitijibibo commented 6 years ago

Stepped on this just the tiniest bit, shouldn't conflict with your current diff but fills in something that, in hindsight, was really obvious when standing right next to the DSP_SETTINGS docs:

https://github.com/flibitijibibo/FACT/commit/2c7f57d98f6eb158d4b6ddaddbe30591abb223f5

lamarqua commented 6 years ago

It shouldn't be too bad, it's just a minor change :) I've avoided merging stuff so far because I have lots of changes in my repo and dislike the merge experience I have right now with git (lots of spurious merges that should be automated)... But I guess I'll have to bite the bullet :sweat_smile: I'm finishing some stuff first and I'll report later today on my progress + questions.

flibitijibibo commented 6 years ago

In preparing for the weekly update I have updated the OP to make it more clear that X3DAUDIO_CALCULATE_MATRIX is all we have left to do, and what the scope of that task really is. Once that's done, the whole thing is ready to go.

lamarqua commented 6 years ago

It took me a while but I think I've managed to rebase on top of your commits and forget all the crappy, messed up history I had. (Didn't quite understood why it was so messy...) It's in the f3daudio-dev branch now. I should be able to track your changes more easily now (rebasing on top every time), and I'll prepare a PR with the work-in-progress I have so far. Gonna do the rest of the report later today. (I'm gonna be afk for a few hours.) (Just wanna point out that the code is very much work-in-progress now, in case you have a look at it!)

lamarqua commented 6 years ago

I just pushed some fixes to build on macOS, so assuming no surprises you should probably be able to build it on Linux.

flibitijibibo commented 6 years ago

If it's any help, there is FAudio_assert which binds to SDL_assert and should match up with all the debug stuff that exists so far:

https://wiki.libsdl.org/CategoryAssertions

lamarqua commented 6 years ago

Alright, here it goes.

Sorry that this may not have been as fast as you wanted :) There was a lot of tediousness due to build issues, etc... at first, but I now have a setup that allows me to code faster and check my code automatically, so this should go faster now. (And I want to finish this quick while still doing as good of a job as possible!)

If you're fine with it, I can send you a PR tomorrow with the current valid but unfinished code so we can minimize conflicts (and I minimize rebase headaches). I'll try to commit more granularly now as well.

lamarqua commented 6 years ago

w.r.t SDL_assert, yeah I'd seen that, I'll switch to that for the final version, I just don't like asserts that pop up modal dialogs for my workflow since I have the test autorunning in a terminal after rebuilds and that tends to capture focus and sometimes crash my terminal :)

flibitijibibo commented 6 years ago

For VS2010 we’ll just stick to 32-bit since that’s all that’s free for Windows peoples without modern VS; for official FNA builds we actually compile with MinGW-w64 since it’s easier to ship without having msvcrt dependencies and 64-bit support is a free bonus.

Good catch with that random value in the middle - maybe they use it when doing REDIRECT_LFE or ZEROCENTER, dunno.

Binary compatibility and accuracy is a definite must, especially since we’re not doing anything to extend the spec at all. A packed struct is one possibility but this seems like a lot of overthinking for what amounts to about 5 number values. Think of it like DXVK, where we want this to eventually be a drop-in library that even general users can apply.

Let’s merge the validation stuff toward the end; it’s definitely good that we have boundaries but the matrix calculation is priority number one and that will need to take precedence over error checking since, in the case of FNA, the input data is always valid. The way I’ll probably merge it, should it be separate, is matrix calc first, validation later second. And the validation layer can work however’s best while you’re working on the matrix stuff.

I wonder if it’d help to ask the OpenAL mailing list for research on this; if it’s anything like doppler calculation there’s a good chance it’ll just perfectly align, and worst case, it’ll at least give us a foundation to tweak and slowly get to accuracy rather than build the whole house of cards with one throw.

flibitijibibo commented 6 years ago

Perhaps this environment variable would be useful?

https://hg.libsdl.org/SDL/file/2ad9729d3975/src/SDL_assert.c#l189

This lets you get the debug output while also setting a default behavior (probably “break”).

flibitijibibo commented 6 years ago

Something that might be worth looking at: @jarikomppa has some 3D audio stuff in SoLoud:

https://github.com/jarikomppa/soloud/blob/master/src/core/soloud_core_3d.cpp

Of particular interest is the output matrix math; cones aren't there but this might be a good start to at least get basic levels involved (especially since FNA doesn't use cones by default anyway). Once we get cones done (which I believe @bartwe needs for Staxel?) maybe we can send that stuff back to them so both of us can get something out of this.

lamarqua commented 6 years ago

So I took the weekend off, but I did have a look at OpenAL soft as you mentioned and they do exactly what I thought about doing (the obvious lerp), and then I had another look at the X3DAudio.h header (which has a lot of stuff that's not documented on MSDN...) and it did say that it's supposed to be linearly interpolated, so I don't understand what they do there :man_shrugging:

I did finish implementing cones today and what I have tested works OK (although I want to add some more tests and stress some of the extreme values). For "normal" InnerAngle/OuterAngle values the difference between the "real" linear interpolation and whatever MS is doing isn't too bad, but the "extreme" cones have quite a lot of difference. I'll show you the plotted curves tomorrow. I've thought about the problem and I think in the worst case it shouldn't be too hard to just go from simple lerp to a tricubic interpolation using a rough sampling of the parameter space (and storing a LUT into the binary). It wouldn't be that costly in terms of CPU and could give really good accuracy. Or the other solution is to figure out what they are doing... (My theory is that they messed up some trig / geometric computation.)

After finishing cones, I started integrating the custom volume curves stuff and working on multi-position emitters. I expect to finish both tomorrow, minus perhaps the testing.

I've also fixed a bunch of errors in the checks and the emitter-angle calculation that was wrong. It's getting a little late here so I'm going to bed, but I'll keep you up to date with the rest of my work tomorrow.

lamarqua commented 6 years ago

The last big piece, "spatialization" (diffusing to the right speakers) is in!

It was a bit of a mouthful to handle, due to several things; in particular I had to recreate the info for every configuration from scratch because it can't necessarily be deduced from the headers. (The SPEAKER_STEREO configuration does not have FRONT_LEFT and FRONT_RIGHT speakers, but SIDE_LEFT and SIDE_RIGHT.) The FindSpeakerAzimuths function also gave me a bit of a headache because of the singularity at the 0 / 2PI azimuth and tricky index arithmetic. I tried to keep it as simple as possible but it could use some more documentation. The rest was standard vector math: projecting the listenerToEmitter vector down to the plane defined by the listener's top vector, and figuring out the azimuth there to see the two speakers between which the emitter lies.

I have only done preliminary tests so far, for example this one which is creating an emitter with an azimuth varying from 0 to 2PI by PI/8 increments, and it shows the proper result. I added support for ZERO_CENTER since it was simply a matter of handling it inside FindSpeakerAzimuths.

One of the things that I expect to be different is the interpolation between two speakers for the spatialization / diffusion step, that is, given an emitter azimuth, and two azimuths for the speakers between which the emitter lies, how much gain do we give to each speaker. I have plotted the X3DAudio curves and it seems that they do not follow a linear interpolation here and they are just slightly non-linear.

Here's the curve in question: index

I have tried a bunch of things but I've had no success in figuring out which formula they use. I plan to dig more into that and provide, under an #ifdef, both the (fast) linear version and possibly an improved version. I have a bunch of ideas for how they did it, but if I can't find, a simple cubic interpolation might give good results. One thing that I tested is that this interpolation curve is independent of the angle between the two speakers, so whether the angle between the two speakers is wide or narrow, the curve is the same when normalized by the angular difference between the two speakers.

So whatever thing they're doing, this is not the same as the interpolation problem that I uncovered for the cones, which depend on the angles. Speaking of that, I have some ideas for what they are doing wrong (because their docs clearly say it's supposed to be linear): I'm thinking they're doing some normalization / interpolation of the vectors out of order. I'll take some time to test that theory as well.

Prior to the spatialization step, I landed the commit for custom curves, and they worked well in my experiments, but they could use more testing.

I have done a bunch of refactoring and testing on other parts of the code, and strengthened some checks.

I also figured out a much more likely explanation for the mystery handle field, which I thought to be a test of having a center and LF speaker, but is actually, the row index of the LF channel, if there is one, into the output matrix, and -1 if there isn't. I realized this when it was apparent in the look up table I use to store information on which speaker maps to which row. I'm not using the mystery field right now, as I think the code is clearer with all the info needed with all the information grouped in one place.

The remaining unimplemented features are:

Unless there's something ridiculous going on, I am very optimistic that I can finish implementing them quickly, as I have carefully laid out all the ground work necessary for them in the current code. (Although testing properly will take time.)

There is a whole lot of cleaning to do in the source code as well, and I have marked quite many of them with TODOs. In particular I'd like to double check the handling of small and null distances, because I think a lot of the code isn't compliant to the original X3DAudio behaviour. (I know that Doppler and Emitter Angle calculations are also wrong in some of these cases.)

There's also the stylistic cleaning to do, "wrap-lining" down long comments and code lines to fit your style (I've been lazy on that front), and stuff like star pointer convention and opening and closes braces.

I added and exported a check routine inside F3DAudio.h/c to allow me to test some of the code during development, and I'm thinking of moving some of the tests I have in smalltool--the ones that don't rely on X3DAudio as an oracle--in there, and creating a small executable driver. Do you have any plan for some kind of test suite for the library? Do you want me to follow something specifically?

There remains a lot of testing to be done to make sure that this is production-ready. I have done simple testing of all the functionality, mostly in isolation, but we'll probably want to test all combinations of the features at some point, perhaps in an automated way. Some kind of automation would be nice, and especially testing both the debug checks, and the extrema values for the parameters would certainly be useful.

Hmm, I think that's all I wanted to say. I'll wrap up the implementation part for the last few remaining pieces (hopefully I'll be done by Sunday), and then I'll do whatever cleanup you think is necessary for you to merge my code upstream, after which I can work on validation and testing.

lamarqua commented 6 years ago

Complementary info: here's a view of what X3DAudio does for cone interpolation (i.e. how to interpolate between InnerValue = 1.0f and OuterValue = 0.5f given an angle between InnerAngle and OuterAngle.), for different angles: (Yellow is a proper lerp, and it's what my implementation currently returns, and what X3DAudio should return...) interm interm2 interm3 small extreme

The last one is a bit extreme, but it's for a cone that spans 2PI (the whole space) for OuterAngle, and PI (half-space) for InnerAngle. I'm not sure these kinds of cone are used much...

flibitijibibo commented 6 years ago

This is great! I'm sure it'll be a while before we know exactly what's happening inside X3DAudio but if we can at least get the right sounds out of the right speakers I'll be happy.

I'm surprised there isn't a SPEAKER_HEADPHONES to deal with that SPEAKER_STEREO problem - there might have to be an extension on our end to deal with that (SPEAKER_REALSTEREO_EXT?).

As for testing, what I can do is make a test/test3d.cpp file next to testparse where we just duplicate Microsoft's 3D XAudio2 sample project but with ImGui and some more options related to the various parameters (and of course we can dump the DSP_SETTINGS output to an info window). I can take care of that though, for now just make sure it works with your tests and I'll make the ImGui test when it's all completed. For a "real" test we would have to write something like a fuzzer that throws literally everything at both F3D and X3D and compares every possible value, but that'll only be useful when we're intending to be 100% identical. For now, I'm just happy with it sounding right.

flibitijibibo commented 6 years ago

Forgot to do weekly updates! Was working on Switch stuff this past week so I lost track, but I can happily say FAudio works on Switch now...

Anything new to report?

lamarqua commented 6 years ago

The remaining unimplemented features are:

  • LFE channels and REDIRECT_TO_LFE
  • Multi-channel emitters
  • InnerRadius / InnerRadiusAngle Unless there's something ridiculous going on, I am very optimistic that I can finish implementing them quickly, as I have carefully laid out all the ground work necessary for them in the current code.

I am eating my own words :-) There's a lot of ridiculous things going on when it comes to InnerRadius and InnerRadiusAngle. I know they technically weren't in scope, but before working on this I had noticed that even if InnerRadius is set to 0, X3DAudio considers that there's a small radius (around 1e-7) that behaves as if it was set to that value. Before that, I handled the problem of a null distance -- when the distance is zero you have to transition from two speakers to all -- in an ad-hoc way, but it made the code messier and didn't match the original behaviour. So I dived a little more into how InnerRadius works. I'm not gonna do the whole story, but it involved staring at curves -- which of course, weren't linear -- long enough for them to reveal their secrets to me, and I figured out a clean approach yesterday. I could probably have skipped the whole InnerRadius thing but this would have meant leaving the unfaithful null distance behaviour in.

The way InnerRadius and speaker diffusion works is interconnected, so I had to do a pretty big refactor anyway to handle things more cleanly in the code. And handling multi-emitter channels is mostly free with decently factored code, but there's some funny business to handle when it comes to LF channels and LFE speakers. ZEROCENTER and REDIRECT_TO_LFE also come mostly for free so they'll be handled as well. (I handle them already pre-refactor.)

InnerRadiusAngle is another whole can of worms, and I will be punting on that one for now. I really don't understand Microsoft on that one. The implementation is just plainly wrong: it doesn't even remotely match what the docs said it should be doing. (An emitter that's inside the cone defined by the angle doesn't see any change, until it is way past inside. So the angle is a lie.) I wonder if there's a single shipping game in the world that even uses it.

Next order of business for me is to finish this ASAP, and send you a PR, so we can hopefully test my code in the wild. I don't expect any deep issues, and I'm pretty confident that my code handles things -- minus the accuracy problem, where I do lerps instead of Microsoft's convoluted curves -- is faithful to the behaviour of the original. I test all my code at every step, but there's a combinatorial explosion of optional features that make it hard to test it all at once manually. I might have missed some corner cases that'll be work for automated validation later.

Note: I'm moving across the Atlantic (to Montréal!) in a week, and I'll be busy for roughly 15 days while I travel around and spend time at a conference in NYC. I want to ship this PR (and hopefully fairly clean code) before I leave, and once the dust settles down I'll be happy to work on validating and strengthening the code towards final, battle-tested production quality.

lamarqua commented 6 years ago

So I just sent the PR for a version that would be a good candidate for field testing; I think it fulfills the initial contract fairly well. I've done some manual testing (including the most general possible cases) and sound always comes out of the right speakers, with some differences due to the fact that I lerp everywhere instead of using whatever curves MS is using. Most of the time the difference is fairly minor, especially considering that these are gain values. (It's much more important perceptually that stuff comes out of the right speaker.) I fixed some minor issues that happen when the distance is zero in the Doppler and Emitter Angle code as well; and added some default values for when LPF / Reverb calculations are requested so that the output values are set properly if the relevant DSP_SETTINGS fields was uninitialized. I have triple checked that no calculations give out NaN / Infs, but I might have missed something, so this is where setting up an automated test framework might be useful. Considering that there are differences in the values that come out of the matrix, automated testing will have to be lenient if we do a comparison with the X3DAudio "oracle". There might be stuff that's worth testing on its own (like checking for NaNs).

On the TODO list, there's some stuff I wanna clean up when I have the time:

I think this is a solid first release though, and as I said I'll be busy in the short-term, but I'm happy to keep working on this on the side if you'd like to.

lamarqua commented 6 years ago

Here's a dump of a general-ish case: first DSP_SETTINGS is X3DAudio, second one is my implementation.

        Dumping emitter                                                                            
ChannelCount: 6                                                                                    
ChannelRadius: 10.000000                                                                           
ChannelAzimuths: [6.283185 0.000000 0.010000 2.120000 1.570796 3.141593 ]                          
Dumping cone:                                                                                      
InnerAngle: 0.250000 PI                                                                            
OuterAngle: 0.250000 PI                                                                            
InnerVolume: 0.900000                                                                              
OuterVolume: 0.600000                                                                              
InnerLPF: 0.000000                                                                                 
OuterLPF: 0.000000                                                                                 
InnerReverb: 0.000000                                                                              
OuterReverb: 0.000000                                                                              
Front: { 0.000000       0.000000        -1.000000 }                                                
Top:   { 0.000000       1.000000        0.000000 }                                                 
Pos:   { 0.420952       10.000000       1.016268 }                                                 
Vel:   { 10.000000      -10.000000      0.000000 }                                                 
InnerRadius: 0.000000                                                                              
InnerRadiusAngle: 0.000000                                                                         
VolumeCurve: (NULL)                                                                                
LFECurve: (NULL)                                                                                   
LPFDirectCurve: (NULL)                                                                             
LPFReverbCurve: (NULL)                                                                             
ReverbCurve: (NULL)                                                                                
CurveDistanceScaler: 1.000000                                                                      
DopplerScaler: 0.000000                                                                            
        Dumping X3DAUDIO_DSP_SETTINGS                                                              
SrcChannelCount: 6                                                                                 
DstChannelCount: 8                                                                                 
Matrix coefficients:                                                                               
SPEAKER_7POINT1                                                                                    
L  [ 0.000000   0.000000        0.000000        0.000000        0.000000        0.002292        ]  
R  [ 0.000000   0.000000        0.000000        0.000000        0.000000        0.000000        ]  
C  [ 0.000000   0.000000        0.000000        0.000000        0.000000        0.000000        ]  
LF [ 0.049700   0.000000        0.000000        0.000000        0.000000        0.000000        ]  
BL [ 0.000000   0.002525        0.002527        0.040348        0.027376        0.047408        ]  
BR [ 0.000000   0.047175        0.047174        0.009353        0.022325        0.000000        ]  
LC [ 0.000000   0.000000        0.000000        0.000000        0.000000        0.000000        ]  
RC [ 0.000000   0.000000        0.000000        0.000000        0.000000        0.000000        ]  
Delay times: (NULL)                                                                                
LPFDirectCoefficient: 0.750000                                                                     
LPFReverbCoefficient: 0.750000                                                                     
ReverbLevel: 0.000000                                                                              
DopplerFactor: 1.000000                                                                            
EmitterToListenerAngle: 0.467790 PI                                                                
EmitterToListenerDistance: 10.0603                                                                 
EmitterVelocityComponent: 9.52162                                                                  
ListenerVelocityComponent: -49.7002                                                                

        Dumping X3DAUDIO_DSP_SETTINGS                                                              
SrcChannelCount: 6                                                                                 
DstChannelCount: 8                                                                                 
Matrix coefficients:                                                                               
SPEAKER_7POINT1                                                                                    
L  [ 0.000000   0.000000        0.000000        0.000000        0.000000        0.001529        ]  
R  [ 0.000000   0.000000        0.000000        0.000000        0.000000        0.000000        ]  
C  [ 0.000000   0.000000        0.000000        0.000000        0.000000        0.000000        ]  
LF [ 0.049700   0.000000        0.000000        0.000000        0.000000        0.000000        ]  
BL [ 0.000000   0.001692        0.001693        0.042493        0.028055        0.048171        ]  
BR [ 0.000000   0.048008        0.048007        0.007207        0.021646        0.000000        ]  
LC [ 0.000000   0.000000        0.000000        0.000000        0.000000        0.000000        ]  
RC [ 0.000000   0.000000        0.000000        0.000000        0.000000        0.000000        ]  
Delay times: (NULL)                                                                                
LPFDirectCoefficient: 0.750000                                                                     
LPFReverbCoefficient: 0.750000                                                                     
ReverbLevel: 0.000000                                                                              
DopplerFactor: 1.000000                                                                            
EmitterToListenerAngle: 0.467790 PI                                                                
EmitterToListenerDistance: 10.0603                                                                 
EmitterVelocityComponent: 9.52162                                                                  
ListenerVelocityComponent: -49.7002                                                                
lamarqua commented 6 years ago

Ah, frack, I just realized I forgot to clean-up long lines in my PR.

flibitijibibo commented 6 years ago

Neat, will check this out tomorrow morning!

flibitijibibo commented 6 years ago

Marking this as finished! We still haven't merged just yet (waiting on Bart's approval) but short of a catastrophe I don't think this will go on for another day or two...