Attack, Decay, Sustain, Release


47

Klangsynthesizer verwenden Hüllkurvengeneratoren, um zu steuern, wie sich bestimmte Parameter des Klangs (z. B. die Gesamtlautstärke) mit der Zeit ändern. In vielen Synthesizern wird eine Hüllkurve durch vier Parameter definiert, wie in der folgenden Abbildung aus Wikipedia dargestellt :

  • Attack Time (A) : Zeit, die die Hüllkurve benötigt, um ihren Maximalpegel zu erreichen, beginnend mit Null, wenn die Taste zum ersten Mal gedrückt wird.
  • Decay Time (D) : Zeit, die die Hüllkurve benötigt, um den angegebenen Sustain-Pegel zu erreichen.
  • Sustain Level (S) : Level, der nach dem ersten Attack und Decay so lange gehalten wird, wie die Taste gedrückt wird.
  • Release Time (R) : Zeit, die der Briefumschlag benötigt, um beim Loslassen der Taste Null zu erreichen.

Bildbeschreibung hier eingeben

Die Herausforderung

Geben Sie die vier Parameter A, D, S, R ein und zeichnen Sie die Hüllkurve .

Parameter sind ganzzahlige Werte von 0 bis 127 .

Das maximale Level (erreicht am Ende der Angriffsphase) wird mit 127 angenommen .

Es wird angenommen, dass das horizontale Segment auf dem Sustain-Pegel eine Dauer von 64 hat (im tatsächlichen Klang ist diese Dauer nicht festgelegt, sondern wird durch die Zeitdauer bestimmt, die die Taste gehalten wird).

Format und weitere Details

Die Ausgabe sollte ein Bild im Raster- oder Vektorformat sein. Wenn es sich um ein Raster handelt, sollte die polygonale Linie vertikal und horizontal mindestens 50 Pixel einnehmen.

Das Bild kann entweder angezeigt oder als Datei in einem Standardbildformat erstellt werden. Die Datei kann auf die Festplatte geschrieben werden, oder der genaue Inhalt kann entweder nach STDERR oder als Funktionsrückgabeargument ausgegeben werden.

Das Diagramm muss nur die polygonale Linie enthalten, die die Hüllkurve definiert. Der Maßstab jeder Achse kann frei gewählt werden. Andere Elemente wie Achsenlinien, numerische Beschriftungen oder Linienfarben sind optional.

Eingabemittel und Format sind wie gewohnt flexibel . Beispielsweise können Sie die vier Zahlen in beliebiger Reihenfolge oder ein Array mit ihnen nehmen. Ein Programm oder eine Funktion kann bereitgestellt werden. Standardlücken sind verboten.

Kürzester Code in Bytes gewinnt.

Testfälle

Die Eingabe erfolgt im Format [A D S R]. Beachten Sie, dass der Maßstab in jeder Figur unterschiedlich ist (gemäß der Regel, dass der Maßstab frei gewählt werden kann)

[15 30 70 40]

Bildbeschreibung hier eingeben

[64 64 64 64]

Bildbeschreibung hier eingeben

[0 10 50 80]

Bildbeschreibung hier eingeben

[0 0 90 80]

Bildbeschreibung hier eingeben

[5 50 0 0]

Bildbeschreibung hier eingeben

[5 50 0 80]

Bildbeschreibung hier eingeben

[24 32 127 48]

Bildbeschreibung hier eingeben


1
Ich hatte eine größere Herausforderung vom Titel erwartet !
Ben

@Ben Dieser Hinweis war auch gedacht :-) Ich liebe Schlafentzug !
Luis Mendo

Antworten:


7

MATL, 31 22 Bytes

Oii64ivYsO127itO5$h&XG

Akzeptiert vier getrennte Eingänge bestellt wie A, D, R,S

Probieren Sie es bei MATL Online aus

Erläuterung

0   % Push a literal 0 to the stack
ii  % Grab the first two inputs
64  % Push the number literal 64 to the stack
i   % Grab the third input
v   % Vertically concatenate all values
Ys  % Compute the cumulative sum
0   % Push the number literal 0 to the stack
127 % Push the number literal 127 to the stack
i   % Grab the fourth input
t   % Duplicate the fourth input
O   % Push the number literal 0 to the stack
5$h % Concatenate the last 5 elements on the stack
&XG % Plot the result using the first array as x and second array as y

Bildbeschreibung hier eingeben


43

TikZ, 195 193 181 177 172 167 163 160 159 Bytes

Vielen Dank an David Carlisle für seine hilfreiche Antwort hier

\documentclass[tikz]{standalone}\begin{document}\tikz\def~#1{\typein[#1];}~\a~\s~\d~\r\def\u{)--(\a+\d}\draw(,)--(\a,127\u,\s\u+64,\s\u+\r+64,);\end{document}

Ja, du hast richtig gehört, TikZ .

Erläuterung

Dabei werden einige Techniken verwendet, um das Ziel zu erreichen. Das erste ist die Eingabe. Die meisten Menschen wissen vielleicht nicht , dass L A T E X - Eingang erfolgen. Nun kann es. Dies wird mit dem Befehl erreicht \typein. Dadurch wird der Compiler angehalten und eine Eingabe vom Benutzer angefordert, um sie einer Variablen zuzuweisen.

Die andere Haupttechnik ist die Verwendung von \def. \defin Tikz ist absurd mächtig. Es definiert im Wesentlichen einen Code und fügt ihn überall dort ein, wo Sie die Variable aufrufen. In diesem Code definieren wir zwei Dinge, \typein[#1]{}damit wir unsere Variablen ordnen können und )--(\a+\dweil dieser Code in der ungolfed-Version einige Male auftaucht.

Hier sind zwei Versionen des Codes (ohne den Wrapper):

Golf gespielt:

\documentclass[tikz]{standalone}\begin{document}\tikz\def~#1{\typein[#1];}~\a~\s~\d~\r\def\u{)--(\a+\d}\draw(,)--(\a,127\u,\s\u+64,\s\u+\r+64,);\end{document}

Ungolfed:

\typein[\a]{}\typein[\s]{}\typein[\d]{}\typein[\r]{}\draw(0,0)--(\a,127)--(\a+\d,)--(\a+\d+64,)--(\a+\d+\r+64,0);

Bild:

Da ich ein PDF-Bild nicht direkt hochladen kann und die Konvertierung in ein anderes Format dazu führt, dass die Zeile nicht mehr angezeigt wird, sieht ein Bild möglicherweise folgendermaßen aus, wenn es in der Vorschau geöffnet wird (Eingabe für dieses Bild ist [64 64 64 64]):

Vorschaubild

Wie Sie sehen, ist es sehr dünn. Da es sich jedoch um ein PDF-Bild und kein Rasterbild handelt, müssen die Dickenanforderungen nicht erfüllt werden.


12
Ich bewundere aufrichtig die Tatsache, dass Sie TikZ so gut kennen, dass es die erste Lösung ist, die Ihnen in den Sinn kommt. (Und wenn nicht, wird sich die Legende daran erinnern.)
Rechtes Bein

1
Nicht input tikz\begin{document}funktioniert?
Fatalize

5
wie wäre es mit Bildern? 😉
Sarge Borsch

Wie rendern Sie das eigentlich? pdflatex adsr.texscheint nicht zu funktionieren. - Oh, warte, es funktioniert, ich hätte einfach nicht erwartet, dass es interaktive Eingaben erfordert!
aufgehört, gegen den Uhrzeigersinn

@ WheatWizard imagemagick kann PDF-Dateien recht gut konvertieren, wenn Sie es richtig machen
Sarge Borsch

20

Python 2, 83 80 79 Bytes

from turtle import*
def f(A,D,S,R):X=A+D+64;map(goto,[A,A+D,X,X+R],[127,S,S,0])

Versuchen Sie es online (83-BitVersion, weil es online läuft)

Beachten Sie, dass bestimmte Ausgaben mit Trinket aufgrund der Funktionsweise der Zeichenfläche möglicherweise nicht vollständig sichtbar sind. Sie müssen Python herunterladen und installieren, damit es besser funktioniert.

Ungolfed:

from turtle import*
A,D,S,R=input()
goto(A,127)
goto(A+D,S)
goto(A+D+64,S)
goto(A+D+64+R,0)

Diese Version funktioniert nicht in Trinket, da Trinket das Entpacken von Eingabewerten nicht unterstützt.


Sie können mit map2 in Python:lambda A,D,S,R:map(goto,[A,A+D,A+D+64,A+D+R+64],[127,S,S,0])
xnor

@xnor bekomme ich SuspensionError: Cannot call a function that blocks or suspends here on line undefined in main.pyauf Trinket. Haben Sie bestätigt, dass es funktioniert? Ich bin mir nicht sicher, ob der Fehler nur bei Trinket auftritt oder nicht.
mbomb007

Funktioniert bei mir im 2.7.12.
Xnor

@xnor Mmk, danke. Es ist wahrscheinlich eine Einschränkung in Skulpt.
mbomb007

Ich habe eine einfachere Version dieses Programms als Beispiel für das Skulpt github repo eingereicht und sie fanden es ein schöner Fund. Hoffentlich werden sie es schaffen, aber das Tempo ihres "Turtle Sprint" scheint eher ein Spaziergang zu sein.
mbomb007

17

Mathematica, 61-58 Bytes

ListLinePlot[{Accumulate@{0,##3,64,#2},{0,127,#,#,0}}]&

ist der Operator für Transposeund wird Tvon Mathematica als hochgestellt dargestellt .

Übernimmt die Argumente in der Reihenfolge S, R, A, Dund gibt ein Vektorgrafikobjekt zurück.

Ergebnisse für alle sieben Testfälle:

Bildbeschreibung hier eingeben Klicken Sie für eine größere Version.


Das war schnell!
Luis Mendo

+1 für mich zu unterrichten ListLinePlot:) Und es gibt auch eine ListStepPlot- so nützlich!
Greg Martin

12

R, 66 63 Bytes

function(A,D,S,R)plot(cumsum(c(0,A,D,64,R)),c(0,127,S,S,0),"l")

Zeigt das Bild mit Achsenlabors als cumsum(c(0,A,D,64,R))und c(0,127,S,S,0)sowie Achsenlinien und numerischen Beschriftungen an.

Vielen Dank an @Zahiro Mor für das Abschneiden von 3 Bytes !

Vorherige Antwort:

function(A,D,S,R)plot(c(0,A,A+D,b<-A+D+64,b+R),c(0,127,S,S,0),"l")

2
Sie können verwenden cumsum(c(0,A,D,64,R)) , um den ersten Term im Plot zu ersetzen. mit cum brauchst du nicht den b trick und function(A,D,S,R)plot(cumsum(c(0,A,D,64,R)),c(0,127,S,S,0),"l")
rasierst

11

Matlab, 50 Bytes

@(A,D,S,R)plot(cumsum([0,A,D,64,R]),[0,127,S,S,0])

Dies ergibt eine anonyme Funktion "ans", die als ans (A, D, S, R) bezeichnet werden muss.


9

JavaScript (ES6) + HTML, 126 + 23 = 149

c=O.getContext`2d`;c.moveTo(a=0,z=O.height=128);g=(y,x=prompt())=>c.lineTo(a+=+x,y)||g;g(0)(s=z+~prompt())(s,64)(z);c.stroke()
<canvas id=O width=512>

Nimmt die Eingabe nacheinander in der Reihenfolge vor A, S, D, R.


9

JavaScript (ES6), 114 111 Byte

f=(a,d,s,r)=>`<svg width=446 height=128><path stroke=red fill=none d=M0,127L${a},0l${d},${127-s}h64l${r},${s}>`
<div oninput=o.innerHTML=f(a.value,d.value,s.value,r.value)><input type=number value=0 min=0 max=127 id=a><input type=number value=63 min=0 max=127 id=d><input type=number value=127 min=0 max=127 id=s><input type=number value=0 min=0 max=127 id=r><div id=o><svg width=446 height=128><path stroke=red fill=none d=M0,127L0,0l63,0h64l0,127 /></svg>

Gibt ein SVG-Bild zurück, das für geeignet ist innerHTML. Fügen Sie 18 Byte für gültiges XML hinzu.


Es ist großartig, wie die Figur in Echtzeit aktualisiert wird!
Luis Mendo

Das ist großartig, ich sollte die SVG-Syntax irgendwann lernen. Vielleicht fügen Sie dem <input>s Standardwerte hinzu ?
ETHproductions

@ETHproductions Hatten Sie besondere Vorgaben? (Angesichts der Tatsache, dass die Standardeinstellungen das ursprüngliche Diagramm sowieso nicht auslösen ...)
Neil,

Ich habe vielleicht nur nachgedacht 64,64,64,64. Normalerweise würde ich die richtige Ausgabe für die Standardeingabe fest
codieren

8

Haskell, 112 110 Bytes

import Graphics.Gloss
(a#d)s r=display(InWindow""(600,300)(0,0))red$line$zip(scanl(+)0[a,d,64,r])[0,127,s,s,0]

Anwendungsbeispiel: (0#10) 50 80 .

ADSR Umschlag

Dies nutzt die GlossBibliothek. Die displayFunktion erwartet, dass ein Fenster ""geplottet wird (hier: ein Fenster ohne Titel ( ), Größe 600x300, Position (0,0)auf dem Desktop), eine Hintergrundfarbe ( red) und ein Bild, das eine Linie entlang des Pfades ist, der durch Zippen der kumulativen Summe von erstellt wird[0,a,d,64,r] = [0,a,a+d,a+d+64,a+d+64+r]als erstellt wird x-Koordinaten und [0,127,s,s,0]als y-Koordinaten.

Edit: Danke @xnor für 2 Bytes!


Sollte kürzer sein, um zu schreibenscanl(+)0[a,d,64,r]
xnor

5

Verarbeitung, 134 108 + 14 (Aufruf an size) = 148 122 Bytes

Zuerst müssen wir sizeirgendwo im Programm aufrufen, damit die Ausgabe in das Fenster passt (Standard bei 100x100).

size(400,400);

Und hier ist die eigentliche Funktion:

void g(int a,int b,int c,int d){line(0,127,a,0);line(a,0,b+=a,c=127-c);line(b,c,b+=64,c);line(b,c,b+d,127);}

Nenne es so f(15,20,70,40);

Bildschirmfoto

15, 20, 70, 40

Bild


Meine neuere Antwort ist einfacher als die ältere, aber ich mag die ältere mehr (auch wenn sie größer ist).

Alte Antwort (148 Bytes)

size(400,400);

und die beiden Funktionen

void f(int[]v){translate(0,127);l(v[0],-127);l(v[1],127-v[2]);l(64,0);l(v[3],v[2]);}void l(int x,int y){line(0,0,x,y);translate(x,y);}

Nenne es so f(int_array_containing_values);und das Ergebnis sieht ungefähr so ​​aus:f(new int[]{15,20,70,40});


4

SmileBASIC, 90 Bytes

INPUT A,D,S,R
B=A+D+64W=#Y-S
GLINE.,#Y,A,0GLINE A,0,A+D,W
GLINE A+D,W,B,W
GLINE B,W,B+R,#Y

4

PHP, 149 130 Bytes

[,$a,$d,$s,$r]=$argv;imagepolygon($i=imagecreatetruecolor(446,127),[0,127,$a,0,$d+=$a,$s,$d+=64,$s,$d+$r,127],5,999);imagepng($i);

Nimmt Eingaben von Befehlszeilenargumenten entgegen und schreibt das Bild (PNG mit Grafik blau auf schwarz) in stdout. Benötigt PHP 7.1 oder höher.

Verwendung zB

# any OS with ImageMagick:
php -r '<code>' <parameters> | display

# linux with feh:
php -r '<code>' <parameters> | feh

+4 Bytes für älteres PHP: Ersetzen [,$a,$d,$s,$r]durch list(,$a,$d,$s,$r).


Da ist ein kleiner Hack drin: statt zu benutzen imageopenpolygon die Grundlinie auszublenden, wird die Endpolygonlinie außerhalb der Zeichenfläche gezeichnet. (y = 127 würde nur auf einem Bild mit einer Höhe> = 128 angezeigt.)

Ich hätte mehr mit Farbe 99 oder 9 anstelle von 999 sparen können; aber diese sind auf Schwarz ziemlich schwer zu erkennen. :)


3

Bash + Grace , 70 Bytes

t=$[$1+$2]
echo "0 0
$1 127
$t $3
$[t+64] $3
$[t+64+$4] 0">f
xmgrace f

Das Skript schreibt, um fdie Koordinaten jedes Punkts abzulegen, und xmgrace (die GUI-Version) liest die Datei und zeigt den Plot standardmäßig mit Linien an.

Ausführen :

./plot_ADSR.sh 15 30 70 40

Ausgabe: (Bildschirm drucken)

15 30 70 40

Ich denke, dies kann direkt von einem Grace-Skript durchgeführt werden, wenn es Eingaben akzeptiert, aber ich bin mit seiner Syntax nicht vertraut. Ich werde es untersuchen.

Erläuterung:

t=$[$1+$2]          # store the value of (A+D) for later usage
echo "0 0           # start writing the coordinates to file "f", first the origin
$1 127              # then (A, 127)
$t $3               # then (A + D, S)
$[t+64] $3          # then (A + D + 64, S)
$[t+64+$4] 0">f     # then (A + D + 64 + R, 0)
xmgrace f           # call xmgrace to plot the generated XY file

2

Los, 947 915 506 Bytes

Dies ist alles andere als optimiert, da versucht wird, die Sprache zu lernen, während an diesen Fragen teilgenommen wird. Sie können jederzeit darauf hinweisen, was ich tun kann.

festes Bild

Kondensiert:

package main;import (."os";."image";k"image/png";c"image/color";."strconv";."math");func main(){g:=NewRGBA(Rect(0,0,127*4,127));a,_:=ParseFloat(Args[1],4);d,_:=ParseFloat(Args[2],4);s,_:=ParseFloat(Args[3],4);r,_:=ParseFloat(Args[4],4);z:=[5][]float64{{0,0},{a,127},{a+d,s},{a+d+64,s},{a+d+64+r,0}};for i:=1;i<len(z);i++{v,w,x,y:=z[i-1][0],z[i-1][1],z[i][0],z[i][1];m:=(y-w)/(x-v);t:=y-m*x;for v<=x{g.Set(int(Ceil(v)),127-int(Ceil(w)),c.RGBA{0,0,0,255});v+=.01;w=m*v+t}};f,_:=Create("o.png");k.Encode(f,g)}

Nicht kondensiert:

package main

import (
    ."os"
    ."image"
    k"image/png"
    c"image/color"
    ."strconv"
    ."math"
    "fmt"
)

func main(){
    g := NewRGBA(Rect(0, 0, 127*4, 127))

    a, _ := ParseFloat(Args[1], 4)
    d, _ := ParseFloat(Args[2], 4)
    s, _ := ParseFloat(Args[3], 4)
    r, _ := ParseFloat(Args[4], 4)

    z := [5][]float64{{0,0},{a,127},{a+d,s},{a+d+64,s},{a+d+64+r,0}}
    for i:=1;i<len(z);i++{
        v,w,x,y:=z[i-1][0],z[i-1][1],z[i][0],z[i][1]
        m:=(y-w)/(x-v)
        t:=y-m*x
        for v<=x{
            g.Set(int(Ceil(v)),127-int(Ceil(w)), c.RGBA{0,0,0,255})
            v+=.01
            w=m*v+t
        }
    }
    f,_:=Create("o.png")
    k.Encode(f,g)
}

@ LuisMendo ist es. Standardmäßig ist 0,0 oben links. Ich werde alles umkehren, sobald ich kann.
Kemicofa

1
Ich habe nie in go codiert, also weiß ich es nicht. Benutzer hier spielen ihren Code manuell ab, weil sie mehr Bytes als ein allgemeiner Minifier sparen können. Hier werden schlechte Codierungspraktiken und -tricks begrüßt. Zum Beispiel, wäre das Ersetzen von Strukturobjekten durch Variablen (wie l1x, l1y, l1X, l1Y) vielleicht besser?
Seshoumara

1
@ Rugdealer Dies kann helfen, falls Sie es nicht gesehen haben
Luis Mendo

1
Fast 400 Bytes durch deinen Link verloren @LuisMendo
kemicofa

1
@rugdealer Wow, das ist eine Menge \ o /
Luis Mendo

1

Gleichstrom, 120 Bytes

Anfangs dachte ich, ich kann nicht in dc antworten, aber ich sehe, dass das Drucken der Syntax eines Vektorbildes erlaubt ist.

?sR127r-sS[<svg><path d="M0 127 L]nrdn[ 0 L]n+dn32PlSn[ L]n64+dn32PlSn[ L]nlR+n[ 127" fill="none" stroke="red"/></svg>]p

Der Code berechnet die übersetzten Koordinaten jedes Punkts und generiert die SVG-Syntax für die Zeichnung. Da ein Bildeditor den Ursprung in der oberen linken Ecke hat, musste ich den subtrahiereny Werte vonheight in diesem Fall 127 , damit das Bild so angezeigt wird, als ob der Ursprung in der linken unteren Ecke liegt.

Beispiel ausführen : oder Online ausprobieren!

dc -f plot_ADSR.dc <<< "15 30 70 40"

Ausgabe:

<svg><path d="M0 127 L15 0 L45 57 L109 57 L149 127" fill="none" stroke="red"/></svg>

Um das Bilddiagramm anzuzeigen, speichern Sie die genaue Ausgabe in einer Datei und öffnen Sie sie beispielsweise mit Gimp, oder geben Sie den Text wie oben beschrieben in eine HTML-Seite ein.

Erläuterung: dc ist ein Reverse-Politur d esk c alculator Stapel Sprache

Das Skript ist eine lange Verkettung der SVG-Syntaxzeichenfolge. Das Schlüsselwort Msteht für Move to Coordinate und Lsteht für Draw Line von der aktuellen Position zur angegebenen Koordinate .

?                           # read input (in reverse order by default). Stack: RSDA
sR                          # pop top value, store it in register 'R'. Stack: SDA
127r-sS                     # push 127, swap top 2 values, pop them and push
                            #subtracting result, save it to 'S', pop it. Stack: DA
[<svg><path d="M0 127 L]n   # [..]n print string (push then pop). Stack: unchanged
rdn                         # swap, duplicate top, print (A) and pop it. Stack: AD
[ 0 L]n                     # printing
+dn                         # pop top 2 values, push addition result, duplicate it,
                            #print and pop it. Stack: (A+D)
32P                         # print a space
lSn                         # push value from register 'S', print and pop it.
                            #Stack: unchanged
[ L]n                       # printing
64+dn                       # push 64, pop top 2 values, push addition result,
                            #duplicate it, print and pop it. Stack: (A+D+64)
32PlSn[ L]n                 # print space, print register 'S', more printing
lR+n                        #push value from register 'R', pop top 2 values, push
                            #addition result, print it and pop it. Stack: empty
[ 127" fill="none" stroke="red"/></svg>]p   # printing
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.