Pernyataan
Tugasnya adalah untuk mensintesis suara (satu nada dimainkan) dari beberapa alat musik (pilihan Anda) menggunakan fungsi dalam beberapa bahasa pemrograman tujuan umum (pilihan Anda).
Ada dua tujuan:
- Kualitas suara yang dihasilkan. Itu harus menyerupai instrumen nyata sehalus mungkin;
- Minimalitas Menyimpan kode di bawah 1500 byte disarankan (kurang jika hanya ada generasi suara dasar).
Hanya fungsi pembangkitan yang perlu disediakan, boilerplate tidak dihitung untuk skor.
Sayangnya tidak ada skor yang dapat dihitung untuk kesetiaan suara, sehingga tidak ada aturan yang ketat.
Aturan:
- Tidak ada ketergantungan pada perpustakaan sampel, hal-hal generasi musik khusus;
- Tidak mengunduh dari jaringan atau mencoba menggunakan MIDI mikrofon atau kartu audio atau sesuatu yang terlalu eksternal seperti ini;
- Unit ukuran ukuran kode adalah byte. File dapat dibuat di direktori saat ini. File yang sudah ada sebelumnya (tabel koefisien, dll) mungkin ada, tetapi konten mereka ditambahkan ke skor + mereka harus dibuka dengan nama.
- Kode boilerplate (tidak dihitung untuk skor) menerima array (daftar) dari bilangan bulat yang ditandatangani dan hanya berurusan dengan mengeluarkannya.
- Format output ditandatangani sedikit kata-kata endian 16-bit, 44100 sampel per detik, dengan header WAV opsional. Tidak mencoba untuk mengeluarkan audio terkompresi, bukan wav biasa;
- Silakan pilih instrumen yang berbeda untuk disintesis (atau kategori ukuran kode vs kualitas lainnya untuk instrumen); tetapi pada awalnya jangan memberi tahu apa yang Anda simulasi - biarkan pengguna lain menebak dalam komentar;
- Instrumen elektronik tidak disarankan;
- Drum adalah instrumen. Suara manusia adalah instrumen.
Pelat boiler
Berikut adalah beberapa pelat untuk beberapa bahasa. Anda dapat menulis pelat ketel yang serupa untuk bahasa Anda juga. Mengomentari fungsi "g" hanya untuk demo (1 detik 440 Hz nada sinus).
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
Contoh
Inilah versi C ungolfed yang dimodelkan setelah suara 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);
}
}
}
}
Skornya sekitar 1330 byte dan memberikan kualitas buruk / biasa-biasa saja.
q
akan terlihat seperti ini: pastebin.com/ZCB1v7QQ . Apakah tuan rumah Anda big-endian?$><<7.chr
dalam Ruby dihitung? : P untuk 9 karakter! atau$><<?\a
untuk 7 karakterJawaban:
Jawa
Pelat ketel saya memainkan suara. Saya bisa bermain golf
g()
sedikit lebih, tetapi saat ini di 273 karakter yang jauh di bawah 1500. Saya awalnya menulis ini untuk 16kHz untuk permainan 4kB dan harus sedikit mengubah konstanta untuk mendapatkan kualitas tonal yang tepat pada pemutaran 44.1kHz, tapi saya Saya cukup senang dengannya.Bacaan lebih lanjut: Sintesis Karplus-Strong .
sumber
java -Djavax.sound.sampled.Clip=com.sun.media.sound.DirectAudioDeviceProvider -Djavax.sound.sampled.Port=com.sun.media.sound.PortMixerProvider -Djavax.sound.sampled.SourceDataLine=com.sun.media.sound.DirectAudioDeviceProvider -Djavax.sound.sampled.TargetDataLine=com.sun.media.sound.DirectAudioDeviceProvider codegolf13003
C
Inilah
g()
fungsinya, tanpa boilerplate.Eksperimen yang menarik adalah bermain dengan loop pertama yang menginisialisasi urutan awal dari nilai acak. Mengganti panggilan
rand()
dengani*i
mengubah karakter suara dengan cara yang masuk akal (artinya, sintesisnya meniru anggota yang berbeda dari keluarga instrumen yang sama).i*i*i
dani*i*i*i
memberikan kualitas suara lainnya, meskipun masing-masing lebih dekat dengan terdengar sepertirand()
. Nilai sukai*327584
ataui*571
, di sisi lain, terdengar sangat berbeda (dan kurang seperti tiruan dari sesuatu yang nyata).Variasi kecil lain dari fungsi yang sama bahkan datang lebih dekat ke instrumen lain, atau setidaknya ada di telinga saya.
Diedit untuk Menambahkan: Saya belum memperlakukan ini sebagai pertanyaan kode golf, karena tidak ditandai seperti itu (di luar batas 1500-char), tetapi karena sudah dimunculkan dalam komentar, inilah versi golf dari yang di atas ( 96 karakter):
(Saya dapat menurunkannya di bawah 80 karakter jika saya dapat mengubah antarmuka fungsi untuk menggunakan variabel global.)
sumber
array
,length
,void
dansigned
dalam kode kedua saya mendapat skor: 113 bytes. Usaha yang sangat bagus. Dan suaranya agak bagus.