BMSTU/02-dspmd-03-hw-report.tex

173 lines
13 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\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}