बस एक नोट - संगीत वाद्ययंत्र संश्लेषित [बंद]


11

बयान

कार्य कुछ सामान्य प्रयोजन प्रोग्रामिंग भाषा (आपकी पसंद के) में फ़ंक्शन का उपयोग करके कुछ संगीत वाद्ययंत्र (आपकी पसंद का एक नोट) को ध्वनि को संश्लेषित करना है।

दो लक्ष्य हैं:

  • परिणामी ध्वनि की गुणवत्ता। इसे यथासंभव वास्तविक उपकरण जैसा दिखना चाहिए;
  • Minimality। 1500 बाइट्स के तहत कोड रखने की सलाह दी जाती है (यदि केवल मूल ध्वनि उत्पन्न होती है)।

केवल पीढ़ी फ़ंक्शन प्रदान करने की आवश्यकता है, बॉयलरप्लेट को स्कोर के लिए नहीं गिना जाता है।

दुर्भाग्य से ध्वनि निष्ठा के लिए कोई स्कोर की गणना नहीं की जा सकती है, इसलिए सख्त नियम नहीं हो सकते हैं।

नियम:

  • नमूना पुस्तकालयों, विशेष संगीत पीढ़ी की चीजों पर कोई निर्भरता नहीं;
  • नेटवर्क से डाउनलोड नहीं करना या माइक्रोफ़ोन या ऑडियो कार्ड के MIDI या इस तरह से बाहरी कुछ भी उपयोग करने की कोशिश करना;
  • कोड आकार माप इकाई बाइट्स है। फ़ाइल वर्तमान निर्देशिका में बनाई जा सकती है। पहले से मौजूद फाइलें (गुणांक तालिकाएं, आदि) मौजूद हो सकती हैं, लेकिन उनकी सामग्री स्कोर में जोड़ी जाती है + उन्हें नाम से खोला जाना चाहिए।
  • बॉयलरप्लेट कोड (स्कोर करने के लिए नहीं गिना जाता) पर हस्ताक्षर किए गए पूर्णांकों की सरणी (सूची) प्राप्त होती है और केवल उन्हें आउटपुट करने से संबंधित है।
  • वैकल्पिक WAV हैडर के साथ आउटपुट फॉर्मेट में प्रति सेकंड 16-बिट शब्दों, 44100 नमूनों पर हस्ताक्षर किए जाते हैं। सादे wav के बजाय संपीड़ित ऑडियो आउटपुट करने की कोई कोशिश नहीं कर रहा है;
  • कृपया सिंथेसाइज़ करने के लिए विभिन्न उपकरणों का चयन करें (या अन्य गुणवत्ता बनाम उपकरण के लिए कोड आकार श्रेणी); लेकिन शुरू में यह नहीं बताएं कि आप क्या अनुकरण कर रहे हैं - अन्य उपयोगकर्ताओं को टिप्पणियों में अनुमान लगाने दें;
  • इलेक्ट्रॉनिक उपकरणों को हतोत्साहित किया जाता है;
  • ढोल एक वाद्य है। मानव आवाज एक यंत्र है।

Boilerplates

यहाँ कुछ भाषाओं के बॉयलर हैं। आप अपनी भाषा के लिए भी इसी तरह की बॉयलर प्लेट लिख सकते हैं। "जी" फ़ंक्शन टिप्पणी के लिए एक डेमो (1 सेकंड 440 हर्ट साइन टोन) के लिए है।

सी:

//#!/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;
}

अजगर 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);

पर्ल 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));

हास्केल:

#!/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

उदाहरण

पियानो ध्वनि के बाद यहां अनलोडेड सी संस्करण प्रस्तुत किया गया है:

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 पियानो.exe पियानो.c" के साथ संकलित किया गया और "पियानो.exe> ​​पियानो.wav" के साथ निष्पादित किया गया। यहां तक ​​कि सरल 440 हर्ट्ज टोन जी फ़ंक्शन का उपयोग करने का एक ही परिणाम है। BTW, आप अपने विशाल संख्या के स्थान पर M_PI का उपयोग कर सकते हैं। यह गणित में परिभाषित किया गया है।
माइक सी

@ माइक C, C बायलरप्लेट के आउटपुट की शुरुआत अधूरे के साथ इस तरह दिखनी qचाहिए: pastebin.com/ZCB1v7QQ । क्या आपका होस्ट बड़ा एंडियन है?
वि।

नहीं, मैं MinGW का उपयोग कर रहा हूं इसलिए मैं x86 हूं। मैं इसे अपने एक लिनक्स बॉक्स पर आज़माता हूँ। मुझे समझ नहीं आता कि मुझे समस्या क्यों हो रही है। अजीब।
माइक सी

करता $><<7.chrरूबी गिनती में? : 9 अक्षरों के लिए P! या $><<?\a7 वर्ण के लिए
दरवाज़े

जवाबों:


2

जावा

मेरी बॉयलरप्लेट ध्वनि बजाती है। मैं g()थोड़ा और गोल्फ कर सकता हूं , लेकिन यह वर्तमान में 273 वर्णों पर है जो 1500 के तहत अच्छी तरह से है। मैंने मूल रूप से 4kB खेल के लिए 16kHz के लिए यह लिखा था और 44.1kHz प्लेबैक पर सही तानवाला गुण प्राप्त करने के लिए स्थिरांक को थोड़ा मोड़ना था, लेकिन मैंने इससे काफी खुश हूं।

import java.io.*;
import javax.sound.sampled.*;

public class codegolf13003 {
    byte[]g(){byte[]d=new byte[88000];int r=1,R=1103515247,b[]=new int[650],i,o,s,y;for(i=0;i<b.length;r*=R)b[i++]=0x4000+((r>>16)&0x3fff);for(i=o=0;i<d.length;o=s){s=(o+1)%b.length;y=(b[o]+b[s])/2*((r&0x10000)<1?-1:1);r*=R;d[i++]=(byte)(b[o]=y);d[i++]=(byte)(y>>8);}return d;}

    public static void main(String[] args) throws Exception {
        byte[] data = new codegolf13003().g();
        ByteArrayInputStream bais = new ByteArrayInputStream(data);
        AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 1, 2, 44100, false/*LE*/);
        AudioInputStream stream = new AudioInputStream(bais, format, data.length / 2);
        new Previewer().preview(stream);
    }

    static class Previewer implements LineListener {
        Clip clip;

        public void preview(AudioInputStream ais) throws Exception {
            AudioFormat audioFormat = ais.getFormat();
            DataLine.Info info = new DataLine.Info(Clip.class, audioFormat);

            clip = (Clip)AudioSystem.getLine(info);
            clip.addLineListener(this);

            clip.open(ais);
            clip.start();
            while (true) Thread.sleep(50); // Avoid early exit of program
        }

        public void update(LineEvent le) {
            LineEvent.Type type = le.getType();
            if (type == LineEvent.Type.CLOSE) {
                System.exit(0);
            }
            else if (type == LineEvent.Type.STOP) {
                clip.close();
            }
        }
    }
}

आगे पढ़ने: Karplus- मजबूत संश्लेषण


पल्सएडियो के बिना शुरू करने के लिए मैं इसका उपयोग करता हूं: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
वीआई।

मान लिया कि आप कुछ टक्कर चाहते थे, लेकिन अनिश्चित जो एक बिल्कुल। यह थोड़ा बहुत "इलेक्ट्रॉनिक" लगता है।
वि।

@ वी।, मैं इसे अन्य लोगों के लिए कहने के लिए छोड़ दूँगा कि उन्हें कौन सा साधन लगता है कि मैं इसका अनावरण करने से पहले लक्ष्य कर रहा हूं।
पीटर टेलर

चूँकि लोगों को अनुमान लगाने में कुछ दिन हो गए हैं, मैं फलियाँ पकाने जा रहा हूँ। अभिप्राय यंत्र एक फंदा है।
पीटर टेलर

क्या आप तुलना करने के लिए वास्तविक रिकॉर्ड किए गए नमूने का लिंक दे सकते हैं?
वि।

2

सी

यहाँ g()बॉयलरप्लेट के बिना फ़ंक्शन होता है।

void g(signed short *array, int* length)
{
    short r[337];
    int c, i;

    *length = 44100 * 6;
    for (i = 0 ; i < 337 ; ++i)
        r[i] = rand();
    *array = *r;
    for (i = c = 1 ; i < *length ; ++i) {
        array[i] = r[c];
        r[c] = (r[c] + array[i - 1]) * 32555 / 65536;
        c = (c + 1) % 337;
    }
}

एक दिलचस्प प्रयोग पहले लूप के साथ खेलना है जो यादृच्छिक मूल्यों की शुरुआत अनुक्रम को शुरू करता है। कॉल को बदलने के rand()साथ i*iध्वनि के चरित्र को एक प्रशंसनीय तरीके से बदल देता है (अर्थात, ऐसा लगता है कि संश्लेषण उसी उपकरण परिवार के एक अलग सदस्य की नकल कर रहा है)। i*i*iऔर i*i*i*iअन्य ध्वनि गुण देते हैं, हालांकि हर एक ध्वनि की तरह करीब आता है rand()। दूसरी तरफ i*327584या जैसे मूल्य i*571, कुछ अलग लगता है (और कुछ असली की नकल की तरह कम)।


उसी फ़ंक्शन का एक और मामूली बदलाव किसी अन्य उपकरण के करीब भी आता है, या कम से कम यह मेरे कान के लिए करता है।

void g(signed short *array, int* length)
{
    int i;

    *length = 44100 * 6;
    for (i = 0 ; i < 337 ; ++i)
        array[i] = rand();
    for ( ; i < *length ; ++i)
        array[i] = (array[i - 337] + array[i - 1]) * 32555 / 65536;
}

जोड़ने के लिए संपादित: मैं इसे एक कोड गोल्फ प्रश्न के रूप में नहीं मान रहा था, क्योंकि यह (1500-चार सीमा से अधिक) के रूप में चिह्नित नहीं किया गया है, लेकिन चूंकि यह टिप्पणियों में लाया गया है, यहां ऊपर का एक गोल्फ संस्करण है ( 96 अक्षर):

g(short*a,int*n){int i=0;for(*n=1<<18;i<*n;++i)
a[i]=i>336?32555*(a[i-337]+a[i-1])/65536:rand();}

(यदि मैं वैश्विक चरों का उपयोग करने के लिए फ़ंक्शन इंटरफ़ेस को बदल सकता हूं, तो मैं इसे 80 वर्णों से नीचे ले जा सकता हूं।)


करप्लस-स्ट्रांग स्ट्रिंग। मेरे लिए एक स्टील की स्ट्रिंग की तरह लगता है।
पीटर टेलर

@PeterTaylor मेरे विचार बिल्कुल। दूसरी ओर, नीचे का संस्करण, हर्टिकॉर्ड के कण (या नायलॉन) स्ट्रिंग की तरह मुझे लगता है। यह केवल भ्रम को पूरा करने के लिए बाद में रिटर्निंग क्वाइल की जरूरत है।
ब्रेडबॉक्स

खाली स्थान के और छोटा करने को हटाने के बाद array, length, voidऔर signed113 बाइट्स: दूसरा कोड में मैं स्कोर मिला है। बहुत अच्छी कोशिश। और ध्वनि बल्कि अच्छा है।
वि।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.