Quantcast
Viewing all 874 articles
Browse latest View live

Updated Wiki: Effects

This is a native Direct3D 11 implementation of the five built-in effects from XNA Game Studio, providing identical functionality and API:
  • BasicEffect supports texture mapping, vertex coloring, directional lighting, and fog
  • AlphaTestEffect supports per-pixel alpha testing
  • DualTextureEffect supports two layer multitexturing (for lightmaps or detail textures)
  • EnvironmentMapEffect supports cubic environment mapping
  • SkinnedEffect supports skinned animation with up to 72 bones and 1, 2, or 4 bone influences per vertex.
DirectX Tool Kit also includes the following built-in effects:
  • DGSLEffect which supports the Visual Studio Shader Designer (DGSL) content pipeline both with and without skinned animation with up to 8 textures.
See also EffectFactory

Image may be NSFW.
Clik here to view.
EffectsExample.jpg


Related tutorials:Simple rendering, Using advanced shaders, Applying lightmaps, Creating custom shaders with DGSL, Writing custom shaders

Header

#include <Effects.h>

Initialization

The built-in effect constructors requires a Direct3D 11 device.

std::unique_ptr<BasicEffect> effect(new BasicEffect(device));
For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr or std::shared_ptr

The DGSLEffect constructor takes a pixelShader instance. If null, it uses one of the three built-in default materials: Unlit, Lambert, and Phong. This class assumes the pixel shader provided is signature compatible with the built-in DGSL vertex shader, and will work for the feature level of the device.

std::unique_ptr<DGSLEffect> effect(new DGSLEffect(device,pixelShader));

Set effect parameters

effect->SetWorld(world);
effect->SetView(view);
effect->SetProjection(projection);

effect->SetTexture(cat);
effect->SetTextureEnabled(true);

effect->EnableDefaultLighting();

The built-in effects default to a standard lighting and color set
  • Matrices are all set to identity
  • Ambient, diffuse, and emissive colors default to black
  • Fully opaque (alpha set to 1)
  • Specular defaults to white with a power of 16
  • Default lights are set to white with no specular highlight and a default direction of [0, -1, 0]. All lights are disabled by default.
The EnableDefaultLighting method sets up a standard three light setup (key, fill, and back) with some ambient light and some soft specular highlights.

Note: To disable specular highlights on a material with BasicEffect, SkinnedEffect and DGSLEffect; DisableSpecular sets the specular color to black [0,0,0] and the specular power to 1. A specular power of 0 can result in strange rendering artifacts.
  • EnvironmentMapEffect always uses vertex lighting, but does not support per-pixel lighting
  • SkinnedEffect always uses vertex or per-pixel lighting
  • DGSLEffect always uses per-pixel lighting if lighting is supported by the effect. It also supports a UV Transform for the texture coordinates, viewport information, and a time variable which may or may not be used by a given DGSL pixel shader. Fog settings are not supported by this effect, but could be 'baked in' to a given DGSL pixel shader.

Draw using the effect

effect->Apply(deviceContext);

deviceContext->IASetInputLayout(...);
deviceContext->IASetVertexBuffers(...);
deviceContext->IASetIndexBuffer(...);
deviceContext->IASetPrimitiveTopology(...);
deviceContext->PSSetSamplers(...);

deviceContext->DrawIndexed(...);

DualTextureEffect and EnvironmentMapEffect require a texture sampler in both slots 0 and 1. DGSLEffect can require up to 8 texture samplers. The other textured effects only require a texture sampler in slot 0. GeometricPrimitive and SpriteBatch only set a texture sampler in slot 0 by default. Model sets a sampler in slots 0 and 1.

DualTextureEffect requires two sets of texture coordinates, while the other textured effects only require a single set. GeometricPrimitive, Model loaded from VBO or CMO, and SpriteBatch only define a single set of texture coordinates in their vertex buffers so they can't be used with DualTextureEffect.

Input Layout

To create an input layout matching the effect vertex shader input signature:

// First, configure effect parameters the way you will be using it. Turning// lighting, texture map, or vertex color on/off alters which vertex shader// is used, so GetVertexShaderBytecode will return a different blob after// you alter these parameters. If you create an input layout using a// BasicEffect that had lighting disabled, but then later enable lighting,// that input layout will no longer match as it will not include the// now-necessary normal vector.voidconst* shaderByteCode;
size_t byteCodeLength;

effect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength);

device->CreateInputLayout(VertexPositionNormalTexture::InputElements,
                          VertexPositionNormalTexture::InputElementCount,
                          shaderByteCode, byteCodeLength,
                          pInputLayout);

For the built-in effects, the trigger for needing to create a new layout would be:
  • Enabling or disabling lighting (which requires a vertex normal)
  • Enabling or disabling per vertex color (which requires a vertex color value)
  • Enabling or disabling textures (which requires vertex texture coordinates)
  • Changing effect class (BasicEffect <-> SkinnedEffect or DGSLEffect)
DGSLEffect is typically used with VertexPositionNormalTangentColorTexture or VertexPositionNormalTangentColorTextureSkinning.

Interfaces

The built-in effects support a number of different settings, some of which are organized into more 'generic' interfaces.
  • IEffect is the basic interface for all effects which includes applying it to the device context and obtaining the shader information needed to create a Direct3D 11 input layout with a signature that matches the effect's shader. Remember that a given Effect instance could return a different shader based on internal state.
  • IEffectMatrices is the interface for setting an effects' world, view, and projection matrices. All the built-in effects support this interface.
  • IEffectLights is the interface for controlling the effects' lighting computations and settings. This is supported by BasicEffect, EnvironmentMapEffect, SkinningEffect, and DGSLEffect
  • IEffectFog is the interface to control the effects' fog settings. This is supported by BasicEffect, AlphaTestEffect, DualTextureEffect, EnvironmentMapEffect, and SkinnedEffect.
  • IEffectSkinning is the interface to control skinned animation settings. This is supported by DGSLEffect and SkinnedEffect. This includes setting the bone transform matrices, and optimizing the number of bone influences per vertex to process (1, 2, or 4; defaults to 4).

Coordinate systems

The built-in effects work equally well for both right-handed and left-handed coordinate systems. The one difference is that the fog settings start & end for left-handed coordinate systems need to be negated (i.e. SetFogStart(6), SetFogEnd(8) for right-handed coordinates becomes SetFogStart(-6), SetFogEnd(-8) for left-handed coordinates).

Feature Level Notes

The built-in shaders are compiled using the vs_4_0_level_9_1 and ps_4_0_level_9_1 profiles to support all feature levels.

The compiled shaders are integrated into the DirectXTK library to avoid the need for runtime compilation, shader reflection, or deploying compiled shader binary files (.cso).

The DGSLEffect includes built-in support for the three default materials: Unlit, Lambert, and Phong. These built-in DGSL materials support all feature levels, as does the built-in DGSL-compatible vertex shader. Visual Studio Shader Designer (DGSL) .DGSL.CSO files support Feature Level 10.0+. The DGSLEffectFactory automatically attempts to locate a suitably named standard .CSO on Feature Level 9.x which is a manually created fall-back shader. The method for creating these fall-back shaders is to use "Export to HLSL..." from the Visual Studio Shader Designer, then modify that .hlsl file so it will successfully compile with ps_4_0_level_9_1 or ps_4_0_level_9_3 (whichever is your minimum supported feature level).

Threading model

Creation is fully asynchronous, so you can instantiate multiple effect instances at the same time on different threads. Each instance only supports drawing from one thread at a time, but you can simultaneously draw on multiple threads if you create a separate effect instance per Direct3D 11 deferred context.
http://msdn.microsoft.com/en-us/library/windows/desktop/ff476892.aspx

Further reading

http://blogs.msdn.com/b/shawnhar/archive/2010/04/28/new-built-in-effects-in-xna-game-studio-4-0.aspx
http://blogs.msdn.com/b/shawnhar/archive/2010/04/30/built-in-effects-permutations-and-performance.aspx
http://blogs.msdn.com/b/shawnhar/archive/2010/04/25/basiceffect-optimizations-in-xna-game-studio-4-0.aspx
http://blogs.msdn.com/b/shawnhar/archive/2008/08/22/basiceffect-a-misnomer.aspx
http://blogs.msdn.com/b/shawnhar/archive/2010/08/04/dualtextureeffect.aspx
http://blogs.msdn.com/b/shawnhar/archive/2010/08/09/environmentmapeffect.aspx
http://blogs.msdn.com/b/chuckw/archive/2012/05/07/hlsl-fxc-and-d3dcompile.aspx

Updated Wiki: IEffect

This is the abstract interfaced implemented by all effects in DirectX Tool Kit, and is typically used as the 'base' reference. For example, ModelMeshPart defines a reference to an effect as

std::shared_ptr<IEffect> effect;

Drawing

The Apply method is used to set up a device context for drawing with the effect. This includes setting up the appropriate vertex and pixel shaders (and potentially other shader stages as well), and updating and setting the required constant buffer(s) consumed by these shaders.

The caller is assumed to handle setting the appropriate input layout, vertex and index buffer, primitive topology, blend state, depth-stencil state, and rasterizer state. Texturing effects will also set the shader resources needed for the texturing modes it supports, but assumes the caller has set up the appropriate samplers.

Note: GeometricPrimitive and Model set the various state settings to reasonable defaults as part of their prepare and/or drawing methods. PrimitiveBatch only sets vertex buffer, index buffer, primitive topology leaving the rest of the device state vector up to the caller.

CommonStates states(device);

...

deviceContext->OMSetBlendState(state.Opaque(), nullptr, 0xFFFFFFFF);
deviceContext->OMSetDepthStencilState(states.DepthDefault(), 0);
deviceContext->RSSetState( states.CullCounterClockwise() );

auto samplerState = states.LinearClamp();
deviceContext->PSSetSamplers(0, 1, &samplerState);

...

effect->Apply( devicecontext );

deviceContext->IASetInputLayout(inputLayout);

auto vertexBuffer = mVertexBuffer.Get();
UINT vertexStride = sizeof(VertexType);
UINT vertexOffset = 0;
deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &vertexStride, &vertexOffset);

deviceContext->IASetIndexBuffer(mIndexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0);

deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

deviceContext->DrawIndexed(mIndexCount, 0, 0);

Input Layouts

Direct3D 11 requires that an input layout is used that matches the signature of the vertex shader used for rendering. Since effect instances are dynamic and use many different shaders depending on various settings, this requires that the caller have access to the correct vertex shader code to create the input layout. The GetVertexShaderBytecode method handles this request.

// Setup effect and parameters

...

voidconst* shaderByteCode;
size_t byteCodeLength;

effect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength);

device->CreateInputLayout(VertexPositionNormalTexture::InputElements,
                          VertexPositionNormalTexture::InputElementCount,
                          shaderByteCode, byteCodeLength,
                          pInputLayout);

Some dynamic state changes in an effect only impact contstant buffer content, which is easily updated. Other state changes can result in a different shader permutation, in which case the the associated input layouts may no longer bind (you'll get a Direct3D 11 error at runtime if this occurs).

For the built-in effects, the trigger for needing to create a new layout would be:
  • Enabling or disabling lighting (which requires a vertex normal)
  • Enabling or disabling per vertex color (which requires a vertex color value)
  • Enabling or disabling textures (which requires vertex texture coordinates)
  • Changing effect class (BasicEffect <-> SkinnedEffect or DGSLEffect)

Built-in Effect Notes

All built-in effects require the SV_Position semantic.

AlphaTestEffect
This effect requires TEXCOORD0, and COLOR if per-vertex colors are enabled,

BasicEffect
This effect requires NORMAL if lighting is enabled, COLOR if per-vertex colors are enabled, and TEXCOORD0 if texturing is enabled.

DGSLEffect
This effect requires NORMAL, TANGENT, and TEXCOORD0. If enableSkinning is true, it also requires BLENDINDICES and BLENDWEIGHT.

DualTextureEffect
This effect requires TEXCOORD0 and TEXCOORD1.

EnvironmentMapEffect
This effect requires NORMAL and TEXCOORD0.

SkinnedEffect
This effect requires NORMAL, TEXCOORD0, BLENDINDICES and BLENDWEIGHT.

Updated Wiki: SpriteFont

This is a native Direct3D 11 implementation of a bitmap font renderer, similar to the SpriteFont type from XNA Game Studio, plus a command line tool (MakeSpriteFont) for building fonts into bitmap format. It is less fully featured than Direct2D and DirectWrite, but may be useful for those who want something simpler and lighter weight.

SpriteFont is particularly useful for the Windows phone 8.0 and Xbox One XDK platforms that lack support for Direct2D and DirectWrite

Image may be NSFW.
Clik here to view.
SpriteFontExample.jpg


Related tutorial:Drawing text

Header

#include <SpriteFont.h>

Initialization

The SpriteFont class requires a SpriteBatch instance and a .spritefont bitmap file.

std::unique_ptr<SpriteBatch> spriteBatch(new SpriteBatch(deviceContext));
std::unique_ptr<SpriteFont> spriteFont(new SpriteFont(device, L"myfile.spritefont"));
For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr or std::shared_ptr

Simple drawing

spriteBatch->Begin();
spriteFont->DrawString(spriteBatch.get(), L"Hello, world!", XMFLOAT2(x, y));
spriteBatch->End();
The DrawString method has several overloads with parameters controlling color, rotation, origin point, scaling, horizontal or vertical mirroring, and layer depth. These work the same way as the equivalent SpriteBatch::Draw parameters.

Constructors

SpriteFont has three constructors:
  • Pass a filename string to read a binary file created by MakeSpriteFont
  • Pass a buffer containing a MakeSpriteFont binary that was already loaded some other way
  • Pass an array of Glyph structs if you prefer to entirely bypass MakeSpriteFont

Helpers

In addition to DrawString with various overloads, SpriteFont includes the following helpers:
  • MeasureString which returns the size of the given string in pixels.
Note: The string size is computed from the origin to the rightmost pixel rendered by any character glyph. This has the effect of ignoring 'trailing spaces'. See work item 674 for more details. https://directxtk.codeplex.com/workitem/674.
  • ContainsCharacter tests to see if a given character is defined in the font
  • FindGlyph can be used to obtain size and other metadata for a character in the font. Note if the character is not defined in the font and there is no default character, this function will throw a C++ exception.
  • GetSpriteSheet returns a reference to the texture used for the sprite font for custom rendering.

Default character

If you try to draw or call MeasureString with a character that is not included in the font, by default you will get an exception. Use SetDefaultCharacter to specify some other character that will be automatically substituted in place of any that are missing. You can also use GetDefaultCharacter to obtain the current default which is also defined as part of the font.

Special characters

SpriteFont will respect new line characters (\n - ASCII character 10), and ignores carriage returns (\r - ASCII character 13). The distance moved for a new line is defined in the font and can be accessed with GetLineSpacing / SetLineSpacing.

There is no special handling for the bell character (\a - ASCII character 7), backspace (\b - ASCII character 8), horizontal tab (\t - ASCII character 9), vertical tab (ASCII character 11), form feed (\f - ASCII character 12), or escape (ASCII character 27). These are all treated as standard characters and if it is missing from the .spritefont, they will all render as the default character or generate an exception if there is no default character defined

Localization

This implementation supports sparse fonts, so if you are localizing into languages such as Chinese, Japanese, or Korean, you can build a spritefont including only the specific characters needed by your program. This is usually a good idea for CJK languages, as a complete CJK character set is too large to fit in a Direct3D texture! If you need full CJK support, DrectWrite would be a better choice if available on your target platform. SpriteFont does not support combining characters or right-to-left (RTL) layout, so it will not work for languages with complex layout requirements such as Arabic or Thai.

ASCII

The default character region for MakeSpriteFont from 32 to 127 covers the standard 7-bit range. For example, here is a C++ Unicode string for the printable characters (this would be an ASCII string if you remove the L prefix).

L" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmn
opqrstuvwxyz{|}~"

http://ascii-table.com/ascii.php

Extended ASCII

If you are wanting to render an 'extended ASCII' string with SpriteFont, you need to capture the full set of characters which are not contiguous in Unicode (see MakeSpriteFont for details). You then need to convert your 'extended ASCII' string to Unicode using Code page 437 before calling DrawString.

char ascii[...];
wchar_t unicode[...];
if (!MultiByteToWideChar(437, MB_PRECOMPOSED,
    ascii, length-of-ascii-string,
    unicode, length-of-unicode-string))
{
    // Error
}
spriteFont->DrawString(spriteBatch.get(), unicode, ...)

For example, here is a C++ Unicode string with the full extended ASCII IBM PC character set from 128 to 255:

L"\x00C7\x00FC\x00E9\x00E2\x00E4\x00E0\x00E5\x00E7\x00EA
\x00EB\x00E8\x00EF\x00EE\x00EC\x00C4\x00C5\x00C9\x00E6\x00C6\x00F4\x00F6\x00F2\x
00FB\x00F9\x00FF\x00D6\x00DC\x00A2\x00A3\x00A5\x20A7\x0192\x00E1\x00ED\x00F3\x00
FA\x00F1\x00D1\x00AA\x00BA\x00BF\x2310\x00AC\x00BD\x00BC\x00A1\x00AB\x00BB\x2591
\x2592\x2593\x2502\x2524\x2561\x2562\x2556\x2555\x2563\x2551\x2557\x255D\x255C\x
255B\x2510\x2514\x2534\x252C\x251C\x2500\x253C\x255E\x255F\x255A\x2554\x2569\x25
66\x2560\x2550\x256C\x2567\x2568\x2564\x2565\x2559\x2558\x2552\x2553\x256B\x256A
\x2518\x250C\x2588\x2584\x258C\x2590\x2580\x03B1\x00DF\x0393\x03C0\x03A3\x03C3\x
00B5\x03C4\x03A6\x0398\x03A9\x03B4\x221E\x03C6\x03B5\x2229\x2261\x00B1\x2265\x22
64\x2320\x2321\x00F7\x2248\x00B0\x2219\x00B7\x221A\x207F\x00B2\x25A0\x00A0"

http://ascii-table.com/ascii-extended-pc-list.php
http://en.wikipedia.org/wiki/Code_page_437

Xbox One exclusive apps MultiByteToWideChar does not support codepage 437.

Feature Levels

The Sprite Font implementation is compatible with all feature levels. The primary limitation is on the size of the sprite sheet texture which should fit into the limits for known feature levels (i.e. to support all feature levels, it should be no larger than 2048 x 2048).

Further reading

http://blogs.msdn.com/b/shawnhar/archive/2007/04/26/bitmap-fonts-in-xna.aspx
http://blogs.msdn.com/b/shawnhar/archive/2011/01/12/spritebatch-billboards-in-a-3d-world.aspx

Updated Wiki: WaveBank

WaveBank is a container class for an XACT-style wave bank that contains individual waves packaged together for more efficient loading and memory management. Sounds in the wave bank can then be played back as one-shot sounds or via SoundEffectInstance.

See XWBTool for more information on building .xwb files.

Note: DirectXTK for Audio uses XAudio 2.8 or XAudio 2.7. It does not make use of the legacy XACT Engine, XACT Cue, or XACT SoundBank.

Header

#include <Audio.h>

Initialization

std::unique_ptr<WaveBank> wb( new WaveBank( audEngine.get(), L"wavebank.xwb" ) );

For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr or std::shared_ptr

Note that in-memory banks may still be loading the wave data asynchronously after the return of this constructor. You can see if the wave data has completed loading by calling IsPrepared (). If you call Play or CreateInstance before the wave data has loaded, then the thread will wait until the load is complete before returning.

Play one-shot sounds

To play a sound in the bank as a 'fire and forget' sound:

wb->Play( index );

index is 0-based
To play the sound in the bank as a 'fire and forget' sound with volume, a pitch-shift, and/or pan setting:

wb->Play( index, volume, pitch, pan );

volume default is 1
pitch ranges from -1 to +1, playback defaults to 0 (which is no pitch-shifting)
pan -1 is fully left, +1 is fully right, and 0 is balanced.
If the wave bank contains 'entry friendly names', you can also use them to trigger a one-shot:

wb->Play( "Bang" );
wb->Play( "Bang", 0.8f, 0.f, 1.f );

You can also make use of the C/C++ header generated by XWBTool or XACTBLD3 to avoid 'magic numbers' in your code:

#include "wavebank.h"

wb->Play( XACT_WAVEBANK_WAVEBANK_BANG );

Note a C++ exception is thrown if attempting to play a one-shot sound from a streaming wavebank.

If the specified index or name is not found, then no one-shot is played and there is no C++ exception thrown.

Playing the sound

To play a sound with full control, looping, and dynamic pitch-shifting/volume control/pan settings:

auto effect = wb->CreateInstance( 2 );
if ( !effect )
    // Index not found in wave bank

To play a sound with positional 3D audio:

auto effect = wb->CreateInstance( 2, SoundEffectInstance_Use3D
                | SoundEffectInstance_ReverbUseFilters);
if ( !effect )
    // Index not found in wave bank

If the wave bank contains 'entry friendly names', you can also use them to create an instance:

auto effect = wb->CreateInstance( "Bang" );
if ( !effect )
    // Name not found in wave bankauto effect = wb->CreateInstance( "Bang", SoundEffectInstance_Use3D
                | SoundEffectInstance_ReverbUseFilters);
if ( !effect )
    // Name not found in wave bank

You can also make use of the C/C++ header generated by XWBTool or XACTBLD3 to avoid 'magic numbers' in your code:

#include "wavebank.h"auto effect = wb->CreateInstance( XACT_WAVEBANK_WAVEBANK_BANG );
if ( !effect )
    // Index not found in wave bankauto effect = wb->CreateInstance( XACT_WAVEBANK_WAVEBANK_BANG, SoundEffectInstance_Use3D
                | SoundEffectInstance_ReverbUseFilters);
if ( !effect )
    // Index not found in wave bank

Note a C++ exception is thrown if attempting to create a sound instance from a streaming wavebank.

If the specified index or name is not found, then CreateInstance returns a 'nullptr'. Client code should be sure to check for this condition. This is done because typically games do not consider missing audio content to be a fatal error during development.

See SoundEffectInstance.

Properties

  • IsPrepared ()
Returns true if the WaveBank has completed loading the wave data. For streaming buffers, they are always prepared after the constructor returns (only the metadata is loaded into memory).
  • IsInUse ()
Returns true if the WaveBank is currently playing as a one-shot or there are SoundEffectInstances referencing it.
  • IsStreamingBank ()
Returns true if the wave bank is a streaming type, false if it is an in-memory wave bank.
  • GetSampleSizeInBytes ( index )
Returns the size of the wave data in bytes. This will return 0 if the index is invalid.
  • GetSampleDuration ( index )
Returns the wave data duration in samples. This does not include any loops. This will return 0 if the index is invalid.
  • GetSampleDurationMS ( index )
Returns the wave data duration in milliseconds. This does not include any loops. This will return 0 if the index is invalid.
  • GetFormat ( index, WAVEFORMATEX* wfx, size_t maxsize )
Fills out a WAVEFORMATEX structure that describes the wave data format. This will return nullptr if the index is invalid, otherwise it returns a pointer to wfx. Since the format can be variable length, the caller provides the buffer and maxsize. At least 64 bytes is recommended as this is large enough to contain WAVEFORMAT, PCMWAVEFORMAT, WAVEFORMATEX, ADPCMWAVEFORMAT with coefficients, WAVEFORMATEXTENSIBLE, or a XMA2WAVEFORMATEX.
char formatBuff[ 64 ]; 
auto wfx = reinterpret_cast<WAVEFORMATEX*>( formatBuff );

wb->GetFormat( 2, wfx, 64 );
  • Find ( const char* name )
Returns the index, or -1 if not found or if there are no entry friendly names present in the wave bank.

Low-level access

FillSubmitBuffer is used internally, but can also be used when implementing your own XAudio2 source voices using the low-level interface access. Note that LoopCount is set to 0 by this function and should be set to a non-zero value by the caller. If looping is not desired, be sure to set LoopBegin and LoopLength to zero as well.

Care needs to be taken to ensure that any referenced WaveBank is not deleted while a source voice is actively playing back content from it or has pending buffers referencing it.

Content support

XAudio 2.8 on Windows 8.x and Windows phone support PCM and ADPCM formats (a variant of MS-ADPCM created by adpcmencode.exe in the Windows 8.x SDK or the legacy DirectX SDK).

XAudio 2.7 on Windows Vista or later via the legacy DirectX End-User Runtime Redistribution (aka DirectSetup) supports PCM, ADPCM, and xWMA (created by xwmaencode.exe in the legacy DirectX SDK).

XAudio on Xbox One supports PCM, ADPCM, and xWMA. Xbox One exclusive app developers can also make use of XMA2 (created by xma2encode.exe in the Xbox One XDK).

XACT-style wave banks support 8-bit and 16-bit PCM (i.e. not 32-bit IEEE float PCM), ADPCM, xWMA, and XMA2 content.

XWB File Format

To aid in debugging, here is a simple console program for dumping out the content of a XWB in a human-readable form.
xwbdump.cpp

Further reading

http://msdn.microsoft.com/en-us/library/windows/desktop/dd757712.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757713.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd743663.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757714.aspx
http://msdn.microsoft.com/en-us/library/bb203879(v=xnagamestudio.40).aspx

Updated Wiki: PrimitiveBatch

This is a helper for easily and efficiently drawing dynamically generated geometry using Direct3D 11 such as lines or trianges. It fills the same role as the legacy Direct3D 9 APIs DrawPrimitiveUP and DrawIndexedPrimitiveUP. Dynamic submission is a highly effective pattern for drawing procedural geometry, and convenient for debug rendering, but is not nearly as efficient as static buffers which is more suited to traditional meshes where the VBs and IBs do not change every frame. Excessive dynamic submission is a common source of performance problems in apps. Therefore, you should prefer to use Model, GeometricPrimitive, or your own VB/IB over PrimitiveBatch unless you really need the flexibility to regenerate the topology every frame.

PrimitiveBatch manages the vertex and index buffers for you, using DISCARD and NO_OVERWRITE hints to avoid stalling the GPU pipeline. It automatically merges adjacent draw requests, so if you call DrawLine 100 times in a row, only a single GPU draw call will be generated.

PrimitiveBatch is responsible for setting the vertex buffer, index buffer, and primitive topology, then issuing the final draw call. Unlike the higher level SpriteBatch helper, it does not provide shaders, set the input layout, or set any state objects. PrimitiveBatch is often used in conjunction with BasicEffect and the structures from VertexTypes, but it can work with any other shader or vertex formats of your own.

Related tutorial:Simple rendering

Header

#include <PrimitiveBatch.h>

Initialization

Initialize a PrimitiveBatch for drawing VertexPositionColor data

std::unique_ptr<PrimitiveBatch<VertexPositionColor>> primitiveBatch(new PrimitiveBatch<VertexPositionColor>(deviceContext));

For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr or std::shared_ptr

The default values assume that your maximum batch size is 2048 vertices arranged in triangles. If you want to use larger batches, you need to provide the additional constructor parameters (be sure to review the Feature Level limitations below).

PrimitiveBatch<T>( ID3D11DeviceContext* deviceContext, size_t maxIndices = DefaultBatchSize * 3, size_t maxVertices = DefaultBatchSize)

Effect and Input Layout

Setting up a suitable BasicEffect and input layout:

std::unique_ptr<BasicEffect> basicEffect(new BasicEffect(device));

basicEffect->SetProjection(XMMatrixOrthographicOffCenterRH(0, screenHeight, screenWidth, 0, 0, 1));
basicEffect->SetVertexColorEnabled(true);

voidconst* shaderByteCode;
size_t byteCodeLength;

basicEffect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength);

ComPtr<ID3D11InputLayout> inputLayout;

device->CreateInputLayout(VertexPositionColor::InputElements,
                          VertexPositionColor::InputElementCount,
                          shaderByteCode, byteCodeLength,
                          inputLayout.GetAddressOf() );

Drawing

CommonStates states( device );
deviceContext->OMSetBlendState( states.Opaque(), nullptr, 0xFFFFFFFF );
deviceContext->OMSetDepthStencilState( states.DepthNone(), 0 );
deviceContext->RSSetState( states.CullCounterClockwise() );

basicEffect->Apply(deviceContext);
deviceContext->IASetInputLayout(inputLayout.Get());

primitiveBatch->Begin();
primitiveBatch->DrawLine(VertexPositionColor(...), VertexPositionColor(...));
primitiveBatch->End();
PrimitiveBatch provides five drawing methods:
  • DrawLine(v1, v2)): Draws a single-pixel line between two vertices
  • DrawTriangle(v1, v2, v3): Draws a triangle between three vertices
  • DrawQuad(v1, v2, v3, v4): draws a quad from four corner vertices (submitted as two triangles)
  • Draw(topology, vertices, vertexCount): Draws an array of vertices with the given topology
  • DrawIndexed(topology, indices, indexCount, vertices, vertexCount): Draws an indexed array of vertices with a given topology.

Optimization

For best performance, draw as much as possible inside the fewest separate Begin/End blocks. This will reduce overhead and maximize potential for batching.

Ideally submit draws of the same topology to avoid flushing, and preferably use D3D_PRIMITIVE_TOPOLOGY_POINTLIST, D3D_PRIMITIVE_TOPOLOGY_LINELIST, or D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.

The PrimitiveBatch constructor allows you to specify what size index and vertex buffers to allocate. You may want to tweak these values to fit your workload, or if you only intend to draw non-indexed geometry, specify maxIndices = 0 to entirely skip creating the index buffer.

Feature Level Notes

In order to support all feature levels, PrimitiveBatch only supports 16-bit indices (DXGI_FORMAT_R16_UINT) which limits to a maximum of 65535 addressable vertices. This does not apply to non-indexed drawing when the PrimitiveBatch constructor is called with a maxIndices of 0.

Keep in mind there is a feature-level based limit on the maximum number of primitives in a single draw call, so the overall batch size needs to be under this limit. To support all feature levels, this should be 65535 or less lines or triangles in a single 'draw batch'.

http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx

http://blogs.msdn.com/b/chuckw/archive/2012/06/20/direct3d-feature-levels.aspx

Threading model

Each PrimitiveBatch instance only supports drawing from one thread at a time, but you can simultaneously submit primitives on multiple threads if you create a separate PrimitiveBatch instance per Direct3D 11 deferred context.
http://msdn.microsoft.com/en-us/library/windows/desktop/ff476892.aspx

Further Reading

http://blogs.msdn.com/b/shawnhar/archive/2012/10/12/directxtk-primitivebatch-helper-makes-it-easy-to-draw-user-primitives-with-d3d11.aspx

http://msdn.microsoft.com/en-us/library/windows/desktop/dn508285.aspx

Updated Wiki: PrimitiveBatch

This is a helper for easily and efficiently drawing dynamically generated geometry using Direct3D 11 such as lines or trianges. It fills the same role as the legacy Direct3D 9 APIs DrawPrimitiveUP and DrawIndexedPrimitiveUP. Dynamic submission is a highly effective pattern for drawing procedural geometry, and convenient for debug rendering, but is not nearly as efficient as static buffers which is more suited to traditional meshes where the VBs and IBs do not change every frame. Excessive dynamic submission is a common source of performance problems in apps. Therefore, you should prefer to use Model, GeometricPrimitive, or your own VB/IB over PrimitiveBatch unless you really need the flexibility to regenerate the topology every frame.

PrimitiveBatch manages the vertex and index buffers for you, using DISCARD and NO_OVERWRITE hints to avoid stalling the GPU pipeline. It automatically merges adjacent draw requests, so if you call DrawLine 100 times in a row, only a single GPU draw call will be generated.

PrimitiveBatch is responsible for setting the vertex buffer, index buffer, and primitive topology, then issuing the final draw call. Unlike the higher level SpriteBatch helper, it does not provide shaders, set the input layout, or set any state objects. PrimitiveBatch is often used in conjunction with BasicEffect and the structures from VertexTypes, but it can work with any other shader or vertex formats of your own.

Related tutorial:Simple rendering

Header

#include <PrimitiveBatch.h>

Initialization

Initialize a PrimitiveBatch for drawing VertexPositionColor data

std::unique_ptr<PrimitiveBatch<VertexPositionColor>> primitiveBatch(
    new PrimitiveBatch<VertexPositionColor>(deviceContext));

For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr or std::shared_ptr

The default values assume that your maximum batch size is 2048 vertices arranged in triangles. If you want to use larger batches, you need to provide the additional constructor parameters (be sure to review the Feature Level limitations below).

PrimitiveBatch<T>( ID3D11DeviceContext* deviceContext, size_t maxIndices = DefaultBatchSize * 3, size_t maxVertices = DefaultBatchSize)

Effect and Input Layout

Setting up a suitable BasicEffect and input layout:

std::unique_ptr<BasicEffect> basicEffect(new BasicEffect(device));

basicEffect->SetProjection(XMMatrixOrthographicOffCenterRH(0, screenHeight, screenWidth, 0, 0, 1));
basicEffect->SetVertexColorEnabled(true);

voidconst* shaderByteCode;
size_t byteCodeLength;

basicEffect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength);

ComPtr<ID3D11InputLayout> inputLayout;

device->CreateInputLayout(VertexPositionColor::InputElements,
                          VertexPositionColor::InputElementCount,
                          shaderByteCode, byteCodeLength,
                          inputLayout.GetAddressOf() );

Drawing

CommonStates states( device );
deviceContext->OMSetBlendState( states.Opaque(), nullptr, 0xFFFFFFFF );
deviceContext->OMSetDepthStencilState( states.DepthNone(), 0 );
deviceContext->RSSetState( states.CullCounterClockwise() );

basicEffect->Apply(deviceContext);
deviceContext->IASetInputLayout(inputLayout.Get());

primitiveBatch->Begin();
primitiveBatch->DrawLine(VertexPositionColor(...), VertexPositionColor(...));
primitiveBatch->End();
PrimitiveBatch provides five drawing methods:
  • DrawLine(v1, v2)): Draws a single-pixel line between two vertices
  • DrawTriangle(v1, v2, v3): Draws a triangle between three vertices
  • DrawQuad(v1, v2, v3, v4): draws a quad from four corner vertices (submitted as two triangles)
  • Draw(topology, vertices, vertexCount): Draws an array of vertices with the given topology
  • DrawIndexed(topology, indices, indexCount, vertices, vertexCount): Draws an indexed array of vertices with a given topology.

Optimization

For best performance, draw as much as possible inside the fewest separate Begin/End blocks. This will reduce overhead and maximize potential for batching.

Ideally submit draws of the same topology to avoid flushing, and preferably use D3D_PRIMITIVE_TOPOLOGY_POINTLIST, D3D_PRIMITIVE_TOPOLOGY_LINELIST, or D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.

The PrimitiveBatch constructor allows you to specify what size index and vertex buffers to allocate. You may want to tweak these values to fit your workload, or if you only intend to draw non-indexed geometry, specify maxIndices = 0 to entirely skip creating the index buffer.

Feature Level Notes

In order to support all feature levels, PrimitiveBatch only supports 16-bit indices (DXGI_FORMAT_R16_UINT) which limits to a maximum of 65535 addressable vertices. This does not apply to non-indexed drawing when the PrimitiveBatch constructor is called with a maxIndices of 0.

Keep in mind there is a feature-level based limit on the maximum number of primitives in a single draw call, so the overall batch size needs to be under this limit. To support all feature levels, this should be 65535 or less lines or triangles in a single 'draw batch'.

http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx

http://blogs.msdn.com/b/chuckw/archive/2012/06/20/direct3d-feature-levels.aspx

Threading model

Each PrimitiveBatch instance only supports drawing from one thread at a time, but you can simultaneously submit primitives on multiple threads if you create a separate PrimitiveBatch instance per Direct3D 11 deferred context.
http://msdn.microsoft.com/en-us/library/windows/desktop/ff476892.aspx

Further Reading

http://blogs.msdn.com/b/shawnhar/archive/2012/10/12/directxtk-primitivebatch-helper-makes-it-easy-to-draw-user-primitives-with-d3d11.aspx

http://msdn.microsoft.com/en-us/library/windows/desktop/dn508285.aspx

Updated Wiki: Model

This is a class hierarchy for drawing simple meshes with support for loading models from Visual Studio 3D Starter Kit .CMO files, legacy DirectX SDK .SDKMESH files, and .VBO files. It is an implementation of a mesh renderer similar to the XNA Game Studio Model, ModelMesh, ModelMeshPart design.

NOTE: Support for loading keyframe animations is not yet included.

A Model consists of one or more ModelMesh instances. The ModelMesh instances can be shared by multiple instances of Model. A ModelMesh instance consists of one or more ModelMeshPart instances.

Each ModelMeshPart references an index buffer, a vertex buffer, an input layout, an Effects instance, and includes various metadata for drawing the geometry. Each ModelMeshPart represents a single material to be drawn at the same time (i.e. a submesh).

Image may be NSFW.
Clik here to view.
ModelExample.jpg


Related tutorial:Rendering a model

Header

#include <Model.h>

Initialization

Model instances can be loaded from either .CMO, .SDKMESH, or .VBO files, or from custom file formats. The Model loaders take an EffectFactory instance to facilitate the sharing of Effects and textures between models. The default EffectFactory always returns built-in BasicEffect, SkinnedEffect, or DualTextureEffect instances. The DGSLEffectFactory can be used with .CMO files to load Visual Studio Shader Designer (DGSL) shaders through DGLSEffect instances.

Visual Studio 2012 and 2013 include a built-in content pipeline that can generate .CMO files from an Autodesk FBX, as well as DDS texture files from various bitmap image formats, as part of the build process. See the Visual Studio 3D Starter Kit for details. http://aka.ms/vs3dkitwin for Windows 8.1, http://aka.ms/vs3dkitwin80 for Windows 8.0.

DGSLEffectFactory fx( device );
// Can also use EffectFactory, but will ignore pixel shader material settingsauto teapot = Model::CreateFromCMO( device, L"teapot.cmo", fx );

For exception safety, the loaders return a std::unique_ptr.

The legacy DirectX SDK has an exporter that will generate .SDKMESH files from an Autodesk FBX. The latest version of this exporter tool can be obtained from http://go.microsoft.com/fwlink/?LinkId=226208

EffectFactory fx( device );
// Can also use DGSLEffectFactory, but will always use default materialsauto tiny = Model::CreateFromSDKMESH( device, L"tiny.sdkmesh", fx );

The VBO file format is a very simple geometry format containing a index buffer and a vertex buffer. It was originally introduced in the Windows 8.0 ResourceLoading sample, but can be generated by DirectXMesh's meshconvert utility http://go.microsoft.com/fwlink/?LinkID=324981

auto ship = Model::CreateFromVBO( device, L"ship.vbo" );

A Model instance also contains a name (a wide-character string) for tracking and application logic. Model can be copied to create a new Model instance which will have shared references to the same set of ModelMesh instances (i.e. a 'shallow' copy).

Simple drawing

The Model::Draw functions provides a high-level, easy to use method for drawing models.

CommonStates states(device);

XMMATRIX local = XMMatrixTranslation( 1.f, 1.f, 1.f );
local = XMMatrixMultiply( world, local );
tiny->Draw( context, states, local, view, projection );
There are optional parameters for rendering in wireframe and to provide a custom state override callback.

Advanced drawing

Rather than using the standard Model::Draw, the ModelMesh::Draw method can be used on each mesh in turn listed in the Model::meshes collection. ModelMesh::Draw can be used to draw all the opaque parts or the alpha parts individually. The ModelMesh::PrepareForRendering method can be used as a helper to setup common render state, or the developer can set up the state directly before calling ModelMesh::Draw. See ModelMesh for an example.

ModelMesh::PrepareForRendering sets the blend state, depth stencil state, raster state, and sets a pixel shader sampler.

More detailed control over rendering can be had by skipping the use of Model::Draw and ModelMesh::Draw in favor of the ModelMeshPart::Draw method. Each Model::meshes collection can be scanned for each ModelMesh::meshParts collection to enumerate all ModelMeshPart instances. For this version of draw, the ModelMeshPart::effect and ModelMeshPart::inputLayout can be used, or a custom effect override can be used instead (be sure to create the appropriate matching input layout for the custom effect beforehand using ModelMeshPart::CreateInputLayout). See ModelMeshPart for an example.

Effects control

The Model loaders create an appropriate Effects instance for each ModelMeshPart in a mesh. Generally all effects in a mesh should use the same lighting and fog settings, which is facilitated by the Model::UpdateEffects method. This calls back for each unique effect in the ModelMesh once.

tiny->UpdateEffects([&](IEffect* effect)
{
    auto lights = dynamic_cast<IEffectLights*>(effect);
    if ( lights )
    {
        XMVECTOR dir = XMVector3Rotate( g_XMOne, quat );
        lights->SetLightDirection( 0, dir );
    }
    auto fog = dynamic_cast<IEffectFog*>(effect);
    if ( fog )
    {
        fog->SetFogEnabled(true);
        fog->SetFogStart(6); // assuming RH coordiantes
        fog->SetFogEnd(8);
        fog->SetFogColor(Colors::CornflowerBlue);
    }
});
It is also possible to change the Effects instance used by a given part (such as when overriding the default effect put in place from a Model loader) by calling ModelMeshPart::ModifyEffect. This will regenerate the ModelMeshPart::inputLayout appropriately.

Be sure to call Model::Modified on all Model instances that reference the impacted ModelMesh instance to ensure the cache used by UpdateEffects is correctly updated. Model::Modified should also be called whenever a Model::meshes or ModelMesh::meshParts collection is modified.

As noted above, it is also possible to render part or all of a model using a custom effect as an override, rather than changing the effect referenced by the ModelMeshPart::effect directly. See ModelMeshPart for an example.

Alpha blending

Proper drawing of alpha-blended models can be a complicated procedure. Each ModelMeshPart has a bool value to indicate if the associated part is fully opaque (isAlpha is false), or has some level of alpha transparency (isAlpha is true). The Model::Draw routine handles some basic logic for the rendering, first rendering the opaque parts, then rendering the alpha parts. More detailed control is provided by the ModelMesh::Draw method which can be used to draw all opaque parts of all meshes first, then go back and draw all alpha parts of all meshes second. See ModelMesh for an example.

To indicate the use of ‘straight’ alpha vs. ‘premultiplied’ alpha blending modes, ModelMesh::pmalpha is set by the various loaders functions controlled by a default parameter (which defaults false to indicate the texture files are using 'straight' alpha). If you make use of DirectXTex's texconv tool with the -pmalpha switch, you should use pmalpha=true instead.

Custom render states

All the various Draw method provide a setCustomState callback which can be used to change the state just before the geometry is drawn.

tiny->Draw( context, states, local, view, projection, false, [&]()
{
    ID3D11ShaderResourceView* srv = nullptr;
    context->PSSetShaderResources( 0, 1, &srv );
});

Coordinate systems

Meshes are authored in a specific winding order, typically using the standard counter-clockwise winding common in graphics. The choice of viewing handedness (right-handed vs. left-handed coordinates) is largely a matter of preference and convenience, but it impacts how the models are built and/or exported.

The Visual Studio 3D Starter Kit’s .CMO files assume the developer is using right-handed coordinates. DirectXTK’s default parameters assume you are using right-handed coordinates as well, so the ‘ccw’ parameter defaults to true. If using a .CMO with left-handed coordinates, you should pass false for the ‘ccw’ parameter which will use clockwise winding instead. This makes the geometry visible, but could make textures on the model appear ‘flipped’ in U.

// When using LH coordinatesauto teapot = Model::CreateFromCMO( device, L"teapot.cmo", fx, false );
The legacy DirectX SDK’s .SDKMESH files assume the developer is using left-handed coordinates. DirectXTK’s default parameters assume you are using right-handed coordinates, so the ‘ccw’ parameter defaults to false which will use clockwise winding and potentially have the ‘flipped in U’ texture problem. If using a .SDKMESH with left-handed coordinates, you should pass true for the ‘ccw’ parameter.

// When using LH coordinatesauto tiny = Model::CreateFromSDKMESH( device, L"tiny.sdkmesh", fx, true );

Feature Level Notes

If any ModelMeshPart makes use of 32-bit indices (i.e. ModelMeshPart:: indexFormat equals DXGI_FORMAT_R32_UINT) rather than 16-bit indices (DXGI_FORMAT_R16_UINT), then that model requires Feature Level 9.2 or greater.

If any ModelMeshPart uses adjacency (i.e. ModelMeshPart::primitiveType equals D3D_PRIMITIVE_TOPOLOGY_*_ADJ), then that model requires Feature Level 10.0 or greater. If using tessellation (i.e. D3D_PRIMITIVE_TOPOLOGY_?_CONTROL_POINT_PATCHLIST), then that model requires Feature Level 11.0 or greater.

Keep in mind that there are maximum primitive count limits per ModelMeshPart based on feature level as well (65535 for Feature Level 9.1, 1048575 or Feature Level 9.2 and 9.3, and 4294967295 for Feature Level 10.0 or greater).

See EffectFactory for more Feature Level notes.

Content Notes

SDKMESH

The SDKMESH exporter http://go.microsoft.com/fwlink/?LinkId=226208 uses Autodesk FBX 2013.3.1 or later.

https://github.com/walbourn/contentexporter
https://directxmesh.codeplex.com/wikipage?title=SDKMesh

CMO

The VS 2012 and 2013 CMO exporter uses Autodesk FBX 2013.1. Recommended settings for exporting an FBX as a CMO include:
  • Geometry: Smoothing Groups, TurboSmooth, Convert Deforming Dummies to Bones, Preserve edge orientation
  • Animation: Bake Animation (Start=0, End=100, Step=1), Deformations, Skins, Morphs
  • Units: Automatic
  • Axis conversion: Y-up
  • FBX File Format: Binary, FBX 2013
https://directxmesh.codeplex.com/wikipage?title=CMO

VBO

A VBO file does not contain any material or attribute information. The loader will create a default untextured BasicEffect when loading the model, or you can provide your own instance to use:

ComPtr<ID3D11ShaderResourceView> defaultTex;
ComPtr<ID3D11ShaderResourceView> cubeMap;
// ...auto effect = std::make_shared<EnvironmentMapEffect>(device);
effect->EnableDefaultLighting();
effect->SetTexture(defaultTex.Get());
effect->SetEnvironmentMap(cubeMap.Get());

auto ship = Model::CreateFromVBO( device, L"ship.vbo", effect );

https://directxmesh.codeplex.com/wikipage?title=VBO

Threading model

The ModelMeshPart is tied to a device, but not a device context. This means that Model creation/loading is ‘free threaded’. Drawing can be done on the immediate context or by a deferred context, but keep in mind device contexts are not ‘free threaded’. See EffectFactory for some additional notes.

Further reading

http://blogs.msdn.com/b/shawnhar/archive/2006/11/20/models-meshes-parts-and-bones.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ff476891.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
http://blogs.msdn.com/b/chuckw/archive/2012/06/20/direct3d-feature-levels.aspx

Updated Wiki: GeometricPrimitive

This is a helper for drawing simple geometric shapes including texture coordinates and surface normals.
  • Cube (aka hexahedron)
  • Sphere
  • Geodesic Sphere
  • Cylinder
  • Cone
  • Torus
  • Tetrahedron
  • Octahedron
  • Dodecahedron
  • Icosahedron
  • Teapot

Image may be NSFW.
Clik here to view.
GeometricPrimitiveExample.jpg


Related tutorial:3D shapes

Header

#include <GeometricPrimitive.h>

Initialization

The GeometryPrimitive class must be created from a factory method which takes the Direct3D 11 device context.

std::unique_ptr<GeometricPrimitive> shape(
GeometricPrimitive::CreateTeapot(deviceContext) );
For exception safety, the factory functions return a std::unique_ptr.
  • CreateCube( deviceContext, float size = 1)
  • CreateSphere( deviceContext, float diameter = 1, size_t tessellation = 16)
  • CreateGeoSphere( deviceContext, float diameter = 1, size_t tessellation = 3)
  • CreateCylinder( deviceContext, float height = 1, float diameter = 1, size_t tessellation = 32)
  • CreateCone( deviceContext, float diameter = 1, float height = 1, size_t tessellation = 32)
  • CreateTorus( deviceContext, float diameter = 1, float thickness = 0.333f, size_t tessellation = 32)
  • CreateTetrahedron ( deviceContext, float size = 1)
  • CreateOctahedron ( deviceContext, float size = 1)
  • CreateDodecahedron ( deviceContext, float size = 1)
  • CreateIcosahedron ( deviceContext, float size = 1)
  • CreateTeapot( deviceContext, float size = 1, size_t tessellation = 8)

Simple drawing

Simple solid shape drawing:
shape->Draw(world, view, projection, Colors::CornflowerBlue);

Simple wireframe shape drawing:
shape->Draw(world, view, projection, Colors::Gray, nullptr, true);

Simple solid textured shape drawing:
shape->Draw(world, view, projection, Colors::Gray, cat);

The Draw method also accepts an optional callback function which can be used to override the default rendering state:
shape->Draw(world, view, projection, Colors::White, catTexture, false, [=]
{
    deviceContext->OMSetBlendState(...);
});
This makes use of a BasicEffect shared by all geometric primitives drawn on that device context.

Advanced drawing

This form of drawing makes use of a custom Effects instance. The caller is responsible for using an input layout that matches the effect.

IEffect* myeffect = ...

Microsoft::WRL::ComPtr<ID3D11InputLayout> inputLayout;
shape->CreateInputLayout( myeffect, inputLayout.GetAddressOf() );

shape->Draw( myeffect, inputLayout.Get() );

This takes an optional parameter for enabling alpha-blending, wireframe, and a callback function which can be used to override the default rendering state.

The Draw operation will only set up a texture sampler in slot 0. If you are using an Effects instance with more than a single texture, you need to set additional samplers manually (perhaps via setCustomState callbacks). For example, if using EnvironmentMapEffect:

shape->Draw( myeffect, inputLayout.Get(), false, false, [=]
{
    ID3D11SamplerState* samplerState[2] = { states.LinearClamp(), states.LinearWrap() };
    deviceContext->PSSetSamplers(0, 2, &samplerState);
});

Note that GeometricPrimitive shapes define a single set of texture coordinates, so you can't use them with DualTextureEffect. They also do not include tangents or bi-normals, so they don't work with DGSLEffect.

Coordinate systems

These geometric primitives (based on the XNA Game Studio conventions) use right-handed coordinates. They can be used with left-handed coordinates by setting the rhcoords parameter on the factory methods to 'false' to reverse the winding ordering (the parameter defaults to 'true').

std::unique_ptr<GeometricPrimitive> shape(
GeometricPrimitive::CreateTeapot( deviceContext, 1.f, 8, false ) );

Note: Using the wrong value for rhcoords for your viewing setup will result in the objects looking 'inside out'.

Alpha blending

Alpha blending defaults to using premultiplied alpha. To make use of 'straight' alpha textures, override the blending mode via the optional callback:

CommonStates states(device);

shape->Draw(world, view, projection, Colors::White, catTexture, false, [=]
{
    deviceContext->OMSetBlendState( states.NonPremultiplied(), nullptr, 0xFFFFFFFF);
});

Feature Level Notes

In order to support all feature levels, the GeometricPrimitive implementation make use of 16-bit indices (DXGI_FORMAT_R16_UINT) which limits to a maximum of 65535 vertices.

Feature Level 9.1 is also limited to a maximum of 65535 primitives in a single draw. This rule out using extremely large numbers for the tessellation factor, although the exact limit depends on the shape implementation.

Note that these shapes tend to duplicate rather than share vertices in order to provide the 'face-normal' lighting expected of sharp geometry.

Threading model

Each GeometricPrimitive instance only supports drawing from one thread at a time, but you can simultaneously submit primitives on multiple threads if you create a separate GeometricPrimitive instance per Direct3D 11 deferred context.
http://msdn.microsoft.com/en-us/library/windows/desktop/ff476892.aspx

Remark

Tetrahedron, Cube/Hexahedron, Octahedron, Dodecahedron, and Icosahedron comprise the five "Platonic solids". The Utah Teapot is sometimes referred to as the "Sixth Platonic solid" due to its prevalence in rendering sample images.

Further Reading

http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx

http://blogs.msdn.com/b/chuckw/archive/2012/06/20/direct3d-feature-levels.aspx

http://en.wikipedia.org/wiki/Cube
http://en.wikipedia.org/wiki/Hexahedron
http://en.wikipedia.org/wiki/Sphere
http://en.wikipedia.org/wiki/Cylinder_(geometry)
http://en.wikipedia.org/wiki/Cone
http://en.wikipedia.org/wiki/Torus
http://en.wikipedia.org/wiki/Tetrahedron
http://en.wikipedia.org/wiki/Octahedron
http://en.wikipedia.org/wiki/Dodecahedron
http://en.wikipedia.org/wiki/Icosahedron
http://en.wikipedia.org/wiki/Utah_teapot
https://en.wikipedia.org/wiki/Platonic_solid

Updated Wiki: DynamicSoundEffectInstance

DynamicSoundEffectInstance is an instance of a sound which plays buffers submitted from the application. This can be used to implement procedural audio generation or to implement streaming. It can be played with 3D positional audio effects, volume and panning control, and pause/resume control. Looping is not supported.

Note that the DynamicSoundEffectInstance does not copy the wave data and instead refers to the data 'owned' by the application. Therefore, the buffers should be kept "live" until all sounds playing from it are finished.

You can use direct low-level XAudio2 interfaces to implement your own streaming or procedural sound submission rather than make use of this class.

Header

#include <Audio.h>

Initialization

This class supports integer PCM 8-bit or 16-bit data (defaults to 16-bit) with 1 - 8 interleaved channels.

// PCM 44100 Hz, 16-bit, 1 channel
std::unique_ptr<DynamicSoundEffectInstance> effect( new DynamicSoundEffectInstance( audEngine.get(),
    [](DynamicSoundEffectInstance*)
    {
        // 'Buffer needed' event handler
    },
    44100, 1 ) )
For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr.

It can optionally support 3D positional audio:

std::unique_ptr<DynamicSoundEffectInstance> effect( new DynamicSoundEffectInstance( audEngine.get(),
    [](DynamicSoundEffectInstance*)
    {
        // 'Buffer needed' event handler
    },
    44100, 1, 16,
    SoundEffectInstance_Use3D ) )

Or use 3D positional audio with reverb effects (if AudioEngine was created using AudioEngine_EnvironmentalReverb | AudioEngine_ReverbUseFilters):

std::unique_ptr<DynamicSoundEffectInstance> effect( new DynamicSoundEffectInstance( audEngine.get(),
    [](DynamicSoundEffectInstance*)
    {
        // 'Buffer needed' event handler
    },
    44100, 1, 16,
    SoundEffectInstance_Use3D | SoundEffectInstance_ReverbUseFilters ) )

Instance flags

This is a combination of SoundEffectInstance_Use3D and/or SoundEffectInstance_ReverbUseFilters. It defaults to SoundEffectInstance_Default.

There is also a SoundEffectInstance_UseRedirectLFE which is used internally by the library.

Note: SOUND_EFFECT_INSTANCE_FLAGS is used as a typed flag enum. Only operator| is overloaded to combine them, so operations like |= are not available without additional static_cast<> statements.

Playback control

  • Play ()
Starts the playback of the sound. If paused, it resumes playback.
  • Stop ( bool immediate = true )
Stops the playback of the voice. If immediate is true, the sound is immediately halted. Otherwise any 'tails' are played.
  • Resume ()
Resumes playback if the sound is PAUSED.
  • Pause ()
Pauses the sound playback. Note that for a 'game' pause, you should use AudioEngine::Suspend() / Resume() instead of 'pausing' the sounds individually.

Audio data submission

Unlike SoundEffectInstance which obtains the audio data from a SoundEffect or a WaveBank, this class only plays data provided directly to the class via SubmitBuffer.

std::vector<uint8_t> audioBytes;
audioBytes.resize( 44100 * 2 );

GenerateSineWave( reinterpret_cast<int16_t*>( &audioBytes.front() ), 44100, 440 );
        
std::unique_ptr<DynamicSoundEffectInstance> effect( new DynamicSoundEffectInstance( audEngine.get(),
    [&audioBytes](DynamicSoundEffectInstance* effect)
    {
        int count = effect->PendingBufferCount();

        while( count < 3 )
        {
            effect->SubmitBuffer( &audioBytes.front(), audioBytes.size() );
            ++count;
        }
    }, 44100, 1, 16 ) );

effect->Play();

...

// The 'Buffer needed' event function is called during some later call to Update() as needed

The 'Buffer needed' callback function is invoked whenever there are <= 2 buffers pending or whenever a buffer completes playback. You should submit sufficient data to avoid starving the voice.

This example uses a simple helper routine which fills a buffer with 1 second of a pure sine wave at a given frequency:

void GenerateSineWave( _Out_writes_(sampleRate) int16_t* data, int sampleRate, int frequency )
{
    constdouble timeStep = 1.0 / double(sampleRate);
    constdouble freq = double(frequency);

    int16_t* ptr = data;
    double time = 0.0;
    for( int j = 0; j < sampleRate; ++j, ++ptr )
    {
        double angle = ( 2.0 * XM_PI * freq ) * time;
        double factor = 0.5 * ( sin(angle) + 1.0 );
        *ptr = int16_t( 32768 * factor );
        time += timeStep;
    }
}

Note: This sample is somewhat contrived and is only for illustrative purposes. If the audio data is static, it's more efficient to use a SoundEffect and then create a SoundEffectInstance from it to play it as a looped sound. Dynamic cases will have different audio data in the buffer on each call to SubmitBuffer. This requires some additional complexity to ensure that each buffer is freed or reused only after it has completed playing.

Volume and panning

  • SetVolume ( float volume )
Sets playback volume. Playback defaults to 1
  • SetPitch ( float pitch )
Sets a pitch-shift factor. Ranges from -1 to +1, playback defaults to 0 (which is no pitch-shifting).
  • SetPan ( float pan )
Sets a pan settings: -1 is fully left, +1 is fully right, and 0 is balanced.
Note panning is only supported for mono and stereo sources, and will overwrite any Apply3D settings.

Positional 3D audio

DirectXTK for Audio uses X3DAudio for positional audio computations. To apply a 3D effect to a sound instance, you call Apply3D with the listener location (i.e. where the player/camera is located) and the emitter (i.e. where the sound source is located in 3D dimensions):

AudioListener listener;
listener.SetPosition( ... );

AudioEmitter emitter;
emitter.SetPosition( ... );

effect->Apply3D( listener, emitter );

Note if the instance was created without SoundEffectInstance_Use3D, then calls to Apply3D will result in a C++ exception being thrown. Apply3D will overwrite any SetPan settings.

See AudioListener, AudioEmitter

Properties

  • GetState ()
Returns STOPPED, PLAYING, or PAUSED.
  • GetPendingBufferCount ()
Returns the number of pending buffers submitted to the instance that are either playing or waiting to play.
  • GetFormat ()
Returns a WAVEFORMATEX that describes the audio format consumed by the sound instance. This is always integer PCM data.

Helper methods

  • GetSampleDuration ( bytes )
Returns duration in samples of a buffer of a given size
  • GetSampleDurationMS ( bytes )
Returns duration in milliseconds of a buffer of a given size
  • GetSampleSizeInBytes( duration )
Returns size of a buffer for a duration given in milliseconds

Further reading

http://msdn.microsoft.com/en-us/library/windows/desktop/ee415714.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.x3daudio.x3daudiocalculate.aspx

Updated Wiki: DynamicSoundEffectInstance

DynamicSoundEffectInstance is an instance of a sound which plays buffers submitted from the application. This can be used to implement procedural audio generation or to implement streaming. It can be played with 3D positional audio effects, volume and panning control, and pause/resume control. Looping is not supported.

Note that the DynamicSoundEffectInstance does not copy the wave data and instead refers to the data 'owned' by the application. Therefore, the buffers should be kept "live" until all sounds playing from it are finished.

You can use direct low-level XAudio2 interfaces to implement your own streaming or procedural sound submission rather than make use of this class.

Header

#include <Audio.h>

Initialization

This class supports integer PCM 8-bit or 16-bit data (defaults to 16-bit) with 1 - 8 interleaved channels.

// PCM 44100 Hz, 16-bit, 1 channel
std::unique_ptr<DynamicSoundEffectInstance> effect( new DynamicSoundEffectInstance( audEngine.get(),
    [](DynamicSoundEffectInstance*)
    {
        // 'Buffer needed' event handler
    },
    44100, 1 ) )
For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr.

It can optionally support 3D positional audio:

std::unique_ptr<DynamicSoundEffectInstance> effect( new DynamicSoundEffectInstance( audEngine.get(),
    [](DynamicSoundEffectInstance*)
    {
        // 'Buffer needed' event handler
    },
    44100, 1, 16,
    SoundEffectInstance_Use3D ) )

Or use 3D positional audio with reverb effects (if AudioEngine was created using AudioEngine_EnvironmentalReverb | AudioEngine_ReverbUseFilters):

std::unique_ptr<DynamicSoundEffectInstance> effect( new DynamicSoundEffectInstance( audEngine.get(),
    [](DynamicSoundEffectInstance*)
    {
        // 'Buffer needed' event handler
    },
    44100, 1, 16,
    SoundEffectInstance_Use3D | SoundEffectInstance_ReverbUseFilters ) )

Instance flags

This is a combination of SoundEffectInstance_Use3D and/or SoundEffectInstance_ReverbUseFilters. It defaults to SoundEffectInstance_Default.

There is also a SoundEffectInstance_UseRedirectLFE which is used internally by the library.

Note: SOUND_EFFECT_INSTANCE_FLAGS is used as a typed flag enum. Only operator| is overloaded to combine them, so operations like |= are not available without additional static_cast<> statements.

Playback control

  • Play ()
Starts the playback of the sound. If paused, it resumes playback.
  • Stop ( bool immediate = true )
Stops the playback of the voice. If immediate is true, the sound is immediately halted. Otherwise any 'tails' are played.
  • Resume ()
Resumes playback if the sound is PAUSED.
  • Pause ()
Pauses the sound playback. Note that for a 'game' pause, you should use AudioEngine::Suspend() / Resume() instead of 'pausing' the sounds individually.

Audio data submission

Unlike SoundEffectInstance which obtains the audio data from a SoundEffect or a WaveBank, this class only plays data provided directly to the class via SubmitBuffer.

std::vector<uint8_t> audioBytes;
audioBytes.resize( 44100 * 2 );

GenerateSineWave( reinterpret_cast<int16_t*>( &audioBytes.front() ), 44100, 440 );
        
std::unique_ptr<DynamicSoundEffectInstance> effect( new DynamicSoundEffectInstance( audEngine.get(),
    [&audioBytes](DynamicSoundEffectInstance* effect)
    {
        int count = effect->PendingBufferCount();

        while( count < 3 )
        {
            effect->SubmitBuffer( &audioBytes.front(), audioBytes.size() );
            ++count;
        }
    }, 44100, 1, 16 ) );

effect->Play();

...

// The 'Buffer needed' event function is called during some later call to Update() as needed

The 'Buffer needed' callback function is invoked whenever there are <= 2 buffers pending or whenever a buffer completes playback. You should submit sufficient data to avoid starving the voice.

This example uses a simple helper routine which fills a buffer with 1 second of a pure sine wave at a given frequency:

void GenerateSineWave( _Out_writes_(sampleRate) int16_t* data, int sampleRate, int frequency )
{
    constdouble timeStep = 1.0 / double(sampleRate);
    constdouble freq = double(frequency);

    int16_t* ptr = data;
    double time = 0.0;
    for( int j = 0; j < sampleRate; ++j, ++ptr )
    {
        double angle = ( 2.0 * XM_PI * freq ) * time;
        double factor = 0.5 * ( sin(angle) + 1.0 );
        *ptr = int16_t( 32768 * factor );
        time += timeStep;
    }
}

Note: This sample is somewhat contrived and is only for illustrative purposes. If the audio data is static, it's more efficient to use a SoundEffect and then create a SoundEffectInstance from it to play it as a looped sound. Dynamic cases will have different audio data in the buffer on each call to SubmitBuffer. This requires some additional complexity to ensure that each buffer is freed or reused only after it has completed playing.

Volume and panning

  • SetVolume ( float volume )
Sets playback volume. Playback defaults to 1
  • SetPitch ( float pitch )
Sets a pitch-shift factor. Ranges from -1 to +1, playback defaults to 0 (which is no pitch-shifting). This will trigger a C++ exception if the object was created with SoundEffectInstance_NoSetPitch.
  • SetPan ( float pan )
Sets a pan settings: -1 is fully left, +1 is fully right, and 0 is balanced.
Note panning is only supported for mono and stereo sources, and will overwrite any Apply3D settings.

Positional 3D audio

DirectXTK for Audio uses X3DAudio for positional audio computations. To apply a 3D effect to a sound instance, you call Apply3D with the listener location (i.e. where the player/camera is located) and the emitter (i.e. where the sound source is located in 3D dimensions):

AudioListener listener;
listener.SetPosition( ... );

AudioEmitter emitter;
emitter.SetPosition( ... );

effect->Apply3D( listener, emitter );

Note if the instance was created without SoundEffectInstance_Use3D, then calls to Apply3D will result in a C++ exception being thrown. Apply3D will overwrite any SetPan settings.

See AudioListener, AudioEmitter

Properties

  • GetState ()
Returns STOPPED, PLAYING, or PAUSED.
  • GetPendingBufferCount ()
Returns the number of pending buffers submitted to the instance that are either playing or waiting to play.
  • GetFormat ()
Returns a WAVEFORMATEX that describes the audio format consumed by the sound instance. This is always integer PCM data.

Helper methods

  • GetSampleDuration ( bytes )
Returns duration in samples of a buffer of a given size
  • GetSampleDurationMS ( bytes )
Returns duration in milliseconds of a buffer of a given size
  • GetSampleSizeInBytes( duration )
Returns size of a buffer for a duration given in milliseconds

Further reading

http://msdn.microsoft.com/en-us/library/windows/desktop/ee415714.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.x3daudio.x3daudiocalculate.aspx

Updated Wiki: SoundEffect

SoundEffect is a container class for wave sample data. This data can then be played back as a one-shot sound or via a SoundEffectInstance.

Header

#include <Audio.h>

Initialization

The SoundEffect class can be created with two main forms of constructor. The first loads from a .wav file on disk.

std::unique_ptr<SoundEffect> effect( new SoundEffect( audEngine.get(), L"sound.wav" );
For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr or std::shared_ptr

The second takes ownership of a memory buffer containing the wave data. The wfx and startAudio pointers are assumed to point into the same memory buffer owned by wavData since they must remain valid for the life of the SoundEffect object.

size_t audioSize = 44100 * 2;
std::unique_ptr<uint8_t[]> wavData( new uint8_t[ audioSize + sizeof(WAVEFORMATEX) ] );

auto startAudio = wavData.get() + sizeof(WAVEFORMATEX);

GenerateSineWave( reinterpret_cast<int16_t*>( startAudio ), 44100, 440 );
        
auto wfx = reinterpret_cast<WAVEFORMATEX*>( wavData.get() );
wfx->wFormatTag = WAVE_FORMAT_PCM;
wfx->nChannels = 1;
wfx->nSamplesPerSec = 44100;
wfx->nAvgBytesPerSec = 2 * 44100;
wfx->nBlockAlign = 2;
wfx->wBitsPerSample = 16;
wfx->cbSize = 0;

std::unique_ptr<SoundEffect> effect( new SoundEffect( audEngine.get(), wavData,
    wfx, startAudio, audioSize );

This example uses a simple helper routine which fills a buffer with 1 second of a pure sine wave at a given frequency:

void GenerateSineWave( _Out_writes_(sampleRate) int16_t* data, int sampleRate, int frequency )
{
    constdouble timeStep = 1.0 / double(sampleRate);
    constdouble freq = double(frequency);

    int16_t* ptr = data;
    double time = 0.0;
    for( int j = 0; j < sampleRate; ++j, ++ptr )
    {
        double angle = ( 2.0 * XM_PI * freq ) * time;
        double factor = 0.5 * ( sin(angle) + 1.0 );
        *ptr = int16_t( 32768 * factor );
        time += timeStep;
    }
}

Play one-shot sounds

To play the sound effect as a 'fire and forget' sound:

soundEffect->Play();

To play the sound effect as a 'fire and forget' sound with volume, a pitch-shift, and/or pan setting:

soundEffect->Play( volume, pitch, pan );

volume default is 1
pitch ranges from -1 to +1, playback defaults to 0 (which is no pitch-shifting)
pan -1 is fully left, +1 is fully right, and 0 is balanced.

Playing the sound

To play the sound with full control, looping, and dynamic pitch-shifting/volume control/pan settings:

auto effect = soundEffect->CreateInstance();

To play the sound with positional 3D audio:

auto effect = soundEffect->CreateInstance( SoundEffectInstance_Use3D
                | SoundEffectInstance_ReverbUseFilters);

See SoundEffectInstance.

Properties

  • IsInUse ()
Returns true if the SoundEffect is currently playing as a one-shot or there are SoundEffectInstances referencing it.
  • GetSampleSizeInBytes ()
Returns the size of the wave data in bytes.
  • GetSampleDuration ()
Returns the wave data duration in samples. This does not include any loops.
  • GetSampleDurationMS ()
Returns the wave data duration in milliseconds. This does not include any loops.
  • GetFormat ()
Returns WAVEFORMATEX structure that describes the wave data format.

Low-level access

FillSubmitBuffer is used internally, but can also be used when implementing your own XAudio2 source voices using the low-level interface access. Note that LoopCount is set to 0 by this function and should be set to a non-zero value by the caller. If looping is not desired, be sure to set LoopBegin and LoopLength to zero as well.

Care needs to be taken to ensure that any referenced SoundEffect is not deleted while a source voice is actively playing back content from it or has pending buffers referencing it.

Content support

XAudio 2.9 on Windows 10 supports PCM, ADPCM, and xWMA.

XAudio 2.8 on Windows 8.x and Windows phone support PCM and ADPCM formats.

XAudio 2.7 on Windows Vista or later via the legacy DirectX End-User Runtime Redistribution (aka DirectSetup) supports PCM, ADPCM, and xWMA.

XAudio on Xbox One supports PCM, ADPCM, and xWMA. Xbox One exclusive app developers can also make use of XMA2.

To compress to ADPCM (a variant of MS-ADPCM) .wav files, use adpcmencode.exe from the Windows 8.x SDK, Xbox One ADK, Xbox One XDK, or legacy DirectX SDK.

To compress to xWMA .wav files, use xwmaencode.exe from the Xbox One ADK, Xbox One XDK, or legacy DirectX SDK.

To compress to XMA2 .wav files, use xma2encode.exe from the Xbox One XDK.

WAV File Format

To aid in debugging, here is a simple console program for dumping out the content of a WAV in a human-readable form.
wavdump.cpp

http://msdn.microsoft.com/en-us/library/windows/desktop/ee415713.aspx

Further reading

http://msdn.microsoft.com/en-us/library/windows/desktop/dd757712.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757713.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd743663.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757714.aspx

Updated Wiki: SoundEffect

SoundEffect is a container class for wave sample data. This data can then be played back as a one-shot sound or via a SoundEffectInstance.

Header

#include <Audio.h>

Initialization

The SoundEffect class can be created with two main forms of constructor. The first loads from a .wav file on disk.

std::unique_ptr<SoundEffect> effect( new SoundEffect( audEngine.get(), L"sound.wav" );
For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr or std::shared_ptr

The second takes ownership of a memory buffer containing the wave data. The wfx and startAudio pointers are assumed to point into the same memory buffer owned by wavData since they must remain valid for the life of the SoundEffect object.

size_t audioSize = 44100 * 2;
std::unique_ptr<uint8_t[]> wavData( new uint8_t[ audioSize + sizeof(WAVEFORMATEX) ] );

auto startAudio = wavData.get() + sizeof(WAVEFORMATEX);

GenerateSineWave( reinterpret_cast<int16_t*>( startAudio ), 44100, 440 );
        
auto wfx = reinterpret_cast<WAVEFORMATEX*>( wavData.get() );
wfx->wFormatTag = WAVE_FORMAT_PCM;
wfx->nChannels = 1;
wfx->nSamplesPerSec = 44100;
wfx->nAvgBytesPerSec = 2 * 44100;
wfx->nBlockAlign = 2;
wfx->wBitsPerSample = 16;
wfx->cbSize = 0;

std::unique_ptr<SoundEffect> effect( new SoundEffect( audEngine.get(), wavData,
    wfx, startAudio, audioSize );

This example uses a simple helper routine which fills a buffer with 1 second of a pure sine wave at a given frequency:

void GenerateSineWave( _Out_writes_(sampleRate) int16_t* data, int sampleRate, int frequency )
{
    constdouble timeStep = 1.0 / double(sampleRate);
    constdouble freq = double(frequency);

    int16_t* ptr = data;
    double time = 0.0;
    for( int j = 0; j < sampleRate; ++j, ++ptr )
    {
        double angle = ( 2.0 * XM_PI * freq ) * time;
        double factor = 0.5 * ( sin(angle) + 1.0 );
        *ptr = int16_t( 32768 * factor );
        time += timeStep;
    }
}

Play one-shot sounds

To play the sound effect as a 'fire and forget' sound:

soundEffect->Play();

To play the sound effect as a 'fire and forget' sound with volume, a pitch-shift, and/or pan setting:

soundEffect->Play( volume, pitch, pan );

volume default is 1
pitch ranges from -1 to +1, playback defaults to 0 (which is no pitch-shifting)
pan -1 is fully left, +1 is fully right, and 0 is balanced.

Playing the sound

To play the sound with full control, looping, and dynamic pitch-shifting/volume control/pan settings:

auto effect = soundEffect->CreateInstance();

To play the sound with positional 3D audio:

auto effect = soundEffect->CreateInstance( SoundEffectInstance_Use3D
                | SoundEffectInstance_ReverbUseFilters);

See SoundEffectInstance.

Properties

  • IsInUse ()
Returns true if the SoundEffect is currently playing as a one-shot or there are SoundEffectInstances referencing it.
  • GetSampleSizeInBytes ()
Returns the size of the wave data in bytes.
  • GetSampleDuration ()
Returns the wave data duration in samples. This does not include any loops.
  • GetSampleDurationMS ()
Returns the wave data duration in milliseconds. This does not include any loops.
  • GetFormat ()
Returns WAVEFORMATEX structure that describes the wave data format.

Low-level access

FillSubmitBuffer is used internally, but can also be used when implementing your own XAudio2 source voices using the low-level interface access. Note that LoopCount is set to 0 by this function and should be set to a non-zero value by the caller. If looping is not desired, be sure to set LoopBegin and LoopLength to zero as well.

Care needs to be taken to ensure that any referenced SoundEffect is not deleted while a source voice is actively playing back content from it or has pending buffers referencing it.

Content support

XAudio 2.9 on Windows 10 supports PCM, ADPCM, and xWMA.

XAudio 2.8 on Windows 8.x and Windows phone support PCM and ADPCM formats.

XAudio 2.7 on Windows Vista or later via the legacy DirectX End-User Runtime Redistribution (aka DirectSetup) supports PCM, ADPCM, and xWMA.

XAudio on Xbox One supports PCM, ADPCM, and xWMA. Xbox One exclusive app developers can also make use of XMA2.

To compress to ADPCM (a variant of MS-ADPCM) .wav files, use adpcmencode.exe from the Windows SDK, Xbox One ADK, Xbox One XDK, or legacy DirectX SDK.

To compress to xWMA .wav files, use xwmaencode.exe from the Xbox One ADK, Xbox One XDK, or legacy DirectX SDK.

To compress to XMA2 .wav files, use xma2encode.exe from the Xbox One XDK.

WAV File Format

To aid in debugging, here is a simple console program for dumping out the content of a WAV in a human-readable form.
wavdump.cpp

http://msdn.microsoft.com/en-us/library/windows/desktop/ee415713.aspx

Further reading

http://msdn.microsoft.com/en-us/library/windows/desktop/dd757712.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757713.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd743663.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757714.aspx

Updated Wiki: WaveBank

WaveBank is a container class for an XACT-style wave bank that contains individual waves packaged together for more efficient loading and memory management. Sounds in the wave bank can then be played back as one-shot sounds or via SoundEffectInstance.

See XWBTool for more information on building .xwb files.

Note: DirectXTK for Audio uses XAudio 2.8 or XAudio 2.7. It does not make use of the legacy XACT Engine, XACT Cue, or XACT SoundBank.

Header

#include <Audio.h>

Initialization

std::unique_ptr<WaveBank> wb( new WaveBank( audEngine.get(), L"wavebank.xwb" ) );

For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr or std::shared_ptr

Note that in-memory banks may still be loading the wave data asynchronously after the return of this constructor. You can see if the wave data has completed loading by calling IsPrepared (). If you call Play or CreateInstance before the wave data has loaded, then the thread will wait until the load is complete before returning.

Play one-shot sounds

To play a sound in the bank as a 'fire and forget' sound:

wb->Play( index );

index is 0-based
To play the sound in the bank as a 'fire and forget' sound with volume, a pitch-shift, and/or pan setting:

wb->Play( index, volume, pitch, pan );

volume default is 1
pitch ranges from -1 to +1, playback defaults to 0 (which is no pitch-shifting)
pan -1 is fully left, +1 is fully right, and 0 is balanced.
If the wave bank contains 'entry friendly names', you can also use them to trigger a one-shot:

wb->Play( "Bang" );
wb->Play( "Bang", 0.8f, 0.f, 1.f );

You can also make use of the C/C++ header generated by XWBTool or XACTBLD3 to avoid 'magic numbers' in your code:

#include "wavebank.h"

wb->Play( XACT_WAVEBANK_WAVEBANK_BANG );

Note a C++ exception is thrown if attempting to play a one-shot sound from a streaming wavebank.

If the specified index or name is not found, then no one-shot is played and there is no C++ exception thrown.

Playing the sound

To play a sound with full control, looping, and dynamic pitch-shifting/volume control/pan settings:

auto effect = wb->CreateInstance( 2 );
if ( !effect )
    // Index not found in wave bank

To play a sound with positional 3D audio:

auto effect = wb->CreateInstance( 2, SoundEffectInstance_Use3D
                | SoundEffectInstance_ReverbUseFilters);
if ( !effect )
    // Index not found in wave bank

If the wave bank contains 'entry friendly names', you can also use them to create an instance:

auto effect = wb->CreateInstance( "Bang" );
if ( !effect )
    // Name not found in wave bankauto effect = wb->CreateInstance( "Bang", SoundEffectInstance_Use3D
                | SoundEffectInstance_ReverbUseFilters);
if ( !effect )
    // Name not found in wave bank

You can also make use of the C/C++ header generated by XWBTool or XACTBLD3 to avoid 'magic numbers' in your code:

#include "wavebank.h"auto effect = wb->CreateInstance( XACT_WAVEBANK_WAVEBANK_BANG );
if ( !effect )
    // Index not found in wave bankauto effect = wb->CreateInstance( XACT_WAVEBANK_WAVEBANK_BANG, SoundEffectInstance_Use3D
                | SoundEffectInstance_ReverbUseFilters);
if ( !effect )
    // Index not found in wave bank

Note a C++ exception is thrown if attempting to create a sound instance from a streaming wavebank.

If the specified index or name is not found, then CreateInstance returns a 'nullptr'. Client code should be sure to check for this condition. This is done because typically games do not consider missing audio content to be a fatal error during development.

See SoundEffectInstance.

Properties

  • IsPrepared ()
Returns true if the WaveBank has completed loading the wave data. For streaming buffers, they are always prepared after the constructor returns (only the metadata is loaded into memory).
  • IsInUse ()
Returns true if the WaveBank is currently playing as a one-shot or there are SoundEffectInstances referencing it.
  • IsStreamingBank ()
Returns true if the wave bank is a streaming type, false if it is an in-memory wave bank.
  • GetSampleSizeInBytes ( index )
Returns the size of the wave data in bytes. This will return 0 if the index is invalid.
  • GetSampleDuration ( index )
Returns the wave data duration in samples. This does not include any loops. This will return 0 if the index is invalid.
  • GetSampleDurationMS ( index )
Returns the wave data duration in milliseconds. This does not include any loops. This will return 0 if the index is invalid.
  • GetFormat ( index, WAVEFORMATEX* wfx, size_t maxsize )
Fills out a WAVEFORMATEX structure that describes the wave data format. This will return nullptr if the index is invalid, otherwise it returns a pointer to wfx. Since the format can be variable length, the caller provides the buffer and maxsize. At least 64 bytes is recommended as this is large enough to contain WAVEFORMAT, PCMWAVEFORMAT, WAVEFORMATEX, ADPCMWAVEFORMAT with coefficients, WAVEFORMATEXTENSIBLE, or a XMA2WAVEFORMATEX.
char formatBuff[ 64 ]; 
auto wfx = reinterpret_cast<WAVEFORMATEX*>( formatBuff );

wb->GetFormat( 2, wfx, 64 );
  • Find ( const char* name )
Returns the index, or -1 if not found or if there are no entry friendly names present in the wave bank.

Low-level access

FillSubmitBuffer is used internally, but can also be used when implementing your own XAudio2 source voices using the low-level interface access. Note that LoopCount is set to 0 by this function and should be set to a non-zero value by the caller. If looping is not desired, be sure to set LoopBegin and LoopLength to zero as well.

Care needs to be taken to ensure that any referenced WaveBank is not deleted while a source voice is actively playing back content from it or has pending buffers referencing it.

Content support

XAudio 2.9 on Windows 10 supports PCM, ADPCM, and xWMA.

XAudio 2.8 on Windows 8.x and Windows phone support PCM and ADPCM formats.

XAudio 2.7 on Windows Vista or later via the legacy DirectX End-User Runtime Redistribution (aka DirectSetup) supports PCM, ADPCM, and xWMA.

XAudio on Xbox One supports PCM, ADPCM, and xWMA. Xbox One exclusive app developers can also make use of XMA2.

XACT-style wave banks support 8-bit and 16-bit PCM (i.e. not 32-bit IEEE float PCM), ADPCM, xWMA, and XMA2 content.

XWB File Format

To aid in debugging, here is a simple console program for dumping out the content of a XWB in a human-readable form.
xwbdump.cpp

Further reading

http://msdn.microsoft.com/en-us/library/windows/desktop/dd757712.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757713.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd743663.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757714.aspx
http://msdn.microsoft.com/en-us/library/bb203879(v=xnagamestudio.40).aspx

Updated Wiki: SoundEffect

SoundEffect is a container class for wave sample data. This data can then be played back as a one-shot sound or via a SoundEffectInstance.

Header

#include <Audio.h>

Initialization

The SoundEffect class can be created with two main forms of constructor. The first loads from a .wav file on disk.

std::unique_ptr<SoundEffect> effect( new SoundEffect( audEngine.get(), L"sound.wav" );
For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr or std::shared_ptr

The second takes ownership of a memory buffer containing the wave data. The wfx and startAudio pointers are assumed to point into the same memory buffer owned by wavData since they must remain valid for the life of the SoundEffect object.

size_t audioSize = 44100 * 2;
std::unique_ptr<uint8_t[]> wavData( new uint8_t[ audioSize + sizeof(WAVEFORMATEX) ] );

auto startAudio = wavData.get() + sizeof(WAVEFORMATEX);

GenerateSineWave( reinterpret_cast<int16_t*>( startAudio ), 44100, 440 );
        
auto wfx = reinterpret_cast<WAVEFORMATEX*>( wavData.get() );
wfx->wFormatTag = WAVE_FORMAT_PCM;
wfx->nChannels = 1;
wfx->nSamplesPerSec = 44100;
wfx->nAvgBytesPerSec = 2 * 44100;
wfx->nBlockAlign = 2;
wfx->wBitsPerSample = 16;
wfx->cbSize = 0;

std::unique_ptr<SoundEffect> effect( new SoundEffect( audEngine.get(), wavData,
    wfx, startAudio, audioSize );

This example uses a simple helper routine which fills a buffer with 1 second of a pure sine wave at a given frequency:

void GenerateSineWave( _Out_writes_(sampleRate) int16_t* data, int sampleRate, int frequency )
{
    constdouble timeStep = 1.0 / double(sampleRate);
    constdouble freq = double(frequency);

    int16_t* ptr = data;
    double time = 0.0;
    for( int j = 0; j < sampleRate; ++j, ++ptr )
    {
        double angle = ( 2.0 * XM_PI * freq ) * time;
        double factor = 0.5 * ( sin(angle) + 1.0 );
        *ptr = int16_t( 32768 * factor );
        time += timeStep;
    }
}

Play one-shot sounds

To play the sound effect as a 'fire and forget' sound:

soundEffect->Play();

To play the sound effect as a 'fire and forget' sound with volume, a pitch-shift, and/or pan setting:

soundEffect->Play( volume, pitch, pan );

volume default is 1
pitch ranges from -1 to +1, playback defaults to 0 (which is no pitch-shifting)
pan -1 is fully left, +1 is fully right, and 0 is balanced.

Playing the sound

To play the sound with full control, looping, and dynamic pitch-shifting/volume control/pan settings:

auto effect = soundEffect->CreateInstance();

To play the sound with positional 3D audio:

auto effect = soundEffect->CreateInstance( SoundEffectInstance_Use3D
                | SoundEffectInstance_ReverbUseFilters);

See SoundEffectInstance.

Properties

  • IsInUse ()
Returns true if the SoundEffect is currently playing as a one-shot or there are SoundEffectInstances referencing it.
  • GetSampleSizeInBytes ()
Returns the size of the wave data in bytes.
  • GetSampleDuration ()
Returns the wave data duration in samples. This does not include any loops.
  • GetSampleDurationMS ()
Returns the wave data duration in milliseconds. This does not include any loops.
  • GetFormat ()
Returns WAVEFORMATEX structure that describes the wave data format.
The actual structure returned could be a WAVEFORMAT, PCMWAVEFORMAT, WAVEFORMATEX, ADPCMWAVEFORMAT with coefficients, WAVEFORMATEXTENSIBLE, or a XMA2WAVEFORMATEX .

Low-level access

FillSubmitBuffer is used internally, but can also be used when implementing your own XAudio2 source voices using the low-level interface access. Note that LoopCount is set to 0 by this function and should be set to a non-zero value by the caller. If looping is not desired, be sure to set LoopBegin and LoopLength to zero as well.

Care needs to be taken to ensure that any referenced SoundEffect is not deleted while a source voice is actively playing back content from it or has pending buffers referencing it.

Content support

XAudio 2.9 on Windows 10 supports PCM, ADPCM, and xWMA.

XAudio 2.8 on Windows 8.x and Windows phone support PCM and ADPCM formats.

XAudio 2.7 on Windows Vista or later via the legacy DirectX End-User Runtime Redistribution (aka DirectSetup) supports PCM, ADPCM, and xWMA.

XAudio on Xbox One supports PCM, ADPCM, and xWMA. Xbox One exclusive app developers can also make use of XMA2.

To compress to ADPCM (a variant of MS-ADPCM) .wav files, use adpcmencode.exe from the Windows SDK, Xbox One ADK, Xbox One XDK, or legacy DirectX SDK.

To compress to xWMA .wav files, use xwmaencode.exe from the Xbox One ADK, Xbox One XDK, or legacy DirectX SDK.

To compress to XMA2 .wav files, use xma2encode.exe from the Xbox One XDK.

WAV File Format

To aid in debugging, here is a simple console program for dumping out the content of a WAV in a human-readable form.
wavdump.cpp

http://msdn.microsoft.com/en-us/library/windows/desktop/ee415713.aspx

Further reading

http://msdn.microsoft.com/en-us/library/windows/desktop/dd757712.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757713.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd743663.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757714.aspx

Updated Wiki: AudioEngine

This class represents an XAudio2 audio graph, device, and mastering voice

Header

#include <Audio.h>

Initialization

This creates an XAudio2 interface, an XAudio2 mastering voice, and other global resources.

XAudio2 requires COM be initialized as a prerequisite using Windows::Foundation::Initialize, CoInitialize, or CoInitializeEx.

// This is only needed in Win32 desktop apps
CoInitializeEx( nullptr, COINIT_MULTITHREADED );

All DirectXTK for Audio components require an AudioEngine instance. For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr.

std::unique_ptr<AudioEngine> audEngine( new AudioEngine() );

The constructor optionally takes a number of parameters:

AudioEngine( AUDIO_ENGINE_FLAGS flags = AudioEngine_Default,
    _In_opt_ const WAVEFORMATEX* wfx = nullptr,
    _In_opt_z_ constwchar_t* deviceId = nullptr,
    AUDIO_STREAM_CATEGORY category = AudioCategory_GameEffects );

flags
A combination of audio engine flags. Defaults to AudioEngine_Default.
  • AudioEngine_Debug - Enables debugging facilities. For XAudio 2.7 this requires the Developer Runtime.
  • AudioEngine_EnvironmentalReverb - Enables I3DL2 environmental reverb effects for 3D positional audio.
  • AudioEngine_ReverbUseFilters - An additional feature for 3D positional audio reverb. Requires AudioEngine_EnvironmentalReverb.
  • AudioEngine_UseMasteringLimiter - Enables a mastering volume limiter xAPO for the mastering voice. This is recommended for avoiding distortion or clipping, particularly when applying 3D positional audio.
  • AudioEngine_DisableVoiceReuse - By default, DirectXTK for Audio will reuse XAudio2 source voices for one-shots if possible. If using this flag, voice reuse is disabled and one-shot sounds will create and destroy source voices on every Play.
  • AudioEngine_ThrowOnNoAudioHW - By default, if there is no audio hardware available DirectXTK for Audio will automatically enter 'silent mode'. If this flag is provided, a C++ exception is generated instead.
Note: AUDIO_ENGINE_FLAGS is used as a typed flag enum. Only operator| is overloaded to combine them, so operations like |= are not available without additional static_cast<> statements.
wfx
Specifies the output format for the XAudio2 mastering voice (primarily the channel count and sample rate). If null, it uses the device defaults.
deviceId
Specifies the output debug for the XAudio2 mastering voice. When using XAudio 2.8, this must be a WinRT device identifier, while on XAudio 2.7 this is a WASAPI audio end-point identifier. If null, it uses the default audio device.
category
Specifies the audio end-point category for the XAudio2 mastering voice. On XAudio 2.7, this value is ignored.

Debugging facilities

When creating the AudioEngine, you can specify enabling of XAudio2 debugging facilities by including the AudioEngine_Debug flag.

AUDIO_ENGINE_FLAGS eflags = AudioEngine_Default;
#ifdef _DEBUG
eflags = eflags | AudioEngine_Debug;
#endif
std::unique_ptr<AudioEngine> audEngine( new AudioEngine( eflags ) );

http://msdn.microsoft.com/en-us/library/windows/desktop/ee415752.aspx

Note: With XAudio 2.7, the developer runtime must be installed on the system for the AudioEngine_Debug case to succeed. With XAudio 2.8 on Windows 8.x, the debug support is built into the OS.

Device enumeration

AudioEngine provides a simple wrapper over the platform-specific audio device enumeration:

auto enumList = AudioEngine::GetRendererDetails();

if ( enumList.empty() )
{
    // No audio devices
}
else
{
   for( auto it = enumList.cbegin(); it != enumList.cend(); ++it )
   {
       // it->deviceId.c_str() - this is the device/end-point identifier you can//     pass as a parameter to AudioEngine// it->description.c_str() - this is a textual description
   }
}

Note: On Windows phone 8 and Xbox One, the enumeration only returns the 'default' audio device identifier with the description "Default"

Silent mode

If the initial device creation fails to find an audio device, by default AudioEngine creation will succeed and be in a 'silent' mode--if AudioEngine_ThrowOnNoAudioHW is given, then it will throw a C++ exception instead. This allows various DirectXTK for Audio objects to be created and methods called, but no audio processing will take place. This can be detected either by a 'false' return from Update () or calling IsAudioDevicePresent ().

At some later point (typically after detecting a new audio device is available on the system), you can retry by calling Reset (). If this returns 'true', then the AudioEngine is no longer in 'silent' mode. After that, future calls to SoundEffect or WaveBank's Play() will result in one-shots being fired. All SoundEffectInstances are in a stopped state, but can be started after the successful call to Reset().

bool Reset( _In_opt_ const WAVEFORMATEX* wfx = nullptr,
    _In_opt_z_ constwchar_t* deviceId = nullptr );

Parameters to Reset are the similar as for the AudioEngine constructor. If the original object was created with AudioEngine_ThrowOnNoAudioHW, then Reset will throw if no default audio device is found.

Win32 desktop applications

For Win32 desktop applications, you can be informed of new audio devices in your application with:

#include <dbt.h>

...

DEV_BROADCAST_DEVICEINTERFACE filter = {0};
filter.dbcc_size = sizeof( filter );
filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
filter.dbcc_classguid = KSCATEGORY_AUDIO;

HDEVNOTIFY hNewAudio = RegisterDeviceNotification( hwnd, &filter, DEVICE_NOTIFY_WINDOW_HANDLE );

...

case WM_DEVICECHANGE:
    if ( wParam == DBT_DEVICEARRIVAL ) {
        auto pDev = reinterpret_cast<PDEV_BROADCAST_HDR>( lParam );
        if( pDev ) {
            if ( pDev->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE ) {
                auto pInter =
                    reinterpret_cast<const PDEV_BROADCAST_DEVICEINTERFACE>( pDev );
                if ( pInter->dbcc_classguid == KSCATEGORY_AUDIO ) {
                    // New audio device

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363431.aspx

Or you can make use of IMMNotificationClient

http://msdn.microsoft.com/en-us/library/windows/desktop/dd371417.aspx

Windows Store applications

You can be informed of new audio devices by using the WinRT class DeviceWatcher in the Windows.Device.Enumeration namespace.

http://code.msdn.microsoft.com/windowsapps/Device-Enumeration-Sample-a6e45169

Per-frame processing

Update () should be called often, usually in a per-frame update. This can be done on the main rendering thread, or from a worker thread. This returns false if the audio engine is the 'silent' mode.

if ( !audEngine->Update() )
{
    // No audio device is activeif ( audEngine->IsCriticalError() )
    {
        ...
    }    
}

Note that if XAudio2 encounters a critical error (typically because the current audio device is disconnected or on the Windows platform if the speakers are unplugged from the current audio device), then the audio engine will automatically be in 'silent' mode. This can be detected either by a 'false' return from Update() or calling IsCriticalError(). If this occurs, you should try calling Reset() to try the new 'default' device' if there is one. If that retry fails, you should wait until a new audio device is available (ala 'silent' mode above).

Pausing

Typically games will suspend audio when paused or the game is 'tabbed away' from. Suspend () and Resume () can be used to globally halt/restart audio processing.

Positional 3D audio

AudioEngine by default supports both standard and positional 3D audio voices, but without environmental reverb. If AudioEngine_EnvironmentalReverb is given, then a reverb effect is created and used for all 3D audio voices--it is not applied to standard voices. You can use SetReverb () with I3DL2 presets or provide 'native' reverb settings.

audEngine->SetReverb( Reverb_Quarry );

...

audEngine->SetReverb( Reverb_Off );

Optionally AudioEngine_ReverbUseFilters can be used with AudioEngine_EnvironmentalReverb to provide some additional reverb/occlusion effects.

Voice management

  • SetDefaultSampleRate( sampleRate ) is used to control the sample rate for voices in the one-shot pool (see Play in SoundEffect and WaveBank). This should be the same rate as used by the majority of your content. It defaults to 44100 Hz. This value is never used if AudioEngine_DisableVoiceReuse was specified.
  • TrimVoicePool() can be used to free up any source voices in the 'idle' list for one-shots, and will cause all non-playing SoundEffectInstance objects to release their source voice. This is used for keeping the total source voice count under a limit for performance or when switching sections where audio content formats change dramatically.
Note that one-shots voices must have completely stopped playing before they are put into the idle pool. You should therefore ensure Update() is called twice with some delay between them before calling TrimVoicePool() for maximum effectiveness.
  • SetMaxVoicePool( maxOneShots, maxInstances ) can be used to set a limit on the number of one-shot source voices allocated and/or to put a limit on the source voices available for SoundEffectInstance. If there are insufficient one-shot voices, those sounds will not be heard. If there are insufficient voices for a SoundEffectInstance to play, then a C++ exception is thrown. These values default to 'unlimited'.

Mastering volume limiter

The XAudio2 audio renderer makes use of single-precision floating-point values, which can exceed the range of the audio hardware, particularly after 3D positional audio computations, custom xAPOs, or volume settings greater than 1.0. This can produce distortion or other clipping artifacts in the final output.

Therefore, DirectXTK for Audio supports attaching a mastering volume limiter xAPO to the mastering voice by setting the AudioEngine_UseMasteringLimiter flag. It uses default settings, which can be modified by calling SetMasteringLimit( release, loudness ).

http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.xapofx.fxmasteringlimiter_parameters.aspx

AUDIO_ENGINE_FLAGS eflags = AudioEngine_UseMasteringLimiter;
#ifdef _DEBUG
eflags = eflags | AudioEngine_Debug;
#endif
std::unique_ptr<AudioEngine> audEngine( new AudioEngine( eflags ) );

Statistics

The GetStatistics function returns information on the number of playing sounds, allocated instances, audio bytes in loaded SoundEffect and WaveBank objects, and XAudio2 source voices allocated for various purposes. These values do not rely on debug faculties to be enabled.

auto stats = engine->GetStatistics();
printf( "\nPlaying: %Iu / %Iu; Instances %Iu; Voices %Iu / %Iu / %Iu / %Iu; %Iu audio bytes\n",
    stats.playingOneShots, stats.playingInstances,
    stats.allocatedInstances, stats.allocatedVoices, stats.allocatedVoices3d,
    stats.allocatedVoicesOneShot, stats.allocatedVoicesIdle,
    stats.audioBytes );

Properties

  • GetOutputFormat ()
Returns the format consumed by the mastering voice (which is the same as the device output if defaults are used) as a WAVEFORMATEXTENSIBLE.
  • GetChannelMask ()
Returns the output channel mask
  • GetOutputChannels ()
Returns the number of output channels
  • IsAudioDevicePresent ()
Returns true if the audio graph is operating normally, false if in 'silent mode'
  • IsCriticalError ()
Returns true if the audio graph is halted due to a critical error (which also places the engine into 'silent mode')

Low-level interface access

The following methods can be used to obtain the low-level XAudio2 interface objects used by DirectXTK for Audio. Be sure to also use RegisterNotify, UnregisterNotify, and the IVoiceNotify interface to get proper notifications from the XAudio2 engine. You should prefer to use AllocateVoice to creating your own source voices if possible, and be sure to use DestroyVoice to free the source voice if it is not a 'oneshot' voice. One shot voices are managed and cleaned up by AudioEngine::Update().
  • IXAudio2* GetInterface ()
  • IXAudio2MasteringVoice* GetMasterVoice ()
  • IXAudio2SubmixVoice* GetReverbVoice ()
  • X3DAUDIO_HANDLE& Get3DHandle ()

Further reading

http://msdn.microsoft.com/en-us/library/windows/desktop/hh405049.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ee415754.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ee415714.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd371455.aspx

Updated Wiki: AudioEngine

This class represents an XAudio2 audio graph, device, and mastering voice

Header

#include <Audio.h>

Initialization

This creates an XAudio2 interface, an XAudio2 mastering voice, and other global resources.

XAudio2 requires COM be initialized as a prerequisite using Windows::Foundation::Initialize, CoInitialize, or CoInitializeEx.

// This is only needed in Win32 desktop apps
CoInitializeEx( nullptr, COINIT_MULTITHREADED );

All DirectXTK for Audio components require an AudioEngine instance. For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr.

std::unique_ptr<AudioEngine> audEngine( new AudioEngine() );

The constructor optionally takes a number of parameters:

AudioEngine( AUDIO_ENGINE_FLAGS flags = AudioEngine_Default,
    _In_opt_ const WAVEFORMATEX* wfx = nullptr,
    _In_opt_z_ constwchar_t* deviceId = nullptr,
    AUDIO_STREAM_CATEGORY category = AudioCategory_GameEffects );

Parameters

flags
A combination of audio engine flags. Defaults to AudioEngine_Default.
  • AudioEngine_Debug - Enables debugging facilities. For XAudio 2.7 this requires the Developer Runtime.
  • AudioEngine_EnvironmentalReverb - Enables I3DL2 environmental reverb effects for 3D positional audio.
  • AudioEngine_ReverbUseFilters - An additional feature for 3D positional audio reverb. Requires AudioEngine_EnvironmentalReverb.
  • AudioEngine_UseMasteringLimiter - Enables a mastering volume limiter xAPO for the mastering voice. This is recommended for avoiding distortion or clipping, particularly when applying 3D positional audio.
  • AudioEngine_DisableVoiceReuse - By default, DirectXTK for Audio will reuse XAudio2 source voices for one-shots if possible. If using this flag, voice reuse is disabled and one-shot sounds will create and destroy source voices on every Play.
  • AudioEngine_ThrowOnNoAudioHW - By default, if there is no audio hardware available DirectXTK for Audio will automatically enter 'silent mode'. If this flag is provided, a C++ exception is generated instead.
Note: AUDIO_ENGINE_FLAGS is used as a typed flag enum. Only operator| is overloaded to combine them, so operations like |= are not available without additional static_cast<> statements.
wfx
Specifies the output format for the XAudio2 mastering voice (primarily the channel count and sample rate). If null, it uses the device defaults.
deviceId
Specifies the output debug for the XAudio2 mastering voice. When using XAudio 2.8, this must be a WinRT device identifier, while on XAudio 2.7 this is a WASAPI audio end-point identifier. If null, it uses the default audio device.
category
Specifies the audio end-point category for the XAudio2 mastering voice. On XAudio 2.7, this value is ignored.

Debugging facilities

When creating the AudioEngine, you can specify enabling of XAudio2 debugging facilities by including the AudioEngine_Debug flag.

AUDIO_ENGINE_FLAGS eflags = AudioEngine_Default;
#ifdef _DEBUG
eflags = eflags | AudioEngine_Debug;
#endif
std::unique_ptr<AudioEngine> audEngine( new AudioEngine( eflags ) );

http://msdn.microsoft.com/en-us/library/windows/desktop/ee415752.aspx

Note: With XAudio 2.7, the developer runtime must be installed on the system for the AudioEngine_Debug case to succeed. With XAudio 2.8 on Windows 8.x, the debug support is built into the OS.

Device enumeration

AudioEngine provides a simple wrapper over the platform-specific audio device enumeration:

auto enumList = AudioEngine::GetRendererDetails();

if ( enumList.empty() )
{
    // No audio devices
}
else
{
   for( auto it = enumList.cbegin(); it != enumList.cend(); ++it )
   {
       // it->deviceId.c_str() - this is the device/end-point identifier you can//     pass as a parameter to AudioEngine// it->description.c_str() - this is a textual description
   }
}

Note: On Windows phone 8 and Xbox One, the enumeration only returns the 'default' audio device identifier with the description "Default"

Silent mode

If the initial device creation fails to find an audio device, by default AudioEngine creation will succeed and be in a 'silent' mode--if AudioEngine_ThrowOnNoAudioHW is given, then it will throw a C++ exception instead. This allows various DirectXTK for Audio objects to be created and methods called, but no audio processing will take place. This can be detected either by a 'false' return from Update () or calling IsAudioDevicePresent ().

At some later point (typically after detecting a new audio device is available on the system), you can retry by calling Reset (). If this returns 'true', then the AudioEngine is no longer in 'silent' mode. After that, future calls to SoundEffect or WaveBank's Play() will result in one-shots being fired. All SoundEffectInstances are in a stopped state, but can be started after the successful call to Reset().

bool Reset( _In_opt_ const WAVEFORMATEX* wfx = nullptr,
    _In_opt_z_ constwchar_t* deviceId = nullptr );

Parameters to Reset are the similar as for the AudioEngine constructor. If the original object was created with AudioEngine_ThrowOnNoAudioHW, then Reset will throw if no default audio device is found.

Win32 desktop applications

For Win32 desktop applications, you can be informed of new audio devices in your application with:

#include <dbt.h>

...

DEV_BROADCAST_DEVICEINTERFACE filter = {0};
filter.dbcc_size = sizeof( filter );
filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
filter.dbcc_classguid = KSCATEGORY_AUDIO;

HDEVNOTIFY hNewAudio = RegisterDeviceNotification( hwnd, &filter, DEVICE_NOTIFY_WINDOW_HANDLE );

...

case WM_DEVICECHANGE:
    if ( wParam == DBT_DEVICEARRIVAL ) {
        auto pDev = reinterpret_cast<PDEV_BROADCAST_HDR>( lParam );
        if( pDev ) {
            if ( pDev->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE ) {
                auto pInter =
                    reinterpret_cast<const PDEV_BROADCAST_DEVICEINTERFACE>( pDev );
                if ( pInter->dbcc_classguid == KSCATEGORY_AUDIO ) {
                    // New audio device

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363431.aspx

Or you can make use of IMMNotificationClient

http://msdn.microsoft.com/en-us/library/windows/desktop/dd371417.aspx

Windows Store applications

You can be informed of new audio devices by using the WinRT class DeviceWatcher in the Windows.Device.Enumeration namespace.

http://code.msdn.microsoft.com/windowsapps/Device-Enumeration-Sample-a6e45169

Per-frame processing

Update () should be called often, usually in a per-frame update. This can be done on the main rendering thread, or from a worker thread. This returns false if the audio engine is the 'silent' mode.

if ( !audEngine->Update() )
{
    // No audio device is activeif ( audEngine->IsCriticalError() )
    {
        ...
    }    
}

Note that if XAudio2 encounters a critical error (typically because the current audio device is disconnected or on the Windows platform if the speakers are unplugged from the current audio device), then the audio engine will automatically be in 'silent' mode. This can be detected either by a 'false' return from Update() or calling IsCriticalError(). If this occurs, you should try calling Reset() to try the new 'default' device' if there is one. If that retry fails, you should wait until a new audio device is available (ala 'silent' mode above).

Pausing

Typically games will suspend audio when paused or the game is 'tabbed away' from. Suspend () and Resume () can be used to globally halt/restart audio processing.

Positional 3D audio

AudioEngine by default supports both standard and positional 3D audio voices, but without environmental reverb. If AudioEngine_EnvironmentalReverb is given, then a reverb effect is created and used for all 3D audio voices--it is not applied to standard voices. You can use SetReverb () with I3DL2 presets or provide 'native' reverb settings.

audEngine->SetReverb( Reverb_Quarry );

...

audEngine->SetReverb( Reverb_Off );

Optionally AudioEngine_ReverbUseFilters can be used with AudioEngine_EnvironmentalReverb to provide some additional reverb/occlusion effects.

Voice management

  • SetDefaultSampleRate( sampleRate ) is used to control the sample rate for voices in the one-shot pool (see Play in SoundEffect and WaveBank). This should be the same rate as used by the majority of your content. It defaults to 44100 Hz. This value is never used if AudioEngine_DisableVoiceReuse was specified.
  • TrimVoicePool() can be used to free up any source voices in the 'idle' list for one-shots, and will cause all non-playing SoundEffectInstance objects to release their source voice. This is used for keeping the total source voice count under a limit for performance or when switching sections where audio content formats change dramatically.
Note that one-shots voices must have completely stopped playing before they are put into the idle pool. You should therefore ensure Update() is called twice with some delay between them before calling TrimVoicePool() for maximum effectiveness.
  • SetMaxVoicePool( maxOneShots, maxInstances ) can be used to set a limit on the number of one-shot source voices allocated and/or to put a limit on the source voices available for SoundEffectInstance. If there are insufficient one-shot voices, those sounds will not be heard. If there are insufficient voices for a SoundEffectInstance to play, then a C++ exception is thrown. These values default to 'unlimited'.

Mastering volume limiter

The XAudio2 audio renderer makes use of single-precision floating-point values, which can exceed the range of the audio hardware, particularly after 3D positional audio computations, custom xAPOs, or volume settings greater than 1.0. This can produce distortion or other clipping artifacts in the final output.

Therefore, DirectXTK for Audio supports attaching a mastering volume limiter xAPO to the mastering voice by setting the AudioEngine_UseMasteringLimiter flag. It uses default settings, which can be modified by calling SetMasteringLimit( release, loudness ).

http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.xapofx.fxmasteringlimiter_parameters.aspx

AUDIO_ENGINE_FLAGS eflags = AudioEngine_UseMasteringLimiter;
#ifdef _DEBUG
eflags = eflags | AudioEngine_Debug;
#endif
std::unique_ptr<AudioEngine> audEngine( new AudioEngine( eflags ) );

Statistics

The GetStatistics function returns information on the number of playing sounds, allocated instances, audio bytes in loaded SoundEffect and WaveBank objects, and XAudio2 source voices allocated for various purposes. These values do not rely on debug faculties to be enabled.

auto stats = engine->GetStatistics();
printf( "\nPlaying: %Iu / %Iu; Instances %Iu; Voices %Iu / %Iu / %Iu / %Iu; %Iu audio bytes\n",
    stats.playingOneShots, stats.playingInstances,
    stats.allocatedInstances, stats.allocatedVoices, stats.allocatedVoices3d,
    stats.allocatedVoicesOneShot, stats.allocatedVoicesIdle,
    stats.audioBytes );

Properties

  • GetOutputFormat ()
Returns the format consumed by the mastering voice (which is the same as the device output if defaults are used) as a WAVEFORMATEXTENSIBLE.
  • GetChannelMask ()
Returns the output channel mask
  • GetOutputChannels ()
Returns the number of output channels
  • IsAudioDevicePresent ()
Returns true if the audio graph is operating normally, false if in 'silent mode'
  • IsCriticalError ()
Returns true if the audio graph is halted due to a critical error (which also places the engine into 'silent mode')

Low-level interface access

The following methods can be used to obtain the low-level XAudio2 interface objects used by DirectXTK for Audio. Be sure to also use RegisterNotify, UnregisterNotify, and the IVoiceNotify interface to get proper notifications from the XAudio2 engine. You should prefer to use AllocateVoice to creating your own source voices if possible, and be sure to use DestroyVoice to free the source voice if it is not a 'oneshot' voice. One shot voices are managed and cleaned up by AudioEngine::Update().
  • IXAudio2* GetInterface ()
  • IXAudio2MasteringVoice* GetMasterVoice ()
  • IXAudio2SubmixVoice* GetReverbVoice ()
  • X3DAUDIO_HANDLE& Get3DHandle ()

Further reading

http://msdn.microsoft.com/en-us/library/windows/desktop/hh405049.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ee415754.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ee415714.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd371455.aspx

Updated Wiki: AudioEngine

This class represents an XAudio2 audio graph, device, and mastering voice

Header

#include <Audio.h>

Initialization

This creates an XAudio2 interface, an XAudio2 mastering voice, and other global resources.

XAudio2 requires COM be initialized as a prerequisite using Windows::Foundation::Initialize, CoInitialize, or CoInitializeEx.

// This is only needed in Win32 desktop apps
CoInitializeEx( nullptr, COINIT_MULTITHREADED );

All DirectXTK for Audio components require an AudioEngine instance. For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr.

std::unique_ptr<AudioEngine> audEngine( new AudioEngine() );

The constructor optionally takes a number of parameters:

AudioEngine( AUDIO_ENGINE_FLAGS flags = AudioEngine_Default,
    _In_opt_ const WAVEFORMATEX* wfx = nullptr,
    _In_opt_z_ constwchar_t* deviceId = nullptr,
    AUDIO_STREAM_CATEGORY category = AudioCategory_GameEffects );

Parameters

flags
A combination of audio engine flags. Defaults to AudioEngine_Default.
  • AudioEngine_Debug - Enables debugging facilities. For XAudio 2.7 this requires the Developer Runtime.
  • AudioEngine_EnvironmentalReverb - Enables I3DL2 environmental reverb effects for 3D positional audio.
  • AudioEngine_ReverbUseFilters - An additional feature for 3D positional audio reverb. Requires AudioEngine_EnvironmentalReverb.
  • AudioEngine_UseMasteringLimiter - Enables a mastering volume limiter xAPO for the mastering voice. This is recommended for avoiding distortion or clipping, particularly when applying 3D positional audio.
  • AudioEngine_DisableVoiceReuse - By default, DirectXTK for Audio will reuse XAudio2 source voices for one-shots if possible. If using this flag, voice reuse is disabled and one-shot sounds will create and destroy source voices on every Play.
  • AudioEngine_ThrowOnNoAudioHW - By default, if there is no audio hardware available DirectXTK for Audio will automatically enter 'silent mode'. If this flag is provided, a C++ exception is generated instead.
Note: AUDIO_ENGINE_FLAGS is used as a typed flag enum. Only operator| is overloaded to combine them, so operations like |= are not available without additional static_cast<> statements.
wfx
Specifies the output format for the XAudio2 mastering voice (primarily the channel count and sample rate). If null, it uses the device defaults.
deviceId
Specifies the output debug for the XAudio2 mastering voice. When using XAudio 2.8, this must be a WinRT device identifier, while on XAudio 2.7 this is a WASAPI audio end-point identifier. If null, it uses the default audio device.
category
Specifies the audio end-point category for the XAudio2 mastering voice. On XAudio 2.7, this value is ignored.

Debugging facilities

When creating the AudioEngine, you can specify enabling of XAudio2 debugging facilities by including the AudioEngine_Debug flag.

AUDIO_ENGINE_FLAGS eflags = AudioEngine_Default;
#ifdef _DEBUG
eflags = eflags | AudioEngine_Debug;
#endif
std::unique_ptr<AudioEngine> audEngine( new AudioEngine( eflags ) );

http://msdn.microsoft.com/en-us/library/windows/desktop/ee415752.aspx

Note: With XAudio 2.7, the developer runtime must be installed on the system for the AudioEngine_Debug case to succeed. With XAudio 2.8 on Windows 8.x, the debug support is built into the OS.

Device enumeration

AudioEngine provides a simple wrapper over the platform-specific audio device enumeration:

auto enumList = AudioEngine::GetRendererDetails();

if ( enumList.empty() )
{
    // No audio devices
}
else
{
   for( auto it = enumList.cbegin(); it != enumList.cend(); ++it )
   {
       // it->deviceId.c_str() - this is the device/end-point identifier you can//     pass as a parameter to AudioEngine// it->description.c_str() - this is a textual description
   }
}

Windows phone 8 and Xbox One: The enumeration only returns the 'default' audio device identifier with the description "Default"

Silent mode

If the initial device creation fails to find an audio device, by default AudioEngine creation will succeed and be in a 'silent' mode--if AudioEngine_ThrowOnNoAudioHW is given, then it will throw a C++ exception instead. This allows various DirectXTK for Audio objects to be created and methods called, but no audio processing will take place. This can be detected either by a 'false' return from Update () or calling IsAudioDevicePresent ().

At some later point (typically after detecting a new audio device is available on the system), you can retry by calling Reset (). If this returns 'true', then the AudioEngine is no longer in 'silent' mode. After that, future calls to SoundEffect or WaveBank's Play() will result in one-shots being fired. All SoundEffectInstances are in a stopped state, but can be started after the successful call to Reset().

bool Reset( _In_opt_ const WAVEFORMATEX* wfx = nullptr,
    _In_opt_z_ constwchar_t* deviceId = nullptr );

Parameters to Reset are the similar as for the AudioEngine constructor. If the original object was created with AudioEngine_ThrowOnNoAudioHW, then Reset will throw if no default audio device is found.

Win32 desktop applications

For Win32 desktop applications, you can be informed of new audio devices in your application with:

#include <dbt.h>

...

DEV_BROADCAST_DEVICEINTERFACE filter = {0};
filter.dbcc_size = sizeof( filter );
filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
filter.dbcc_classguid = KSCATEGORY_AUDIO;

HDEVNOTIFY hNewAudio = RegisterDeviceNotification( hwnd, &filter, DEVICE_NOTIFY_WINDOW_HANDLE );

...

case WM_DEVICECHANGE:
    if ( wParam == DBT_DEVICEARRIVAL ) {
        auto pDev = reinterpret_cast<PDEV_BROADCAST_HDR>( lParam );
        if( pDev ) {
            if ( pDev->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE ) {
                auto pInter =
                    reinterpret_cast<const PDEV_BROADCAST_DEVICEINTERFACE>( pDev );
                if ( pInter->dbcc_classguid == KSCATEGORY_AUDIO ) {
                    // New audio device

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363431.aspx

Or you can make use of IMMNotificationClient

http://msdn.microsoft.com/en-us/library/windows/desktop/dd371417.aspx

Windows Store applications

You can be informed of new audio devices by using the WinRT class DeviceWatcher in the Windows.Device.Enumeration namespace.

http://code.msdn.microsoft.com/windowsapps/Device-Enumeration-Sample-a6e45169

Per-frame processing

Update () should be called often, usually in a per-frame update. This can be done on the main rendering thread, or from a worker thread. This returns false if the audio engine is the 'silent' mode.

if ( !audEngine->Update() )
{
    // No audio device is activeif ( audEngine->IsCriticalError() )
    {
        ...
    }    
}

Note that if XAudio2 encounters a critical error (typically because the current audio device is disconnected or on the Windows platform if the speakers are unplugged from the current audio device), then the audio engine will automatically be in 'silent' mode. This can be detected either by a 'false' return from Update() or calling IsCriticalError(). If this occurs, you should try calling Reset() to try the new 'default' device' if there is one. If that retry fails, you should wait until a new audio device is available (ala 'silent' mode above).

Pausing

Typically games will suspend audio when paused or the game is 'tabbed away' from. Suspend () and Resume () can be used to globally halt/restart audio processing.

Positional 3D audio

AudioEngine by default supports both standard and positional 3D audio voices, but without environmental reverb. If AudioEngine_EnvironmentalReverb is given, then a reverb effect is created and used for all 3D audio voices--it is not applied to standard voices. You can use SetReverb () with I3DL2 presets or provide 'native' reverb settings.

audEngine->SetReverb( Reverb_Quarry );

...

audEngine->SetReverb( Reverb_Off );

Optionally AudioEngine_ReverbUseFilters can be used with AudioEngine_EnvironmentalReverb to provide some additional reverb/occlusion effects.

Voice management

  • SetDefaultSampleRate( sampleRate ) is used to control the sample rate for voices in the one-shot pool (see Play in SoundEffect and WaveBank). This should be the same rate as used by the majority of your content. It defaults to 44100 Hz. This value is never used if AudioEngine_DisableVoiceReuse was specified.
  • TrimVoicePool() can be used to free up any source voices in the 'idle' list for one-shots, and will cause all non-playing SoundEffectInstance objects to release their source voice. This is used for keeping the total source voice count under a limit for performance or when switching sections where audio content formats change dramatically.
Note that one-shots voices must have completely stopped playing before they are put into the idle pool. You should therefore ensure Update() is called twice with some delay between them before calling TrimVoicePool() for maximum effectiveness.
  • SetMaxVoicePool( maxOneShots, maxInstances ) can be used to set a limit on the number of one-shot source voices allocated and/or to put a limit on the source voices available for SoundEffectInstance. If there are insufficient one-shot voices, those sounds will not be heard. If there are insufficient voices for a SoundEffectInstance to play, then a C++ exception is thrown. These values default to 'unlimited'.

Mastering volume limiter

The XAudio2 audio renderer makes use of single-precision floating-point values, which can exceed the range of the audio hardware, particularly after 3D positional audio computations, custom xAPOs, or volume settings greater than 1.0. This can produce distortion or other clipping artifacts in the final output.

Therefore, DirectXTK for Audio supports attaching a mastering volume limiter xAPO to the mastering voice by setting the AudioEngine_UseMasteringLimiter flag. It uses default settings, which can be modified by calling SetMasteringLimit( release, loudness ).

http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.xapofx.fxmasteringlimiter_parameters.aspx

AUDIO_ENGINE_FLAGS eflags = AudioEngine_UseMasteringLimiter;
#ifdef _DEBUG
eflags = eflags | AudioEngine_Debug;
#endif
std::unique_ptr<AudioEngine> audEngine( new AudioEngine( eflags ) );

Statistics

The GetStatistics function returns information on the number of playing sounds, allocated instances, audio bytes in loaded SoundEffect and WaveBank objects, and XAudio2 source voices allocated for various purposes. These values do not rely on debug faculties to be enabled.

auto stats = engine->GetStatistics();
printf( "\nPlaying: %Iu / %Iu; Instances %Iu; Voices %Iu / %Iu / %Iu / %Iu; %Iu audio bytes\n",
    stats.playingOneShots, stats.playingInstances,
    stats.allocatedInstances, stats.allocatedVoices, stats.allocatedVoices3d,
    stats.allocatedVoicesOneShot, stats.allocatedVoicesIdle,
    stats.audioBytes );

Properties

  • GetOutputFormat ()
Returns the format consumed by the mastering voice (which is the same as the device output if defaults are used) as a WAVEFORMATEXTENSIBLE.
  • GetChannelMask ()
Returns the output channel mask
  • GetOutputChannels ()
Returns the number of output channels
  • IsAudioDevicePresent ()
Returns true if the audio graph is operating normally, false if in 'silent mode'
  • IsCriticalError ()
Returns true if the audio graph is halted due to a critical error (which also places the engine into 'silent mode')

Low-level interface access

The following methods can be used to obtain the low-level XAudio2 interface objects used by DirectXTK for Audio. Be sure to also use RegisterNotify, UnregisterNotify, and the IVoiceNotify interface to get proper notifications from the XAudio2 engine. You should prefer to use AllocateVoice to creating your own source voices if possible, and be sure to use DestroyVoice to free the source voice if it is not a 'oneshot' voice. One shot voices are managed and cleaned up by AudioEngine::Update().
  • IXAudio2* GetInterface ()
  • IXAudio2MasteringVoice* GetMasterVoice ()
  • IXAudio2SubmixVoice* GetReverbVoice ()
  • X3DAUDIO_HANDLE& Get3DHandle ()

Further reading

http://msdn.microsoft.com/en-us/library/windows/desktop/hh405049.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ee415754.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ee415714.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd371455.aspx

Updated Wiki: Audio

The DirectXTK for Audio components implement a low-level audio API similar to XNA Game Studio's Microsoft.Xna.Framework.Audio. This consists of the following classes all declared in the Audio.h header (in the Inc folder of the distribution):
  • AudioEngine - This class represents an XAudio2 audio graph, device, and mastering voice.
  • SoundEffect - A container class for sound resources which can be loaded from .wav files.
  • SoundEffectInstance - Provides a single playing, paused, or stopped instance of a sound
  • DynamicSoundEffectInstance - SoundEffectInstance where the application provides the audio data on demand
  • WaveBank - A container class for sound resources packaged into an XACT-style .xwb wave bank.
  • AudioListener, AudioEmitter - Utility classes used with SoundEffectInstance::Apply3D.
Note: DirectXTK for Audio uses XAudio 2. It does not make use of the legacy XACT Engine, XACT Cue, or XACT SoundBank.

Related tutorials:Adding the DirectX Tool Kit for Audio, Adding audio to your project, Creating and playing sounds, Using positional audio

Header

#include <Audio.h>

Initialization

The first step in using DirectXTK for Audio is to create the AudioEngine, which creates an XAudio2 interface, an XAudio2 mastering voice, and other global resources.

// This is only needed in Windows desktop apps
CoInitializeEx( nullptr, COINIT_MULTITHREADED );

AUDIO_ENGINE_FLAGS eflags = AudioEngine_Default;
#ifdef _DEBUG
eflags = eflags | AudioEngine_Debug;
#endif
std::unique_ptr<AudioEngine> audEngine( new AudioEngine( eflags ) );

Per-frame processing

The application should call Update () every frame to allow for per-frame engine updates, such as one-shot voice management. This could also be done in a worker thread rather than on the main rendering thread.

if ( !audEngine->Update() )
{
    // No audio device is activeif ( audEngine->IsCriticalError() )
    {
        ...
    }    
}

Update() returns false if no audio is actually playing (either due to there being no audio device on the system at the time AudioEngine was created, or because XAudio2 encountered a Critical Error--typically due to speakers being unplugged). Calls to various DirectXTK for Audio methods can still be made in this state but no actual audio processing will take place. See AudioEngine for more information.

Loading and a playing a looping sound

Creating SoundEffectInstances allows full control over the playback, and are provided with a dedicated XAudio2 source voice. This allows control of playback, looping, volume control, panning, and pitch-shifting.

std::unique_ptr<SoundEffect> soundEffect( new SoundEffect( audEngine.get(), L"Sound.wav" ) );
auto effect = soundEffect->CreateInstance();

...

effect->Play( true );

Playing one-shots

A common way to play sounds is to trigger them in a 'fire-and-forget' mode. This is done by calling SoundEffect::Play() rather than creating a SoundEffectInstance. These use XAudio2 source voices managed by AudioEngine, are cleaned up automatically when they finish playing, and can overlap in time. One-shot sounds cannot be looped or have positional 3D effects.

std::unique_ptr<SoundEffect> soundEffect( new SoundEffect( audEngine.get(), L"Explosion.wav" ) );
soundEffect->Play();

...

soundEffect->Play();

Applying 3D audio effects to a sound

DirectXTK for Audio supports positional 3D audio with optional environmental reverb effects using X3DAudio.

AUDIO_ENGINE_FLAGS eflags =  AudioEngine_EnvironmentalReverb
            | AudioEngine_ReverbUseFilters;
#ifdef _DEBUG
eflags = eflags | AudioEngine_Debug;
#endif
std::unique_ptr<AudioEngine> audEngine( new AudioEngine( eflags ) );
audEngine->SetReverb( Reverb_ConcertHall );

...

std::unique_ptr<SoundEffect> soundEffect( new SoundEffect( audEngine.get(), L"Sound.wav" ) );
auto effect = soundEffect->CreateInstance( SoundEffectInstance_Use3D | SoundEffectInstance_ReverbUseFilters );

...

effect->Play(true);

...

AudioListener listener;
listener.SetPosition( ... );

AudioEmitter emitter;
emitter.SetPosition( ... );

effect->Apply3D( listener, emitter );

Note: A C++ exception is thrown if you call Apply3D for a SoundEffectInstance that was not created with SoundEffectInstance_Use3D

Using wave banks

Rather than loading individual .wav files, a more efficient method is to package them into a "wave bank". This allows for more efficient loading and memory organization. DirectXTK for Audio's WaveBank class can be used to play one-shots or to create SoundEffectInstances from 'in-memory' wave banks.

std::unique_ptr<WaveBank> wb( new WaveBank( audEngine.get(), L"wavebank.xwb" ) );

A SoundEffectInstance can be created from a wavebank referencing a particular wave in the bank:

auto effect = wb->CreateInstance( 10 );
if ( !effect )
    // Error (invalid index for wave bank)

...

effect->Play( true );

One-shot sounds can also be played directly from the wave bank.

wb->Play( 2 );
wb->Play( 6 );

XACT3-style "wave banks" can be created by using the XWBTool command-line tool, or they can be authored using XACT3 in the DirectX SDK. Note that the XWBTool will not perform any format conversions or compression, so more full-featured options are better handled with the XACT3 GUI or XACTBLD, or it can be used on .wav files already compressed by adpcmencode.exe, xwmaencode.exe, xma2encode.exe, etc.

xwbtool -o wavebank.xwb Sound.wav Explosion.wav Music.wav

DirectXTK for Audio does not make use of the XACT engine, nor does it make use of XACT "sound banks" .xsb or "cues". We only use .xwb wave banks as a method for packing .wav data.

Voice management

Each instance of a SoundEffectInstance will allocate it's own source voice when played, which won't be released until it is destroyed. Each time a one-shot sound is played from a SoundEffect or a WaveBank, a voice will be created or a previously used one-shot voice will be reused if possible.

See AudioEngine for more information.

Platform support

Windows 8.x, Windows 10, Windows phone 8.x, and Xbox One all include XAudio 2.8 or later. Therefore, the standard DirectXTK.lib includes DirectXTK for Audio for all these platforms:
  • DirectXTK_Windows10
  • DirectXTK_Windows81
  • DirectXTK_Windows8
  • DirectXTK_WindowsPhone81
  • DirectXTK_XAMLSilverlight_WindowsPhone81
  • DirectXTK_WindowsPhone8
  • DirectXTK_XboxOneXDK
  • DirectXTK_XboxOneADK
For Windows desktop applications targeting Windows 8.x or later, you can make use of XAudio 2.8. The DirectXTKAudioWin8.lib contains the XAudio 2.8 version of DirectXTK for Audio, while DirectXTK.lib for Windows desktop contains only the math/graphics components. To support Windows desktop applications on Windows 7 and Windows Vista, we must make use XAudio 2.7, the legacy DirectX SDK, and the legacy DirectX End-User Runtime Redistribution packages (aka DirectSetup). The DirectXTKAudioDX.lib is the XAudio 2.7 version of DirectXTK for Audio.

DirectXTK_Desktop_2015, DirectXTK_Desktop_2013, DirectXTK_Desktop_2012, and DirectXTK_Desktop_2010 do not include DirectXTK for Audio. To add DirectXTK for Audio support for a Windows desktop application, you must also add one of the following projects from the Audio folder of the distribution to your solution and Add a Reference to it (see DirectXTK for more details).

When targeting Windows 8.x or later:
  • DirectXTKAudio_Desktop_2012_Win8 - DirectXTK for Audio using VS 2012 and XAudio 2.8
  • DirectXTKAudio_Desktop_2013_Win8 - DirectXTK for Audio using VS 2013 and XAudio 2.8
  • DirectXTKAudio_Desktop_2015_Win8 - DirectXTK for Audio using VS 2015 and XAudio 2.8

When targeting Windows Vista, Windows 7, or Windows 8.x:
  • DirectXTKAudio_Desktop_2010_DXSDK - DirectXTK for Audio project for VS 2010 + Windows 8.1 SDK + legacy DirectXTK using XAudio 2.7
  • DirectXTKAudio_Desktop_2012_DXSDK - DirectXTK for Audio project for VS 2012 + Windows 8.0 SDK + legacy DirectXTK using XAudio 2.7
  • DirectXTKAudio_Desktop_2013_DXSDK - DirectXTK for Audio project for VS 2013 + Windows 8.1 SDK + legacy DirectXTK using XAudio 2.7
VS 2010 Note: We only support DirectXTK for Audio with the legacy DirectX SDK due to some issues with using the VS 2010 toolset and with Windows 8.x SDK WinRT headers.

http://msdn.microsoft.com/en-us/library/windows/desktop/ee415802.aspx
http://support.microsoft.com/kb/2728613
http://msdn.microsoft.com/en-us/library/windows/desktop/ee663275.aspx

DirectXTK makes use of the latest Direct3D 11.1 headers available in the Windows 8.x SDK, and there are a number of file conflicts between the Windows 8.x SDK and the legacy DirectX SDK. Therefore, when building for down-level support with XAudio 2.7, Audio.h explicitly includes the DirectX SDK version of XAudio2 headers with a full path name. These reflect the default install locations, and if you have installed it elsewhere you will need to update this header. The *_DXSDK.vcxproj files use the DXSDK_DIR environment variable, so only the Audio.h references need updating for an alternative location.

// Using XAudio 2.7 requires the DirectX SDK
#include <C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include\comdecl.h>
#include <C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include\xaudio2.h>
#include <C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include\xaudio2fx.h>
#pragma warning(push)
#pragma warning( disable : 4005 )
#include <C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include\x3daudio.h>

Content Pipeline

Note: When adding .xwb files to your Windows Store app or Windows phone app project, you need to manually set the file properties to "Content: Yes" for all configurations to have these files included in your AppX package. .wav files are automatically detected as a media file and are included as content by default.

Threading model

The DirectXTK for Audio methods assume it is always called from a single thread. This is generally either the main thread or a worker thread dedicated to audio processing. The XAudio2 engine itself makes use of lock-free mechanism to make it 'thread-safe'.

Note that IVoiceNotify::OnBufferEnd is called from XAudio2's thread, so the callback must be very fast and use thread-safe operations.

Further reading

http://blogs.msdn.com/b/chuckw/archive/2012/05/15/learning-xaudio2.aspx
http://blogs.msdn.com/b/chuckw/archive/2012/04/02/xaudio2-and-windows-8-consumer-preview.aspx
http://xbox.create.msdn.com/en-US/education/catalog/utility/soundlab

Updated Wiki: WaveBank

WaveBank is a container class for an XACT-style wave bank that contains individual waves packaged together for more efficient loading and memory management. Sounds in the wave bank can then be played back as one-shot sounds or via SoundEffectInstance.

See XWBTool for more information on building .xwb files.

Note: DirectXTK for Audio uses XAudio 2. It does not make use of the legacy XACT Engine, XACT Cue, or XACT SoundBank.

Header

#include <Audio.h>

Initialization

std::unique_ptr<WaveBank> wb( new WaveBank( audEngine.get(), L"wavebank.xwb" ) );

For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr or std::shared_ptr

Note that in-memory banks may still be loading the wave data asynchronously after the return of this constructor. You can see if the wave data has completed loading by calling IsPrepared (). If you call Play or CreateInstance before the wave data has loaded, then the thread will wait until the load is complete before returning.

Play one-shot sounds

To play a sound in the bank as a 'fire and forget' sound:

wb->Play( index );

index is 0-based
To play the sound in the bank as a 'fire and forget' sound with volume, a pitch-shift, and/or pan setting:

wb->Play( index, volume, pitch, pan );

volume default is 1
pitch ranges from -1 to +1, playback defaults to 0 (which is no pitch-shifting)
pan -1 is fully left, +1 is fully right, and 0 is balanced.
If the wave bank contains 'entry friendly names', you can also use them to trigger a one-shot:

wb->Play( "Bang" );
wb->Play( "Bang", 0.8f, 0.f, 1.f );

You can also make use of the C/C++ header generated by XWBTool or XACTBLD3 to avoid 'magic numbers' in your code:

#include "wavebank.h"

wb->Play( XACT_WAVEBANK_WAVEBANK_BANG );

Note a C++ exception is thrown if attempting to play a one-shot sound from a streaming wavebank.

If the specified index or name is not found, then no one-shot is played and there is no C++ exception thrown.

Playing the sound

To play a sound with full control, looping, and dynamic pitch-shifting/volume control/pan settings:

auto effect = wb->CreateInstance( 2 );
if ( !effect )
    // Index not found in wave bank

To play a sound with positional 3D audio:

auto effect = wb->CreateInstance( 2, SoundEffectInstance_Use3D
                | SoundEffectInstance_ReverbUseFilters);
if ( !effect )
    // Index not found in wave bank

If the wave bank contains 'entry friendly names', you can also use them to create an instance:

auto effect = wb->CreateInstance( "Bang" );
if ( !effect )
    // Name not found in wave bankauto effect = wb->CreateInstance( "Bang", SoundEffectInstance_Use3D
                | SoundEffectInstance_ReverbUseFilters);
if ( !effect )
    // Name not found in wave bank

You can also make use of the C/C++ header generated by XWBTool or XACTBLD3 to avoid 'magic numbers' in your code:

#include "wavebank.h"auto effect = wb->CreateInstance( XACT_WAVEBANK_WAVEBANK_BANG );
if ( !effect )
    // Index not found in wave bankauto effect = wb->CreateInstance( XACT_WAVEBANK_WAVEBANK_BANG, SoundEffectInstance_Use3D
                | SoundEffectInstance_ReverbUseFilters);
if ( !effect )
    // Index not found in wave bank

Note a C++ exception is thrown if attempting to create a sound instance from a streaming wavebank.

If the specified index or name is not found, then CreateInstance returns a 'nullptr'. Client code should be sure to check for this condition. This is done because typically games do not consider missing audio content to be a fatal error during development.

See SoundEffectInstance.

Properties

  • IsPrepared ()
Returns true if the WaveBank has completed loading the wave data. For streaming buffers, they are always prepared after the constructor returns (only the metadata is loaded into memory).
  • IsInUse ()
Returns true if the WaveBank is currently playing as a one-shot or there are SoundEffectInstances referencing it.
  • IsStreamingBank ()
Returns true if the wave bank is a streaming type, false if it is an in-memory wave bank.
  • GetSampleSizeInBytes ( index )
Returns the size of the wave data in bytes. This will return 0 if the index is invalid.
  • GetSampleDuration ( index )
Returns the wave data duration in samples. This does not include any loops. This will return 0 if the index is invalid.
  • GetSampleDurationMS ( index )
Returns the wave data duration in milliseconds. This does not include any loops. This will return 0 if the index is invalid.
  • GetFormat ( index, WAVEFORMATEX* wfx, size_t maxsize )
Fills out a WAVEFORMATEX structure that describes the wave data format. This will return nullptr if the index is invalid, otherwise it returns a pointer to wfx. Since the format can be variable length, the caller provides the buffer and maxsize. At least 64 bytes is recommended as this is large enough to contain WAVEFORMAT, PCMWAVEFORMAT, WAVEFORMATEX, ADPCMWAVEFORMAT with coefficients, WAVEFORMATEXTENSIBLE, or a XMA2WAVEFORMATEX.
char formatBuff[ 64 ]; 
auto wfx = reinterpret_cast<WAVEFORMATEX*>( formatBuff );

wb->GetFormat( 2, wfx, 64 );
  • Find ( const char* name )
Returns the index, or -1 if not found or if there are no entry friendly names present in the wave bank.

Low-level access

FillSubmitBuffer is used internally, but can also be used when implementing your own XAudio2 source voices using the low-level interface access. Note that LoopCount is set to 0 by this function and should be set to a non-zero value by the caller. If looping is not desired, be sure to set LoopBegin and LoopLength to zero as well.

Care needs to be taken to ensure that any referenced WaveBank is not deleted while a source voice is actively playing back content from it or has pending buffers referencing it.

Content support

XAudio 2.9 on Windows 10 supports PCM, ADPCM, and xWMA.

XAudio 2.8 on Windows 8.x and Windows phone support PCM and ADPCM formats.

XAudio 2.7 on Windows Vista or later via the legacy DirectX End-User Runtime Redistribution (aka DirectSetup) supports PCM, ADPCM, and xWMA.

XAudio on Xbox One supports PCM, ADPCM, and xWMA. Xbox One exclusive app developers can also make use of XMA2.

XACT-style wave banks support 8-bit and 16-bit PCM (i.e. not 32-bit IEEE float PCM), ADPCM, xWMA, and XMA2 content.

XWB File Format

To aid in debugging, here is a simple console program for dumping out the content of a XWB in a human-readable form.
xwbdump.cpp

Further reading

http://msdn.microsoft.com/en-us/library/windows/desktop/dd757712.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757713.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd743663.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757714.aspx
http://msdn.microsoft.com/en-us/library/bb203879(v=xnagamestudio.40).aspx

Updated Wiki: Version History

July 1, 2015
  • Added Keyboard, Mouse class
  • Support for loading pre-lit models with SDKMESH
  • GamePad imlpemented using Windows.Gaming.Input for Windows 10
  • DirectXTK for Audio updates for xWMA support with XAudio 2.9
  • Added FindGlyph and GetSpriteSheet methods to SpriteFont

March 27, 2015
  • Added projects for Windows apps Technical Preview
  • GamePad temporarily uses 'null' device for universal Windows application platform

February 25, 2015 (NuGet version 2015.2.25.1)
  • DirectXTK for Audio updates
    • breaking change pitch now defined as -1 to 1 with 0 as the default
    • One-shot Play method with volume, pitch, and pan
    • GetMasterVolume/SetMasterVolume method for AudioEngine
    • Fix for compact wavebank validation
    • Improved voice cleanup and shutdown
  • Minor code cleanup and C++11 =default/=delete usage

January 26, 2015 (NuGet version 2015.1.26.1)
  • GamePad class: emulate XInputEnable behavior for XInput 9.1.0
  • DirectXTK for Audio fix for Stop followed by Play doing a proper restart
  • DirectXTK for Audio fix when using XAudio 2.7 on a system with no audio device
  • Updates for Xbox One platform support
  • Minor code cleanup and C99 printf string conformance

November 24, 2014 (NuGet version 2014.11.24.1, 2014.11.24.2)
  • SimpleMath fix for Matrix operator !=
  • DirectXTK for Audio workaround for XAudio 2.7 on Windows 7 problem
  • Updates for Windows phone 8.1 platform support
  • Updates for Visual Studio 2015 Technical Preview
  • Minor code cleanup

October 28, 2014
  • Model support for loading from VBO files
  • Model render now sets samplers on slots 0,1 by default for dual-texture effects
  • Updates for Xbox One platform support
  • Minor code cleanup

September 5, 2014
  • GamePad class: gamepad controller helper using XInput on Windows, IGamepad for Xbox One
  • SimpleMath updates; Matrix billboard methods; breaking change: Matrix::Identity() -> Matrix::Identity
  • SpriteBatch new optional SetViewport method
  • SpriteFont fix for white-space character rendering optimization
  • DDSTextureLoader fix for auto-gen mipmaps for volume textures
  • Explicit calling-convention annotation for public headers
  • Updates for Xbox One platform support
  • Minor code and project cleanup

July 15, 2014 (NuGet version 2014.7.15.1)
  • DirectXTK for Audio and XWBTool fixes
  • Updates to Xbox One platform support

April 3, 2014
  • Windows phone 8.1 platform support

February 24, 2014
  • DirectXHelper: new utility header with MapGuard and public version of SetDebugObjectName template
  • DDSTextureLoader: Optional support for auto-gen mipmaps
  • DDSTextureLoader/ScreenGrab: support for Direct3D 11 video formats including legacy "YUY2" DDS files
  • GeometricPrimtive: Handedness fix for tetrahedron, octahedron, dodecahedron, and icosahedron
  • SpriteBatch::SetRotation(DXGI_MODE_ROTATION_UNSPECIFIED) to disable viewport matrix
  • XboxDDSTextureLoader: optional forceSRGB parameter

January 24, 2014
  • DirectXTK for Audio updated with voice management and optional mastering volume limiter
  • Added orientation rotation support to SpriteBatch
  • Fixed a resource leak with GetDefaultTexture() used by some Effects
  • Code cleanup (removed DXGI_1_2_FORMATS control define; d2d1.h workaround not needed; ScopedObject typedef removed)

December 24, 2013
  • DirectXTK for Audio
  • Xbox One platform support
  • MakeSpriteFont tool updated with more progress feedback when capturing large fonts
  • Minor updates for .SDKMESH Model loader
  • Fixed bug in .CMO Model loader when handling multiple textures
  • Improved debugging output

October 28, 2013
  • Updated for Visual Studio 2013 and Windows 8.1 SDK RTM
  • Added DGSLEffect, DGSLEffectFactory, VertexPositionNormalTangentColorTexture, and VertexPositionNormalTangentColorTextureSkinning
  • Model loading and effect factories support loading skinned models
  • MakeSpriteFont now has a smooth vs. sharp antialiasing option: /sharp
  • Model loading from CMOs now handles UV transforms for texture coordinates
  • A number of small fixes for EffectFactory
  • Minor code and project cleanup
  • Added NO_D3D11_DEBUG_NAME compilation define to control population of Direct3D debug layer names for debug builds

July 1, 2013
  • VS 2013 Preview projects added and updates for DirectXMath 3.05 vectorcall
  • Added use of sRGB WIC metadata for JPEG, PNG, and TIFF
  • SaveToWIC functions updated with new optional setCustomProps parameter and error check with optional targetFormat

May 30, 2013
  • Added more GeometricPrimitives: Cone, Tetrahedron, Octahedron, Dodecahedron, Icosahedron
  • Updated to support loading new metadata from DDS files (if present)
  • Fixed bug with loading of WIC 32bpp RGBE format images
  • Fixed bug when skipping mipmaps in a 1D or 2D array texture DDS file

February 22, 2013 (NuGet version 2.22.13.23)
  • Added SimpleMath header
  • Fixed bug that prevented properly overriding EffectFactory::CreateTexture
  • Fixed forceSRGB logic in DDSTextureLoader and WICTextureLoader
  • Break circular reference chains when using SpriteBatch with a setCustomShaders lambda
  • Updated projects with /fp:fast for all configs, /arch:SSE2 for Win32 configs
  • Sensibly named .pdb output files
  • Added WIC_USE_FACTORY_PROXY build option (uses WindowsCodecs.dll entrypoint rather than CoCreateInstance)

January 25, 2013
  • GeometricPrimitive support for left-handed coordinates and drawing with custom effects
  • Model, ModelMesh, and ModelMeshPart added with loading of rigid non-animating models from .CMO and .SDKMESH files
  • EffectFactory helper class added

December 11, 2012
  • Ex versions of DDSTextureLoader and WICTextureLoader
  • Removed use of ATL's CComPtr in favor of WRL's ComPtr for all platforms to support VS Express editions
  • Updated VS 2010 project for official 'property sheet' integration for Windows 8.0 SDK
  • Minor fix to CommonStates for Feature Level 9.1
  • Tweaked AlphaTestEffect.cpp to work around ARM NEON compiler codegen bug
  • Added dxguid.lib as a default library for Debug builds to resolve GUID link issues

November 15, 2012
  • Added support for WIC2 when available on Windows 8 and Windows 7 with KB 2670838
  • Cleaned up warning level 4 warnings

October 30, 2012
  • Added project files for Windows phone 8

October 12, 2012
  • Added PrimitiveBatch for drawing user primitives
  • Debug object names for all D3D resources (for PIX and debug layer leak reporting)

October 2, 2012
  • Added ScreenGrab module
  • Added CreateGeoSphere for drawing a geodesic sphere
  • Put DDSTextureLoader and WICTextureLoader into the DirectX C++ namespace

September 7, 2012
  • Renamed project files for better naming consistency
  • Updated WICTextureLoader for Windows 8 96bpp floating-point formats
  • Win32 desktop projects updated to use Windows Vista (0x0600) rather than Windows 7 (0x0601) APIs
  • Tweaked SpriteBatch.cpp to workaround ARM NEON compiler codegen bug

May 31, 2012
  • Updated Metro project for Visual Studio 2012 Release Candidate changes
  • Cleaned up x64 Debug configuration warnings and switched to use "_DEBUG" instead of "DEBUG"
  • Minor fix for DDSTextureLoader's retry fallback that can happen with 10level9 feature levels

May 2, 2012
  • Added SpriteFont implementation and the MakeSpriteFont utility

March 29, 2012
  • WICTextureLoader updated with Windows 8 WIC native pixel formats

March 6, 2012
  • Fix for too much temp memory used by WICTextureLoader
  • Add separate Visual Studio 11 projects for Desktop vs. Metro builds

March 5, 2012
  • Bug fix for SpriteBatch with batches > 2048

February 24, 2012
  • Original release
Viewing all 874 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>