Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #44, ИЮЛЬ 2004 г.

Direct Sound в объятиях программиста

Фленов Михаил

Спецвыпуск Xakep, номер #044, стр. 044-014-5


Песни и пляски

Если при кодинге звука через MMSystem для обеспечения нормальной параллельной работы проги и звука приходилось создавать отдельный поток и в нем запускать цикл работы с буфером, то здесь это происходит автоматом. Заметь, что никаких потоков нет, а все работает, не загружая систему.

Конечно, мы рассмотрели самый сложный способ, при котором данные загружаются в буфер ручками, и потом запускается воспроизведение. Если таким образом грузить MP3, то придется самостоятельно, на лету преобразовывать данные. А зачем это делать, если в системе точно установлен фильтр, который сможет сделать это за нас? Пара телодвижений функциями DirectSound - и никаких проблем.

Листинг 1

function InitDirectSound(hDlg: hWnd): boolean;

var

hr : hResult;

dsbd : TDSBufferDesc;

DSBPrimary : IDirectSoundBuffer;

wfx : TWaveFormatEx;

begin

Result := false;

// Инициализация Direct Sound

hr := DirectSoundCreate(NIL, DS, NIL);

if failed(hr) then exit;

// Устанавливаем уровень приоритета

hr := DS.SetCooperativeLevel(hDlg, DSSCL_PRIORITY);

if failed(hr) then exit;

FillChar(dsbd, SizeOf(dsbd), 0);

dsbd.dwSize := SizeOf(dsbd);

dsbd.dwFlags := DSBCAPS_PRIMARYBUFFER;

hr := DS.CreateSoundBuffer(dsbd, DSBPrimary, NIL);

if failed(hr) then

exit;

FillChar(wfx, SizeOf(wfx), 0);

with wfx do

begin

wFormatTag := WAVE_FORMAT_PCM;

nChannels := 1;

nSamplesPerSec := 22050;

wBitsPerSample := 16;

nBlockAlign := (wBitsPerSample shr 3) * nChannels;

nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;

end;

hr := DSBPrimary.SetFormat(@wfx);

if failed(hr) then exit;

if Assigned(DSBPrimary) then DSBPrimary := NIL;

Result := true;

end;

Листинг 2

function PlayBuffer(looped: boolean): boolean;

var

hr : hResult;

dwLooped : dWord;

begin

Result := false;

if not Assigned(DSBuffer) then exit;

if not RestoreBuffers then exit;

if looped then

dwLooped := DSBPLAY_LOOPING

else

dwLooped := 0;

hr := DSBuffer.Play(0, 0, dwLooped);

if failed(hr) then exit;

Result := true;

end;

Чтобы не заморачиваться с кодингом Direct Sound, для простых программ можно поступить умнее – использовать через COM компоненту Media Player.

Асинхронная работа Direct Sound достигается автоматически. В других технологиях приходится создавать отдельные потоки и мучиться с ними.

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

В Direct Sound можно изменять громкость звучания каждого буфера в отдельности.

Назад на стр. 044-014-4  Содержание