声明
任务是使用(您选择的)通用编程语言的功能来合成(您选择的)某种乐器的声音(弹奏一个音符)。
有两个目标:
- 产生的声音的质量。它应尽可能类似于真实乐器;
- 极简主义。建议将代码保持在1500字节以下(如果仅产生基本声音,则应减少)。
只需要提供生成功能,不计入样板。
不幸的是,无法为声音保真度计算分数,因此没有严格的规则。
规则:
- 不依赖样本库,不需要专门的音乐生成工具;
- 禁止从网络下载或尝试使用麦克风或声卡的MIDI或类似外部的东西;
- 代码大小的度量单位是字节。可以在当前目录中创建文件。可能存在预先存在的文件(系数表等),但其内容将添加到乐谱中,并且必须按名称将其打开。
- 样板代码(不计分)接收有符号整数的数组(列表),仅处理输出它们。
- 输出格式是带符号的小尾数16位字,每秒44100个样本,并带有可选的WAV标头。没有尝试输出压缩音频而不是普通的波形;
- 请选择用于合成的其他乐器(或该乐器的其他质量与代码大小类别);但最初不要告诉您要模拟什么-让其他用户猜测评论;
- 不鼓励使用电子仪器;
- 鼓是一种乐器。人的声音是一种乐器。
样板
这是某些语言的样板。您也可以为您的语言编写类似的样板。注释掉的“ g”功能仅用于演示(1秒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
例
这是仿照钢琴声音的非高尔夫C版本:
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);
}
}
}
}
它的得分约为1330字节,质量较差/中等。
2
要成为合适的代码高尔夫挑战者,您需要定义一个客观的获胜标准。(鉴于此挑战的性质,我认为这必须是“人气竞赛”,即最多的投票数。)
—
面包盒
该示例似乎不起作用。输出完全失真,并且其中有很多损坏。在MinGW中使用“ gcc -o piano.exe piano.c”进行编译,并通过“ piano.exe> piano.wav”执行。即使使用简单的440 Hz音调g功能也具有相同的结果。顺便说一句,您可以使用M_PI代替庞大的数字。它在math.h中定义。
—
Mike C
@Mike C,不带注释的C样板输出的开始
—
六。
q
应如下所示:pastebin.com/ZCB1v7QQ。您的房东是大端吗?
不,我正在使用MinGW,所以我是x86。我将在我的Linux机器上尝试一下。我不明白为什么我有问题。奇怪。
—
Mike C
确实
—
门把手
$><<7.chr
在Ruby中计?:P为9个字符!或$><<?\a
7个字符