Описание проблемы

Описание проблемы

Описание проблемы

По сути, я хотел бы воссоздать следующее изображение в TikZ:

http://krashan.ppa.pl/articles/u1synth/adsr.png

Это сводится к вопросу окак умножить синусоиду на кусочно-линейную функцию в TikZ/pgf.

Ограничения и свободы

  • Цвета из оригинального изображения не обязательно воспроизводить :)
  • Я хотел бы решить эту проблему без необходимости хранить данные во внешнем файле.
  • Я с удовольствием использую pgfplotsи/илиpgfmath

Минимальный (не)рабочий пример

У меня складывается впечатление, что подходящим механизмом для решения этой проблемы в TikZ/pgf является механизм объявления функций (но я не уверен, прав ли я).

В примере ниже я реализовал только первую часть кусочно-линейной функции, чтобы попытаться умножить ее на функцию синуса. Однако, когда я это делаю, весь график исчезает (закомментируйте строку, отмеченную TODOв примере ниже, чтобы подтвердить).

\documentclass{article}

\usepackage{pgfplots}

% Declare (first part of) piecewise linear function
\pgfmathdeclarefunction{p}{1}{%
  \pgfmathparse{ ((x>=0) && (x<=50))*x/50 }
}

\begin{document}

\begin{tikzpicture}[domain=0:500]

  \begin{axis}

    % Plot piecewise linear function
    \addplot[thick, blue]{p(x)};

    % Plot sine function
    \addplot[red, samples=500, smooth]{sin(20*x)};

    % Plot product of both. TODO: Makes entire plot disappear
    %\addplot[thick, green, samples=500, smooth]{sin(30*x)*p(x)};

  \end{axis}

\end{tikzpicture}

\end{document}

Бонусные идеи для реализации

  • Максимальный сигнал кусочно-линейной функции всегда должен быть +1
  • Ось x должна отображать миллисекунды.
  • Общая длительность огибающей должна быть около 500 мс, но:
  • Было бы неплохо, если бы пользователь мог задать следующие параметры:
    • Общее время T=A+D+S+R
    • Время атаки А
    • Время распада D
    • Время выпуска R
    • Уровень сустейна L
  • Время сустейна S будет автоматически выведено как S = T-(A+D+R)

решение1

Вы можете определить кусочно-линейную функцию, умножив части на условия, которые проверяют интервал, и сложив их. Затем вам просто нужно умножить функцию синуса на кусочно-линейную функцию.

В чем проблема вашего решения? На самом деле не хватает только одного символа: добавьте знак процента после выражения \pgfmathparse:

\pgfmathdeclarefunction{p}{1}{%
  \pgfmathparse{ ((x>=0) && (x<=50))*x/50 }% <<<<<<<<
}

Без этого при каждом вызове функции слева от графика будет добавляться пробел, поэтому график сместится за пределы страницы вправо.

введите описание изображения здесь

\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{calc}

\pgfmathdeclarefunction{ADSR}{1}{%
  \pgfmathparse
    {(                  #1<=\pA      )*(#1/\pA)                          +%
     (and(#1>\pA      , #1<=(\pA+\pD))*(#1*(-\pL)/\pD + 1 + \pA*\pL/\pD) +%
     (and(#1>(\pA+\pD), #1<=(\pT-\pR))*(1-\pL)                           +%
     (and(#1>(\pT-\pR), #1<=\pT      )*((1-\pL)/\pR*(-#1+\pT))
    }%
}

\begin{document}
\begin{tikzpicture}
\newcommand\pT{500} % total
\newcommand\pA{100} % attack
\newcommand\pD{100} % decay
\newcommand\pR{100} % release
\newcommand\pL{0.2} % sustain level
\newcommand\pF{50}  % frequency (not in Hz, but proportional)
  \begin{axis}[x=0.2mm,y=2cm]
    \addplot[domain=0:\pT, green, samples=5000] {ADSR(x)*sin(\pF*x)};
    \addplot[domain=0:\pT, red, samples=100] {ADSR(x)};
  \end{axis}
\end{tikzpicture}
\end{document}

Связанный контент