Atak, rozkład, podtrzymanie, uwolnienie

47

Syntezatory dźwięku używają generatorów obwiedni do kontrolowania, w jaki sposób niektóre parametry dźwięku (takie jak ogólna głośność) zmieniają się z czasem. W wielu syntezatorach obwiednia jest zdefiniowana przez cztery parametry, jak pokazano na poniższym rysunku z Wikipedii :

  • Czas ataku (A) : czas potrzebny na osiągnięcie przez kopertę maksymalnego poziomu, zaczynając od zera, gdy klawisz zostanie naciśnięty po raz pierwszy.
  • Czas rozpadu (D) : czas potrzebny do osiągnięcia przez kopertę określonego poziomu podtrzymania.
  • Poziom podtrzymania (S) : poziom, który jest utrzymywany po pierwszym ataku i rozpadzie, dopóki wciśnięty jest klawisz.
  • Czas zwolnienia (R) : czas potrzebny do osiągnięcia przez kopertę zera po zwolnieniu klucza.

wprowadź opis zdjęcia tutaj

Wyzwanie

Wprowadź cztery parametry A, D, S, R i wykreśl obwiednię .

Parametry będą liczbami całkowitymi od 0 do 127 .

Maksymalny poziom (osiągnął na koniec fazy ataku) będą traktowane jako 127 .

Odcinka poziomego na poziomie utrzymania będą zakłada się, że czas trwania 64 (w rzeczywisty czas trwania dźwięku to nie jest stała, lecz zależy od ilości czasu, że klucz jest utrzymywany).

Format i dalsze szczegóły

Wyjście powinno być obrazem w formacie rastrowym lub wektorowym. Jeśli jest to raster, linia wielokątna powinna zajmować co najmniej 50 pikseli w pionie i poziomie.

Obraz może być wyświetlany lub wytwarzany jako plik w standardowym formacie obrazu. Plik może być zapisany na dysku lub jego dokładna zawartość może być wyprowadzona do STDERR lub jako argument powrotu funkcji.

Wykres musi zawierać tylko wielokątną linię, która określa obwiednię. Skalę każdej osi można dowolnie wybierać. Inne elementy, takie jak linie osi, etykiety numeryczne lub kolory linii są opcjonalne.

Środki wprowadzania i format są jak zwykle elastyczne . Na przykład możesz wziąć cztery liczby w dowolnej kolejności lub tablicę je zawierającą. Można zapewnić program lub funkcję . Standardowe luki są zabronione.

Najkrótszy kod w bajtach wygrywa.

Przypadki testowe

Dane wejściowe są w formacie [A D S R]. Należy pamiętać, że skala jest różna na każdej figurze (zgodnie z zasadą, że skala może być dowolnie wybierana)

[15 30 70 40]

wprowadź opis zdjęcia tutaj

[64 64 64 64]

wprowadź opis zdjęcia tutaj

[0 10 50 80]

wprowadź opis zdjęcia tutaj

[0 0 90 80]

wprowadź opis zdjęcia tutaj

[5 50 0 0]

wprowadź opis zdjęcia tutaj

[5 50 0 80]

wprowadź opis zdjęcia tutaj

[24 32 127 48]

wprowadź opis zdjęcia tutaj

Luis Mendo
źródło
@Ben To odniesienie też było zamierzone :-) Uwielbiam brak snu !
Luis Mendo

Odpowiedzi:

7

MATL, 31 22 bajtów

Oii64ivYsO127itO5$h&XG

Akceptuje cztery oddzielne wejścia zamawiać A, D, R,S

Wypróbuj to w MATL Online

Wyjaśnienie

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

wprowadź opis zdjęcia tutaj

Suever
źródło
43

TikZ, 195 193 181 177 172 167 163 160 159 bajtów

Podziękowania dla Davida Carlisle'a za pomocną odpowiedź tutaj

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

Tak, dobrze słyszałeś TikZ .

Wyjaśnienie

Wykorzystuje kilka technik, aby osiągnąć swój cel. Pierwszą rzeczą jest wejście. Większość ludzi może nie wiedzieć, że L A T E X może przyjmować dane wejściowe. Cóż, może. Osiąga się to za pomocą polecenia \typein. Spowoduje to zatrzymanie kompilatora i zażądanie danych wejściowych od użytkownika, ponieważ przypisze je do zmiennej.

Inną główną techniką jest użycie \def. \defw Tikz jest absurdalnie potężny. Zasadniczo definiuje fragment kodu i wkleja go wszędzie tam, gdzie wywoływana jest zmienna. W tym kodzie definiujemy dwie rzeczy \typein[#1]{}, abyśmy mogli przypisywać nasze zmienne w sposób golfowy i )--(\a+\dponieważ ten kod pojawia się wiele razy w wersji bez golfa.

Oto dwie wersje kodu (bez opakowania):

Gra w golfa:

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

Nie golfowany:

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

Wizerunek:

Ponieważ nie mogę przesłać obrazu pdf bezpośrednio, a przekonwertowanie go na inny format wydaje się powodować całkowite zniknięcie linii, oto jak może wyglądać obraz po otwarciu w podglądzie (dane wejściowe dla tego obrazu to [64 64 64 64]:)

Podgląd obrazu

Jak widać jest bardzo cienki. Ponieważ jednak jest to obraz PDF, a nie obraz rastrowy, nie musi spełniać wymagań dotyczących grubości.

Kreator pszenicy
źródło
12
Szczerze podziwiam fakt, że znasz TikZ tak dobrze, że to pierwsze rozwiązanie, które przychodzi ci na myśl. (A jeśli nie było, to właśnie ta legenda zapamięta)
Prawa Noga
1
Nie input tikz\begin{document}działa?
Fatalize
5
co ze zdjęciami? 😉
Sarge Barszcz
Jak to w rzeczywistości renderujesz? pdflatex adsr.texwydaje się nie działać. - Och, czekaj, to działa, po prostu nie spodziewałem się, że poprosi o interaktywne wejście!
przestał się obracać przeciwnie do zegara
@WheatWizard imagemagick może przekonwertować plik PDF dość dobrze, jeśli zrobisz to dobrze
Sarge Borsch
20

Python 2, 83 80 79 bajtów

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])

Wypróbuj online (wersja 83-bajtowa, ponieważ działa online)

Zwróć uwagę, że niektóre wyniki mogą nie być całkowicie widoczne przy użyciu Talizmanu, ze względu na sposób działania płótna. Musisz pobrać i zainstalować Python, jeśli chcesz, aby działał lepiej.

Nie golfowany:

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)

Ta wersja nie działa w Trinket, ponieważ Trinket nie obsługuje rozpakowywania wartości danych wejściowych.

mbomb007
źródło
Możesz używać mapw Pythonie 2:lambda A,D,S,R:map(goto,[A,A+D,A+D+64,A+D+R+64],[127,S,S,0])
xnor
@ xnor I get SuspensionError: Cannot call a function that blocks or suspends here on line undefined in main.pyon Trinket. Czy potwierdziłeś, że to działa? Nie jestem pewien, czy błąd jest unikalny dla Talizmanu, czy nie.
mbomb007
Działa dla mnie w 2.7.12.
xnor
@xnor Mmk, dzięki. Prawdopodobnie jest to ograniczenie w Skulpt.
mbomb007
Przedstawiłem prostszą wersję tego programu jako przykład do repozytorium Skulpt github, a oni uznali, że to miłe znalezisko. Miejmy nadzieję, że będą w stanie to naprawić, ale tempo ich „żółwiowego sprintu” wydaje się bardziej chodzić.
mbomb007
17

Mathematica, 61 58 bajtów

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

jest operatorem Transposei jest renderowany jako indeks górny Tprzez Mathematica.

Pobiera argumenty w kolejności S, R, A, Di zwraca obiekt grafiki wektorowej.

Wyniki dla wszystkich siedmiu przypadków testowych:

wprowadź opis zdjęcia tutaj Kliknij, aby zobaczyć większą wersję.

Martin Ender
źródło
To było szybkie!
Luis Mendo
+1 za nauczenie mnie ListLinePlot:) I jest też jeden ListStepPlot- bardzo przydatny!
Greg Martin
12

R 66 66 bajtów

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

Wyświetla obraz z laboratorium osi cumsum(c(0,A,D,64,R))i c(0,127,S,S,0), a także liniami osi i etykietami numerycznymi.

Dzięki @Zahiro Mor za golenie 3 bajtów !

Poprzednia odpowiedź:

function(A,D,S,R)plot(c(0,A,A+D,b<-A+D+64,b+R),c(0,127,S,S,0),"l")
Frédéric
źródło
2
możesz użyć, cumsum(c(0,A,D,64,R)) aby zastąpić pierwszy termin w fabule. z sumą nie będziesz potrzebować sztuczki b i nadal golisz 3 bajty :) function(A,D,S,R)plot(cumsum(c(0,A,D,64,R)),c(0,127,S,S,0),"l")
Zahiro Mor
11

Matlab, 50 bajtów

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

Daje to anonimową funkcję „ans”, którą należy wywołać jako ans (A, D, S, R).

Lukas K.
źródło
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>

Pobiera dane wejściowe pojedynczo w kolejności A, S, D, R.

ETHprodukcje
źródło
9

JavaScript (ES6), 114 111 bajtów

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>

Zwraca odpowiedni obraz SVG innerHTML. Dodaj 18 bajtów dla poprawnego XML.

Neil
źródło
To wspaniałe, jak ta liczba jest aktualizowana w czasie rzeczywistym!
Luis Mendo,
To świetnie, powinienem kiedyś nauczyć się składni SVG. Być może dodać wartości domyślne do <input>s?
ETHprodukcje
@ETHproductions Czy miałeś na myśli jakieś szczególne ustawienia domyślne? (Biorąc pod uwagę, że ustawienie wartości domyślnych i tak nie uruchomi początkowego wykresu ...)
Neil
Myślałem, może po prostu 64,64,64,64. Normalnie kodowałbym poprawne wyjście dla domyślnego wejścia, ale widzę, jak byłoby to tutaj trudne ...
ETHproductions
8

Haskell, 112 110 bajtów

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]

Przykład użycia: (0#10) 50 80.

koperta reklamowa

To korzysta z Glossbiblioteki. Ta displayfunkcja oczekuje, że okno zostanie wydrukowane (tutaj: okno bez tytułu ( ""), rozmiar 600 x 300, pozycja (0,0)na pulpicie), kolor tła ( red) i obraz, który jest linią wzdłuż ścieżki utworzonej przez skompresowanie skumulowanej sumy [0,a,d,64,r]= [0,a,a+d,a+d+64,a+d+64+r]jako współrzędne x i [0,127,s,s,0]jako współrzędne y.

Edycja: Dzięki @xnor za 2 bajty!

nimi
źródło
Powinien być krótszy do napisaniascanl(+)0[a,d,64,r]
xnor
5

Przetwarzanie, 134 108 + 14 (wywołanie do size) = 148 122 bajtów

Najpierw potrzebujemy wywołania sizegdzieś w programie, aby wyjście zmieściło się w oknie (domyślnie 100 x 100).

size(400,400);

A oto faktyczna funkcja:

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);}

Nazwij to jak f(15,20,70,40);

Zrzut ekranu

15, 20, 70, 40

wizerunek


Moja nowsza odpowiedź jest prostsza niż starsza, ale bardziej podoba mi się starsza (nawet jeśli jest większa).

Stara odpowiedź (148 bajtów)

size(400,400);

i dwie funkcje

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);}

Nazwij to tak, f(int_array_containing_values);a wynik będzie wyglądał mniej więcej tak:f(new int[]{15,20,70,40});

Kritixi Lithos
źródło
4

SmileBASIC, 90 bajtów

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
12Me21
źródło
4

PHP, 149 130 bajtów

[,$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);

pobiera dane z argumentów wiersza poleceń, zapisuje obraz (PNG z niebieskim kolorem na czarnym) na standardowe wyjście. Wymaga PHP 7.1 lub nowszego.

użycie np

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

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

+4 bajtów dla starszych PHP: Wymień [,$a,$d,$s,$r]się list(,$a,$d,$s,$r).


Jest tam mały hack: zamiast imageopenpolygonukrywać linię bazową, końcowa linia wielokąta jest rysowana poza płótnem. (y = 127 będzie wyświetlane tylko na obrazie o wysokości> = 128.)

Mógłbym zaoszczędzić więcej dzięki kolorowi 99 lub 9 zamiast 999; ale trudno je zobaczyć na czarno. :)

Tytus
źródło
3

Bash + łaska , 70 bajtów

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

Skrypt zapisuje do pliku fwspółrzędne każdego punktu, a xmgrace (wersja GUI) odczytuje plik i domyślnie wyświetla wykres za pomocą linii.

Uruchom :

./plot_ADSR.sh 15 30 70 40

Wyjście: (ekran drukowania)

15 30 70 40

Myślę, że można to zrobić bezpośrednio za pomocą skryptu łaski, jeśli akceptuje on dane wejściowe, ale nie znam jego składni. Przyjrzę się temu.

Wyjaśnienie:

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
seshoumara
źródło
2

Idź, 947 915 506 bajtów

Jest to daleki od zoptymalizowanego, próbując nauczyć się języka, biorąc udział w tych pytaniach. Wskaż, co mogę zrobić.

naprawiony obraz

Skondensowany:

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

Bez zastrzeżeń:

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)
}
kemicofa
źródło
@LuisMendo to jest. Domyślnie 0,0 jest w lewym górnym rogu. Zniosę wszystko jak najszybciej.
kemicofa
1
Nigdy nie kodowałem go, więc nie wiem. Użytkownicy tutaj golfowo kodują swój kod ręcznie, ponieważ mogą zaoszczędzić więcej bajtów niż ogólny minizer. Mile widziane są złe praktyki kodowania i sztuczki. Na przykład, czy zastąpienie obiektów struct zmiennymi (takimi jak l1x, l1y, l1X, l1Y) nie byłoby bardziej golfowe?
seshoumara
1
@rugdealer Może to pomóc, na wypadek, gdybyś go nie widział
Luis Mendo
1
Straciłem prawie 400 bajtów dzięki Twojemu linkowi @LuisMendo
kemicofa
1
@rugdealer Wow, to dużo \ o /
Luis Mendo
1

dc, 120 bajtów

Początkowo myślałem, że nie mogę odpowiedzieć w DC, ale widzę, że drukowanie składni obrazu wektorowego jest dozwolone.

?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

Kod oblicza przetłumaczone współrzędne każdego punktu i generuje składnię SVG dla wykresu. Ponieważ edytor obrazów ma początek w lewym górnym rogu, musiałem odjąć ywartości od height127 w tym przypadku, aby obraz był wyświetlany tak, jakby początek znajdował się w lewym dolnym rogu.

Uruchom przykład: lub Wypróbuj online!

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

Wynik:

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

Aby wyświetlić wykres obrazu, zapisz dokładne dane wyjściowe w pliku i otwórz je na przykład za pomocą Gimp, lub wprowadź tekst na stronie HTML tak jak powyżej.

Opis: dc Jest to odwrotnego polskiego d ESK C alculator język stos

Skrypt jest długim połączeniem łańcucha składniowego SVG. Słowo kluczowe Moznacza ruch do współrzędnych i Loznacza linię rysowania od bieżącej pozycji do podanej współrzędnej .

?                           # 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
seshoumara
źródło