Главная » Программирование звука » Конфигурирование потока и подключение к серверу

0

Установление  связи  с  сервером  и  конфигурирование  подходящего  потока  скучная, но неизбежная операция. Этот поток состоит из двух элементов. Клиент импорта  хранитданные,  полученные  от  клиента,  и,  при  необходимости,  запрашивает дополнительные данные. Устройство экспорта передает данные получателю. Встречаются  устройства  экспорта,  предназначенные  для  работы  с  несколькими звуковыми картами и сетевыми службами. B нашем случае я просто хочу убедиться,  что  устройство,  на  которое  мы  выводим  данные,  является  устройством  выводавфизическом  смысле  (громкоговоритель)  и  поддерживает  работу  с  требуемым количеством каналов (моно или стерео). После регистрации потока наступает время для последнего шага регистрации функции обратного вызова.

Библиотечная    функция    AuOpenServer просматривает    несколько    стандарт-

ных  мест в поисках  сервера, который следует  использовать.  Сначала  она пробует

считать  значение  переменной  среды  AUDIOSERVER.  Если  эта  переменная  отсутствует, то используется переменная среды DISPLAY. B отличие от версий, рассчитанных  для  работы  в  Mac  OS  или  Windows,  вам  незачем  беспокоиться  о  том, с какими данными сможет работать сервер NAS 16-битными или 8-битными.

Все серверы NAS воспринимают данные обоих типов и, при необходимости, про-

водят внутреннюю конвертацию.

Листинг 8.4. Реализация класса NasPlayer (продолжение)

void NasPlayer::OpenServer(){ AuDeviceID deviceID = AuNone;

// Открываем  подключение  к  серверу.

const char * const NullString = (const char *)NULL;

char *server_message;

_server = AuOpenServer(

NullString,0,NullString,0,NullString,  // Используем

// значения

// по  умолчанию.

&server_message);       // Сообщение

// об  ошибке.

if (server_message != (char *)NULL) {

// He удалось  подключиться к  аудиосерверу. Сервер:

cerr << "Could not connect to audio server.\n"; cerr << "Server: " << server_message << "\n"; exit(1);

}

if (!_server) {

// He удалось  подключиться к  аудиосерверу.

cerr << "Could not connect to audio server.\n";

exit(1);

}

// Выбираем  первое  подходящее устройство  вывода. for (int i=0; i< AuServerNumDevices(_server); i++) {

AuDeviceAttributes *device = AuServerDevice(_server,i);

if ((AuDeviceKind(device) == AuComponentKindPhysicalOutput)

&&

(AuDeviceNumTracks(device) == Channels())) {

deviceID = AuDeviceIdentifier(device);

break;

}

}

if (deviceID == AuNone) {

// He обнаружено подходящего устройства  вывода.

cerr << "No suitable audio output device found.\n";

exit(1);

}

// Запрос на   организацию нового  потока  на   сервере.

_flow = AuGetScratchFlow(_server,NULL);

if (_flow == AuNone) {

// He удалось создать  аудиопоток на   сервере.

cerr << "Could not create audio flow on server.\n";

exit (1);

}

// Необходимо сообщить серверу   NAS о  том, какой

// размер  должен иметь его  буфер.

long requestSize = (nasBufferSize)/Channels()/2;

// Создание элементов  для  нашего потока.

AuElement elements[2];

// Первый   элемент это  клиент  импорта (я подаю   данные).

AuMakeElementImportClient(&elements[0],   // Первый   элемент.

SamplingRate(),                        // Частота

// дискретизации. NasFormatCode(16),                // Получаем  код   формата. Channels(),                       // Число  каналов.

AuTrue,                           // При  запуске -

// в состоянии паузы. requestSize,            // Сколько отсчетов  запрашивать. requestSize/2,          // Минимальный  уровень.

0,NULL);                // He действуем.

// Последний элемент  это  устройство вывода.

AuMakeElementExportDevice(&elements[1],

0,                    // Ha вход  получаем  данные

// от предыдущего.

deviceID,              // ID устройства вывода.

SamplingRate(),       // Частота дискретизации. AuUnlimitedSamples,   // Играть вечно.

0, NULL);              // He действуем.

// Регистрация этого  потока

// на   сервере.

AuStatus status; AuSetElements(_server,_flow,AuTrue,2,elements,&status); if (status) {

// He удалось  сконфигурировать поток.

cerr << "Couldn’t configure flow.\n";

exit(1);

}

// Регистрация  обработчика  событий

// клиента импорта.

AuEventHandlerRec *handler = AuRegisterEventHandler(_server,

reinterpret_cast<AuPointer>(this)); // Это

// вспомогательные

// данные.

if (!handler) { AuReleaseScratchFlow(_server,_flow,NULL);

// He удалось  зарегистрировать  обработчик событий.

cerr << "Couldn’t register event handler\n";

exit(1);

}

}

Пример приложения для UNIX

B  этой  элементарной  программе,  работающей  в  текстовом  режиме,  функция main выглядит  очень  просто.  Учтите,  что  эта  функция  не  может  получать  данные из cin, так как нам необходима функция OpenFormat для поиска в файле.

Листинг 8.5. Программа nasmain.cpp

#include "open.h"

#include "aplayer.h"

#include "nasplayr.h"

#include <fstream>

int main(int argc, char **argv) {

while (–argc) {

++argv;

cerr << "File: " << *argv << "…\n";

ifstream input(*argv);

if (!input.is_open()) {

// He удалось  открыть файл.

cerr << "Couldn’t open file " << *argv << "\n";

continue;

}

AudioAbstract *audioFile = OpenFormat(input);

if (audioFile) {

NasPlayer player(audioFile);

player.Play();

delete audioFile;

// Закончено воспроизведение  файла.

cerr << "Finished playing " << *argv << ".\n";

}

cerr << "\n";

}

return 0;

}

Глава 9. Компрессия звука

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

Несмотря  на  то,  что  общепринято  различать  «сжатые»  и  «несжатые»  звуковые данные, говорить просто о различных способах «кодирования» звука было бы, вероятно,  уместнее.  Самый  простой  способ  кодировки,  с  которым  вы  столкнетесь при работе с цифровым звуком, это ИКМ, описанная в главе 3. Даже этот простой  формат  сложнее,  чем  могло  бы  показаться,  и  существует,  по  крайней  мере, четыре  формата  ИКМ,  широко  используемые  для  записи  файлов.  Более  подробно эти вопросы рассматриваются в главе 10.

Большинство программистов считают, что звук, записанный с помощью ИКМ, компрессии  не  подвергается.  Если  вы  начнете  работать  с  форматом  ИКМ,  то  алгоритмы  компрессии  звука  преобразуют  ИКМ в  более  компактный  формат. B ос-

тавшейся  части  данной  главы  я  приведу  краткий  обзор  используемых  для  этого

методов.  Несколько  последующих  глав  посвящены  более  детальному  рассмотре-

нию своеобразных алгоритмов компрессии звука, применяемых на практике.

Источник: Кинтцель Т.  Руководство программиста по работе со звуком = A Programmer’s Guide to Sound: Пер. с англ. М.: ДМК Пресс, 2000. 432 с, ил. (Серия «Для программистов»).

По теме:

  • Комментарии