\begingroup

的开头部分。这是由以下组成的4 个八度上下

C add2、Am add2、C add2、Am add2、F add2、G add2、G♯大写7、A♯大写7

规则:

  • 运行代码时必须播放实际的声音。使用什么环境由您决定,例如它可以是,或带有 IBM PC 兼容内置扬声器的计算机。
  • 任何乐器都可以,包括简单的哔哔声,只要旋律清晰可辨。
  • 速度80 bpm,单个音符为,因此弹奏8个和弦的琶音需要48秒。
  • 第一个音符是 C 3,其440 221 / 12≈130.8440221/12130.8440\cdot2^{-21/12}\approx130.8Hz。上升 4 个八度后,琶音从 C 7开始回落,使用相同和弦的音符。然后开始下一个和弦。其他和弦从以下位置开始:A 2、C 3、A 2、F 2、G 2、G♯ 2和 A♯ 2
  • 频率和节奏可能存在轻微的误差。
  • 如果这样更简单,您可以用 A♭ maj7和 B♭ maj7代替最后两个和弦。

评分:

  • 这是代码高尔夫,因此最短的代码获胜。
  • 分数乘以您使用的语言和外部工具的数量。因此,system("sox …")从 C 调用的乘数为 3,因为它使用 C、shell 和 sox。
  • 程序的解释器(如果有)不计入乘数。因此,如果您的程序只是一个 MP3 文件,其解释器可以是音乐播放器,因此它的乘数为 1。

\endgroup

9

  • \begingroup
    那么,例如任何 Cadd2 都可以还是只有 [0,2,4,7] 可以?
    \endgroup


    – 

  • 1
    \begingroup
    @G.Sliepen 我不懂音乐。“[0,2,4,7,12,14,…, 43]”这些数字对应的是什么?这些数字出现在你的评论中,但没有出现在问题本身中。
    \endgroup


    – 

  • 1
    \begingroup
    @Jordan 那些是。从哪里开始计数有点随意,但在和弦的上下文中,基音是 0,大三度比基音高 4 个半音,纯五度是 7。而“Cadd2”中的“add2”表示在和弦中添加了一个比基音高 2 个半音的额外音符。它们还与频率有很好的关系:半音 n 的频率等于基音的频率乘以 2^(n/12)。(所有这些都假设。)
    \endgroup


    – 


  • 4
    \begingroup
    @G.Sliepen 您能按顺序列出乐曲的所有半音或所有频率吗?也许只有我一个人这样,但似乎这项任务的主要内容是将和弦名称转换为半音或频率,而不是真正打高尔夫球。
    \endgroup


    – 

  • 6
    \begingroup
    这毫无帮助。它迫使人们学习音乐理论来获得一个数字序列,而你本可以轻松地在问题中列出这些数字序列。我会问 CoP​​ilot
    \endgroup


    – 



5 个回答
5

\begingroup

(1 种语言),78 字节

0'!4XC@nRAxt~&'F5:ZaKe16:Y)tP[AaABOlHN]0Y(_&vhYs"1875:YPE*76/@12/W*Y,E]&h1e4Y#

它采用平均律,C 3频率为 131.6 Hz(可以花费 2 或 3 个字节来实现更精确的值,即76在代码中用76.4或替换76.45)。

音色对应于幅度减半的正弦波(此削波占用 1 个字节,但产生的声音比纯正弦波更好;后者可以通过删除E代码末尾附近来获得)。

尝试一下

\endgroup

\begingroup

ZX Spectrum 48K/128K Basic,246 字节

  10 LET t=VAL ".13": FOR i=SGN
PI TO VAL "8": READ a$,b$: FOR j
=NOT PI TO INT PI: FOR k=SGN PI
TO VAL "4": BEEP t,VAL "12"*j+CO
DE b$(k)-VAL a$: NEXT k: NEXT j:
 FOR j=INT PI TO NOT PI STEP -SG
N PI: FOR k=VAL "5" TO VAL "2" S
TEP -SGN PI: BEEP t,VAL "12"*j+C
ODE b$(k)-VAL a$: NEXT k: NEXT j
: NEXT i: DATA "60","0247<","63"
,"0237<","60","0247<","63","0237
<","67","0247<","65","0247<","64
","047;<","62","047;<"

由于 ZX Spectrum 的屏幕宽度为 32 个字符,因此以上就是程序在屏幕上的列表。字节数是通过减去程序结束和开始的系统变量来计算的;这将比保存文件长度少 1,因为空程序的保存文件长度为 1。不幸的是,我使用的在线模拟器只有保存快照选项,因此您必须自己重新输入才能进行测试。在 48K 模式下,所有关键字都已标记,因此请检查模拟器的键盘布局以了解如何输入适当的标记,但在 128K 模式下,您可以输入单词,它们将为您标记。在这两种模式下,您可能还需要使用键盘布局输入一些特殊字符,例如-*。说明:

  10

任意行号(始终占用 2 个字节)。

LET t=VAL ".13"

时间变量,经过调整,使整体运行时间约为实际时间的 48 秒。(处理开销使程序运行时间比实际注释时间长约 50%)。

FOR i=SGN PI TO VAL "8"

重复8次数。VAL用作其他数字在内部表示时会占用六个额外字节,但却SGN PI是表达的更短方式1

READ a$,b$

获取下一个和弦的主音和琶音。

FOR j=NOT PI TO INT PI

重复四个八度;NOT PI0INT PI当然是3

FOR k=SGN PI TO VAL "4"

重复四个音符。

BEEP t,VAL "12"*j+CODE b$(k)-VAL a$

计算音符索引(C₄=0)并演奏。

NEXT k: NEXT j

重复上述步骤,完成其余的上升琶音。

FOR j=INT PI TO NOT PI STEP -SGN PI

循环回到八度音程。

FOR k=VAL "5" TO VAL "2" STEP -SGN PI

循环播放音符。

BEEP t,VAL "12"*j+CODE b$(k)-VAL a$

计算并弹奏音符。

NEXT k: NEXT j: NEXT i

重复上述步骤,完成前奏的剩余部分。

DATA "60","0247<","63","0237<","60","0247<","63","0237<","67","0247<","65","0247<","64","047;<","62","047;<"

主音和琶音数据。

\endgroup

1

  • \begingroup
    我不知道 ZX Spectrum Basic 标记器的细节,但它会节省VAL "12"*j+CODE a$(k)-CODE a$(0)k递增和$a合并$b到同一字符串有关的字节吗?或者你甚至可以DATA完全丢弃它们,而使用单个字符串并进行一些额外的索引运算?
    \endgroup


    – 

\begingroup

,190 字节

xxd 转储:

00000000: 4d54 6864 0000 0006 0001 0002 00dc 4d54  MThd..........MT
00000010: 726b 0000 0013 00ff 5103 07a1 2000 ff58  rk......Q... ..X
00000020: 0404 0218 0801 ff2f 004d 5472 6b00 0000  ......./.MTrk...
00000030: 8d00 c000 0090 3050 0034 5000 3750 8670  ......0P.4P.7P.p
00000040: 3000 0034 0000 3700 0039 5000 3d50 0040  0..4..7..9P.=P.@
00000050: 5086 7030 5000 3450 0037 5000 3900 003d  P.p0P.4P.7P.9..=
00000060: 0000 4000 8670 3000 0034 0000 3700 0039  ..@..p0..4..7..9
00000070: 5000 3d50 0040 5086 7035 5000 3900 0039  P.=P.@P.p5P.9..9
00000080: 5000 3c50 003d 0000 4000 8670 3500 0038  P.<P.=..@..p5..8
00000090: 5000 3900 003c 0000 3c50 003f 5086 7038  P.9..<..<P.?P.p8
000000a0: 0000 3a50 003c 0000 3e50 003f 0000 4150  ..:P.<..>P.?..AP
000000b0: 8670 3a00 003e 0000 4100 01ff 2f00       .p:..>..A.../.

环境:一台现代的 Linux 计算机,安装了 alsa(许多发行版中的默认软件,但已被 pipewire 取代),并且安装了 midi 卡(可以是 USB midi 卡)​​,可在 midi 端口 x 上使用。

玩法:将代码保存到文件中,然后

aplaymidi --port=x.0 <filepath>

您可能已经猜到了,这只是我用适当的音符和节奏生成的直接 midi 文件。

\endgroup

\begingroup

,401 字节

$C=130,146,164,196,261,196,164,146
$A=110,123,130,174,220,174,130,123
$G=103,130,155,196,207,196,155,130
function P($c,$h){for($i=0;$i-lt8;$i++){if($i-lt4){for($n=0;$n-lt4;$n++){[console]::Beep(($c[$n%$c.Length])*[math]::Pow(2,$i + $h/12),187)}}else{for($n=4;$n-lt8;$n++){[console]::Beep(($c[$n%$c.Length])*[math]::Pow(2,8-$i-1+$h/12),187)}}}}
P $C 0
P $A 0
P $C 0
P $A 0
P $C -7
P $C -5
P $G 0
P $G 2

这是一个非常强力的解决方案,因为我是 PowerShell 新手。定义一个函数,P该函数以给定的半音偏移量演奏和弦(数字数组,截断为最接近的整数),首先向上 4 次,然后向下 4 次。每个音符都使用内置方法播放[System.Console]::Beep

要运行,请将其粘贴到.ps1文件中,然后在 PowerShell 中运行它。

\endgroup

2

  • \begingroup
    看起来您在P:中遗漏了几个空格$i + $h/12
    \endgroup


    – 


  • \begingroup
    我不知道 PowerShell 但是($c[$n % $c.Length]可以$c.Length替换为8,或者我误解了那里的值$c是什么?
    \endgroup


    – 

\begingroup

,677 字节

data 131,147,165,196,262,294,330,392,523,587,659,784,1047,1175,1319,1568,2093
data 110,123,131,165,220,247,262,330,440,494,523,659,880,988,1047,1319,1760
data 131,147,165,196,262,294,330,392,523,587,659,784,1047,1175,1319,1568,2093
data 87,98,110,131,175,196,220,262,349,392,440,523,698,784,880,1047,1397
data 98,110,123,147,196,220,247,294,392,440,494,587,784,880,988,1175,1568
data 104,123,156,185,208,247,311,370,415,494,622,740,831,988,1245,1480,1661
data 116,139,165,208,233,277,330,415,466,554,659,831,932,1109,1319,1661,1865
for j=1 to 7:dim m(16):for i=0 to 16:read m(i):next
for i=0 to 16:s(m(i)):next:for i=0 to 15:s(m(15-i)):next:next
sub s(n):sound n,.18,50:return

可能将所有频率都转换为整数,导致数据处理过度。我相信有更好的方法,使用基频和有趣的公式(使用 2 的幂)来编码。但今天就够了。

\endgroup