Ataque, descomposición, mantenimiento, liberación

47

Los sintetizadores de sonido usan generadores de envolvente para controlar cómo ciertos parámetros del sonido (como el volumen general) cambian con el tiempo. En muchos sintetizadores, una envolvente se define mediante cuatro parámetros, como se representa en la siguiente figura de Wikipedia :

  • Tiempo de ataque (A) : tiempo que tarda el sobre en alcanzar su nivel máximo, comenzando desde cero, cuando se presiona la tecla por primera vez.
  • Tiempo de caída (D) : tiempo que tarda la envoltura en alcanzar el nivel de sostenimiento especificado.
  • Nivel de mantenimiento (S) : nivel que se mantiene, después del ataque inicial y la descomposición, mientras se mantenga presionada la tecla.
  • Tiempo de liberación (R) : tiempo que tarda el sobre en llegar a cero cuando se suelta la tecla.

ingrese la descripción de la imagen aquí

El reto

Ingrese los cuatro parámetros A, D, S, R y trace el sobre .

Los parámetros serán valores enteros de 0 a 127 .

Se supondrá que el nivel máximo (alcanzado al final de la fase de ataque) es 127 .

Se supondrá que el segmento horizontal en el nivel de sostenimiento tiene una duración 64 (en el sonido real, esta duración no es fija, sino que está determinada por la cantidad de tiempo que se mantiene presionada la tecla).

Formato y más detalles

El resultado debe ser una imagen en formato ráster o vectorial. Si es ráster, la línea poligonal debe ocupar al menos 50 píxeles verticalmente y horizontalmente.

La imagen se puede mostrar o producir como un archivo en un formato de imagen estándar. El archivo puede escribirse en el disco o su contenido exacto puede enviarse a STDERR o como argumento de retorno de función.

El gráfico solo necesita contener la línea poligonal que define la envolvente. La escala de cada eje se puede elegir libremente. Otros elementos como líneas de eje, etiquetas numéricas o colores de línea son opcionales.

Los medios de entrada y el formato son flexibles como de costumbre. Por ejemplo, puede tomar los cuatro números en cualquier orden o una matriz que los contenga. Se puede proporcionar un programa o una función . Las lagunas estándar están prohibidas.

El código más corto en bytes gana.

Casos de prueba

La entrada está en el formato [A D S R]. Tenga en cuenta que la escala es diferente en cada figura (de acuerdo con la regla de que la escala se puede elegir libremente)

[15 30 70 40]

ingrese la descripción de la imagen aquí

[64 64 64 64]

ingrese la descripción de la imagen aquí

[0 10 50 80]

ingrese la descripción de la imagen aquí

[0 0 90 80]

ingrese la descripción de la imagen aquí

[5 50 0 0]

ingrese la descripción de la imagen aquí

[5 50 0 80]

ingrese la descripción de la imagen aquí

[24 32 127 48]

ingrese la descripción de la imagen aquí

Luis Mendo
fuente
1
¡Esperaba un desafío más simio del título !
Ben
@Ben Esa referencia también fue pensada :-) ¡Me encanta la falta de sueño !
Luis Mendo

Respuestas:

7

MATL, 31 22 bytes

Oii64ivYsO127itO5$h&XG

Acepta cuatro entradas separadas ordenados como A, D, R,S

Pruébelo en MATL Online

Explicación

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

ingrese la descripción de la imagen aquí

Suever
fuente
43

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

Gracias a David Carlisle por su útil respuesta aquí.

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

Sí, escuchaste bien TikZ .

Explicación

Esto utiliza un par de técnicas para lograr su objetivo. Lo primero es la entrada. Es posible que la mayoría de la gente no sepa que L A T E X puede recibir información. Bien puede. Esto se logra con el comando \typein. Esto detendrá el compilador y solicitará la entrada del usuario al asignarlo a una variable.

La otra técnica principal es el uso de \def. \defen Tikz es absurdamente poderoso. Básicamente, define un fragmento de código y lo pega en todas partes donde llame a la variable. En este código definimos dos cosas \typein[#1]{}para que podamos asignar nuestras variables a golfily y )--(\a+\dporque este código aparece un montón de veces en la versión sin golf.

Aquí hay dos versiones del código (sin el contenedor):

Golfizado:

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

Sin golf:

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

Imagen:

Como no puedo cargar una imagen pdf directamente, y convertirla a cualquier otro formato parece hacer que la línea desaparezca por completo, así es como podría verse una imagen cuando se abre en Vista previa (la entrada para esta imagen es [64 64 64 64]):

Imagen de vista previa

Como puedes ver es muy delgado. Sin embargo, debido a que es una imagen PDF y no una imagen ráster, no tiene que cumplir con los requisitos de grosor.

Asistente de trigo
fuente
12
Admiro sinceramente el hecho de que conoces TikZ tan bien que es la primera solución que se te ocurre. (Y si no fuera así, eso es lo que la leyenda recordará)
Pierna derecha
1
No input tikz\begin{document} funciona
Fatalize
55
¿qué tal fotos? 😉
Sarge Borsch
¿Cómo se hace realmente esto? pdflatex adsr.texno parece funcionar - Oh, espera, funciona, ¡simplemente no esperaba que solicitara una entrada interactiva!
dejó de girar en contra del reloj
@WheatWizard imagemagick puede convertir PDF razonablemente bien si lo hace bien
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])

Pruébelo en línea (versión de 83 bytes, porque se ejecuta en línea)

Tenga en cuenta que ciertas salidas pueden no ser completamente visibles usando Trinket, debido a la forma en que funciona el lienzo. Tendrá que descargar e instalar Python si desea que funcione mejor.

Sin golf:

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 versión no funciona en Trinket, porque Trinket no admite el desempaquetado de valor de la entrada.

mbomb007
fuente
Puede usar mapen Python 2:lambda A,D,S,R:map(goto,[A,A+D,A+D+64,A+D+R+64],[127,S,S,0])
xnor
@xnor me subo SuspensionError: Cannot call a function that blocks or suspends here on line undefined in main.pya Trinket. ¿Has confirmado que funciona? No estoy seguro de si el error es exclusivo de Trinket o no.
mbomb007
Funciona para mí en 2.7.12.
xnor
@xnor Mmk, gracias. Probablemente sea una limitación en Skulpt.
mbomb007
Envié una versión más simple de este programa como ejemplo al repositorio Skulpt github, y pensaron que era un buen hallazgo. Esperemos que puedan arreglarlo, pero el ritmo de su "carrera de tortuga" parece ser más bien una caminata.
mbomb007
17

Mathematica, 61 58 bytes

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

es el operador para Transposey se representa como un superíndice Tpor Mathematica.

Toma los argumentos en el orden S, R, A, Dy devuelve un objeto de gráficos vectoriales.

Resultados para los siete casos de prueba:

ingrese la descripción de la imagen aquí Haga clic para una versión más grande.

Martin Ender
fuente
¡Eso fue rápido!
Luis Mendo
+1 por enseñarme ListLinePlot:) Y también hay una ListStepPlot, ¡tan ú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")

Muestra la imagen, siendo los laboratorios de ejes cumsum(c(0,A,D,64,R))yc(0,127,S,S,0) , así como líneas de eje y etiquetas numéricas.

¡Gracias a @Zahiro Mor por recortar 3 bytes !

Respuesta 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")
Frédéric
fuente
2
puede usar cumsum(c(0,A,D,64,R)) para reemplazar el primer término en la trama. con cumsum no necesitarás el truco b y aún function(A,D,S,R)plot(cumsum(c(0,A,D,64,R)),c(0,127,S,S,0),"l")
afeitarte
11

Matlab, 50 bytes

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

Esto produce una función anónima "ans" que debe llamarse como ans (A, D, S, R).

Lukas K.
fuente
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>

Toma una entrada a la vez en el orden A, S, D, R.

ETHproducciones
fuente
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>

Devuelve una imagen SVG adecuada para innerHTML. Agregue 18 bytes para XML válido.

Neil
fuente
¡Es genial cómo se actualiza la figura en tiempo real!
Luis Mendo
Esto es genial, debería aprender la sintaxis SVG alguna vez. ¿Quizás agregar valores predeterminados a la <input>s?
ETHproductions
@ETHproductions ¿Tenía en mente algunos valores predeterminados? (Dado que la configuración predeterminada no activará el gráfico inicial de todos modos ...)
Neil
Estaba pensando tal vez solo 64,64,64,64. Normalmente codificaría la salida correcta para la entrada predeterminada, pero veo cómo sería difícil aquí ...
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]

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

sobre adsr

Esto usa la Glossbiblioteca. La displayfunción espera que se trace una ventana (aquí: una ventana sin título ( ""), tamaño 600x300, posición (0,0)en el escritorio), un color de fondo ( red) y una imagen de bruja es una línea a lo largo del camino realizado comprimiendo la suma acumulativa de [0,a,d,64,r]= [0,a,a+d,a+d+64,a+d+64+r]como coordenadas x y [0,127,s,s,0]como las coordenadas y.

Editar: ¡Gracias @xnor por 2 bytes!

nimi
fuente
Debería ser más corto de escribirscanl(+)0[a,d,64,r]
xnor
5

Procesamiento, 134 108 + 14 (llamada a size) = 148 122 bytes

Primero necesitamos una llamada a sizealgún lugar del programa para que la salida quepa en la ventana (por defecto a 100x100).

size(400,400);

Y aquí está la función 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);}

Llámalo como f(15,20,70,40);

Captura de pantalla

15, 20, 70, 40

imagen


Mi respuesta más nueva es más directa que la anterior, pero me gusta más la anterior (incluso si es más grande).

Respuesta anterior (148 bytes)

size(400,400);

y las dos funciones

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

Llámalo así f(int_array_containing_values);y el resultado se verá así:f(new int[]{15,20,70,40});

Kritixi Lithos
fuente
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
12Me21
fuente
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);

toma datos de los argumentos de la línea de comandos, escribe la imagen (PNG con el gráfico azul sobre negro) en stdout. Requiere PHP 7.1 o posterior.

uso por ejemplo

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

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

+4 bytes para PHP anterior: reemplazar [,$a,$d,$s,$r]con list(,$a,$d,$s,$r).


Hay un pequeño truco allí: en lugar de usar imageopenpolygon para ocultar la línea base, la línea de polígono de acabado se dibuja fuera del lienzo. (y = 127 solo se mostraría en una imagen con altura> = 128.)

Podría haber ahorrado más con el color 99 o 9 en lugar de 999; pero esos son bastante difíciles de ver en negro. :)

Titus
fuente
3

Bash + gracia , 70 bytes

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

El script escribe para archivar flas coordenadas de cada punto, y xmgrace (la versión de la GUI) lee el archivo y muestra el diagrama usando líneas por defecto.

Ejecutar :

./plot_ADSR.sh 15 30 70 40

Salida: (pantalla de impresión)

15 30 70 40

Creo que esto puede hacerse directamente mediante un script de gracia, si puede aceptar entradas, pero no estoy familiarizado con su sintaxis. Lo miraré.

Explicación:

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
fuente
2

Go, 947 915 506 bytes

Esto está lejos de ser optimizado, tratando de aprender el idioma mientras participa en estas preguntas. Siéntase libre de señalar lo que puedo hacer.

imagen fija

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

Sin condensación:

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
fuente
@LuisMendo lo es. Por defecto 0,0 es arriba a la izquierda. Invertiré todo tan pronto como pueda.
kemicofa
1
Nunca codifiqué ir, así que no lo sé. Los usuarios aquí juegan golf su código manualmente porque pueden guardar más bytes que un minificador general. Las malas prácticas de codificación y los trucos son bienvenidos aquí. Por ejemplo, ¿no sería mejor reemplazar objetos de estructura con variables (como l1x, l1y, l1X, l1Y)?
seshoumara
1
@rugdealer Esto puede ayudar, en caso de que no lo hayas visto
Luis Mendo
1
Perdió casi 400 bytes gracias a su enlace @LuisMendo
kemicofa
1
@rugdealer Wow, eso es mucho \ o /
Luis Mendo
1

dc, 120 bytes

Inicialmente pensé que no podía responder en CC, pero veo que se permite imprimir la sintaxis de una imagen vectorial.

?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

El código calcula las coordenadas traducidas de cada punto y genera la sintaxis SVG para el gráfico. Como un editor de imágenes tiene el origen en la esquina superior izquierda, tuve que restar ely valores height, 127 en este caso, para que la imagen se muestre como si el origen estuviera en la esquina inferior izquierda.

Ejecute el ejemplo: o ¡ Pruébelo en línea!

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

Salida:

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

Para mostrar el gráfico de la imagen, guarde ese resultado exacto en un archivo y ábralo con Gimp, por ejemplo, o ingrese el texto en una página html como lo hice anteriormente.

Explicación: dc es una polaca inversa d esk c lenguaje pila alculator

El script es una larga concatenación de la cadena de sintaxis SVG. La palabra clave Msignifica movimiento para coordinar y Lrepresenta la línea de dibujo desde la posición actual hasta la coordenada dada .

?                           # 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
fuente