утверждение
Задача состоит в том, чтобы синтезировать звук (одну сыгранную ноту) какого-либо музыкального инструмента (по вашему выбору) с использованием функции на каком-то универсальном языке программирования (по вашему выбору).
Есть две цели:
- Качество получаемого звука. Он должен напоминать реальный инструмент настолько хорошо, насколько это возможно;
- Минимальности. Рекомендуется хранить код менее 1500 байт (меньше, если есть только базовое генерирование звука).
Должна быть предусмотрена только функция генерации, шаблон не учитывается при оценке.
К сожалению, для верности звука нельзя рассчитать баллы, поэтому не может быть строгих правил.
Правила:
- Нет зависимости от библиотек сэмплов, специализированных вещей для генерации музыки;
- Никакой загрузки из сети или попытки использовать MIDI микрофон или звуковую карту или что-то слишком внешнее, как это;
- Единица измерения размера кода - байты. Файл может быть создан в текущем каталоге. Существующие ранее файлы (таблицы коэффициентов и т. Д.) Могут существовать, но их содержимое добавляется в счет + они должны открываться по имени.
- Стандартный код (не учитывается при оценке) получает массив (список) целых чисел со знаком и имеет дело только с их выводом.
- Выходной формат представляет собой 16-разрядные слова с прямым порядком байтов, 44100 выборок в секунду, с необязательным заголовком WAV. Не пытайтесь выводить сжатый звук вместо простого wav;
- Пожалуйста, выберите различные инструменты для синтеза (или другую категорию качества по сравнению с размером кода для инструмента); но сначала не говорите, что вы имитируете - пусть другие пользователи догадаются в комментариях;
- Электронные инструменты не рекомендуется;
- Барабан - это инструмент. Человеческий голос - это инструмент.
Макеты
Вот шаблоны для некоторых языков. Вы можете написать аналогичную табличку для вашего языка. Функция «g» закомментирована только для демонстрации (1 секунда, синусоидальный сигнал 440 Гц).
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 байт и обеспечивает плохое / посредственное качество.
q
должно выглядеть следующим образом: pastebin.com/ZCB1v7QQ . Является ли ваш хост big-endian?
$><<7.chr
в счете Руби? : P для 9 символов! или $><<?\a
за 7 символов