Declaración
La tarea es sintetizar el sonido (una nota tocada) de algún instrumento musical (de su elección) utilizando la función en algún lenguaje de programación de propósito general (de su elección).
Hay dos objetivos:
- Calidad del sonido resultante. Debe parecerse al instrumento real lo más fino posible;
- Minimalidad Se recomienda mantener el código por debajo de 1500 bytes (menos si solo hay una generación de sonido básica).
Solo se debe proporcionar la función de generación, no se cuenta el repetitivo para la puntuación.
Lamentablemente, no se puede calcular la puntuación para la fidelidad del sonido, por lo que no puede haber reglas estrictas.
Reglas:
- Sin dependencia de bibliotecas de muestras, cosas especializadas en generación de música;
- No descargar desde la red o intentar usar el micrófono o la tarjeta de audio MIDI o algo demasiado externo como este;
- La unidad de medida del tamaño del código es bytes. El archivo se puede crear en el directorio actual. Pueden existir archivos preexistentes (tablas de coeficientes, etc.), pero su contenido se agrega a la partitura + deben abrirse por nombre.
- El código repetitivo (sin contar para calificar) recibe una matriz (lista) de enteros con signo y solo trata de generarlos.
- El formato de salida está firmado con pequeñas palabras endian de 16 bits, 44100 muestras por segundo, con encabezado WAV opcional. No intente emitir audio comprimido en lugar de wav simple;
- Elija diferentes instrumentos para sintetizar (u otra categoría de calidad vs tamaño de código para el instrumento); pero no digas inicialmente qué estás simulando: deja que otros usuarios adivinen en los comentarios;
- Se desaconsejan los instrumentos electrónicos;
- El tambor es un instrumento. La voz humana es un instrumento.
Calderas
Aquí hay repeticiones para algunos idiomas. También puede escribir una caldera similar para su idioma. La función "g" comentada es solo para una demostración (1 segundo de tono sinusoidal de 440 Hz).
C:
//#!/usr/bin/tcc -run
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
/*
void g(signed short *array, int* length) {
*length = 44100;
int i;
for(i=0; i<44100; ++i) array[i]=10000*sin(i*2.0*3.14159265358979323*440.0/44100.0);
}
*/
// define your g here
signed short array[44100*100];
int main(int argc, char* argv[]) {
int size=0;
memset(array,0,sizeof array);
// i(array); // you may uncomment and implement some initialization
g(array, &size);
fwrite("RIFFH\x00\x00\x00WAVEfmt\x20\x12\x00\x00\x00\x01\x00\x01\x00\x44\xac\x00\x00\x88X\x01\x00\x02\x00\x10\x00\x00\x00LIST\x1a\x00\x00\x00INFOISFT\x0e\x00\x00\x00GolfNote\0\0\0\0\0\0data\x00\xff\xff\xff", 1, 80, stdout);
fwrite(array, 1, size*sizeof(signed short), stdout);
return 0;
}
Python 2:
#!/usr/bin/env python
import os
import re
import sys
import math
import struct
import array
#def g():
# return [int(10000*math.sin(1.0*i*2*3.141592654*440.0/44100.0)) for i in xrange(0,44100)]
# define your g here
sys.stdout.write("RIFFH\x00\x00\x00WAVEfmt\x20\x12\x00\x00\x00\x01\x00\x01\x00\x44\xac\x00\x00\x88X\x01\x00\x02\x00\x10\x00\x00\x00LIST\x1a\x00\x00\x00INFOISFT\x0e\x00\x00\x00GolfNotePy\0\0\0\0data\x00\xff\xff\xff");
array.array("h", g()).tofile(sys.stdout);
Perl 5:
#!/usr/bin/perl
#sub g() {
# return (map 10000*sin($_*3.14159265358979*2*440.0/44100.0), 0..(44100-1))
#}
# define you g here
my @a = g();
print "RIFFH\x00\x00\x00WAVEfmt\x20\x12\x00\x00\x00\x01\x00\x01\x00\x44\xac\x00\x00\x88X\x01\x00\x02\x00\x10\x00\x00\x00LIST\x1a\x00\x00\x00INFOISFT\x0e\x00\x00\x00GolfNotePl\0\0\0\0data\x00\xff\xff\xff";
print join("",map(pack("s", $_), @a));
Haskell
#!/usr/bin/runhaskell
import qualified Data.Serialize.Put as P
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as C8
import Data.Word
import Control.Monad
-- g :: [Word16]
-- g = map (\t->floor $ 10000 * sin(t*2*3.14159265358979*440/44100)) [0..44100-1]
-- insert your g here
main = do
B.putStr $ C8.pack $ "RIFFH\x00\x00\x00WAVEfmt\x20\x12\x00\x00\x00\x01\x00\x01\x00\x44\xac\x00\x00\x88X\x01\x00\x02\x00\x10\x00\x00\x00LIST\x1a\x00\x00\0INFOISFT\x0e\x00\x00\x00GolfNote\0\0\0\0\0\0data\x00\xff\xff\xff"
B.putStr $ P.runPut $ sequence_ $ map P.putWord16le g
Ejemplo
Aquí hay una versión C sin golf modelada a partir del sonido del piano:
void g(signed short *array, int* length) {
*length = 44100*5;
int i;
double overtones[]={4, 1, 0.5, 0.25, 0.125};
double freq[] = {393, 416, 376, 355, 339, 451, 555};
double freq_k[] = {40, 0.8, 1, 0.8, 0.7, 0.4, 0.25};
double corrector = 1/44100.0*2*3.14159265358979323;
double volumes_begin[] ={0, 0.025, 0.05, 0.4};
double volumes_end [] ={0.025, 0.05, 0.4, 5};
double volumes_kbegin[]={0, 1.8, 1, 0.4};
double volumes_kend [] ={1.8, 1, 0.4, 0};
for(i=0; i<44100*5; ++i) {
int j;
double volume = 0;
for(j=0; j<sizeof volumes_begin/sizeof(*volumes_begin); ++j) {
double t = i/44100.0;
if(t>=volumes_begin[j] && t<volumes_end[j]) {
volume += volumes_kbegin[j]*(volumes_end[j]-t )/(volumes_end[j]-volumes_begin[j]);
volume += volumes_kend[j] *(t-volumes_begin[j])/(volumes_end[j]-volumes_begin[j]);
}
}
int u;
for(u=0; u<sizeof freq/sizeof(*freq); ++u) {
for(j=0; j<sizeof overtones/sizeof(*overtones); ++j) {
double f = freq[u]*(j+1);
array[i] += freq_k[u]*volume*10000.0/(f)/1*overtones[j]*sin(1.0*i*corrector*f);
}
}
}
}
Obtiene aproximadamente 1330 bytes y proporciona una calidad pobre / mediocre.
q
no comentados debería verse así: pastebin.com/ZCB1v7QQ . ¿Es su anfitrión big-endian?
$><<7.chr
en el recuento de Ruby? : P para 9 caracteres! o $><<?\a
por 7 caracteres