Sound/ru

From KolibriOS wiki
Revision as of 11:29, 14 June 2012 by XVilka (talk | contribs) (Some additional info)
Jump to navigation Jump to search

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

К сожалению какой либо внятной документации по Infinity нет, есть только исходники и файлы SDK.

Звуковая система Infinity содержит следующие сервисы:

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

SDK содержит следующие вспомогательные библиотеки:

init.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

setbuf.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

sndgetfmt.asm

; int _stdcall  GetFormat(SNDBUF hBuff, unsigned int *format);
_GetFormat@8:        ;str:dword, p_fmt:dword

sndgetmvol.asm

; int _stdcall  GetMasterVol(int* vol);
proc _GetMasterVol@4 stdcall, pvol:dword
proc _GetDevInfo@8   stdcall, hSrv:dword, p_info:dword

sndgetpan.asm

; int _stdcall  GetPan(SNDBUF hBuff, int *pan);
_GetPan@8:           ;str:dword, p_pan:dword

sndgetpos.asm

; int _stdcall  GetBufferPos(SNDBUF hBuff, int *offset);
_GetBufferPos@8:     ;str:dword, p_pos:dword

sndgetsize.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

sndgetvol.asm

; int _stdcall  GetVolume(SNDBUF hBuff, int *left, int *right);
proc _GetVolume@12   stdcall, str:dword, pleft:dword,pright:dword

sndout.asm

; int _stdcall  WaveOut(SNDBUF hBuff,void *buff, int size);
_WaveOut@12:         ;str:dword, src:dword, size:dword

sndreset.asm

; int _stdcall  ResetBuffer(SNDBUF hBuff, unsigned int flags);
_ResetBuffer@8:      ;str:dword, flags:dword

sndsetfmt.asm

; int _stdcall  SetFormat(SNDBUF hBuff, unsigned int format);
_SetFormat@8:        ;str:dword, fmt:dword

Устанавливает новый формат звукового буфера. Применимо для PCM_OUT и PCM_STATIC буферов.

sndsetmvol.asm

; int _stdcall  SetMasterVol(int vol);
_SetMasterVol@4:     ;vol:dword

sndsetpan.asm

; int _stdcall  SetPan(SNDBUF hBuff, int pan);
_SetPan@8:           ;str:dword, pan:dword

Устанавливает баланс левого и правого каналов. Баланс задаётся в сотых долях децибела в диапазоне -10000 - 10000, где -10000 - тишина в правом канале 10000 - тишина в левом канале 0 - нормальный баланс каналов

sndsetpos.asm

; int _stdcall  SetBufferPos(SNDBUF hBuff, int offset);
_SetBufferPos@8:     ;str:dword, offs:dword

sndsetvol.asm

; int _stdcall  SetVolume(SNDBUF hBuff, int left, int right);
_SetVolume@12:       ;str:dword, lvol:dword,rvol:dword

Устанавливает уровень громкости для правого и левого каналов. Уровень задаётся как ослабление сигнала в сотых долях децибела в диапазоне 0 - -10000, где 0 - максимальная громкость -10000 (-100dB) - полная тишина

stopbuf.asm

; int _stdcall  StopBuffer(SNDBUF hBuff);
_StopBuffer@4:       ;str:dword

wavhdr.asm

proc _test_wav@4     stdcall, hdr:dword

Примеры

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

#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;
    }

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

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

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;
    };

Применение

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