Sound/ru

From KolibriOS wiki
Jump to navigation Jump to search

Изначально Колибри унаследовала от Менуэт только звуковой драйвер для SoundBlaster, встроенный в ядро. Позже в (2005-2006) была написана полноценная звуковая подсистема Infinity, автор Сергей Семёнов aka Serge.

К сожалению какой либо внятной документации по Infinity нет, есть только исходники и файлы SDK. См. этот комментарий http://board.kolibrios.org/viewtopic.php?p=51462#p51462

Звуковая система Infinity содержит следующие сервисы: <syntaxhighlight lang="asm"> SRV_GETVERSION equ 0 SND_CREATE_BUFF equ 1 SND_DESTROY_BUFF equ 2 SND_SETFORMAT equ 3 SND_GETFORMAT equ 4 SND_RESET equ 5 SND_SETPOS equ 6 SND_GETPOS equ 7 SND_SETBUFF equ 8 SND_OUT equ 9 SND_PLAY equ 10 SND_STOP equ 11 SND_SETVOLUME equ 12 SND_GETVOLUME equ 13 SND_SETPAN equ 14 SND_GETPAN equ 15 SND_GETBUFFSIZE equ 16 SND_GETFREESPACE equ 17 SND_SETTIMEBASE equ 18 SND_GETTIMESTAMP equ 19 </syntaxhighlight> SDK содержит следующие вспомогательные библиотеки:

init.asm

<syntaxhighlight lang="asm">

int _stdcall InitSound(int *version);

_InitSound@4: ;p_ver:dword

int _stdcall CreateBuffer(unsigned int format,int size,SNDBUF *buf);

_CreateBuffer@12: ;format:dword,size:dword,p_str:dword

int _stdcall DestroyBuffer(SNDBUF hBuff);

_DestroyBuffer@4: ;str:dword </syntaxhighlight>

setbuf.asm

<syntaxhighlight lang="asm">

int _stdcall SetBuffer(SNDBUF hBuff,void* buff, int offs, int size);

_SetBuffer@16: ;str:dword, src:dword, offs:dword, size:dword

int _stdcall PlayBuffer(SNDBUF hBuff,unsigned int flags);

_PlayBuffer@8: ;str:dword,flags:dword </syntaxhighlight>

sndgetfmt.asm

<syntaxhighlight lang="asm">

int _stdcall GetFormat(SNDBUF hBuff, unsigned int *format);

_GetFormat@8: ;str:dword, p_fmt:dword </syntaxhighlight>

sndgetmvol.asm

<syntaxhighlight lang="asm">

int _stdcall GetMasterVol(int* vol);

proc _GetMasterVol@4 stdcall, pvol:dword proc _GetDevInfo@8 stdcall, hSrv:dword, p_info:dword </syntaxhighlight>

sndgetpan.asm

<syntaxhighlight lang="asm">

int _stdcall GetPan(SNDBUF hBuff, int *pan);

_GetPan@8: ;str:dword, p_pan:dword </syntaxhighlight> Возвращает баланс левого и правого каналов. Баланс задаётся в сотых долях децибела в диапазоне -10000 - 10000, где -10000 - тишина в правом канале 10000 - тишина в левом канале 0 - нормальный баланс каналов

sndgetpos.asm

<syntaxhighlight lang="asm">

int _stdcall GetBufferPos(SNDBUF hBuff, int *offset);

_GetBufferPos@8: ;str:dword, p_pos:dword </syntaxhighlight>

sndgetsize.asm

<syntaxhighlight lang="asm">

int _stdcall GetBufferSize(SNDBUF hBuff, int *size);

_GetBufferSize@8: ;str:dword, p_size:dword

int _stdcall GetBufferFree(SNDBUF hBuff, int *free);

_GetBufferFree@8: ;str:dword, p_free:dword </syntaxhighlight>

sndgetvol.asm

<syntaxhighlight lang="asm">

int _stdcall GetVolume(SNDBUF hBuff, int *left, int *right);

proc _GetVolume@12 stdcall, str:dword, pleft:dword,pright:dword </syntaxhighlight>

sndout.asm

<syntaxhighlight lang="asm">

int _stdcall WaveOut(SNDBUF hBuff,void *buff, int size);

_WaveOut@12: ;str:dword, src:dword, size:dword </syntaxhighlight>

sndreset.asm

<syntaxhighlight lang="asm">

int _stdcall ResetBuffer(SNDBUF hBuff, unsigned int flags);

_ResetBuffer@8: ;str:dword, flags:dword </syntaxhighlight>

sndsetfmt.asm

<syntaxhighlight lang="asm">

int _stdcall SetFormat(SNDBUF hBuff, unsigned int format);

_SetFormat@8: ;str:dword, fmt:dword </syntaxhighlight> Устанавливает новый формат звукового буфера. Применимо для PCM_OUT и PCM_STATIC буферов.

sndsetmvol.asm

<syntaxhighlight lang="asm">

int _stdcall SetMasterVol(int vol);

_SetMasterVol@4: ;vol:dword </syntaxhighlight>

sndsetpan.asm

<syntaxhighlight lang="asm">

int _stdcall SetPan(SNDBUF hBuff, int pan);

_SetPan@8: ;str:dword, pan:dword </syntaxhighlight> Устанавливает баланс левого и правого каналов. Баланс задаётся в сотых долях децибела в диапазоне -10000 - 10000, где -10000 - тишина в правом канале 10000 - тишина в левом канале 0 - нормальный баланс каналов

sndsetpos.asm

<syntaxhighlight lang="asm">

int _stdcall SetBufferPos(SNDBUF hBuff, int offset);

_SetBufferPos@8: ;str:dword, offs:dword </syntaxhighlight> Устанавливает начальную позицию для статического звукового буфера.

sndsetvol.asm

<syntaxhighlight lang="asm">

int _stdcall SetVolume(SNDBUF hBuff, int left, int right);

_SetVolume@12: ;str:dword, lvol:dword,rvol:dword </syntaxhighlight> Устанавливает уровень громкости для правого и левого каналов. Уровень задаётся как ослабление сигнала в сотых долях децибела в диапазоне 0 - -10000, где 0 - максимальная громкость -10000 (-100dB) - полная тишина

stopbuf.asm

<syntaxhighlight lang="asm">

int _stdcall StopBuffer(SNDBUF hBuff);

_StopBuffer@4: ;str:dword </syntaxhighlight>

wavhdr.asm

<syntaxhighlight lang="asm"> proc _test_wav@4 stdcall, hdr:dword </syntaxhighlight>

Примеры

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

<syntaxhighlight lang="c">

  1. include <sound.h>
   int    err;
   int    version =-1;
   if((err = InitSound(&version)) !=0 ){
       goto epic_fail;
   };
   if( (SOUND_VERSION>(version&0xFFFF)) ||
       (SOUND_VERSION<(version >> 16))){
       goto epic_fail;
   }

</syntaxhighlight>

Звуковые буферы

Создаём звуковой буфер. Есть три вида буферов - статические (PCM_STATIC), потоковые (PCM_OUT) и кольцевые (PCM_RING). Самый простой для программирования - потоковый. Статический буфер не сильно отличается от буфера в DirectSound. SetBuffer заполняет буфер, GetBufferPos и SetBufferPos получают и устанавливают текущую позицию в буфере. Кольцевой буфер позволяет выводить звук с минимальной задержкой. Это аналог Direct Sound буфера с событиями, поделённого на две части.

<syntaxhighlight lang="c"> SNDBUF hBuff;

   void* buffer; //семплы в формате snd_format
   int buffer_size; // размер буфера в байтах
   if((err = CreateBuffer(snd_format|PCM_OUT, 0, &hBuff)) != 0)
   {
       goto epic_fail;
   };

выводим звук

   WaveOut(hBuff,buffer,buffer_size);


Для статического буфера размером 1Mб

   if((err = CreateBuffer(snd_format|PCM_STATIC, 1024*1024, &hBuff)) != 0)
   {
       goto epic_fail;
   };

заполняем буфер

   int offset; // смещение от начала звукового буфера
   SetBuffer(hBuff, buffer, offset, buffer_size);

выводим звук асинхронно - функция возвращает управление немедленно

   if((err = PlayBuffer(hBuff, 0)) !=0 ){
       goto exit_whith_error;
   };

синхронно - поток блокируется пока весь буфер не будет воспроизведён

   if((err = PlayBuffer(hBuff, PLAY_SYNC)) !=0 ){
       goto exit_whith_error;
   };

</syntaxhighlight>

Применение

  1. Статический буфер: простая звуковая сигнализация, озвучка интерфейса и т.п. Позволяет одновременно использовать звуковые данные в разных форматах.
  2. Потоковый буфер: различные аудиоплееры. Программа загружает большие объёмы звуковых данных из сети, накопителей или генерирует их в реальном времени.
  3. Кольцевой буфер: игры и другие приложения с повышенными требованиями к синхронности аудио- и видеоряда.