Ataque, Decadência, Sustentar, Lançamento


47

Os sintetizadores de som usam geradores de envelope para controlar como certos parâmetros do som (como o volume geral) mudam com o tempo. Em muitos sintetizadores, um envelope é definido por quatro parâmetros, conforme representado na figura a seguir da Wikipedia :

  • Tempo de ataque (A) : tempo necessário para o envelope atingir seu nível máximo, começando do zero, quando a tecla é pressionada pela primeira vez.
  • Tempo de decaimento (D) : tempo necessário para o envelope atingir o nível de sustentação especificado.
  • Nível de sustentação (S) : nível que é mantido, após o ataque e deterioração inicial, enquanto a tecla estiver sendo pressionada.
  • Tempo de liberação (R) : tempo necessário para o envelope chegar a zero quando a tecla é liberada.

insira a descrição da imagem aqui

O desafio

Insira os quatro parâmetros A, D, S, R e plote o envelope .

Os parâmetros serão valores inteiros de 0 a 127 .

O nível máximo (atingido no final da fase de ataque) será assumido como 127 .

O segmento horizontal ao nível sustentar será assumido como tendo duração de 64 (o som real, a sua duração não é fixo, mas é determinada pela quantidade de tempo que a tecla é mantida).

Formato e mais detalhes

A saída deve ser uma imagem em formato raster ou vetorial. Se for raster, a linha poligonal deve ocupar pelo menos 50 pixels na vertical e na horizontal.

A imagem pode ser exibida ou produzida como um arquivo em um formato de imagem padrão. O arquivo pode ser gravado no disco ou seu conteúdo exato pode ser gerado para STDERR ou como argumento de retorno da função.

O gráfico precisa conter apenas a linha poligonal que define o envelope. A escala de cada eixo pode ser escolhida livremente. Outros elementos, como linhas de eixo, etiquetas numéricas ou cores de linha, são opcionais.

Os meios e o formato de entrada são flexíveis, como de costume. Por exemplo, você pode pegar os quatro números em qualquer ordem ou em uma matriz que os contenha. Um programa ou uma função pode ser fornecida. As brechas padrão são proibidas.

O menor código em bytes vence.

Casos de teste

A entrada está no formato [A D S R]. Observe que a escala é diferente em cada figura (de acordo com a regra de que a escala pode ser escolhida livremente)

[15 30 70 40]

insira a descrição da imagem aqui

[64 64 64 64]

insira a descrição da imagem aqui

[0 10 50 80]

insira a descrição da imagem aqui

[0 0 90 80]

insira a descrição da imagem aqui

[5 50 0 0]

insira a descrição da imagem aqui

[5 50 0 80]

insira a descrição da imagem aqui

[24 32 127 48]

insira a descrição da imagem aqui


1
Eu estava esperando um desafio mais simiano do título !
Ben

@ Ben Essa referência também se destinava :-) Eu amo a privação do sono !
18746 Luis MendoFev

Respostas:


7

MATL, 31 22 bytes

Oii64ivYsO127itO5$h&XG

Aceita quatro entradas separadas encomendado como A, D, R,S

Experimente no MATL Online

Explicação

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

insira a descrição da imagem aqui


43

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

Agradecemos a David Carlisle por sua resposta útil aqui

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

Sim, você ouviu o TikZ certo .

Explicação

Isso usa algumas técnicas para atingir seu objetivo. A primeira coisa é entrada. A maioria das pessoas pode não saber que L A T E X pode receber informações. Bem, pode. Isto é conseguido com o comando \typein. Isso interromperá o compilador e solicitará a entrada do usuário como atribuída a uma variável.

A outra técnica principal é o uso de \def. \defem Tikz é absurdamente poderoso. Essencialmente, ele define um pedaço de código e o cola em todos os lugares que você chama de variável. Neste código, definimos duas coisas \typein[#1]{}para que possamos atribuir nossas variáveis ​​de forma golfificada e )--(\a+\dporque esse código aparece várias vezes na versão não-armazenada.

Aqui estão duas versões do código (sem o wrapper):

Golfe:

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

Imagem:

Como não consigo fazer upload de uma imagem em PDF diretamente, e convertê-la para qualquer outro formato parece fazer com que a linha desapareça completamente, eis a aparência de uma imagem quando aberta na Visualização (a entrada para esta imagem é [64 64 64 64]):

Visualizar imagem

Como você pode ver, é muito fino. No entanto, por ser uma imagem PDF e não uma imagem raster, não precisa atender aos requisitos de espessura.


12
Sinceramente, admiro o fato de você conhecer o TikZ tão bem que é a primeira solução que vem à sua mente. (E se não foi, isso é o que lenda vai se lembrar)
Perna Direita

1
Não input tikz\begin{document}funciona?
Fatalize

5
que tal fotos? 😉
Sarge Borsch

Como você realmente renderiza isso? pdflatex adsr.texparece não funcionar. - Ah, espere, funciona, eu simplesmente não esperava que solicitasse informações interativas!
deixou de girar contra-

Imagemagick @WheatWizard pode converter PDF razoavelmente bem se você fizer isso direito
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])

Experimente online (versão de 83 bytes, porque funciona online)

Observe que determinadas saídas podem não estar completamente visíveis usando o Trinket, devido à maneira como a tela funciona. Você precisará baixar e instalar o Python, se quiser que ele funcione melhor.

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)

Esta versão não funciona no Trinket, porque o Trinket não suporta a descompactação de valor da entrada.


Você pode usar mapno Python 2:lambda A,D,S,R:map(goto,[A,A+D,A+D+64,A+D+R+64],[127,S,S,0])
xnor 14/02

@xnor Eu entro SuspensionError: Cannot call a function that blocks or suspends here on line undefined in main.pyno Trinket. Você confirmou que funciona? Não tenho certeza se o erro é exclusivo do Trinket ou não.
Mbomb007

Funciona para mim em 2.7.12.
xnor 14/02

@xnor Mmk, obrigado. Provavelmente é uma limitação no Skulpt.
Mbomb007

Enviei uma versão mais simples deste programa como exemplo ao repositório do gulub do Skulpt, e eles acharam que era uma boa descoberta. Espero que eles consigam consertá-lo, mas o ritmo de sua "corrida de tartarugas" parece ser mais uma caminhada.
Mbomb007

17

Mathematica, 61 58 bytes

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

é o operador Transposee é renderizado como um sobrescrito Tpelo Mathematica.

Recebe os argumentos na ordem S, R, A, De retorna um objeto de gráficos vetoriais.

Resultados para todos os sete casos de teste:

insira a descrição da imagem aqui Clique para uma versão maior.


Aquilo foi rápido!
Luis Mendo

+1 por me ensinar ListLinePlot:) E também há uma ListStepPlot- tão útil!
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")

Exibe a imagem, com laboratórios de eixos sendo , cumsum(c(0,A,D,64,R))e c(0,127,S,S,0)também linhas de eixo e etiquetas numéricas.

Obrigado a @Zahiro Mor por cortar 3 bytes !

Resposta anterior:

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
você pode usar cumsum(c(0,A,D,64,R)) para substituir o primeiro termo na plotagem. com cumSum você não vai precisar o truque b e ainda raspar 3 bytes :) 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 bytes

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

Isso gera uma função anônima "ans" que deve ser chamada como ans (A, D, S, R).


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>

Recebe uma entrada de cada vez na ordem A, S, D, R.


9

JavaScript (ES6), 114 111 bytes

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>

Retorna uma imagem SVG adequada para innerHTML. Adicione 18 bytes para XML válido.


É ótimo como a figura é atualizada em tempo real!
Luis Mendo

Isso é ótimo, eu deveria aprender a sintaxe SVG em algum momento. Talvez adicione valores padrão aos <input>s?
ETHproductions

@ETHproductions Você tinha algum padrão específico em mente? (Dado que a definição de padrões não vai realmente provocar o gráfico inicial de qualquer maneira ...)
Neil

Eu estava pensando talvez apenas 64,64,64,64. Normalmente eu codificar a saída correta para a entrada padrão, mas não vejo como isso seria difícil aqui ...
ETHproductions

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]

Exemplo de uso: (0#10) 50 80.

envelope adsr

Isso usa a Glossbiblioteca. A displayfunção espera que uma janela seja ""plotada (aqui: uma janela sem título ( ), tamanho 600x300, posição (0,0)na área de trabalho), uma cor de plano de fundo ( red) e uma figura que seja uma linha ao longo do caminho feita ao compactar a soma cumulativa de [0,a,d,64,r]= [0,a,a+d,a+d+64,a+d+64+r]como o coordenadas x e [0,127,s,s,0]como as coordenadas y.

Edit: Obrigado @xnor por 2 bytes!


Deve ser mais curto para escreverscanl(+)0[a,d,64,r]
xnor

5

Processando, 134 108 + 14 (ligue para size) = 148 122 bytes

Primeiro, precisamos de uma chamada para sizealgum lugar do programa para que a saída caiba na janela (padrão em 100x100).

size(400,400);

E aqui está a função real:

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

Chame como f(15,20,70,40);

Captura de tela

15, 20, 70, 40

imagem


Minha resposta mais recente é mais direta do que a resposta mais antiga, mas eu gosto mais da mais antiga (mesmo que seja maior).

Resposta antiga (148 bytes)

size(400,400);

e as duas funções

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

Chame assim f(int_array_containing_values);e o resultado será algo como: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);

recebe entrada dos argumentos da linha de comando, grava a imagem (PNG com gráfico azul no preto) no stdout. Requer PHP 7.1 ou posterior.

uso por exemplo

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

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

+4 bytes para o PHP mais antigo: Substitua [,$a,$d,$s,$r]por list(,$a,$d,$s,$r).


Há um pequeno corte lá: em vez de usar imageopenpolygonpara ocultar a linha de base, a linha de polígono final é desenhada fora da tela. (y = 127 seria exibido apenas em uma imagem com altura> = 128.)

Eu poderia ter economizado mais com a cor 99 ou 9 em vez de 999; mas esses são bem difíceis de ver no preto. :)


3

Bash + graça , 70 bytes

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

O script grava para arquivar fas coordenadas de cada ponto, e o xmgrace (a versão da GUI) lê o arquivo e exibe o gráfico usando linhas por padrão.

Execute :

./plot_ADSR.sh 15 30 70 40

Saída: (tela de impressão)

15 30 70 40

Eu acho que isso pode ser feito diretamente por um script de graça, se ele aceita entrada, mas não estou familiarizado com sua sintaxe. Eu vou dar uma olhada.

Explicação:

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

Go, 947 915 506 bytes

Isso está longe de ser otimizado, tentando aprender o idioma enquanto participa dessas perguntas. Sinta-se livre para apontar o que eu posso fazer.

imagem fixa

Condensado:

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

Incondicional:

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 é. Por padrão, 0,0 é o canto superior esquerdo. Vou inverter tudo o mais rápido que puder.
Kevicofa

1
Eu nunca codifiquei ir, então não sei. Os usuários aqui inserem seu código manualmente, porque podem salvar mais bytes que um minificador geral. Práticas e truques ruins de codificação são bem-vindos aqui. Por exemplo, substituir objetos de estrutura por variáveis ​​(como l1x, l1y, l1X, l1Y) talvez não seja mais interessante?
seshoumara

1
@rugdealer Isso pode ajudar, caso você ainda não tenha visto #
Luis Mendo

1
Perdeu quase 400 bytes graças ao seu link @LuisMendo
kemicofa

1
@rugdealer Uau, isso é um monte \ o /
Luis Mendo

1

dc, 120 bytes

Inicialmente, pensei que não poderia responder em CC, mas vejo que a impressão da sintaxe de uma imagem vetorial é permitida.

?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

O código calcula as coordenadas traduzidas de cada ponto e gera a sintaxe SVG para o gráfico. Como um editor de imagens tem a origem no canto superior esquerdo, tive que subtrair os yvalores de height127 nesse caso, para que a imagem seja mostrada como se a origem estivesse no canto inferior esquerdo.

Execute o exemplo: ou Experimente Online!

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

Resultado:

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

Para exibir o gráfico da imagem, salve a saída exata em um arquivo e abra-o no Gimp, por exemplo, ou digite o texto em uma página html, como fiz acima.

Explicação: dc é uma linguagem de pilha do d esk c alculator com polimento reverso

O script é uma concatenação longa da cadeia de sintaxe SVG. A palavra-chave Msignifica mover para coordenar e Lsignifica desenhar linha da posição atual para a coordenada especificada .

?                           # 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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.