XNA Creators Club Online
Page 1 of 1 (13 items)
Sort Posts: Previous Next

Using xWMA

Last post 05-29-2008 2:03 PM by Jammy1986. 12 replies.
  • 05-09-2008 1:57 PM

    Using xWMA

    Well I have leapt into the new xAudio2 API, and this is my first foray into sound programming. First impressions are that it's excellent, very simple and makes great sense, well done to those that made it.

    I have successfully loded a .wav file in using the included tutorial as a guide. Next I looked for a compressed format, and quickly found xWMA, but I could not find any tutorials, and MSDN reference had a short descriptive paragraph telling me to use the command line to make them, that's fine, but could someone please point me towards something that I can use to play them. I understand from the description that they are basically better compressed WMA's? Now I believe I have successfully managed to fill the XMA_XMA2WAVEFORMATEX struct, and the XAUDIO2_BUFFER_WMA struct, but only one sound sample is played before the program leaves the loop and quits... If anyone could give me a little poke in the right direction it would be greatly appreciated.

  • 05-09-2008 2:54 PM In reply to

    Re: Using xWMA

    xWMA is the regular WMA encoder, just stored in a different file format that makes it easier to decode on Xbox hardware.
    I think there is an upper limit to the size of data you can pass in a single buffer for xWMA -- and I also think there is an alignment requirement (does 128 bytes sound reasonable? I'm not at the docs right now). Try playing with that and see if you can get more than one buffer to be queued and playing.

    Jon Watte, Direct3D MVP kW X-port 3ds Max .X exporter kW Animation source code
  • 05-09-2008 2:58 PM In reply to

    Re: Using xWMA

    So far this post by Dungan is the only description outside of MSDN.
    We are boki. The rest is known.
    The not so known part of the rest: It is Björn or Bjoern, but never Bjorn.
    Vote: Allow use of non-ASCII characters in names and titles
  • 05-15-2008 6:39 PM In reply to

    Re: Using xWMA

    Answer

    Thanks for the kudos Jammy!  It's great to hear.  We feel validated  :-)  It's been a long road getting this out to you guys, and I hope it's a major improvement over XAudio classic and DirectSound.

    So xWMA.  We will definitely document it a little better, but for now, see if this code snippet can get you on the right track:

    // Read pInputFormat from the XWM file's FMT chunk (it's a standard RIFF file, like WAV)
    pXAudio2->CreateSourceVoice(&pSourceVoice, pInputFormat);

    // Read nWMADataSize and pWMAData from the XWM file's DATA chunk
    XAUDIO2_BUFFER packet = {XAUDIO2_END_OF_STREAM};
    packet.AudioBytes = nWMADataSize;
    packet.pAudioData = pWMAData;

    // Read pDecodedPacketCumulativeBytes from the DPDS chunk (="decoded packet data size"),
    // and set nPacketCount = DPDS chunk's size divided by 4 (so you get a DWORD count)
    XAUDIO2_BUFFER_WMA packetWMA;
    packetWMA.pDecodedPacketCumulativeBytes = pDecodedPacketCumulativeBytes;
    packetWMA.PacketCount = nPacketCount;

    // Submit the data to the XAudio2 voice and start it
    pSourceVoice->SubmitSourceBuffer(&packet, &packetWMA);
    pSourceVoice->Start(0);

    There's more meat to this of course, but this is a start at least.

    Dugan Porter [MS]
    Game Audio Team

    Dugan Porter [MS]
    Game Audio Team
  • 05-16-2008 12:37 PM In reply to

    Re: Using xWMA

    Well I can't get it to work yet... I think my problem is with the pDecodedPacketCumulativeBytes. This is a pointer to a UINT32, so I'm not sure exactly how I need to read data into this.

    Thanks for your help so far.

  • 05-16-2008 9:59 PM In reply to

    Re: Using xWMA

    Answer
    See if this works: divide the DPDS chunk's size in bytes by 4 to get a length in DWORDs, and then allocate a DWORD array of that length.  Then just read the entire DPDS chunk into your array, and you should be good to go.
    Dugan Porter [MS]
    Game Audio Team
  • 05-17-2008 1:55 PM In reply to

    Re: Using xWMA

    SWEET!!! Thank you so much for your help, it works perfectly.
  • 05-21-2008 3:51 PM In reply to

    Re: Using xWMA

    One last question, when using this method I have to allocate memory dynamically. Where exactly do I clear this up, either the source voice takes care of clean up (unlikely), the source voice copies the stuff into it's own memory and I can delete immediately after deleting, or else it points to that memory, so I have to hold onto it until the end of the program...
  • 05-22-2008 7:39 AM In reply to

    Re: Using xWMA

    Hello! Can you give me small simple example application, which shows how to load and play xWMA sound? I already have spent a lot of time for the decision of this problem but while nothing turns out.
  • 05-22-2008 8:49 AM In reply to

    Re: Using xWMA

    Hey kamenkova, this is what I came up with, it's a little messy, and uses a few of the dreaded GOTO's. Also it uses the ifstream class:

     

    1 #define _WIN32_DCOM  
    2 #include <xaudio2.h>
    3 #include <windows.h>  
    4 #include <iostream>
    5 #include <fstream>  
    6 using std::cout;  
    7 using std::endl;  
    8 using std::ifstream;  
    9  
    10 int main()  
    11 {  
    12     IXAudio2MasteringVoice* pMasteringVoice = NULL;  
    13     IXAudio2* pXAudio2 = NULL;  
    14     IXAudio2SourceVoice* pSourceVoice = NULL;  
    15     char* buffer = NULL;  
    16     CoInitializeEx(0, COINIT_MULTITHREADED);  
    17     while(1) //Non-neccesary loop to reduce code reproduction.  
    18     {  
    19         if(FAILED(XAudio2Create(&pXAudio2, 0)))  
    20         {  
    21             cout << "Failed on creation" << endl;  
    22             break;  
    23         }  
    24       
    25         if(FAILED(pXAudio2->CreateMasteringVoice(&pMasteringVoice)))  
    26         {  
    27             cout << "Failed creating mastering voice" << endl;  
    28             break;  
    29         }  
    30  
    31         ifstream xwmaFile("Techno", std::ios::binary);  
    32         if(!xwmaFile.is_open())  
    33         {  
    34             cout << "Failure to open file" << endl;  
    35             break;  
    36         }  
    37           
    38         char riff[4];  
    39         xwmaFile.read(riff, sizeof(riff));  
    40  
    41         long fileSize = 0;  
    42         xwmaFile.read((char*)&fileSize, sizeof(fileSize));  
    43  
    44         char xwmafmt[8];  
    45         xwmaFile.read(xwmafmt, sizeof(xwmafmt));  
    46  
    47         unsigned long xwmafmtSize;  
    48         xwmaFile.read((char*)&xwmafmtSize, sizeof(xwmafmtSize));  
    49  
    50         XMA2WAVEFORMATEX format;  
    51         xwmaFile.read((char*)&format.wfx, sizeof(format.wfx));  
    52         if(xwmafmtSize > sizeof(format.wfx))  
    53         {  
    54             xwmaFile.read((char*)&format.NumStreams, sizeof(format.NumStreams));  
    55             xwmaFile.read((char*)&format.ChannelMask, sizeof(format.ChannelMask));  
    56             xwmaFile.read((char*)&format.SamplesEncoded, sizeof(format.SamplesEncoded));  
    57             xwmaFile.read((char*)&format.BytesPerBlock, sizeof(format.BytesPerBlock));  
    58             xwmaFile.read((char*)&format.EncoderVersion, sizeof(format.EncoderVersion));  
    59             xwmaFile.read((char*)&format.BlockCount, sizeof(format.BlockCount));  
    60         }  
    61  
    62         xwmaFile  
    63         //Find the dpds chunk.  
    64         char dpds = 'a';  
    65 DPDSFAIL:  
    66         do 
    67             xwmaFile.read(&dpds, 1);  
    68         while(dpds != 'd');  
    69         xwmaFile.read(&dpds, 1);  
    70         if(dpds != 'p')  
    71             goto DPDSFAIL;  
    72         xwmaFile.read(&dpds, 1);  
    73         if(dpds != 'd')  
    74             goto DPDSFAIL;  
    75         xwmaFile.read(&dpds, 1);  
    76         if(dpds != 's')  
    77             goto DPDSFAIL;  
    78  
    79         XAUDIO2_BUFFER_WMA wmaBuffer = {0};  
    80         long dpdsSize = 0;  
    81         xwmaFile.read((char*)&dpdsSize, sizeof(dpdsSize));  
    82         wmaBuffer.PacketCount = dpdsSize / 4;  
    83         UINT32* DecodedPacket = new UINT32[wmaBuffer.PacketCount];  
    84         xwmaFile.read((char*)DecodedPacket, dpdsSize);  
    85         wmaBuffer.pDecodedPacketCumulativeBytes = DecodedPacket;  
    86  
    87         //Find the data chunk.  
    88         char data = 'a';  
    89 DATAFAIL:  
    90         do 
    91             xwmaFile.read(&data, 1);  
    92         while(data != 'd');  
    93         xwmaFile.read(&data, 1);  
    94         if(data != 'a')  
    95             goto DATAFAIL;  
    96         xwmaFile.read(&data, 1);  
    97         if(data != 't')  
    98             goto DATAFAIL;  
    99         xwmaFile.read(&data, 1);  
    100         if(data != 'a')  
    101             goto DATAFAIL;  
    102  
    103         unsigned long dataSize = 0;  
    104         xwmaFile.read((char*)&dataSize, sizeof(dataSize));  
    105         HRESULT hr;  
    106         if(FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&format)))  
    107         {  
    108             cout << "Failed to create a source voice: " << (hr & 0xFFFF) << endl;  
    109             break;  
    110         }  
    111         buffer = new char[dataSize];  
    112         xwmaFile.read(buffer, dataSize);  
    113         xwmaFile.close();     
    114  
    115         XAUDIO2_BUFFER xBuffer = {0};  
    116         xBuffer.pAudioData = ((unsigned char*)buffer);  
    117         xBuffer.Flags = XAUDIO2_END_OF_STREAM;  
    118         xBuffer.AudioBytes = dataSize;  
    119           
    120         if(FAILED(pSourceVoice->SubmitSourceBuffer(&xBuffer, &wmaBuffer)))  
    121         {  
    122             cout << "Failed to submit the source buffer." << endl;  
    123             break;  
    124         }  
    125         if(SUCCEEDED(pSourceVoice->Start(0)))  
    126         {  
    127             bool isRunning = true;  
    128             while(isRunning)  
    129             {  
    130                 XAUDIO2_VOICE_STATE state;  
    131                 pSourceVoice->GetState(&state);  
    132                 isRunning =