Komunikat
Zadanie polega na syntezie dźwięku (jednej nuty) wybranego instrumentu muzycznego (wybranego) za pomocą funkcji w jakimś języku programowania ogólnego przeznaczenia (wybranym przez Ciebie).
Istnieją dwa cele:
- Jakość uzyskanego dźwięku. Powinien przypominać prawdziwy instrument tak dobrze, jak to możliwe;
- Minimalizm. Zalecane jest utrzymanie kodu poniżej 1500 bajtów (mniej, jeśli istnieje tylko podstawowe generowanie dźwięku).
Należy podać tylko funkcję generowania, płyta kotła nie jest liczona jako wynik.
Niestety nie można obliczyć żadnego wyniku dla wierności dźwięku, więc nie mogą istnieć surowe zasady.
Zasady:
- Bez zależności od bibliotek próbek, specjalistycznych rzeczy do generowania muzyki;
- Żadnego pobierania z sieci ani próbowania korzystania z MIDI mikrofonu lub karty dźwiękowej, lub czegoś zbyt zewnętrznego;
- Jednostką miary wielkości kodu są bajty. Plik można utworzyć w bieżącym katalogu. Istniejące pliki (tabele współczynników itp.) Mogą istnieć, ale ich zawartość jest dodawana do partytury + należy je otworzyć według nazwy.
- Kod bojlera (nie liczony do wyniku) otrzymuje tablicę (listę) liczb całkowitych ze znakiem i zajmuje się tylko ich wyprowadzaniem.
- Format wyjściowy jest podpisany małymi 16-bitowymi słowami endian, 44100 próbek na sekundę, z opcjonalnym nagłówkiem WAV. Nie ma potrzeby wysyłania skompresowanego dźwięku zamiast zwykłego wav;
- Proszę wybrać inne instrumenty do syntezy (lub inną kategorię jakości względem wielkości kodu dla instrumentu); ale początkowo nie mów, co symulujesz - pozwól innym użytkownikom zgadywać w komentarzach;
- Instrumenty elektroniczne są odradzane;
- Bęben jest instrumentem. Ludzki głos jest instrumentem.
Kotły
Oto plansze dla niektórych języków. Możesz również napisać podobną płytę kotłową dla swojego języka. Skomentowana funkcja „g” jest tylko dla wersji demonstracyjnej (1 sekunda sinusoidy 440 Hz).
DO:
//#!/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
Przykład
Oto nie golfowa wersja C wzorowana na brzmieniu fortepianu:
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);
}
}
}
}
Ma około 1330 bajtów i zapewnia słabą / przeciętną jakość.
q
powinien wyglądać tak: pastebin.com/ZCB1v7QQ . Czy Twój gospodarz to big-endian?
$><<7.chr
się liczyć Ruby? : P dla 9 znaków! lub $><<?\a
na 7 znaków