Главная » Программирование звука » Воспроизведение звука в Mac OS

0

Хотя  в  техническом  смысле  Mac  OS  не  является  многопотоковой  операционной системой, работа со звуком в ней весьма схожа с работой со звуком в Windows. Вместо  использования  отдельного  потока  из  процедуры  службы  обработки  прерываний происходит  обращение  к  функции  обратного  вызова.  Это  накладывает  еще  более строгие ограничения на то, что можно делать с помощью функции обратного вызова: процедуры службы обработки прерываний должны выполняться быстро.

Листинг 7.1. Программа macplayr.h

/*

* Класс проигрывателя  для Mac OS

*/

#ifndef MAC_PLAYER_H_INCLUDED

#define MAC_PLAYER_H_INCLUDED

#include "audio.h"

#include "aplayer.h"

#include <Resources.h>

#include <Sound.h>

#include <Memory.h>

#include <Events.h>

#include <StandardFile.h>

#define doubleBufferSize 0x1000

class MacPlayer : public AbstractPlayer {

private:

friend pascal void NextBlockCallback(SndChannelPtr, SndDoubleBufferPtr);

void NextBlock(SndChannelPtr, SndDoubleBufferPtr);

public:

MacPlayer(AudioAbstract *a):AbstractPlayer(a) {};

~MacPlayer() {};

void Play() { Play(0); }

void Play(void (*serviceFunc)(void));      // Собственно

// воспроизведение.

};

#endif

И снова обращаю ваше внимание на то, что функция обратного вызова объявляется как friend, это означает, что из нее можно обращаться к скрытому методу NextBlock.

Листинг 7.2. Программа macplayr.cpp

#include <Resources.h>

#include <Sound.h>

#include <Memory.h>

#include <Menus.h>

#include <istream>

#include <fstream>

#include "audio.h"

#include "aplayer.h"

#include "macplayr.h"

Вызов подсистемы

Функция   NextBlockCallBack вызывается   Распорядителем   Звука,   когда   при двойной буферизации один из буферов становится пустым. Учтем, что данный вызов производится во время прерывания, поэтому эта процедура должна выполняться относительно  быстро  и не  использовать  вызовов,  которые  могли  бы  занять  или освободить  память  в  динамически  распределяемой  системной  области.  (B  частности,  нельзя  задействовать  операции  new  и  delete  языка  C++,  иногда  применяемые для захвата или освобождения памяти в системной области.)

Функция  NextBlockCallBack просто  возвращает  указатель  на  объект  и  инициирует  метод.  Вся  остальная  работа  выполняется  методом  FromQueue,  который аккуратно  разработан  так,  чтобы  не  использовать  никаких  служб  операционной системы.

B  настоящий  момент  в  этой  программе  используются  только  16-битные  отсчеты.  При  написании  более  изощренной  программы  вам,  возможно,  потребуется вместо  16-битного  использовать  8-битное  представление  выборок.  B  таком  случае   учтите,   что   управляющая   звуком   программа   Mac   Sound   Manager   работает в предположении, что 8-битные отсчеты записаны в беззнаковом формате (см. раздел  «Беззнаковая  8-битная  ИКМ»  в  главе  10).  Ниже  я  привел  две  строки,  с  помощью  которых  байтовый  буфер  можно  преобразовать  из  знакового  в  беззнаковый формат (или наоборот):

for(long i=0; i<copied; i++)

pDest[i]^=0x80;

Листинг 7.3. Реализация класса Macplayer

pascal void NextBlockCallback(SndChannelPtr scp, SndDoubleBufferPtr doubleBuffer)

{

MacPlayer *me

= reinterpret_cast<MacPlayer *>(doubleBuffer-

>dbUserInfo[0]);

me->NextBlock(scp,doubleBuffer);

}

void MacPlayer::NextBlock(SndChannelPtr, SndDoubleBufferPtr doubleBuffer) {

AudioSample *pDest =

reinterpret_cast<Sample16 *>(doubleBuffer->dbSoundData); long copied = FromQueue(pDest,doubleBufferSize); doubleBuffer->dbNumFrames = copied/Channels();

doubleBuffer->dbFlags = (doubleBuffer->dbFlags) |

dbBufferReady;

if (_endOfQueue)

doubleBuffer->dbFlags = (doubleBuffer->dbFlags) |

dbLastBuffer;

};

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

По теме:

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