//----------------------------------------------------------
//	Файл:		SOUND.CPP
//	Описание:	Выполняет всю черновую работу с DirectSound
//----------------------------------------------------------
#define STRICT

#include <windows.h>
#include <dsound.h>

#include "main.h"
#include "sound.h"
#include "cwave.h"



LPDIRECTSOUND pDS = NULL;
CMappedWave* pWave=NULL;

//------------------------------------------
//счетчик звуков
int sound_num=0;
//массив звуковых буферов
LPDIRECTSOUNDBUFFER SoundBuffer[soundMax];
//------------------------------------------

//Очищает все объекты, связанные с DirectSound
void RemoveDirectSound()
{
    if (pWave)
	{
		delete pWave;
		pWave=NULL;
	}

	for(int i=0;i<soundMax;i++)
		if (SoundBuffer[i])
		{
			SoundBuffer[i]->Release();
			SoundBuffer[i]=NULL;
		}

	if (pDS)
	{
		pDS->Release();
		pDS=NULL;
	}
}

//-------------------------------------------
//Главная функция инициализации DirectSound
bool InitDirectSound (HWND hwnd)
{
	HRESULT	hRet;
	
    
	//Создаём объект DirectSound
	hRet=DirectSoundCreate( NULL, &pDS, NULL );
	if (hRet!=DS_OK)
	{
		return (false);
	}
	
	//Устанавливаем режим совместного доступа
	hRet=pDS->SetCooperativeLevel(hwnd,DSSCL_PRIORITY);
	if (hRet!=DS_OK)
	{
		return (false);
	}

	return (true);
}
//-------------------------------------------------------------
//Создаёт звуковой буфер на основе файла WAV
bool load_sound(int* pointer,char* filename)
{
	int n=*pointer;
	if(n<0||n>soundMax+1)return(false);//выйти с ошибкой
	//----------------------------------
	HRESULT hRet; 
	DSBUFFERDESC dsbd;

	// Cоздаём объект для работы с файлом WAV
	pWave = new CMappedWave();
	if (!pWave)
	{
		ErrorHandle(hWnd, "pWave");
		return (false);
	}

	//Открываем нужный файл при помощи объекта класса CMappedWave 
	if (!pWave->Open( filename ))
	{
		ErrorHandle(hWnd, "pWave-Open sounds");
		return (false);
	}
	//----------------------------------
	//если звуковой буфер существует - уничтожить его
	if (SoundBuffer[n])
	{
		SoundBuffer[n]->Release();
		SoundBuffer[n]=NULL;
	}
	//----------------------------------
	//Заполняем структуру описания...
	ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
	dsbd.dwSize        = sizeof(DSBUFFERDESC);
	dsbd.dwFlags       = DSBCAPS_STATIC | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | 
                       DSBCAPS_CTRLFREQUENCY ;
	dsbd.dwBufferBytes = pWave->GetWaveSize();
	dsbd.lpwfxFormat   = pWave->GetWaveHeader();

	//... и с её помощью создаём звуковой буфер!
	hRet=pDS->CreateSoundBuffer( &dsbd, &SoundBuffer[n], NULL );
	if (hRet!=DS_OK)
	{
		ErrorHandle(hWnd, "CreateSoundBuffer");
		return (false);
	}

	//
	VOID*   pPtr1  = NULL;
	VOID*   pPtr2 = NULL;
	DWORD   dwSize1;
	DWORD   dwSize2;

	//Запоминаем размер звуковых данных
	DWORD dwWaveSize=pWave->GetWaveSize();

	pWave->Reset();

	//Пытаемся заблокировать звуковой буфер 
	hRet = SoundBuffer[n]->Lock( 0, dwWaveSize, &pPtr1, &dwSize1, 
                                   &pPtr2, &dwSize2, 0L);
	if (hRet!=DS_OK)
	{
		ErrorHandle(hWnd, "SoundBuffer[n]->Lock");
		return (false);
	}		
     
	//Если получилось, считываем в буфер звуковые данные 
	pWave->Read((PBYTE)pPtr1,dwWaveSize);
	
	//Не забываем разблокировать буфер 
	SoundBuffer[n]->Unlock( pPtr1, dwWaveSize, NULL, 0 );

	//----------------------------------
	//если все прошло успешно - передаем номер созданного звукового буфера указателю
	*pointer=n;
	//выйти с успехом
	return (true);
}
//возвращает номер созданного звукового буфера
//если вернул -1, то скорее всего неправильно указан путь к файлу, или файл не существует
int LoadSound(char* filename)
{
	int sound=sound_num;
	if(!load_sound(&sound,filename))return -1;
	sound_num++;//увеличить счетчик звуков
	return sound;
}
//--------------------------------------------------------------
void StopSound(int buf)
{
    // проверить существует ли буфер
    if(SoundBuffer[buf]==NULL)return ;
    SoundBuffer[buf]->Stop();
}
//изменение частоты воспроизведения звука
void SoundFrequency(int buf,int freq)
{
    // проверить существует ли буфер
    if(SoundBuffer[buf]==NULL)return ;
    SoundBuffer[buf]->SetFrequency(freq);
}
bool SoundStatus(int buf)
{
    // проверить существует ли буфер
    if(SoundBuffer[buf]==NULL)return false;
	ULONG status; 
	SoundBuffer[buf]->GetStatus(&status);
	if(status & DSBSTATUS_PLAYING)return true;
	return false;
}
//--------------------------------------------------------------
//Проигрывает звуковой буфер
void PlaySound(int pan,int volume,int loop,int buf)
{
    // проверить существует ли буфер
    if(SoundBuffer[buf]==NULL)return ;
	//Перемещаем в начало текущую позицию проигрывания
	SoundBuffer[buf]->SetCurrentPosition(0);
	//Установка Левого или Правого положения звука
	SoundBuffer[buf]->SetPan(pan);// -10000 и 10000
	//Установка дальности звука
	SoundBuffer[buf]->SetVolume(volume);//DSBVOLUME_MAX==0;DSBVOLUME_MIN==-10000.
	//Начинаем воспроизводить звук
	SoundBuffer[buf]->Play(0, 0, loop);//DSBPLAY_LOOPING
}
//Проигрывает звуковой эффект
void PlayEffect(int pan,int volume,int buf)
{
    // проверить существует ли буфер
    if(SoundBuffer[buf]==NULL)return ;
	//Перемещаем в начало текущую позицию проигрывания
	SoundBuffer[buf]->SetCurrentPosition(0);
	//Установка дальности звука
	SoundBuffer[buf]->SetVolume(volume);//DSBVOLUME_MAX==0;DSBVOLUME_MIN==-10000.
	//Установка Левого или Правого положения звука
	SoundBuffer[buf]->SetPan(pan);// -10000 и 10000
	//Начинаем воспроизводить звук
	SoundBuffer[buf]->Play(0, 0, 0);//DSBPLAY_LOOPING );
}
