問題の説明
基本的には、次の画像を 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
区間をチェックする条件を各部分に掛け合わせて加算することで、区分線形関数を定義できます。その後、正弦関数と区分線形関数を掛け合わせるだけです。
あなたの解決策の問題点は何ですか?
実際には、欠けている文字は 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}