-
|
|
|
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.
|
|
-
|
|
|
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
|
|
-
|
|
|
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. Björn does not stalk John Sedlak
|
|
-
|
|
|
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
|
|
-
|
|
|
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.
|
|
-
|
|
|
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
|
|
-
|
|
|
SWEET!!! Thank you so much for your help, it works perfectly.
|
|
-
|
|
|
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...
|
|
-
|
|
|
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.
|
|
-
|
|
|
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(& | | | |