65.9K
CodeProject 正在变化。 阅读更多。
Home

隐写术 20 - 从文本生成旋律。

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.98/5 (25投票s)

2011年1月15日

CPOL

5分钟阅读

viewsIcon

65072

downloadIcon

2977

通过对音符进行排序来编码文本。

引言

隐写术 19 - 代码的顺序 中,您学习了如何通过对任意集合进行排序来编码消息。音乐由旋律组成,旋律是音符的集合。为什么不创作一首歌曲来编码旋律中的文本呢?

screen

您需要定义的只是要在歌曲中使用的音符集合。由于有 Factorial(count) 种可枚举的排列,更多的可能音符意味着更大的秘密消息字母表。在本文中,我们不会花费时间讨论和声和作曲。我们将混合整个半音阶来编码一个长词或几个短词。对于较长的消息,您可以连接几个旋律。

Hello World

让我们从一个简单的例子开始。每个音阶有 12 个音符,两个音阶有 24 个音符,这足以满足“hello world”。消息文本被视为 BigInteger。空消息是 '0',这是音符的默认排序。

chromatic scale

我决定允许 42 个不同的字符:a-z 0-9 .:() 和空格。使用这个字母表,“hello world”的数字表示如下计算:

h =  7        w = 22
e =  4        o = 14
l = 11        r = 17
l = 11        l = 11
o = 14        d =  3
------------------------
   7 * (42^10)   h
+  4 * (42^9)    e
+ 11 * (42^8)    l
+ 11 * (42^7)    l
+ 14 * (42^6)    o

+ 36 * (42^5)    [space]

+ 22 * (42^4)    w
+ 14 * (42^3)    o
+ 17 * (42^2)    r
+ 11 * (42^1)    l
+  3 * (42^0)    d
------------------------
= 121297199112622725

这个数字可以被馈送到 前面解释过的 算法中,以半音阶作为载体列表。(非音乐家的提醒:C C# D D# E F F# G G# A H B c c# d d# e f f# g g# a h b。)

结果如下:

mixed up notes

d d# D e f A G# f# F H g F# C# E g# c# B a G D# c C h b

字母更少,单词更多

最大数字消息(因此文本消息的长度)受 Factorial(countNotes) 的限制。要编码更多文本,我们可以使用更多音符,或者保持数字值更小。在上面的例子中,基数 42 产生了非常高的值。如果您将字符限制为 a-z 和空格,则基数为 27,“hello world”的值仅为 1474967912327400。这意味着,我们可以将更长的文本存储在相同长度的旋律中。

   7 * (27^10)   h        + 22 * (27^4)    w
+  4 * (27^9)    e        + 14 * (27^3)    o
+ 11 * (27^8)    l        + 17 * (27^2)    r
+ 11 * (27^7)    l        + 11 * (27^1)    l
+ 14 * (27^6)    o        +  3 * (27^0)    d
+ 36 * (27^5)    [space]
---------------------------------------------------
= 1474967912327400

节奏 - 纯属娱乐

一连串普通的四分音符听起来可能很无聊。但一旦音符排序完毕,您就可以在任何地方插入重复项。所有重复项将在解码前被删除。由于时间并不重要(至少在这个原型中),您可以随意将四分音符拆分为八分音符。这些都不会影响编码的消息。以下是“coding in c sharp”的几个版本(对于 27 个字符的字母表,该数字为 201255931456816565832252)。

  • 文本:“coding in c sharp”
  • 音阶:从 A 开始
  • 旋律:f e c# b g a G h F# H g# G# A D c f# E F C d C# B d# D#

  • 文本:“coding in c sharp”
  • 音阶:从 D 开始
  • 旋律:H A F# e c d C d# b D# c# C# D g F B a h f G f# E G# g#

  • 文本:“coding in c sharp”
  • 音阶:从 F 开始
  • 旋律:c# c A g d# f D# f# D F# e E F h G# d C C# g# H a G B b

  • 文本:“coding in c sharp”
  • 音阶:从 G 开始
  • 旋律:dis d B a f g F gis E Gis fis Fis G C H e D Dis h c b A cis Cis

演示应用程序

该演示应用程序让您通过四个步骤将文本编码为音乐:

  1. 选择半音阶的偏移量(为将来的使用命名为调性)。
  2. 选择一个字母表。所选字符显示在标题栏中。
  3. 输入您的消息。
  4. 混合您的旋律。如果结果不够理想,请勾选“随机旋律”并一次又一次地混合,直到听起来可以接受为止。

当然,您也可以将旋律解码回文本。

  1. 选择用于编码的偏移量。
  2. 选择相同的字母表。
  3. 在结果框中输入音符名称。
  4. 将音符取消混合为纯文本。

该应用程序是为演示而编写的,因此存在一些隐藏功能,不会通过可见按钮或菜单干扰听众。

数字游戏

有些极客问我 pi 的文本含义是什么。在这些情况下,文本和数字字段可以互换:双击“内容数字”字段。然后它将变得可编辑,您输入的数字将被解码为文本。

快速笔记

要保存 TextBox 的内容以备将来使用,请聚焦该框并按 Ctrl+Y。文本将被附加到可执行文件目录中的 clipboard.txt

保存图片

该应用程序同步显示结果作为音符名称和绘制的音符。但由于只有音符名称可以输入并重新解码,因此只能将它们复制到剪贴板。不过,有一种方法可以抓取图片:左键单击 PictureBox。音符将被保存到可执行文件目录中的 PNG 文件。

保存声音

“播放”按钮发出的旋律也可以保存:右键单击 PictureBox。声音将被保存到可执行文件目录中的 WAV 文件。

Mono/Linux 的解决方法

在某些 Mono 版本和音频驱动程序的组合下,Console.Beep 会保持静默。如果您遇到此类问题,请Form1.cs 中定义预编译器变量 IsMono

#define IsMono

代替蜂鸣声,应用程序将把声音保存到临时文件,并让 SoX 播放它。与通常的行为相比,不应有任何可见/可听见的区别。

Outlook(展望)

演示应用程序仅展示了基本思想。也许我会对其进行增强,以将长消息分割成几个旋律部分,确保特定的调性,为给定的旋律添加和声而不是生成随机旋律,等等。作曲家在他们的歌曲中添加秘密内容是没有限制的。

© . All rights reserved.