Вечером приду, напишу тебе в аське по поводу Инфинити. У меня есть пару простых примеров, но я не уверен насчет их лицензионной чистоты и блаблабла Может, на их основе получится сделать документацию.
typedef unsigned int SNDBUF;
int _stdcall InitSound(int *version);
int _stdcall CreateBuffer(unsigned int format,int size,SNDBUF *buf);
int _stdcall DestroyBuffer(SNDBUF hBuff);
int _stdcall SetFormat(SNDBUF hBuff, unsigned int format);
int _stdcall GetFormat(SNDBUF hBuff, unsigned int *format);
int _stdcall ResetBuffer(SNDBUF hBuff, unsigned int flags);
int _stdcall SetBufferPos(SNDBUF hBuff, int offset);
int _stdcall GetBufferPos(SNDBUF hBuff, int *offset);
int _stdcall GetBufferSize(SNDBUF hBuff, int *size);
int _stdcall GetBufferFree(SNDBUF hBuff, int *free);
int _stdcall SetBuffer(SNDBUF hBuff,void* buff,
int offs, int size);
int _stdcall WaveOut(SNDBUF hBuff,void *buff, int size);
int _stdcall PlayBuffer(SNDBUF hBuff,unsigned int flags);
int _stdcall StopBuffer(SNDBUF hBuff);
int _stdcall SetVolume(SNDBUF hBuff, int left, int right);
int _stdcall GetVolume(SNDBUF hBuff, int *left, int *right);
int _stdcall SetPan(SNDBUF hBuff, int pan);
int _stdcall GetPan(SNDBUF hBuff, int *pan);
int _stdcall GetMasterVol(int* vol);
int _stdcall SetMasterVol(int vol);
int _stdcall SetTimeBase(SNDBUF hBuff, double base);
int _stdcall GetTimeStamp(SNDBUF hBuff, double *stamp);
#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 буфера с событиями, поделённого на две части. Spoiler:snd_format одна из констант вида PCM_X_Y_Z где
X- число каналов
Y- разрядность в битах на канал
Z- частота в КГц из фиксированного набора 11025Гц, 12000Гц, 16000Гц, 22050Гц, 24000Гц, 32000Гц, 44100Гц, 48000Гц
Если формат не известен заранее используется константа PCM_ALL. Окончательно формат устанавливается вызовом SetFormat.
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;
};
Изменение параметров воспроизведения
Spoiler:SetFormat(hBuff, snd_format);
Устанавливает новый формат звукового буфера. Применимо для PCM_OUT и PCM_STATIC буферов.
SetVolume(hBuff, left, right);
Устанавливает уровень громкости для правого и левого каналов. Уровень задаётся как ослабление сигнала в сотых долях децибела в диапазоне 0 - -10000, где
0 - максимальная громкость
-10000 (-100dB) - полная тишина
SetPan(hBuff, pan);
Устанавливает баланс левого и правого каналов. Баланс задаётся в сотых долях децибела в диапазоне -10000 - 10000, где
-10000 - тишина в правом канале
10000 - тишина в левом канале
0 - нормальный баланс каналов
Last edited by Serge on Sun Apr 22, 2012 10:48 pm, edited 6 times in total.
А ниче что последовательность их вызовов тоже надо вылавливать из Сишных исходников? Впрочем ладно забей, раз тебе даже лень на письма в личку отвечать.
Serge
1. Откуда берется buffer_size, когда CreateBuffer с размером 0?
2. Сколько буферов может создать один поток.
3. Может ли поток создавать разные типы буферов.
4. В каких случаях следует применять виды: статические (PCM_STATIC), потоковые (PCM_OUT) и кольцевые (PCM_RING). По каким признакам выбирать вообще? (типичные примеры)
Вернее я даже представляю как работает кольцевой - там допустим музыка играет в кольце соответственно. Но чем отличаются потоковый и статический не понял.
1. Для PCM_OUT это размер данных, которые необходимо воспроизвести. Данные должны целиком помещаться в адресное пространство приложения.
Для PCM_RING размер определяется вызовом GetBufferSize(SNDBUF hBuff, int *size);
2. На сколько хватит ОЗУ.
3. Да, хотя в этом нет необходимости.
4. Статический буфер: простая звуковая сигнализация, озвучка интерфейса и т.п. Позволяет одновременно использовать звуковые данные в разных форматах.
Потоковый буфер: различные аудиоплееры. Программа загружает большие объёмы звуковых данных из сети, накопителей или генерирует их в реальном времени.
Кольцевой буфер: игры и другие приложения с повышенными требованиями к синхронности аудио- и видеоряда.
Serge
А что если я создам кучу буферов в памяти и буду подсовывать их при необходимости? Т.е. я так и не понял в чем принципиальное отличие статического и потокового буфера. В чем фишка? Объясни совсем уж по тупому "на пальцах".
Mario
И получишь массу проблем с синхронизацией. Звук начинает выводиться не в момент вызова PlayBuffer, а спустя некоторое время после прерывания от контроллера. Для кольцевого буфера минимальная латентость 0.085с . Для остальных ещё хуже. В результате буферы попадающие в один квант звуковой карты (4096/48000 = 0.85(3) с) начнут воспроизводиться одновременно.
Статический буфер это простая пищалка, один бип, дзинь и т.п.
Потоковый буфер похож на чёрный ящик. Ты кидаешь в него байты, он превращает их в звук. Не важно сколько их, не важно что происходит внутри, рано или поздно он их все перемелет.