2013-02-28 70 views
0

我想加载一个* .wav文件,它是一个微软的wav/8bit pcm文件。我使用下面的代码加载数据:XAudio2和* .wav加载,HRESULT 0x88960001

class WavFile : public AudioSource, public LoadableObject 
{ 
public: 
    WavFile(void) 
     : AudioSource() 
     , LoadableObject() 
    { } 

    virtual concurrency::task<void> Load(Platform::String^ path) 
    { 
     buffer = nullptr; 

     BasicReaderWriter^ rw = ref new BasicReaderWriter(); 
     return rw->ReadDataAsync(path).then([this, path](const Platform::Array<byte>^ arr){ 

      DWORD chunkId = 0, fileSize = 0, chunkSize = 0, extra = 0; 

      ByteStream stream(arr); 

      stream.ReadData(&chunkId, sizeof(chunkId)); 
      //chunkId = stream.ReadDWORD(); 
      char test[4]; 
      for(unsigned int i=0; i <4; i++) 
       test[i] = ((char *)&chunkId)[i]; 
      if (chunkId != 'FFIR') throw ref new Platform::FailureException(L"Could not get RIFF chunk in file " + path + L", chunkId=" + chunkId.ToString()); 

      fileSize = stream.ReadDWORD(); 
      if (fileSize <= 16) throw ref new Platform::FailureException(L"Wave file size is too small; " + path); 

      extra = stream.ReadDWORD(); 
      for(unsigned int i=0; i <4; i++) 
       test[i] = ((char *)&extra)[i]; 
      if (extra != 'EVAW') throw ref new Platform::FailureException(L"Could not get WAVE chunk in file " + path + L", chunkId=" + chunkId.ToString()); 

      bool formatChunk = false; 
      for(unsigned int i = 12; i < fileSize;) 
      { 
       stream.Seek(i, true); 
       chunkId = stream.ReadDWORD(); 
       stream.Seek(i + 4, true); 
       chunkSize = stream.ReadDWORD(); 
       if (chunkId = ' tmf') 
       { 
        stream.Seek(i + 8, true); 
        stream.ReadData(&waveFormat, sizeof(WAVEFORMATEX)); 
        formatChunk = true; 
        break; 
       } 

       chunkSize += 8 + 1; 
       chunkSize &= 0xfffffffe; 
       stream.Seek(chunkSize, false); 
       i += chunkSize; 
      } 
      if (!formatChunk) throw ref new Platform::FailureException(L"Could not get fmt chunk in file " + path); 

      bool filledData = false; 
      for(unsigned int j=12; j < fileSize;) 
      { 
       stream.Seek(j, true); 
       chunkId = stream.ReadDWORD(); 
       for(unsigned int i=0; i <4; i++) 
        test[i] = ((char *)&chunkId)[i]; 
       stream.Seek(j + 4, true); 
       chunkSize = stream.ReadDWORD(); 
       if (chunkId == 'atad') 
       { 
        byte *bufferData = new byte[chunkSize]; 
        stream.Seek(j + 8, true); 
        stream.ReadData(bufferData, chunkSize); 
        buffer = ref new Platform::Array<byte>(bufferData, (unsigned int)chunkSize); 
        delete bufferData; 

        xbuffer.AudioBytes = chunkSize; 
        xbuffer.pAudioData = buffer->Data; 
        xbuffer.PlayBegin = 0; 
        xbuffer.PlayLength = 0; 

        filledData = true; 
        break; 
       } 
       chunkSize += 8 + 1; 
       chunkSize &= 0xfffffffe; 
       j += chunkSize; 
      } 
      if (!filledData) throw ref new Platform::FailureException(L"Could not find data chunk in file " + path); 

     }); 
    } 
}; 

它解析wav文件正确,这里是WAVEFORMATEX数据的样子:

{ wFormatTag=1, nChannels=2, nSamplesPerSec=22050, nAvgBytesPerSec=44100, nBlockAlign=2, wBitsPerSample=8, cbSize=24932 }

当我打电话instance->CreateSourceVoice(&voice, wave->GetWaveFormat(), 0, XAUDIO2_DEFAULT_FREQ_RATIO, reinterpret_cast<IXAudio2VoiceCallback*>(&voiceIn[id]->callbacks)),我得到HRESULT = 0x88960001,其中instance是类型IXAudio2*,我将它包含在类中静态共享并使用我的类构造函数/析构函数初始化/销毁的类中:

AudioManager::AudioManager(void) 
{ 
    instance_count++; 
    if (instance == nullptr) 
    { 
     DX::ThrowIfFailed(XAudio2Create(&instance, 0)); 
    } 
} 


AudioManager::~AudioManager(void) 
{ 
    /* Remove all the voices that were added in this audio manager */ 

    instance_count--; 
    if (instance_count == 0) 
    { 
     HaltAudio(); 
     instance->Release(); 
     instance = nullptr; 
    } 
} 

我已经在多个地方看过这个HRESULT是某种Windows 8的bug,一年多来还没有被修复。我不能接受这是一个持续的错误,更倾向于认为这是我的代码的问题。你可以看看my full implemention for XAudio2 in this gist

+0

这就是XAUDIO2_E_INVALID_CALL,它不像你传递的参数值。 – 2013-03-01 02:06:01

+0

啊,所以我并没有首先创造一个母音,这显然需要到位。我很惊讶没有更好的HRESULT值来描述这种情况。 – OzBarry 2013-03-01 14:34:56

回答

1

将XAudio2SourceVoice *的sendList设置为NULL时,IXAudio2接口必须至少有一个主控语音已设置。