問題描述
我基本上想在 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
- 起音時間A
- 衰減時間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}