Глава 5(фрагмент) Звуковой канал DirectShow
Сбор и предварительное прослушивание звука
Примечание.
Перед чтением этого раздела следует предварительно ознакомиться с главой "Системный звуковой микшер".
Для обработки звука DirectShow предоставляет фильтр захвата звука базирующийся на звуковой карте. Каждая карта установленная в системе представляет отдельный экземпляр фильтра. Кроме фильтра сбора звука DirectShow предоставляет еще два фильтра, фильтр Audio Renderer (WaveOut) и фильтр DirectSound Renderer. Фильтр Audio Renderer (WaveOut) использует waveOut* API для обработки звука. Фильтр DirectSound Renderer реализует те же самые возможности, что и фильтр Audio Renderer, но по умолчанию используется только фильтр DirectSound Renderer. При записи телепрограммы фильтр DirectSound Renderer обеспечивает канал прослушивания записываемого звука. В режиме предварительного просмотра в канале звука может использоваться фильтр DirectSound Renderer, но фильтр звуковой карты полностью обеспечивает прослушивание телепрограммы, и принципиальной необходимости в фильтре DirectSound Renderer нет. Возможно, в каких-то особых случаях могут понадобиться эффекты DirectSound при прослушивании телепрограммы, но для обычных задач звукового сопровождения телевизионного просмотра фильтр DirectSound Renderer не нужен. Данный фильтр необходим для контроля звукового канала, если производится запись телепрограммы. В тоже время данный фильтр принимает участие в процессе построения звуковой ветви графа по умолчанию, то есть при использовании методов "интеллектуального" построения графа, что приводит к некоторым проблемам. Подробно этот вопрос рассматривается далее.
Если следовать рекомендациям документации DirectShow, то ветка графа для записи и прослушивания звука должна строиться так, как показано на рисунке 5.1. Построим граф в соответствии с рекомендациями и проверим его функционирование.
Рис.5.1. Сбор и воспроизведения звука.
Для реализации ветви графа в таком виде, необходимо произвести установку фильтра сбора в граф по данным моникера, установку фильтра Infinite Pin Tee и достройку звуковой части графа до воспроизводящего фильтра звука включительно. Запись звука в файл будет рассматриваться отдельно в главе посвященной записи файлов. Фильтр Infinite Pin Tee устанавливается и подключается только вручную. С выхода фильтра можно Infinite Pin Tee можно использовать методы для автоматической достройки графа.
Метод CCapture::InitCaptureAudio строит граф обработки звука в соответствии с рекомендациями DirectShow.
BOOL CCapture::InitCaptureAudio(IMoniker* pMoniker)
{
HRESULT hr=S_OK;
BOOL bret = TRUE;
string sErr = "Error InitCaptureAudio";
//Указатель на фильтр Infinite Pin Tee
IBaseFilter* pIT=0;
//Указатели на контакты фильтров
IPin* pOutCapA=0, *pInIT=0, *pOutIT=0;
try
{
pMoniker->AddRef();
//Установка фильтра звуковой карты
if(S_OK != (hr=
m_pGraph2->AddSourceFilterForMoniker(pMoniker ,NULL,NULL,&m_pCapA)))
throw hr;
//Если использовать RenderStream установится
//Smart Tee. Он будет работать, но рекомендуется
//использовать фильтр Infinite Pin Tee
//hr = m_pBuilder->RenderStream(
// &PIN_CATEGORY_CAPTURE,&MEDIATYPE_Audio, m_pCapA, NULL,NULL);
//Установка фильтра разделителя данных
//Infinite Pin Tee
if(S_OK != (hr = CoCreateInstance(CLSID_InfTee
,NULL, CLSCTX_INPROC,IID_IBaseFilter
,reinterpret_cast<void **>(&pIT))))
throw hr;
if(S_OK != (hr = m_pGraph->AddFilter(pIT,L"Infinite Pin Tee")))
throw hr;
//Находим выходной контакт звуковой карты
if(S_OK != (hr = m_pBuilder->FindPin(m_pCapA,PINDIR_OUTPUT,&PIN_CATEGORY_CAPTURE
,0,0,0,&pOutCapA)))
throw hr;
//Находим входной контакт фильтра Infinite Pin Tee
if(S_OK != (hr = m_pBuilder->FindPin(pIT,PINDIR_INPUT, NULL,0,0,0,&pInIT)))
throw hr;
//Находим выходной контакт фильтра Infinite Pin Tee
if(S_OK != (hr = m_pBuilder->FindPin(pIT,PINDIR_OUTPUT,NULL,0,0,0,&pOutIT)))
throw hr;
//Подключаем Infinite Pin Tee к звуковой карте
if(S_OK != (hr = m_pGraph2->Connect(pOutCapA,pInIT)))
throw hr;
//Достраиваем граф от выхода Infinite Pin Tee, метод будет устанавливать воспроизводящий звуковой //фильтр по умолчанию
if(S_OK != (hr = m_pGraph2->Render(pOutIT)))
throw hr;
}
catch(HRESULT h)
{
bret = 0;
CTVshowApp::MessageError(h,sErr);
}
pMoniker->Release();
if(pIT) { pIT->Release(); pIT=0; }
if(pOutCapA) { pOutCapA->Release(); pOutCapA=0; }
if(pInIT) { pInIT->Release(); pInIT=0; }
if(pOutIT) { pOutIT->Release(); pOutIT=0; }
return bret;
}
Результат работы метода можно увидеть в графическом редакторе. Часть картинки графического редактора показана ниже. Часть графа для записи не построена, но она пока и нужна.
Рис.5.2. Реализация воспроизведения звука.
Возможно, что такая схема построения звуковой ветви графа для определенных типов звуковых карт не доставит никаких неприятностей, и будет работать хорошо.
Проблема заключается в том, что ни фильтр DirectSound Renderer, ни фильтр звуковой карты не обеспечивают полноценного управления звуковым микшером, что может привести к образованию канала обратной связи через шину PCI или параллельного (двойного) канала звука. То есть предоставляемые интерфейсы фильтра звуковой карты и (или) интерфейсы фильтра DirectSound Renderer обеспечивают только частичное управление микшером звуковой карты, не перекрывая возможностей управления даже интегрированной звуковой карты. Более подробно об этом рассказано в главе "Системный звуковой микшер".
Например, если звуковая карта допускает подключение линии …SRC_WAVEOUT к входу мультиплексора записи, а такая возможность есть у многих типов карт, то при записи сигнала через смеситель канала воспроизведения возможно появление цепи обратной связи. Вследствие этого возникает многократное эхо в структуре записываемого сигнала. Предупредить появление эха при таком режиме записи можно, отключив линию …SRC_WAVEOUT , но это невозможно средствами DirectShow и приходится привлекать системную программу sndvol32.exe. Если не использовать фильтр DirectSound Renderer, то удается избежать появления канала обратной связи, но при этом теряется возможность контролировать на слух уровень записываемого звукового сигнала. Прослушать сигнал можно по каналу воспроизведения звука, но это будет не записываемый сигнал, а сигнал с выхода воспроизведения звуковой карты. Если только просматривать телепередачи, то тогда этого достаточно, но в и этом случае не удается организовать управление каналом звука на входе (линейном) карты, поскольку интерфейс IAMAudioInputMixer управляет только линией записи. Таким образом, невозможность контролировать линию воспроизведения средствами DirectShow приводит к дополнительным проблемам.
Подводя итог сказанному выше, можно сделать вывод, что ни интерфейс IAMAudioInputMixer на фильтре звуковой карты ни фильтр DirectSound Renderer не обеспечивают полноценного управления. В результате приходится привлекать системную программу sndvol32.exe для предварительной настройки канала звука, какие-то входы отключать, другие подключать. Процесс требует определенных знаний и зачастую ставит в тупик пользователя. Дополнительно учитывая тот факт, что уровни звука разных телепрограмм могут значительно отличаться по уровню сигнала, можно констатировать прискорбный факт частого обращения к системной программе sndvol32.exe при просмотре телепередач. Некоторые источники предлагают создание дополнительного фильтра DirectShow, который в определенной степени решает эту проблему. Это не самое лучшее решение. Можно решить задачу проще, не создавая фильтра, а введя в программу управление системным микшером.
[в начало]