\documentclass[a4paper,fontsize=14bp]{article} \input{../common-preamble} \input{../bmstu-preamble} \input{../fancy-listings-preamble} \numerationBottom \newcolumntype{s}{>{\tiny{}}c} \begin{document} \thispagestyle{empty} \makeBMSTUHeader \makeReportTitle{домашней}{3}{Звуковой эффект}{Микропроцессорные устройства обработки сигналов}{}{проф. каф. ИУЗ, д.т.н. \\В.С. Выхованец} \newpage \thispagestyle{empty} \tableofcontents \addtocontents{toc}{\vspace{2ex}} \newpage \pagestyle{fancy} \section{Постановка задачи} Целью домашнего задания является разработка алгоритма звукового эффекта «Контроллер динамического диапазона». Для выполнения домашнего задания необходимо: \begin{itemize} \item ознакомиться с рекомендованной литературой \cite{dsp:lectures}; \item привести в отчете описание звукового эффекта; \item описать алгоритм обработки сигналов и данных. \end{itemize} При разработке алгоритма необходимо учесть, что исходный звуковой сигнал поступает на обработку от звукового кодека по одному отсчету, получаемому при вызове функции \code{sam = GetSample()}, где \code{sam} – текущий входной отсчет звукового сигнала в формате с фиксированной запятой. Обработанные отсчеты передаются звуковому кодеку обратно путем вызова функции \code{PutSample(res)}, где \code{res} – текущий выходной отсчет звукового сигнала в формате с фиксированной запятой. \section{Выполнение} \subsection{Описание звукового эффекта} Контроллер динамического диапазона - это адаптивная регулировка динамического диапазона сигнала. Динамический диапазон - это соотношение между наибольшими и наименьшими значениями, которые может принять определенная величина. Существует несколько типов контроллеров. В данной лабораторной работе будет рассматриваться ограничитель. Назначение ограничителя состоит в том, чтобы обеспечить контроль над самыми высокими пиками сигнала, но при этом, как можно меньше изменять динамику сигнала. Это достигается за счёт использования характеристической кривой с бесконечным отношением \cite[с. 109]{dsp:dafx}. Ограничитель динамического диапазона подавляет громкость звуков, пересекающих заданный порог (рисунок \hrf{pic:limiter}). \begin{figure}[H] \captionsetup{labelsep=endash} \centering \def\svgwidth{100mm} \input{pics/02-dsp-03lab-limiter.pdf_tex} \caption{Иллюстрация работы ограничителя сигнала} \label{pic:limiter} \end{figure} Для достижения плавности кривой применяемого ослабления громкости используются такие параметры, как время атаки и высвобождения. Время атаки и время высвобождения соответствуют времени, за которое сигнал увеличивается или уменьшается до конечного значения (рисунок \hrf{pic:limiter-explain}). На рисунке видно, что при отсутствии времени атаки и освобождения усиление применяется сразу, создавая неплавные «обрезанные» кривые (жёсткое урезание). \begin{figure}[H] \captionsetup{labelsep=endash} \centering \def\svgwidth{170mm} \input{pics/02-dsp-03lab-limiter-explain.pdf_tex} \caption{Иллюстрация влияния времени атаки и освобождения} \label{pic:limiter-explain} \end{figure} Ограничитель обычно используется для того, чтобы «поймать» самые громкие моменты источника, уменьшив их таким образом, чтобы защитить от нежелательных искажений и сохранить целостность общего баланса звука. \subsection{Математическое описание ограничителя} \label{sect:description} Динамическая обработка выполняется усилительными устройствами, где коэффициент усиления автоматически регулируется уровнем входного сигнала. Динамическая обработка проходит в несколько этапов: \begin{enumerate}[label=\arabic*),ref=\arabic*] \item Сначала используется схема определения амплитуды/уровня по алгоритму PEAK \cite[с. 107]{dsp:dafx}. В начале алгоритма значение переменной $X_{peak}$ равно нулю. Далее сравнивается модуль поступающего сигнала $|x(n)|$ с предыдущим значением $X_{peak}$. В случае если значение модуля поступающего сигнала больше, то значение $X_{peak}$ для текущего элемента вычисляется с использованием коэффициента $AT$, которое используется, как сокращение для времени атаки (attack time). В ином случае вычисление значения $X_{peak}$ для текущего элемента производится с помощью коэффициента $RT$, то есть времени освобождения (release time). Математическая формула описанного выше алгоритма \begin{equation} X_{p}(n) = \begin{cases} (1 - AT) \times X_{p}(n - 1) + AT \times |X(n)|, |X(n)| > X_{p}(n - 1)\\ (1 - RT) \times X_{p}(n - 1), |X(n)| \leq X_{p}(n - 1), \end{cases} \end{equation} где $X_{p}$ - пиковое значение $X_{peak}$, $AT$ – время атаки, $RT$ – время освобождения, $n$ – номер текущего элемента. \item После определения значения $X_{peak}$ выполняется функция для получения коэффициента усиления $f$ по формуле \begin{equation} f(n) = min \bigg( 1; \frac{lt}{X_{peak}n} \bigg), \end{equation} где $n$ – номер текущего элемента, $lt$ – пороговое значение. \item После вычисления коэффициента усиления используется сглаживающий фильтр для предотвращения слишком резких изменений усиления. Для его реализации используется формула \begin{equation} cfc = \begin{cases} AT, f(n) < f(n-1)\\ RT, f(n) \geq f(n-1), \end{cases} \end{equation} где $n$ – номер текущего элемента. \item Далее вычисляется множитель для регулирования входного сигнала по формуле \begin{equation} g(n) = (1 - cfc) \times g(n - 1) + cfc \times f(n) \end{equation} \item После получения искомого множителя входного сигнала, его значение умножается на задержанный в буфере задержки входной сигнал. Сигнал задерживается для того, чтобы компенсировалась любая задержка при вычислении множителя \cite[с. 106]{dsp:dafx}. \end{enumerate} Результирующая комбинированная система, схематично демонстрирующая все шаги преобразования, изображена на рисунке \hrf{pic:limiter-scheme} \cite[с. 109]{dsp:dafx}. \begin{figure}[H] \captionsetup{labelsep=endash} \centering \def\svgwidth{165mm} \input{pics/02-dsp-03lab-limiter-scheme.pdf_tex} \caption{Принципиальная схема алгоритма работы ограничителя} \label{pic:limiter-scheme} \end{figure} \subsection{Алгоритм обработки сигналов} Алгоритм реализован на основе раздела \hrf{sect:description}. Основная реализующая алгоритм функция приведена в приложении \hrf{appendix:dyn-control-func}. На вход алгоритма принимается массив с отсчетами. Пороговое значение задаётся константой \code{LT} в теле функции. \subsubsection{Основная программа \code{main}} Функция \code{main} вызывается при запуске программы и реализует следующие шаги: \begin{enumerate}[label=\arabic*),ref=\arabic*] \item Инициализация кодека; \item Чтение из кодека текущего отсчета сигнала; \item Получение выходного отсчета сигнала; \item Переход на шаг 2. \end{enumerate} \subsubsection{Функция ограничителя \code{dynDiaCtrl}} Функция ограничителя получает в качестве аргумента текуший отсчет \code{х} и возвращает его модифицированное значение \code{у}. Функция реализует следующие шаги алгоритма. \begin{enumerate}[label=\arabic*),ref=\arabic*] \item Получение модуля входного значения; \item Определение коэффициента для вычисления уровня; \item Вычисление уровня; \item Определение коэффициента усиления; \item Определение коэффициента для вычисления управляющего коэффициента; \item Запись выходного отсчета; \item Возврат из функции. \end{enumerate} Функция использует математические функции из стандартной библиотеки для корректной работы с числами в формате с фиксированной запятой. \section{Выводы} В результате выполнения домашнего задания изучен звуковой эффект «Контроллер динамического диапазона», на примере ограничителя, для которого разработан и описан реализующий его алгоритм. \nocite{gost:texts} \newpage \printbibliography[heading=bibintoc, title={Список литературы}, resetnumbers=1] \newpage \begin{appendices} \renewcommand{\thesubsection}{\Asbuk{subsection}} \subsection{Функция контроллера динамического диапазона} \label{appendix:dyn-control-func} \begin{lstlisting}[language=C,style=CCodeStyle] volatile Int16 xpeak = 0; volatile Int16 g = 1; void dynDiaCtrl(Int16 *x, Int16 *y, Int16 nx) { const Int16 at_cfc = 9830; const Int16 rt_cfc = 328; int i; for (i = 0; i < nx; i++) { // step 1 Int16 a = abs(x[i]); xpeak = (a > xpeak) ? (_smpy((32767 - at_cfc), xpeak) + _smpy(at_cfc, a)) : _smpy((32767 - rt_cfc), xpeak); // step 2 Int16 cmp = LT / xpeak; Int16 f = (cmp < 1) ? cmp : 1; // step 3 Int16 cfc = (f < g) ? at_cfc : rt_cfc; // step 4 g = _smpy((1 - cfc), g) + _smpy(cfc, f); y[i] = _smpy(g, x[i]); } \end{lstlisting} \end{appendices} \end{document}