Об’єкти-програвачі

Перш ніж ви станете по-справжньому добре розбиратися в методах роботи зі звуком, вам потрібно навчитися передавати дані на гучномовець для того, щоб ви могли чути получающийся звук B цій і ще кількох наступних розділах ми подивимося, як це можна зробити в декількох системах B цій главі розробимо кілька загальних фрагментів коду, які будуть корисні у багатьох системах

Як ви зможете переконатися самі, у всіх трьох системах, які є предметом нашої уваги, прийнята одна і та ж модель: спочатку система опитується щодо того, які типи звуків вона може обробляти Часто засоби роботи зі звуком у системі приймають форму різних логічних звукових пристроїв Після цього ви обираєте формат, найбільш підходящий для того звуку, який ви збираєтеся відтворити І нарешті, вам необхідно організувати чергування запису та отримання нових порцій звукових даних так, щоб відтворення не припинявся

Класипрогравачіввідповідають за передачу звукових даних на гучномовець в конкретно заданій системі Їх загальні властивості описані в класі AbstractPlayer, який ми і будемо створювати в цьому розділі

Лістинг 51 Програма aplayerh

#ifndef ABSTRACTPLAYER_H_INCLUDED

#define ABSTRACTPLAYER_H_INCLUDED

#include &quotaudioh&quot

#endif

Програвачі: основи

B бібліотеках багатьох систем є прості функції для відтворення окремих звуків, записаних у файлах або зберігаються в блоках памяті Хоча ці функції відмінно підходять для відтворення простих звуків попередження та інших коротких фрагментів, їх використання являє собою проблему при відтворенні складних звуків, які формуються динамічно по мірі відтворення Після отримання запиту на відтворення окремого звуку системою спочатку проводиться значний обсяг підготовчої роботи, в тому числі виділення памяті і конфігурація відповідного апаратного забезпечення

Ці підготовчі операції проводяться кожного разу при отриманні запиту на відтворення звуку, а після його закінчення все повертається в початковий стан Якщо ви робите кілька послідовних викликів, то в результаті цих операцій між відтворюваними звуковими блоками буде помітна невелика пауза

B залежності від використовуваної системи, тривалість цієї паузи може змінюватися від сотих часток секунди до настільки великої величини, як півсекунди Навіть сама коротка пауза помітна на слух, і її наявність може викликати серйозні проблеми, якщо вам потрібно синхронізувати відтворення звуку з відтворенням відео або іншими операціями, які вимагають точної синхронізації

Єдиний спосіб уникнути цієї неприємності полягає в тому, щоб забезпечити системі гарантований запас даних B більшості систем для цього використовується метод, званий  подвійна буферизація:організуються два буфера, і в кожний момент часу система зчитує дані з одного з них Як тільки будуть повністю зчитані дані з одного буфера, відбувається автоматичне перемикання на інший, а програма отримує можливість заповнювати щойно звільнився буфер Потрібно тільки, щоб ваша програма обовязково встигала заповнити цей буфер до того, як він знадобиться системі

Подібну схему дії можна реалізувати і при використанні звичайного кільцевого буфера Система стежить за кількістю даних в буфері, і як тільки це кількість впаде нижче мінімальної позначки, система попросить вас додати дані в буфер B кінцевому підсумку, цей метод дає такий же ефект, що і подвійна буферизація

Незалежно від того, яким саме методом ви скористаєтеся, вам знадобиться швидко передавати дані системі, як тільки вона їх зажадає B класі AbstractPlayer для цього використовується чергу аудіоданих Робиться це так Ви періодично викликаєте FillQueue, запитувач дані у решти модулів обробки звуку і поміщає їх у кінець черги Після цього викликається метод FromQueue, за допомогою якого дані з черги копіюються в довільну системну структуру даних, використовувану вами

Ця системна структура, безумовно, може і не зберігати значення AudioSample B звязку з цим в класі AbstractPlayer визначається два нових типи даних: Samplel6, для запису 16-бітових відліків і Sample8 для 8-бітних Метод FromQueue, c допомогою якого виробляється копіювання даних з черги, був перевантажений так, щоб повертати дані в будь-якому з цих двох форматів

Лістинг 52 Клас AbstractPlayer

class AbstractPlayer : public AudioAbstract {

protected:

typedef short Sample16

typedef signed char Sample8

volatile AudioSample * _queue, * _queueEnd / / Початок кінець

/ / Області памяті,

/ / Відведеної

/ / Під чергу

volatile AudioSample * volatile _queueFirst / / Перша

/ / Вибірка

volatile AudioSample * volatile _queueLast / / Остання

/ / Вибірка

void InitializeQueue (unsigned long queueSize) / / Створює

/ / Чергу

void FillQueue (void) / / Заповнює

/ / Чергу

long FromQueue(Sample8 *pDest,long bytes) long FromQueue(Sample16 *pDest,long bytes) private:

void DataToQueue (long) / / Використовується методом FillQueue

void DataFromQueue (Sample8 *, long) / / Використовується методом

/ / FromQueue (Sample8 .) void DataFromQueue (Sample16 *, long) / / Використовується методом

// FromQueue(Sample16..)

private:

size_t GetSamples(AudioSample *,size_t) { exit(1) return 0

}

He завжди просто визначити момент, коли звук вже закінчився Після того як вважається вся початкова інформація, дані будуть зберігатися в черзі Коли дані в черзі закінчаться, система може продовжити «програвати» дані зі своїх внутрішніх буферів B класі AbstractPlayer використовуються два прапори, які служать ознаками того, що черга спорожніла або закінчилися дані в зовнішньому джерелі

Лістинг 52 Клас AbstractPlayer (продовження)

protected:

bool _endOfSource / / Істина, якщо із зовнішнього джерела

/ / Зчитані останні дані

bool _endOfQueue / / Істина, якщо із зовнішнього джерела

/ / Зчитані останні дані

public:

AbstractPlayer(AudioAbstract *a)

~AbstractPlayer()

virtual void Play () = 0 / / Власне відтворення запису

}

Лістинг 5З Програма aplayercpp

#include &quotaplayerh&quot AbstractPlayer::AbstractPlayer(AudioAbstract *a) : AudioAbstract(a) {

_endOfSource = false

_endOfQueue = false

_queue = _queueEnd = _queueFirst = _queueLast = 0

}

AbstractPlayer::~AbstractPlayer(void) {

if (_queue)

// MS VC++ 50 c a n t delete a volatile pointer!?!

/ / Компілятор MS VC + + 50 не може видалити покажчик

/ / Типу volatile!?!

delete [] const_cast&ltAudioSample *&gt(_queue)

}

Джерело: Кінтцель Т Керівництво програміста по роботі зі звуком = A Programmers Guide to Sound: Пер з англ М: ДМК Пресс, 2000 432 с, іл (Серія «Для програмістів»)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*