⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 core_sound.cpp

📁 [游戏开发参考书-用DirectX编写RPG游戏]这是一个系列的丛书如果你都看并且懂的话你就可以你工作啦!
💻 CPP
📖 第 1 页 / 共 2 页
字号:

  // Create the notification interface
  if(FAILED(m_pDSBuffer->QueryInterface(IID_IDirectSoundNotify8, (void**)&m_pDSNotify)))
    return FALSE;

  // Get an event for this
  if(m_Sound->AssignEvent(this, &m_Event, &hEvent) == FALSE)
    return FALSE;

  // Setup the 4 notification positions
  dspn[0].dwOffset = g_SoundBufferChunk - 1;
  dspn[0].hEventNotify = hEvent;
  dspn[1].dwOffset = g_SoundBufferChunk * 2 - 1;
  dspn[1].hEventNotify = hEvent;
  dspn[2].dwOffset = g_SoundBufferChunk * 3 - 1;
  dspn[2].hEventNotify = hEvent;
  dspn[3].dwOffset = g_SoundBufferSize - 1;
  dspn[3].hEventNotify = hEvent;
  if(FAILED(m_pDSNotify->SetNotificationPositions(4, dspn)))
    return FALSE;

  // set the pan and default volume
  SetVolume(100);
  SetPan(0);

  return TRUE;
}

BOOL cSoundChannel::Create(cSound *Sound, cSoundData *SoundDesc)
{
  return Create(Sound, SoundDesc->m_Frequency, SoundDesc->m_Channels, SoundDesc->m_BitsPerSample);
}

BOOL cSoundChannel::Free()
{
  // Stop any playback
  Stop();

  // Release the notification
  ReleaseCOM(m_pDSNotify);

  // Release the buffer
  ReleaseCOM(m_pDSBuffer);

  // Release event from parent cSound class
  m_Sound->ReleaseEvent(this, &m_Event);

  // Set to no parent sound
  m_Sound = NULL;

  return TRUE;
}

BOOL cSoundChannel::Play(cSoundData *Desc, long VolumePercent, long Loop)
{
  if(Desc == NULL)
    return FALSE;
  if(m_pDSBuffer == NULL)
    return FALSE;
  if(m_pDSNotify == NULL)
    return FALSE;

  // Stop any playback
  Stop();

  // Restore a lost buffer just in case
  m_pDSBuffer->Restore();

  // Setup playing information
  m_Desc.Copy(Desc);
  
  // Set looping data
  m_Loop = Loop;

  // Calculate stop section position
  if(!m_Loop)
    m_StopSection = -1;
  else
    m_StopSection = (short)(((m_Desc.m_Size * m_Loop) % g_SoundBufferSize) / g_SoundBufferChunk);

  // Buffer in data
  m_LoadSection = 0;
  BufferData();
  BufferData();
  BufferData();
  BufferData();

  // Set the volume
  SetVolume(VolumePercent);

  // Set position and begin play
  m_NextNotify = 0;
  if(FAILED(m_pDSBuffer->SetCurrentPosition(0)))
    return FALSE;
  if(FAILED(m_pDSBuffer->Play(0,0,DSBPLAY_LOOPING)))
    return FALSE;

  // Flag as playing
  m_Playing = TRUE;

  return TRUE;
}

BOOL cSoundChannel::Stop()
{
  if(m_pDSBuffer)
    m_pDSBuffer->Stop();

  m_Playing = FALSE;

  return TRUE;
}

long cSoundChannel::GetVolume()
{
  return m_Volume;
}

BOOL cSoundChannel::SetVolume(long Percent)
{
  long Volume;

  if(m_pDSBuffer == NULL)
    return FALSE;

  // calculate a usable volume level
  if(!Percent)
    Volume = DSBVOLUME_MIN;
  else 
    Volume = -20 * (100 - (Percent % 101));

  if(FAILED(m_pDSBuffer->SetVolume(Volume)))
    return FALSE;

  m_Volume = Percent % 101;

  return TRUE;
}

signed long cSoundChannel::GetPan()
{
  return m_Pan;
}

BOOL cSoundChannel::SetPan(signed long Level)
{
  signed long Pan;

  if(m_pDSBuffer == NULL)
    return FALSE;

  // calculate a usable setting
  if(Level < 0) 
    Pan = DSBPAN_LEFT / 100 * ((-Level) % 101);
  else
    Pan = DSBPAN_RIGHT / 100 * (Level % 101);

  if(FAILED(m_pDSBuffer->SetPan(Pan)))
    return FALSE;

  m_Pan = Level % 101;

  return TRUE;  
}

long cSoundChannel::GetFrequency()
{
  return m_Frequency;
}

BOOL cSoundChannel::SetFrequency(long Level)
{
  if(m_pDSBuffer == NULL)
    return FALSE;

  if(FAILED(m_pDSBuffer->SetFrequency(Level)))
    return FALSE;

  m_Frequency = Level;

  return TRUE;
}

BOOL cSoundChannel::IsPlaying()
{
  if(m_Sound == NULL || m_pDSBuffer == NULL || m_pDSNotify == NULL)
    return FALSE;

  return m_Playing;
}

BOOL cSoundChannel::BufferData()
{
  long Pos, Size;
  long ToLoad, LoadPos;
  char *Ptr;

  if(m_pDSBuffer == NULL)
    return FALSE;

  // Setup position to load in
  Pos  = (m_LoadSection % 4) * g_SoundBufferChunk;
  if(FAILED(m_pDSBuffer->Lock(Pos, g_SoundBufferChunk, (void**)&Ptr, (DWORD*)&Size, NULL, NULL, 0)))
    return FALSE;
    
  // Clear out buffer if nothing left to load
  if(!m_Desc.m_Left)
    ZeroMemory(Ptr, Size);
  else {
    // Load in the data - take looping into account
    ToLoad = Size;
    LoadPos = 0;
    for(;;) {
      if(m_Desc.m_Left > ToLoad) {
        if(m_Desc.m_fp != NULL) {
          fseek(m_Desc.m_fp, m_Desc.m_Pos, SEEK_SET);
          fread(&Ptr[LoadPos], 1, ToLoad, m_Desc.m_fp);
        } else 
          memcpy(&Ptr[LoadPos], &m_Desc.m_Ptr[m_Desc.m_Pos], ToLoad);
        m_Desc.m_Left -= ToLoad;
        m_Desc.m_Pos += ToLoad;
        break;
      } else {
        if(m_Desc.m_fp != NULL) {
          fseek(m_Desc.m_fp, m_Desc.m_Pos, SEEK_SET);
          fread(&Ptr[LoadPos], 1, m_Desc.m_Left, m_Desc.m_fp);
        } else 
          memcpy(&Ptr[LoadPos], &m_Desc.m_Ptr[m_Desc.m_Pos], m_Desc.m_Left);
        ToLoad -= m_Desc.m_Left;
        LoadPos += m_Desc.m_Left;

        // Check if we need to stop loop
        if(m_Loop >= 1) {
          m_Loop--;
          if(!m_Loop) {
            // Clear out remaining buffer space
            if(ToLoad)
              ZeroMemory(&Ptr[LoadPos], ToLoad);
            m_Desc.m_Left = 0L;
            break;
          }
        }

        m_Desc.m_Pos = m_Desc.m_StartPos;
        m_Desc.m_Left = m_Desc.m_Size;

        // See if we need to stop loading data
        if(!ToLoad)
          break;
      }
    }
  }

  // Unlock the buffer
  m_pDSBuffer->Unlock(Ptr, Size, NULL, 0);

  // Mark next section to load
  if((m_LoadSection+=1) > 3)
    m_LoadSection = 0;

  return TRUE;
}

BOOL cSoundChannel::Update()
{
  // Check for end of sound
  if(m_NextNotify == m_StopSection && !m_Desc.m_Left) {
    Stop();
  } else {
    // Buffer in more data
    BufferData();
    if((m_NextNotify+=1) > 3)
      m_NextNotify = 0;
  }

  return TRUE;
}

//////////////////////////////////////////////////////////////////////
//
// cMusicChannel Functions
//
//////////////////////////////////////////////////////////////////////
cMusicChannel::cMusicChannel()
{
  m_Sound      = NULL;
  m_pDMSegment = NULL;
  m_Volume     = 0;
}

cMusicChannel::~cMusicChannel()
{
  Free();
}

IDirectMusicSegment8 *cMusicChannel::GetSegmentCOM()
{
  return m_pDMSegment;
}

BOOL cMusicChannel::Create(cSound *Sound)
{
  Free();

  // Make sure all objects there
  if((m_Sound = Sound) == NULL)
    return FALSE;
  if(m_Sound->GetPerformanceCOM() == NULL)
    return FALSE;
  if(m_Sound->GetLoaderCOM() == NULL)
    return FALSE;

  return TRUE;
}

BOOL cMusicChannel::Load(char *Filename)
{
  DMUS_OBJECTDESC dmod;

  Free();

  if(m_Sound == NULL)
    return FALSE;
  if(m_Sound->GetPerformanceCOM() == NULL)
    return FALSE;
  if(m_Sound->GetLoaderCOM() == NULL)
    return FALSE;

  // Get the object
  ZeroMemory(&dmod, sizeof(DMUS_OBJECTDESC));
  dmod.dwSize = sizeof(DMUS_OBJECTDESC);
  dmod.guidClass = CLSID_DirectMusicSegment;
  dmod.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH;
  mbstowcs(dmod.wszFileName, Filename, MAX_PATH);
  if(FAILED(m_Sound->GetLoaderCOM()->GetObject(&dmod, IID_IDirectMusicSegment8, (LPVOID*)&m_pDMSegment)))
    return FALSE;

  // Setup MIDI playing
  if(strstr(Filename, ".mid") != NULL) {
    if(FAILED(m_pDMSegment->SetParam(GUID_StandardMIDIFile, 0xFFFFFFFF, 0, 0, NULL)))
      return FALSE;
  }

  // Download the band
  if(FAILED(m_pDMSegment->Download(m_Sound->GetPerformanceCOM())))
    return FALSE;

  return TRUE;
}

BOOL cMusicChannel::Free()
{
  Stop();

  if(m_Sound != NULL) {
    // unload instrument data
    if(m_pDMSegment != NULL) {
      if(m_Sound->GetPerformanceCOM() != NULL) {
        if(FAILED(m_pDMSegment->Unload(m_Sound->GetPerformanceCOM())))
          return FALSE;
      }

      // free loader data
      if(m_Sound->GetLoaderCOM() != NULL) {
        if(FAILED(m_Sound->GetLoaderCOM()->ReleaseObjectByUnknown(m_pDMSegment)))
          return FALSE;
      }
    }
  }

  // release the segment
  ReleaseCOM(m_pDMSegment);
  
  return TRUE;
}

BOOL cMusicChannel::SetDLS(cDLS *DLS)
{
  if(DLS == NULL)
    return FALSE;
  if(DLS->GetCollectionCOM() == NULL)
    return FALSE;
  if(m_Sound == NULL)
    return FALSE;
  if(m_Sound->GetPerformanceCOM() == NULL)
    return FALSE;
  if(m_pDMSegment == NULL)
    return FALSE;

  // Connect to the collection
  if(FAILED(m_pDMSegment->SetParam(GUID_ConnectToDLSCollection, 0xFFFFFFFF, 0, 0, (void*)DLS->GetCollectionCOM())))
    return FALSE;

  // unload and then re-download new instruments
  if(FAILED(m_pDMSegment->Unload(m_Sound->GetPerformanceCOM())))
    return FALSE;
  if(FAILED(m_pDMSegment->Download(m_Sound->GetPerformanceCOM())))
    return FALSE;
  
  return TRUE;
}

BOOL cMusicChannel::Play(long VolumePercent, long Loop)
{
  Stop();

  // Return if not setup correctly
  if(m_Sound == NULL)
    return FALSE;
  if(m_Sound->GetPerformanceCOM() == NULL)
    return FALSE;
  if(m_pDMSegment == NULL)
    return FALSE;

  // Set the number of loops
  if(!Loop)
    m_pDMSegment->SetRepeats(DMUS_SEG_REPEAT_INFINITE);
  else
    m_pDMSegment->SetRepeats(Loop-1);

  // Set the playback volume
  SetVolume(VolumePercent);

  // Play on default audio path
  if(FAILED(m_Sound->GetPerformanceCOM()->PlaySegmentEx(
               m_pDMSegment, NULL, NULL, 
               0, 0, NULL, NULL, NULL)))
    return FALSE;

  return TRUE;
}

BOOL cMusicChannel::Stop()
{
  // Return if not setup correctly
  if(m_Sound == NULL)
    return FALSE;
  if(m_Sound->GetPerformanceCOM() == NULL)
    return FALSE;
  if(m_pDMSegment == NULL)
    return FALSE;

  // Stop playback 
  if(FAILED(m_Sound->GetPerformanceCOM()->Stop(m_pDMSegment, NULL, 0, 0)))
    return FALSE;

  return TRUE;
}

long cMusicChannel::GetVolume()
{
  return m_Volume;
}

BOOL cMusicChannel::SetVolume(long Percent)
{
  IDirectMusicAudioPath8 *pDMAudioPath;
  long Volume;

  if(m_Sound == NULL)
    return FALSE;
  if(m_Sound->GetPerformanceCOM() == NULL)
    return FALSE;

  if(FAILED(m_Sound->GetPerformanceCOM()->GetDefaultAudioPath(&pDMAudioPath)))
    return FALSE;

  // calculate a usable volume level
  if(!Percent)
    Volume = -9600;
  else
    Volume = (long)(-32.0 * (100.0 - (float)(Percent % 101)));

  if(FAILED(pDMAudioPath->SetVolume(Volume,0))) {
    pDMAudioPath->Release();
    return FALSE;
  }
  pDMAudioPath->Release();

  m_Volume = Percent % 101;

  return TRUE;
}

BOOL cMusicChannel::SetTempo(long Percent)
{
  float Tempo;

  if(m_Sound == NULL)
    return FALSE;
  if(m_Sound->GetPerformanceCOM() == NULL)
    return FALSE;

  // calculate tempo setting based on percentage
  Tempo = (float)Percent / 100.0f;

  // set master performance tempo
  if(FAILED(m_Sound->GetPerformanceCOM()->SetGlobalParam(GUID_PerfMasterTempo, (void*)&Tempo, sizeof(float))))
    return FALSE;

  return TRUE;
}

BOOL cMusicChannel::IsPlaying()
{
  // Return if not setup correctly
  if(m_Sound == NULL)
    return FALSE;
  if(m_Sound->GetPerformanceCOM() == NULL)
    return FALSE;
  if(m_pDMSegment == NULL)
    return FALSE;

  if(m_Sound->GetPerformanceCOM()->IsPlaying(m_pDMSegment, NULL) == S_OK)
    return TRUE;

  return FALSE;
}

cDLS::cDLS()
{
  m_Sound = NULL;
  m_pDMCollection = NULL;
}

cDLS::~cDLS()
{
  Free();
}

BOOL cDLS::Create(cSound *Sound)
{
  Free();

  if((m_Sound = Sound) == NULL)
    return FALSE;
  if(m_Sound->GetLoaderCOM() == NULL)
    return FALSE;

  return TRUE;
}

BOOL cDLS::Load(char *Filename)
{
  DMUS_OBJECTDESC dmod;

  Free();

  if(m_Sound == NULL)
    return FALSE;
  if(m_Sound->GetLoaderCOM() == NULL)
    return FALSE;

  ZeroMemory(&dmod, sizeof(DMUS_OBJECTDESC));
  dmod.dwSize = sizeof(DMUS_OBJECTDESC);
  dmod.guidClass = CLSID_DirectMusicCollection;

  if(Filename == NULL) {
    // Get the default collection
    dmod.guidObject = GUID_DefaultGMCollection;
    dmod.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_OBJECT;
  } else {
    // Get the collection object
    dmod.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH;
    mbstowcs(dmod.wszFileName, Filename, MAX_PATH);
  }

  if(FAILED(m_Sound->GetLoaderCOM()->GetObject(&dmod, IID_IDirectMusicCollection8, (LPVOID*)&m_pDMCollection)))
    return FALSE;

  return TRUE;
}

BOOL cDLS::Free()
{
  if(m_Sound == NULL)
    return FALSE;
  if(m_Sound->GetLoaderCOM() == NULL)
    return FALSE;

  if(m_pDMCollection != NULL) {
    if(FAILED(m_Sound->GetLoaderCOM()->ReleaseObjectByUnknown(m_pDMCollection)))
      return FALSE;
  }
  ReleaseCOM(m_pDMCollection);

  return TRUE;
}

IDirectMusicCollection8 *cDLS::GetCollectionCOM()
{
  return m_pDMCollection;
}

long cDLS::GetNumPatches()
{
  HRESULT hr;
  DWORD   dwPatch;
  long    i;

  hr = S_OK;
  for(i=0; hr == S_OK; i++) {
    hr = m_pDMCollection->EnumInstrument(i, &dwPatch, NULL, 0);
    if(hr != S_OK)
      break;
  }
  return i;
}

long cDLS::GetPatch(long Index)
{
  DWORD dwPatch;

  if(m_pDMCollection == NULL)
    return -1;

  if(FAILED(m_pDMCollection->EnumInstrument(Index, &dwPatch, NULL, 0)))
    return -1;

  return (long)dwPatch;
}

BOOL cDLS::Exists(long Patch)
{
  IDirectMusicInstrument8 *pDMInstrument;

  if(m_pDMCollection == NULL)
    return FALSE;

  if(FAILED(m_pDMCollection->GetInstrument(Patch, &pDMInstrument)))
    return FALSE;
  pDMInstrument->Release();

  return TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -