Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming / GameProg / RPG_Programming_2ed.pdf
Скачиваний:
243
Добавлен:
12.02.2016
Размер:
12.06 Mб
Скачать

Глава 6. Создаем ядро игры

значения. Чтобы это произошло, вы должны сперва установить формат воспроизведения с помощью функции SetFormat, которая является

самодокументируемой. Затем вы должны проанализировать заголовок волнового файла, воспользовавшись функцией LoadWAVHeader, в

отношении параметров аналогичной LoadWAV.

И, наконец, если звук будет храниться в памяти, вы должны создать буфер с помощью функции cSoundData::Create. Вы можете сами

указать размер буфера, или позволить функции использовать размер буфера,

вычисленный LoadWAVHeader. Вызов cSoundData::GetPtr

возвращает указатель на буфер, который вы безопасно можете использовать для хранения звука.

В качестве примера предположим, что вы хотите воспроизвести

большой WAV-файл с именем BigSound.wav. Для инициализации класса cSoundData можно использовать следующий код:

cSoundData

Data;

 

 

FILE *fp =

fopen("BigSound.wav",

"rb");

Data.LoadWAVHeader(NULL, fp); //

Получаем параметры воспроизведения

Data.SetSource(fp);

//

Устанавливаем файл источника

// Воспроизводим звук и по завершении закрываем файл fclose(fp);

Воспроизведение звука с cSoundChannel

Сейчас у вас есть инициализированная звуковая система и загруженные

звуковые данные. Вполне естественно перейти к воспроизведению звука. Это назначение класса cSoundChannel, объявление которого показано ниже.

// Фиксированные размеры буферов звукового канала const long g_SoundBufferSize = 65536;

const long g_SoundBufferChunk = g_SoundBufferSize / 4;

Перед тем, как углубляться в код, я хочу поговорить о двух глобальных константах. Первая, g_SoundBufferSize, представляет количество

байтов, выделяемых для каждого буфера DirectSound, используемого при воспроизведении звука. Я использую 65 536 байт, чего достаточно для хранения нескольких секунд воспроизводимых данных даже в форматах с высоким качеством.

Вторая переменная, g_SoundBufferChunk, это размер отдельного

фрагмента, которых всего четыре. Каждый фрагмент содержит небольшую выборку потокового звука. Когда воспроизведение фрагмента завершено, начинается воспроизведение следующего в списке фрагмента, в то время как в предыдущий фрагмент загружаются новые звуковые данные.

Не следует менять эти значения, только если вы не хотите сэкономить память; в этом случае измените значение g_SoundBufferSize на

меньшее. Есть несколько преимуществ наличия звуковых буферов большего

334

netlib.narod.ru

Джим Адамс

размера — чем больше размер, тем реже ядро должно подгружать в поток новые данные. Конечно, это означает больший расход памяти, но что такое для современной системы с сотнями мегабайт памяти, пара мегабайт, потраченные для звуковых данных?

Давайте вернемся к объявлению класса cSoundChannel:

class cSoundChannel

{

friend class cSound; // Предоставить доступ классу cSound

protected:

cSound *m_Sound; // Родительский класс cSound

IDirectSoundBuffer8 *m_pDSBuffer; // Звуковой буфер DS IDirectSoundNotify8 *m_pDSNotify; // Объект уведомления

short

m_Event;

// Клоичество событий для уведомлений

long

m_Volume;

// Текущая громкость 0-100%

signed long m_Pan;

// Позиционирование от -100 до +100

BOOL

m_Playing;

// Флаг воспроизведения канала

long

m_Loop;

// Количество повторов воспроизведения

long m_Frequency;

// Формат воспроизведения

short m_BitsPerSample;

// для инициализированного

short m_Channels;

// канала

cSoundData m_Desc;

// Описание источника звука

// Переменные для потокового воспроизведения

short m_LoadSection;

// Следующий загружаемый фрагмент

short m_StopSection;

// На каком фрагменте остановиться

short m_NextNotify;

// Какой фрагмент следующий

BOOL BufferData();

// Входной буфер потоковых данных

BOOL Update();

// Обновление воспроизведения канала

public:

cSoundChannel(); // Конструктор

~cSoundChannel(); // Деструктор

//Функции для получения COM-объектов

IDirectSoundBuffer8 *GetSoundBufferCOM(); IDirectSoundNotify8 *GetNotifyCOM();

//Создание и освобождение звукового канала

BOOL Create(cSound *Sound, long Frequency = 22050,

short Channels = 1, short BitsPerSample = 16); BOOL Create(cSound *Sound, cSoundData *SoundDesc);

BOOL Free();

// Воспроизведение и остановка канала

BOOL Play(cSoundData *Desc, long VolumePercent = 100, long Loop = 1);

BOOL Stop();

// Получение и установка уровня громкости (0-100%) long GetVolume();

BOOL SetVolume(long Percent);

//Получение и установка позиционирования

//(от -100 слева до +100 справа)

netlib.narod.ru

335

Глава 6. Создаем ядро игры

signed long GetPan();

BOOL SetPan(signed long Level);

// Получение и установка частоты воспроизведения long GetFrequency();

BOOL SetFrequency(long Level);

BOOL IsPlaying(); // Возвращает TRUE если звук воспроизводится

};

На фоне простого класса cSoundData размер класса cSoundChannel впечатляет. Вы можете создать 32 экземпляра этого

класса, а это значит, что вы одновременно можете воспроизводить 32 канала (звуковое ядро не позволяет иметь одновременно более 32 экземпляров класса — инициализация класса после первых 32 будет вызывать ошибку).

Каждый звуковой канал инициализируется вызовом cSoundChannel::Create.

При вызове Create вы предоставляете ранее инициализированный класс cSound и формат воспроизведения. Чтобы жизнь была легче, вы

можете создать звуковой канал, используя формат воспроизведения, хранящийся в классе cSoundData. Когда вы завершите работу с классом cSoundChannel, освободите его ресурсы, вызвав cSoundChannel::Free.

Скорее всего, вы будете работать с cSoundChannel для

воспроизведения и остановки звуков и, возможно, будете менять их громкость. Для воспроизведения звука передайте cSoundChannel объект cSoundData, содержащий требуемый звук, вместе с уровнем громкости и

количеством повторов воспроизведения. Чтобы звук воспроизводился в бесконечном цикле, укажите в параметре Loop значение 0.

Остальные функции самодокументируемы. Для уровня громкости и позиционирования используются процентные значения от –100% (тишина

или крайняя левая позиция) до +100% (полная громкость или крайняя правая позиция). Вызов cSoundChannel::IsPlaying возвращает TRUE, если звук воспроизводится, и FALSE — если нет.

Вот пример, который загружает отдельный звук и запускает потоковое воспроизведение большого звука, используя два звуковых канала:

// Глобальные объявления cSound g_Sound; cSoundData g_Data[2]; cSoundChannel g_Channel[2];

//Инициализация звуковой системы

//Подразумеваем, что hWnd уже содержит

//инициализированный дескриптор окна g_Sound.Init(hWnd);

//Загрузка звуков

g_Data[0].LoadWAV("SmallSound.wav"); FILE *fp = fopen("BigSound.wav", "rb");

336

netlib.narod.ru

Джим Адамс

g_Data[1].LoadWAVHeader(NULL, fp); g_Data[1].SetSource(fp);

// Создание звуковых каналов g_Channels[0].Create(&g_Sound, &g_Data[0]); g_Channels[1].Create(&g_Sound, &g_Data[1]);

// Начало воспроизведения

// Один раз воспроизводим

g_Channels[0].Play(&g_Data[0]);

 

// первый звук

второй звук

g_Channels[1].Play(&g_Data[1], 100, 0); // Воспроизводим

 

// в бесконечном

цикле

// Когда все готово, останавливаем все и завершаем работу g_Channels[0].Stop();

g_Channels[0].Free(); g_Channels[1].Stop(); g_Channels[1].Free(); g_Data[0].Free(); g_Data[1].Free(); fclose(fp); g_Sound.Shutdown();

Слушаем музыку с cMusicChannel

Повторю еще раз, что за удовольствие от игры без музыки? Пришло время нанести удар с помощью класса cMusicChannel, который воспроизводит

MIDI-файлы и песни в родном формате DirectMusic (*.SGT):

class cMusicChannel

{

friend class cSound; // Разрешаем классу cSound доступ к данным

protected:

// Родительский класс

cSound

cSound *m_Sound;

IDirectMusicSegment8 *m_pDMSegment; // Объект сегмента DM

 

long m_Volume;

// Уровень громкости 0-100%

public:

cMusicChannel(); //

Конструктор

~cMusicChannel(); //

Деструктор

IDirectMusicSegment8

*GetSegmentCOM(); // Получить COM сегмента

BOOL Create(cSound *Sound);

//

Инициализация класса

BOOL Load(char *Filename);

//

Загрузка музыкального файла

BOOL Free();

//

Освобождение музыкального файла

BOOL SetDLS(cDLS *DLS);

//

Установка нового DLS

// Воспроизведение и остановка

музыки

BOOL Play(long VolumePercent = 100, long Loop = 1);

BOOL Stop();

 

 

// Получение и установка уровня громкости (0-100%)

long GetVolume();

= 100);

BOOL SetVolume(long Percent

BOOL SetTempo(long Percent = 100); // Установка темпа

BOOL IsPlaying(); // TRUE если песня воспроизводится,

// FALSE - если нет

};

netlib.narod.ru

337

Соседние файлы в папке GameProg