Воспроизведение звука при помощи библиотеки BASS

Дата публикации:2006
Twitter Facebook Vkontakte

Предварительные замечания

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

Все имеющиеся в статье примеры написаны на языке программирования C. Примеры достаточно просты, и предполагается, что у программистов, использующих другие языки программирования, не будет трудностей с пониманием этих примеров.

Общая характеристика

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

Существуют варианты BASS для Win32 и MacOSX (платформы PowerPC и Intel). Текущая версия библиотеки (ноябрь, 2006) - 2.3 (.0.1). Ниже речь пойдет преимущественно о дистрибутиве, предназначенном для Win32. Все необходимые ссылки помещены в соответствующем разделе после статьи.

Библиотека BASS достаточно проста в использовании, имеет небольшой размер и поддерживает следующие возможности:

  • воспроизведение звуковых образцов (сэмплов) в формате WAV/AIFF/MP3/MP2/MP1/OGG;
  • потоковое воспроизведение звуковых файлов в формате MP3/MP2/MP1/OGG/WAV/AIFF;
  • потоковое воспроизведение звука из интернет (по протоколам http и ftp, с поддержкой серверов Shoutcast, Icecast & Icecast2);
  • воспроизведение файлов музыкальных форматов (XM, IT, S3M, MOD, MTM, UMX), а также формата MO3 (mod музыка, сжатая MP3/OGG);
  • запись звука;
  • поддержка эффектов обработки звуков и эффектов DirectX 8 (только для Win32): Chorus / compressor / distortion / echo / flanger / gargle / parametric eq / reverb и т.д.;
  • поддержка многоканального (а не только стерео) звука, в том числе и многоканальных OGG/WAV/AIFF файлов;
  • поддержка многопотоковых звуковых карт;
  • поддержка позиционируемого 3D звука и EAX;
  • поддержка расширений (плагинов);
  • и многое другое.

На платформе Win32 библиотека BASS требует для своей работы DirectX версии 3 и выше. BASS использует аппаратное ускорение функций DirectSound и DirectSound3D(если это поддерживается звуковой картой). На MacOSX для вывода звука используется CoreAudio (рекомендуется OSX 10).

Кроме основного модуля (bass.dll), на сайте можно найти дополнения (плагины), расширяющие возможности библиотеки. Так, для воспроизведения файлов в формате wma необходимо использовать плагин basswma.dll.

Дистрибутив BASS представляет собой zip-архив и содержит библиотеку bass.dll, библиотеку импорта bass.lib, заголовочные файлы и файлы с исходными кодами примеров для C/C++ , Delphi, MASM, VisualBasic, а также подробную справку в формате .chm. Следует заметить, что в состав пакета FreeBASIC входят заголовочный файл и библиотека импорта, необходимые для работы с BASS.

BASS не требует инсталляции: достаточно распаковать архив соответствующим архиватором.

Библиотека импорта bass.lib является библиотекой в формате coff, то есть может быть использована только с Visual C++ и MASM. Если предполагается использовать Borland C++ или MINGW (gcc), то придётся изготовить необходимые библиотеки импорта самостоятельно или загрузить по ссылке после статьи.

Основные понятия

Как и в большинстве библиотек для работы со звуковыми данными, в BASS представлены следующие звуковые объекты:

  • sample (сэмплы) - это звуковые данные из небольших по размеру звуковых файлов различных форматов. "Небольшие" означает, что эти звуковые данные при воспроизведении целиком загружаются в память.
  • stream (потоки) - это звуковые данные, которые считываются порциями из звуковых файлов или из интернета и тут же передаются на воспроизводящее устройство. Потоковое воспроизведение позволяет проигрывать большие по размеру звуковые файлы и при этом не загружать их в память целиком.
  • mod music (музыкальные модули) - это данные, представленные в музыкальных (так называемых "трекерных") форматах. В файлах с трекерной музыкой, как правило, содержатся команды или "паттерны" для воспроизводящей программы (например, наподобие нотной записи) и образцы звучания инструментов, которые используются при воспроизведении (синтезе) этого музыкального модуля.

Непосредственное воспроизведение звука происходит через так называемые "каналы", поэтому все виды звуковых данных (sample, stream и mod music) связываются с каналами воспроизведения звука.

Среди функций, составляющих API библиотеки BASS, можно выделить следующие группы:

  • функции управления библиотекой (конфигурирование, инициализация, выгрузка, получение информации и т.д.);
  • функции с префиксом BASS_Sample..., предназначенные для работы с samples (загрузка, управление, выгрузка и т.д.);
  • функции с префиксом BASS_Stream..., предназначенные для работы с streams (загрузка, выгрузка, управление и т.д.);
  • функции с префиксом BASS_Music..., предназначенные для работы с mod music (загрузка, выгрузка, управление и т.д.);
  • функции с префиксом BASS_Channel..., предназначенные для работы с каналами (воспроизведение, остановка, позиционирование, управление громкостью, балансировка каналов и т.д.);
  • функции с префиксом BASS_Record..., предназначенные для записи звука;
  • функции с префиксом BASS_FXS..., предназначенные для создания различных звуковых эффектов;
  • прочие функции.

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

Проверка версии BASS

Для библиотеки BASS не гарантируется совместимость версий на уровне API, поэтому для того чтобы избежать ошибок при выполнении программы, необходимо проверить версию dll. Для этого используются функция BASS_GetVersion(), которая возвращает номер версии dll, и константа BASSVERSION, которая содержит номер версии библиотеки, необходимой для работы прикладной программы. Константа BASSVERSION соответствует старшим двум цифрам в полном номере версии и не содержит младших цифр номера.

Функция BASS_GetVersion не имеет параметров и возвращает номер версии в виде 32-разрядного шестнадцатеричного числа. Например, результат 0x02030001 соответствует версии 2.3.0.1. Для сравнения с константой BASSVERSION можно использовать макрос HIWORD, а для определения субверсии - макрос LOWORD, например:

if (HIWORD(BASS_GetVersion())!=BASSVERSION) {
	/*... обработка ошибки... */
}

Инициализация и завершение работы BASS

Прежде чем воспользоваться функциями BASS, необходимо выполнить инициализацию звуковой подсистемы. Исключение составляют лишь функции записи звука, которые доступны без предварительной инициализации. Делается это при помощи функции BASS_Init, прототип которой:

BOOL BASS_Init(
 int device,
 DWORD freq,
 DWORD flags,
 HWND win,
 GUID *clsid
);

Здесь первый параметр device - это номер звукового устройства, с которым будет работать библиотека. Если device равно -1 (минус один), то используется устройство, выбранное в системе по умолчанию. Значение 0 соответствует отсутствию звукового устройства. Значения 1, 2 и так далее указывают первую, вторую и последующие звуковые карты соответственно (если они установлены в системе).

Параметр freq устанавливает частоту дискретизации в Герцах для выходного микшера. Параметр flags содержит комбинацию флагов, объединенных операцией логическое ИЛИ и устанавливающим параметры работы устройства воспроизведения. В частности, при помощи флага BASS_DEVICE_3D устанавливается режим позиционируемого 3D звука. Параметр win содержит дескриптор окна приложения, с которым будет связано воспроизведение звука. Значение 0 соответствует текущему окну и должно использоваться для консольных приложений. Параметр clsid содержит идентификатор DirectSound, который библиотека BASS должна использовать для инициализации DirectSound. Значение NULL соответствует идентификатору, используемому по умолчанию.

Функция BASS_Init возвращает TRUE в случае успешного выполнения и FALSE в случае ошибки.

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

Перед завершением работы приложения необходимо вызвать функцию BASS_Free, которая закроет все существующие каналы воспроизведения и освободит системные ресурсы. У этой функции нет параметров.

Функция BASS_Free освобождает текущее устройство, поэтому если были инициализированы несколько устройств, то BASS_Free должна вызываться для каждого из них (сменить устройство можно при помощи функции BASS_SetDevice).

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

#include <windows.h>
#include <conio.h> /* нужен для других примеров */
#include "bass.h"
/* подключаем библиотеку импорта */
#if defined __BORLANDC__
/* для Borland C++ */
#pragma comment (lib, "bass-dcc.lib")
#elif defined _MSC_VER
/* для Visual C++ */
#pragma comment (lib, "bass.lib")
#endif
int main (void)
{
/* проверка версии BASS */
	if (HIWORD(BASS_GetVersion())!=BASSVERSION) {
	MessageBox (NULL, "Ошибка версии BASS.", NULL, 0);
	return 1;
}
if (!BASS_Init (-1, 22050, BASS_DEVICE_3D , 0, NULL)) {
	MessageBox (NULL, "Не удалось инициализировать BASS.", NULL, 0);
	return 1;
}
/*
		... работаем со звуком ...
*/
BASS_Free ();
return 0;
}

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

После инициализации устройства можно приступать к воспроизведению звука. Для начала разберём, что необходимо сделать, чтобы воспроизвести небольшой звуковой образец (sample).

Последовательность действий здесь такая:

  • создать sample из звукового файла при помощи функции BASS_SampleLoad;
  • создать канал воспроизведения для sample при помощи функции BASS_SampleGetChannel;
  • установить необходимые параметры воспроизведения (например, громкость, пространственные координаты источника и т.п.);
  • начать воспроизведение при помощи функции BASS_ChannelPlay;
  • по окончанию воспроизведения освободить ресурсы при помощи функции BASS_SampleFree.

Прекратить воспроизведение можно, вызвав функцию BASS_ChannelStop, а проверить, играет ли еще канал или нет - функцией BASS_ChannelIsActive.

Остановимся подробнее на некоторых из вышеназванных функций. Функция BASS_SampleLoad имеет следующий прототип:

HSAMPLE BASS_SampleLoad(
 BOOL mem,
 void *file,
 DWORD offset,
 DWORD length,
 DWORD max,
 DWORD flags
);

Здесь параметр mem указывает, что звуковые данные берутся из памяти (TRUE) или из файла (FALSE). Параметр file указывает на строку символов с именем файла, если звуковые данные должны быть загружены из файла, или является адресом памяти, если данные должны считываться из памяти. Параметр offset задает смещение позиции чтения данных от начала файла (в VASS версии 2.4.x тип этого параметра был изменён на QWORD). Параметр length указывает длину считываемого фрагмента данных. Если этот параметр равен нулю, то считываются все данные до конца файла. Параметр max указывает максимальное число каналов, одновременно воспроизводящих этот звуковой образец. Параметр flags содержит комбинацию флагов, устанавливающих свойства канала воспроизведения. Например, флаг BASS_SAMPLE_LOOP устанавливает циклическое повторение звука при воспроизведении. Флаг BASS_SAMPLE_3D указывает, что для данного канала необходима поддержка функций позиционирования звука в пространстве, а флаг BASS_SAMPLE_MONO принудительно устанавливает монофонический режим при воспроизведении файлов mp3/mp2/mp1. Принудительная установка монофонического режима бывает полезной при работе с 3D звуком, так как в этом случае допускаются только монофонические источники звука. Флаг BASS_UNICODE указывает, что имя файла задано в кодировке Unicode (UDF16). Кроме этих, существуют и другие флаги, о назначении которых можно узнать из входящего в дистрибутив справочного файла.

Функция BASS_SampleLoad в случае успешного завершения возвращает дескриптор HSAMPLE созданного образца звука. Этот дескриптор может быть использован для создания канала воспроизведения звука.

Функция BASS_SampleGetChannel имеет следующий прототип:

HCHANNEL BASS_SampleGetChannel(
 HSAMPLE handle,
 BOOL onlynew
);

Здесь параметр handle - это дескриптор sample, который был возвращен функцией BASS_SampleLoad. Параметр onlynew указывает, надо ли повторно использовать для воспроизведения один из уже существующих каналов.

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

Функция BASS_ChannelPlay требует передачи двух параметров. Первый параметр - это дескриптор канала. Второй параметр указывает, надо ли начинать воспроизведение звукового образца с самого начала (иначе воспроизведение начнется с текущей позиции).В случае успеха эта функция возвращает TRUE.

Функция BASS_ChannelSet3DPosition задает положение источника звука в трехмерном пространстве и имеет прототип:

BOOL BASS_ChannelSet3DPosition(
 DWORD handle,
BASS_3DVECTOR *pos,
BASS_3DVECTOR *orient,
BASS_3DVECTOR *vel
);

Здесь параметр handle - это дескриптор канала воспроизведения. Параметр pos - это указатель на структуру, определяющей координаты источника звука. Если этот параметр равен NULL, то координаты источника звука не меняются. Параметр orient - это указатель на структуру, задающую пространственную ориентацию источника звука. Если этот параметр равен NULL, то ориентация источника не меняется. Параметр vel - это указатель на структуру, задающую координаты вектора скорости, с которой перемещается объект. Если этот параметр равен NULL, то координаты скорости источника не меняются. Следует помнить, что координаты скорости используются библиотекой BASS исключительно для расчета эффекта Доплера, а не для вычисления новых пространственных координат источника звука.

Функция в случае успеха возвращает TRUE, а в случае ошибки - FALSE.

Структура BASS_3DVECTOR, которая используется для задания векторов и пространственных координат, имеет следующее определение:

typedef struct {
 float x;
 float y;
 float z;
} BASS_3DVECTOR;

При работе с функциями позиционирования звука в 3D пространстве следует использовать функцию BASS_Apply3D, чтобы изменения пространственной звуковой картины вступили в силу. Эта функция не имеет параметров.

Ниже представлен фрагмент исходного кода, в котором реализовано воспроизведение движущегося в пространстве источника звука. Звуковые данные загружаются из файла test.mp3. Фрагменты кода, связанные с инициализацией и выгрузкой BASS, в этом и последующих примерах не приводятся.

HSAMPLE samp;		/*дескриптор сэмпла */
HCHANNEL ch; 	/* дескриптор канала */
char filename[] = "test.mp3";
BASS_3DVECTORpos ={ 0.0f, 0.0f, 1.0f}; /* координаты источника звука */
/* загрузка звукового образца из файла*/
samp =BASS_SampleLoad(FALSE,filename, 0, 0,1, BASS_SAMPLE_3D | BASS_SAMPLE_LOOP );
if (!samp) {
	/* ... обработка ошибки ... */
	return 1;
}
/* создание канала воспроизведения */
ch = BASS_SampleGetChannel(samp,FALSE);
if (!ch) {
	/*... обработка ошибки */
	return 1;
}
/* воспроизводим звук */
if (!BASS_ChannelPlay(ch,FALSE)) {
	/* ... обработка ошибки ... */
	return 1;
}
/* цикл, прерываемый по нажатию клавиши */
while (!kbhit()) {
	if (pos.y > 10.0f) pos.y= -10.0f;
	else pos.y+= 0.2f;
	BASS_ChannelSet3DPosition (ch, &pos, NULL, NULL);
	BASS_Apply3D();
	Sleep (200);
}
/* остановка воспроизведения */
BASS_ChannelStop(ch);
/* освобождение ресурсов */
BASS_SampleFree (samp);

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

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

Для создания потокового звука (stream), связанного с файлом в формате MP3, MP2, MP1, OGG, WAV, AIFF (а также в одном из форматов, поддерживаемых плагинами), в библиотеке BASS предусмотрена функция BASS_StreamCreateFile, которая имеет следующий прототип:

HSTREAM BASS_StreamCreateFile(
 BOOL mem,
 void *file,
 DWORD offset,
 DWORD length,
 DWORD flags
);

Здесь параметр mem указывает, что звуковые данные берутся из памяти (TRUE) или из файла (FALSE). Параметр file указывает на строку символов с именем файла, если звуковые данные должны быть загружены из файла, или является адресом памяти, если данные должны считываться из памяти. Параметр offset задает смещение позиции чтения данных от начала файла. Параметр length указывает длину считываемых данных. Если этот параметр равен 0, то при воспроизведении будут считаны все данные до конца файла. Параметр flags является комбинацией флагов, устанавливающих режим воспроизведения потокового звука. Например, флаг BASS_SAMPLE_3D указывает, что для этого stream необходима поддержка функций позиционирования в 3D пространстве. Флаг BASS_SAMPLE_LOOP устанавливает циклический режим воспроизведения, то есть после окончания воспроизведения файла автоматически этот файл зазвучит снова. Флаг BASS_UNICODE указывает на то, что имя файла задано в Unicode (UDF16). О других флагах и их назначении можно узнать из файла справки.

В случае успешного завершения функция BASS_StreamCreateFileвозвращает дескриптор потока (тип HSTREAM ), который можно использовать в функциях управления каналом воспроизведения вместо дескриптора канала.

Ниже приводится фрагмент исходного кода, реализующего воспроизведение звукового файла в формате mp3 ("song.mp3").

HSTREAM stream;	/* дескриптор потока */
char filename[] = "song.mp3";
/* ... */
/* создаем потоковый звук, связанный с файлом */
 stream = BASS_StreamCreateFile(FALSE, filename, 0, 0, 0);
if (!stream) {
	/* ...обработка ошибки... */
	return 1;
}
/* воспроизводим звук */
BASS_ChannelPlay(stream,TRUE);
/* цикл, прерываемый нажатием клавиши или завершением воспроизведения файла */
while (!kbhit() && BASS_ChannelIsActive(stream) != BASS_ACTIVE_STOPPED) {
	Sleep (200);
}
/* останавливаем звучание */
BASS_ChannelStop(stream);
/* освобождаем ресурсы */
BASS_StreamFree(stream);

Воспроизведение аудиоданных из сети Интернет

Библиотека BASS позволяет воспроизводить звуковые данные, получаемые из сети Интернет, причем это могут быть как файлы, расположенные на каком-либо сайте (например, в формате mp3), так и аудиопоток, поступающий от интернет-радиостанций. Для создания потокового звука, связанного с аудиоданными, получаемыми из сети Интернет, необходимо использовать функцию BASS_StreamCreateURL, которая имеет следующий прототип:

HSTREAM BASS_StreamCreateURL(
 char *url,
 DWORD offset,
 DWORD flags,
DOWNLOADPROC *proc,
 DWORD user
);

Здесь параметр url - это указатель на строку с интернет-адресом, откуда должны быть получены аудиоданные. Интернет-адрес должен начинаться с указания протокола: "http://" или "ftp://". Параметр offset указывает смещение от начала аудиоданных. Значение этого параметра игнорируется, если отсутствует информация о размере файла (что бывает при "прямом" вещании в Интернет). Параметр flags является комбинацией флагов, устанавливающих параметры потокового звука. Параметр proc - это адрес пользовательской CALLBACK функции, которая будет вызвана как только файл будет загружен из сети. Если значение этого параметра NULL, то вызов CALLBACK функции не выполняется. Параметр user содержит данные, которые будут переданы пользовательской CALLBACK функции при ее вызове (если такая функция определена).

Пользовательская CALLBACK функция должна иметь следующий прототип:

void CALLBACK YourDownloadProc(
 void *buffer,
 DWORD length,
 DWORD user
);

Эта функция в параметре buffer получает указатель на загруженные данные. Если этот указатель равен NULL, то загрузка данных завершена. В параметре length функция получает количество загруженных данных в байтах. Параметр user содержит значение, указываемое в последнем параметре функции BASS_StreamCreateURL.

Ниже приведен фрагмент исходного кода, в котором реализовано воспроизведение звуковых данных, поступающих от интернет-радиостанции.

HSTREAM stream;	/* дескриптор потока */
char url[] ="http://radio.echo.msk.ru:8000";

/* ... */
/* создаем поток, связанный с url */
stream =BASS_StreamCreateURL(url, 0, 0, NULL, 0);
 if (!stream) {
	/* ...обработка ошибки... */
	return 1;
}
/* воспроизводим звук */
BASS_ChannelPlay(stream,TRUE);
/* цикл, прерываемый нажатием клавиши */
while (!kbhit()) Sleep (200);
/* останавливаем воспроизведение */
BASS_ChannelStop(stream);
/* освобождаем ресурсы */
BASS_StreamFree(stream);

Воспроизведение музыки

Для загрузки музыки из файлов в форматах MO3 / IT / XM / S3M / MTM / MOD / UMX необходимо использовать функцию BASS_MusicLoad, которая имеет следующий прототип:

HMUSIC BASS_MusicLoad(
 BOOL mem,
 void *file,
 DWORD offset,
 DWORD length,
 DWORD flags,
 DWORD freq
);

Здесь параметр mem указывает, загружаются ли данные из памяти (TRUE) или из файла (FALSE). Параметр file является указателем на строку с именем файла, если данные загружаются из файла, или адресом памяти, если данные берутся из памяти. Параметр offset задает смещение от начала файла. Параметр length указывает размер данных. Если этот параметр равен 0, то обрабатываются все данные до конца файла. Параметр flags содержит комбинацию флагов, определяющих параметры воспроизведения музыки. Параметр freq устанавливает частоту воспроизведения. Если этот параметр равен 0, то используется значение, указанное при вызове функции BASS_Init.

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

Ниже приведен фрагмент исходного кода, реализующего воспроизведение файла в формате s3m ("test.s3m").

HMUSIC mus;
char filename[] = "test.s3m";
/* ... */
/* загружаем файл s3m */
/* для примера указан флаг BASS_MUSIC_SURROUND */
mus = BASS_MusicLoad(FALSE,filename, 0, 0, BASS_MUSIC_SURROUND, 0);
if (!mus) {
	/* ...обработка ошибки... */
	return 1;
}
/* цикл, прерываемый нажатием клавиши или окончанием воспроизведения */
while (!kbhit() && BASS_ChannelIsActive(mus) != BASS_ACTIVE_STOPPED) {
	Sleep (200);
}
/* останавливаем воспроизведение */
BASS_ChannelStop(mus);
/* освобождаем ресурсы */
BASS_MusicFree(mus);

Обработка ошибок

Большинство функций библиотеки BASS в случае ошибки возвращают FALSE. Для того чтобы получить более подробную информацию о возникшей ошибке, необходимо вызвать функцию BASS_ErrorGetCode. Эта функция не имеет параметров и возвращает код ошибки.

Функцию BASS_ErrorGetCode следует вызывать сразу после вызова той функции, результат которой необходимо проверить на наличие ошибок. Если ошибок не было функция вернет значение BASS_OK.

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

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

Вот простейший пример вызова функции BASS_ErrorGetCode:

samp =BASS_SampleLoad(FALSE,filename, 0, 0,1, BASS_SAMPLE_3D | BASS_SAMPLE_LOOP );
if (!samp) {
	printf ("Error code: %d\n", BASS_ErrorGetCode());
}
  1. Официальная страница поддержки библиотеки BASS - На этой странице находятся свежая информация о библиотеке BASS и ссылки для загрузки дистрибутивов.
  2. Библиотеки импорта BASS для Borland C++ и MINGW32 (gcc).


Распространение материалов сайта означает, что распространитель принял условия лицензионного соглашения.
Идея и реализация: © Владимир Довыденков и Анатолий Камынин,  2004-2017