一闪一闪亮晶晶


27

编写程序来播放流行的英语童谣。

乐谱 (此文件采用知识共享协议授权署名-网上百科全书:许可署名Helix84英文维基百科 ; Blahedo英文维基百科

某些Wikipedia文章可能有用:

您提交的一些准则:

  • 您的程序必须使用计算机的声卡。如果您的编程语言无法方便地访问音频硬件,则您的程序必须创建某种标准格式的输出文件,例如WAV或MIDI。

  • 您的程序必须实际生成其输出。例如,不允许从Wikipedia嵌入Ogg Vorbis文件。

  • 音频质量必须可以接受。至少,这首歌应该易于识别。最好也听起来不错。

  • 重点应该放在代码大小,声音质量或两者上(说明您决定的代码)。优雅的解决方案也将很棒。玩得开心!

  • 这是一个,因此最短的代码获胜


我可以估计音符频率吗?
Ming-Tang

1
为什么关闭?
程序员

@ programmer5000我要说接近的原因非常好地描述了它
完全是人类的

2
即使将代码编码为高尔夫球,我也会说这仍然不是话题。 音频质量必须可以接受。不是客观的有效性标准。
丹尼斯

3
@丹尼斯,我想这更像是“不清楚”而不是“离题”。
Erik the Outgolfer

Answers:


30

QBasic(56)

A$="CCGGAAG2FFEEDDC2"
B$="GGFFEED2"
PLAY "L4"+A$+B$+B$+A$

重点在于回忆:)

(但是没有QBasic对此进行测试)


1
至少可以在我的DOSBox安装上运行,但是您可以修改它以播放完整的歌曲吗?
2011年

做完了 我将着手提高阅读技巧:/
Eelvex

嗯,这页错了吗? en.wikibooks.org/wiki/QBasic/Appendix#PLAY- >八度以C开头,以B结束。我确实期望QBASIC以中间C为基础,但是如果完全正确的话,则表示它是基于A220的:)
mootinator 2011年

6
哇,这使我回想起了我最初在QBasic上编程的经历……其中包括编写俗气的音乐!
丹尼尔·斯坦迪奇

3
+1向下存储通道!现在,我只需要一个DRAW命令示例即可:)
系统

16

的JavaScript(214个 212 211字符)

打开Safari,Opera或Google Chrome to JavaScript Shell,然后输入以下代码:

for(s="",y=192e3;x=--y/4e3|0;)s+="~ "[(y%4e3>800|x%8==1)&Math.pow(2,"024579702457245702457970"[x>>1]/12)*y/31%2];open("data:audio/wav;base64,UklGRiXuAgBXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQHuAgCA"+btoa(s))

可读性未减(即使那样也可能很难理解):

for(s = "", y = 192E3; x = --y / 4E3 | 0;) {
  s += "~ "[(y % 4E3 > 800 | x % 8 == 1) & Math.pow(2, "024579702457245702457970"[x >> 1] / 12) * y / 31 % 2];
}
open("data:audio/wav;base64,UklGRiXuAgBXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQHuAgCA" + btoa(s));

如果再添加几个字符,它也可以在Firefox上运行,但是您可以更改该audio/wav部分以至少保存WAV文件。


1
在Chrome中运行正常。
mootinator

@mootinator:也为我工作。我没想到要在Chrome中检查它-直到最近才获得WAV文件支持。code.google.com/p/chromium/issues/detail?id=23916
PleaseStand 2011年

哇!太好了
菲利普·森

“有几个字符”是什么意思?这些字符是什么?
菲利普·森

@cf_PhillipSenn:在Firefox上运行代码时,我得到了一个无法运行的QuickTime Player。我必须将代码更改open(...)Audio(...).play()(另外8个字符),才能使用Firefox的工作内置音频播放器。

11

C#(长度:LOL)

因此,我在这里所做的是实现支持,该支持从C#中用于QBasic解决方案的字符串生成.wav文件(单个八度,无意外)。重点是:

  1. 避免unsafe代码块
  2. 不浪费太多的我的时间很多做
  3. 使扩展相对简单

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.IO;

namespace ConsoleApplication1
{
    public static class Extension
    {
        public static byte[] ToByteArray(this object o)
        {
            return o.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .SelectMany(x =>
                                {
                                    var value = x.GetValue(o, null);
                                    if (value.GetType().Equals(typeof (UInt16)))
                                    {
                                        return BitConverter.GetBytes((UInt16) value);
                                    }
                                    if (value.GetType().Equals(typeof (UInt32)))
                                    {
                                        return BitConverter.GetBytes((UInt32) value);
                                    }
                                    if (value.GetType().Equals(typeof(char[])))
                                    {
                                        return ((char[]) value).Select(y => Convert.ToByte(y));
                                    }
                                    if (value.GetType().Equals(typeof(byte[])))
                                    {
                                        return (byte[]) value;
                                    }
                                    throw new NotImplementedException();
                                }).ToArray();
        }
    }
    public class Wave
    {
        public readonly byte[] WavFile; 

        public Wave(string notes)
        {
            var header = new Header();
            var data = new List<Chunk>();
            var f = new Fmt(8000);
            data.Add(f);
            data.Add(new WavData(notes, f));
            var thefile = data.SelectMany(x => x.ToByteArray()).ToArray();
            header.Size = (uint)thefile.Length + 4;
            WavFile = header.ToByteArray().Concat(thefile).ToArray();
        }
        class WavData: Chunk
        {
            private static IEnumerable<byte> RenderNote(string note, int length, Fmt fmt)
            {
                double frequency;
                switch (note)
                {
                    case "A":
                        frequency = 440;
                        break;
                    case "B":
                        frequency = 493.883;
                        break;
                    case "C":
                        frequency = 261.626;
                        break;
                    case "D":
                        frequency = 293.665;
                        break;
                    case "E":
                        frequency = 329.628;
                        break;
                    case "F":
                        frequency = 349.228;
                        break;
                    case "G":
                        frequency = 391.995;
                        break;
                    default:
                        throw new NotImplementedException("Unsupported Note");
                }
                var result = new byte[fmt.SampleRate / length * 2];  // For 120BPM tempo
                for (int i = 0; i < result.Length; i++)
                {
                    double time = (i % fmt.SampleRate) / (double)fmt.SampleRate;
                    double position = time * frequency;
                    if (result.Length - i <= fmt.SampleRate / 16)
                        result[i] = 127;
                    else
                        result[i] = (byte)Math.Round((Math.Sin(position * 2 * Math.PI) + 1) * 127);
                }
                return result;
            }
            public WavData(string notes, Fmt fmt)
            {
                Samples = new byte[0];
                foreach (var note in Regex.Matches(notes, @"[A-G][1|2|4|8]?").OfType<Match>().Select(x => x.Value))
                {
                    Samples = Samples.Concat(RenderNote(note[0] + "", note.Length > 1 ? note[1] - '0' : 4, fmt)).ToArray();
                }

            }
            public override char[] Id
            {
                get { return "data".ToCharArray(); }
            }
            public override uint DataSize
            {
                get { return (uint)Samples.Length; }
            }
            public byte[] Samples { get; private set; }
        }
        class Fmt : Chunk
        {
            public Fmt(UInt32 sampleRate)
            {
                CompressionCode = 1; // Unknown/PCM
                Channels = 1;
                SampleRate = sampleRate;
                SignificantBits = 8;
            }
            public override char[] Id
            {
                get { return "fmt ".ToCharArray();}
            }
            public override uint DataSize
            {
                get { return 16; }
            }
            public UInt16 CompressionCode { get; private set; }
            public UInt16 Channels { get; private set; }
            public UInt32 SampleRate { get; private set; }
            public UInt32 AvgBytesPerSecond { get { return SampleRate*BlockAlign; } }
            public UInt16 BlockAlign { get { return (UInt16) (SignificantBits/8*Channels); } }
            public UInt16 SignificantBits { get; private set; }
        }
        class Header
        {
            public Header()
            {
                Type = "RIFF".ToCharArray();
                RiffType = "WAVE".ToCharArray();
                Size = 0;
            }

            public char[] Type { get; private set; }
            public UInt32 Size { get; set; }
            public char[] RiffType { get; private set; }
        }
        abstract class Chunk
        {
            public abstract char[] Id { get; }
            public abstract UInt32 DataSize { get; }
        }
    }
    class Program
    {
        public static void Main(string[] args)
        {
            var p1 = "CCGGAAG2";
            var p2 = "FFEEDDC2";
            var p3 = "GGFFEED2";
            var w = new Wave(p1+p2+p3+p3+p1+p2);
            using (var f = new FileStream("testfile.wav", FileMode.Create))
                f.Write(w.WavFile, 0, w.WavFile.Length);
        }
    }
}

我注意到上面的答案中的输出波幅度很小。显然,我缺少有关8位样本工作原理的信息。
监督员2011年

嗯,解决了。操作顺序很重要。此处的示例输出:dl.dropbox.com/u/469380/testfile.wav
mootinator 2011年

FromDigits["LOL",36]==28101这并没有像LOL <sub> 36 </ sub>字节...
CalculatorFeline

6

巨蟒(259)

import pysynth

c=('c',4)
g=('g',4)
a=('a',4)
b=('b',4)
d=('d',4)
e=('e',4)
f=('f',4)
g2=('g',2)
c2=('c',2)
d2=('d',2)

s=(c,c,g,g,a,a,g2,f,f,e,e,d,d,c2,g,g,f,f,e,e,d2,g,g,f,f,e
            ,e,d2,c,c,g,g,a,a,g2,f,f,e,e,d,d,c2)

pysynth.make_wav(s,fn="s.wav")

3
不能缩短为import ttls
zzzzBov 2011年

@zzz:嗯,这是个玩笑吗?
约翰

2
@zzz:-Bangs-head-on-desk-您到底在说什么?
约翰(John)

1
@约翰显然是koan。你应该鞠躬或打他。
ixtmixilix 2011年

1
(非常晚的评论)作为参考,是-60字节的版本,因为它确实打过高尔夫球。
暴民埃里克

5

C,277个字符

#include<math.h>
a[]={0,7,9,7,5,4,2,0,7,5,4,2,7,5,4,2,0,7,9,7,5,4,2,0},i,j,f;main(){unsigned char
b[8000];f=open("/dev/dsp",1);for(i=0;i<24;i++){for(j=0;j<8000;j++){b[j]=(i%4==3
||j/400%20!=9?1+sinf(j*powf(2,a[i]/12.)):1)*127;}for(j=0;j<8000;j+=write(f,b+j,
8000-j));}close(f);}

Perl,203个字符

open F,'>:raw','/dev/dsp';for$a(0,7,9,17,5,4,2,10,7,5,4,12,7,5,4,12,0,7,9,17,5,4
,2,10){$b=pack'C*',map 127*($a>9||$_/400%20!=9?1+sin($_*2**($a%10/12)):1),0..
7999;$b=substr$b,syswrite F,$b while length$b}

方便地,OSS/dev/dsp默认值为8kHz单声道u8。我在这里所做的只是打开设备并编写计算样本。


单独发布Perl;您正在使用代码高尔夫:)
Eelvex 2011年

179 -j,f;main(i){char b[8000];f=open("/dev/dsp",1);for(i=24;i--;write(f,b,j))for(j=0;j<8000;j++)b[j]=(i%4&&j/400%20==9?1:1+sinf(j*powf(2,("@BDEGIG@BDEGBDEG@BDEGIG@"[i]-64)/12.)))*127;}
gastropner

4

PowerShell的:207

高尔夫代码:

filter n {switch($_){C{262}D{294}E{330}F{349}G{392}A{440}}}$t="CCGGAAGFFEEDDCGGFFEEDGGFFEEDCCGGAAGFFEEDDC";1..6|%{$t[0..5]|n|%{[console]::beep($_,600)};$t[6]|n|%{[console]::beep($_,1200)};$t=$t.SubString(7)}

取消评论,并附有评论:

# Filter to define note frequencies.
filter n {switch($_){C{262}D{294}E{330}F{349}G{392}A{440}}}

# Notes for Twinkle, Twinkle, Little Star.
$t="CCGGAAGFFEEDDCGGFFEEDGGFFEEDCCGGAAGFFEEDDC"

# Run through each phrase in the song.
1..6|%{
    # Play first six notes as quarter notes.
    $t[0..5]|n|%{[console]::beep($_,600)}
    # Play seventh note as half note.
    $t[6]|n|%{[console]::beep($_,1200)}
    # Left-shift $t by 7 notes.
    $t=$t.SubString(7)
}

这首歌虽然听上去不是最响亮的声音,但可以奏效。


1
(最新评论)可以n{代替n {吗?
暴民埃里克

4

C-520

#include <linux/fd.h>
#include <time.h>
struct timespec t,p;char*q="AAHHJJH  FFEECCA  HHFFEEC  HHFFEEC  AAHHJJH  FFEECCA";x,y,z,v,w;main(){x=open("/dev/fd0",3);for(y;q[y];y++){clock_gettime(CLOCK_MONOTONIC,&p);if(q[y]>' ')for(w=z=0;z<4e8;z+=t.tv_nsec,w++){struct floppy_raw_cmd s={0};s.flags=FD_RAW_NEED_SEEK;v=!v;s.track=v;ioctl(x,FDRAWCMD,&s);clock_gettime(CLOCK_MONOTONIC,&t);t.tv_nsec=(w+1)*5e8/pow(2.,q[y]/12.)-(t.tv_sec-p.tv_sec)*1e9-t.tv_nsec+p.tv_nsec;t.tv_sec=0;nanosleep(&t,0);}t.tv_nsec=2e8;nanosleep(&t,0);}}

为什么要使用上个世纪的扬声器和耳机等硬件?这段出色的代码使您可以在现代硬件上播放歌曲:软盘驱动器!
无特殊要求:

  • IDE软盘驱动器
  • Linux内核
  • 编译 -lm
  • 确保程序可以访问/dev/fd0,因此可以锁定设备或以超级用户身份运行

稍微修改一下规则,但让我们再考虑一下软盘驱动器和声音设备,而IDE控制器则是集成声卡。


我会说这是合理的,您的软盘驱动器具有出色的能力,适用于youtu.be/LkqYLOa76E0
Hotkeys

3

HyperCard的 2.2 - 113

play harpsichord "c c g g a a gh fq f e e d d ch gq g f f e e dh gq g f f e e dh cq c g g a a gh fq f e e d d ch"

用法:启动HyperCard,键入⌘M打开消息框,粘贴上面的代码,然后按Enter。

harpsichord可能会替换为fluteboing获得不同的声音。


(非常晚的评论)harpsichord-> flute-6删除了仪器和引号之间的空格-1总计-7
Outgolfer的Erik

3

C,96个字符

main(t){for(;++t>>16<3;)putchar(t*!!(t>>9&7|!(-t>>12&7))*(96+"#d|dOE3#dOE3dOE3"[t>>13&15])>>5);}

以经典的字节拍样式生成原始的8位无符号单声道音频数据。建议的回放采样率在8到16 kHz之间。更改采样率会更改速度和音调。

要在Linux上编译和播放,请将上面的代码另存为twinkle.c并运行以下命令:

gcc twinkle.c -o twinkle
./twinkle | aplay

有关代码工作方式的一些注意事项:

  • 用于字节拍合成的一般技巧是putchar()采用整数值,但仅输出其低八位。因此,putchar(t)t处增加计数器,将生成锯齿波,并且可以通过乘以t适当的值来更改波的频率。

  • !!(t>>9&7|!(-t>>12&7))产生重复的6 + 1音符模式。具体来说,将!!(t>>9&7)评估0为何时t>>9 & 7 == 0以及1其他情况。因此,它每4096个样本在波形中产生512个样本的间隙,而!(-t>>12&7)每八个这样的间隙消除一次。

  • 96+"#d|dOE3#dOE3dOE3"[t>>13&15]产生旋律:字符串中每个字符的ASCII码加96给出相应音符的相对频率。实际上,这些值是在第3个/小八度音阶中音乐会音高音的Hz近似频率,即A对应于220。但是,由于与这些值相乘的基本音约为64 Hz(以16 kHz播放时,或以8 kHz播放时为32 Hz),我们需要将结果按比例缩小五个八度,>>5以使频率回到合理的范围内。

附言 如果要在基于JavaScript的字节拍播放器上尝试此代码,请替换[t>>13&15].charCodeAt(t>>13&15)


2

蟒蛇 317 305 301

这是我的解决方案,仅使用标准python库:

import math,wave,struct;d=24000;r=1100.;t=wave.open("t.wav","w");t.setparams((1,2,int(r),d,"NONE",""));a=[0,7,9,7];b=[5,4,2,0];c=[7,5,4,2]
for h in[math.sin(6*[240*2**(j/12.)for j in a+b+c+c+a+b][x/1000]*(x/r))*(x%500>9 or x/1000%4>2)for x in range(d)]:t.writeframes(struct.pack('h', int(h*64000/2)))

为了增加可读性,这里还有一些空白:

import math,wave,struct;d=24000;r=1100.
a=[0,7,9,7];b=[5,4,2,0];c=[7,5,4,2];s=[240*2**(j/12.) for j in a+b+c+c+a+b]
z=[math.sin(6*s[int(x/1000)]*(x/r))*(x%500>10 or int(x/1000)%4>2) for x in range(d)]
t=wave.open("t.wav","w");t.setparams((1,2,int(r),d,"NONE",""))
for h in z:t.writeframes(struct.pack('h', int(h*64000./2)))

2

Mathematica,86个字符

s=SoundNote;If[#>9,s[#-10,2],{s@#,s@#}]&/@Join[a={0,7,9,17,5,4,2,10},b={7,5,4,12},b,a]

2

Arduino的,688

int length=15;char notes[]="ccggaag ffeeddc ggffeed ggffeed ccggaag ffeeddc";int beats[]={1,1,1,1,1,1,2,1,1,1,1,1,1,2,4};int tempo=300;void playTone(int tone,int duration){for(long i=0;i<duration*1000L;i+=tone*2){digitalWrite(11,HIGH);delayMicroseconds(tone);digitalWrite(11, LOW);delayMicroseconds(tone);}}void playNote(char note, int duration){char names[]={'c','d','e','f','g','a','b','C'};int tones[]={1915,1700,1519,1432,1275,1136,1014,956};for(int i=0;i<8;i++){if(names[i]==note){playTone(tones[i], duration);}}}void setup(){pinMode(11, OUTPUT);}void loop(){for(int i=0;i<length;i++){if(notes[i]==' '){delay(beats[i]*tempo);}else{playNote(notes[i],beats[i]*tempo);}delay(tempo/2);}}

在输出11上插入蜂鸣器。我主要关注质量,但也关注代码长度。


(后期评论)"ccggaag ffeeddc ggffeed ggffeed ccggaag ffeeddc "删除空间?int beats[] =删除空间?for (long删除空间?11, LOW删除空间?note, int删除空间?i], duration删除空间?11, OUTPUT删除空间?
暴民埃里克(Erik the Outgolfer)

您实际上忘记了一些空格吗?据我了解,空间中ffeeddc "存在某种延迟,这是您最终不需要的,并且beats[] =没有理由拥有空间。另外,您应该仅针对代码长度来制作一个专注于代码长度的版本!
暴民埃里克(Erik the Outgolfer)

我想这些变量可能都是一个字母,但我认为花这么长时间回答不值得。感谢您的提示。
Timtech '16

好的,如果您愿意,可以将其作为单独的答案发布。
Timtech '16

@Timtech由于问题已解决,很遗憾无法完成... :-(
wizzwizz4

2

bash + say + gunzip,136个字节

say,当然是OS X文字转语音指令。真是 是的,让我们一起努力吧。

printf '<117 bytes>'|gunzip|sh

当然,这117个字节是包含不可打印字符的gzip流。这是脚本的xxd转储,包括那些字符:

00000000: 7072 696e 7466 2027 1f8b 085c 305c 305c  printf '...\0\0\
00000010: 305c 305c 3002 032b 4eac 54d0 2d0b c9c8  0\0\0..+N.T.-...
00000020: cf4d 2c56 c8e7 c2ca 75cc cb4b c4ce 71cb  .M,V....u..K..q.
00000030: ccc7 c90b 4b4d 85f0 7252 530b 14f4 4ca0  ....KM..rRS...L.
00000040: c2de 8945 a979 4061 6cbc e0c4 dcc4 bc92  ...E.y@al.......
00000050: 8c44 dc02 2e89 7999 a939 685c 5c74 7723  .D....y..9h\\tw#
00000060: ec44 755c 6e2a 8f8a ee19 581b 8767 1402  .Du\n*....X..g..
00000070: 5c30 fa36 7e25 2599 025c 305c 3027 7c67  \0.6~%%..\0\0'|g
00000080: 756e 7a69 707c 7368                      unzip|sh

说明

117个字节是以下压缩后的脚本:

say -vThomas o
say -vThomas o
say -vAnna o
say -vAnna o
say -vFiona o
say -vFiona o
say -vVeena o
sleep .4
say -vKaren o
say -vKaren o
say -vSamantha o
say -vSamantha o
say -vDaniel o
say -vDaniel o
say -vThomas o
sleep .4
say -vVeena o
say -vVeena o
say -vKaren o
say -vKaren o
say -vSamantha o
say -vSamantha o
say -vDaniel o
sleep .4
say -vVeena o
say -vVeena o
say -vKaren o
say -vKaren o
say -vSamantha o
say -vSamantha o
say -vDaniel o
sleep .4
say -vThomas o
say -vThomas o
say -vAnna o
say -vAnna o
say -vFiona o
say -vFiona o
say -vVeena o
sleep .4
say -vKaren o
say -vKaren o
say -vSamantha o
say -vSamantha o
say -vDaniel o
say -vDaniel o
say -vThomas o

没错,我只是发出了许多不同的say声音说“ o”。为了弄清楚哪一个,我写了一个脚本,使用auponotes来快速估算每个声音的音调,然后进行了很多次尝试,然后找出听起来最正确的声音。

我考虑过尝试手动打高尔夫球,但是重复的次数太多,以至于Zopfli会做得更短一些,所以我采取了简单的方法。


1

SmileBASIC,45字节

BGMPLAY"{M=CCGGAAG2FFEEDDC2}{M}[GGFFEED2]2{M}

0

的powershell,120个 117字节

[Console]::beep,音符标签和频率受Iszi启发

 ($a='ccggaaGffeeddC')+'ggffeeD'*2+$a|% t*y|%{[console]::beep((0,110,0,65,73,82,87,98)[$_-band7]*4,600+600*($_-lt97))}

主要思想

  • 旋律编码为字符串。
  • 该票据编码字符有ACDEFG
  • 大写表示double duration
  • 3个低位比特($_-band7)的每个音符的用途作为频率数组中的索引的(A->1C->3D->4...)
  • 该脚本使用降低的频率采样率:(0,110,0,65,73,82,87,98)[$_-band7]*4代替Iszi的(0,440,0,262,294,330,349,392)[$_-band7][console]::Beep不是最准确的乐器,所以它可能会有点假:)

说明:对于旋律字符串中的每个字符ccggaaGffeeddCggffeeDggffeeDccggaaGffeeddC,脚本:

  • 使用低位作为索引从数组中查找频率
  • 根据char大写/小写计算持续时间
  • 呼叫[console]::beep播放音符
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.