Descripción del problema

Descripción del problema

Descripción del problema

Básicamente me gustaría recrear la siguiente imagen en TikZ:

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

Esto se reduce a la cuestión decómo multiplicar una onda sinusoidal con una función lineal por partes en TikZ/pgf.

Restricciones y libertades

  • No es necesario reproducir los colores de la imagen original :)
  • Me gustaría resolver este problema sin tener que almacenar datos en un archivo externo.
  • Estoy feliz de usar pgfplotsy/opgfmath

Ejemplo mínimo (no) funcional

Tengo la sensación de que el mecanismo apropiado para atacar este problema en TikZ/pgf es su mecanismo de declaración de funciones (pero no estoy seguro de tener razón).

En el siguiente ejemplo, he implementado solo la primera parte de la función lineal por partes, para intentar multiplicarla por una función seno. Sin embargo, cuando lo hago, toda la trama desaparece (comente la línea marcada TODOen el ejemplo a continuación para confirmar).

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

Ideas adicionales para la implementación

  • La señal máxima de la función lineal por partes siempre debe ser +1
  • El eje x debe representar milisegundos.
  • La duración total de la envolvente debería ser de unos 500 ms, pero:
  • Sería bueno que el usuario pudiera configurar los siguientes parámetros:
    • Tiempo total T=A+D+S+R
    • Tiempo de ataque A
    • Tiempo de caída D
    • Tiempo de liberación R
    • Nivel de mantenimiento L
  • El tiempo de mantenimiento S se derivaría automáticamente como S = T-(A+D+R)

Respuesta1

Puede definir una función lineal por partes multiplicando las partes con las condiciones que verifican el intervalo y sumándolas. Luego sólo tienes que multiplicar la función seno por la función lineal por partes.

¿Cuál es el problema con tu solución? De hecho, sólo falta un carácter: agregue un signo de porcentaje después de la \pgfmathparseexpresión:

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

Sin él, se agregará un espacio a la izquierda del gráfico para cada llamada de la función, por lo que el gráfico sale de la página hacia la derecha.

ingrese la descripción de la imagen aquí

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

información relacionada