「玩一玩」神笔马良——把图形「画」在音频里(译文 Draw Into Sound)

Conmajia 2012-05-09 09:52:40
加精
生活太平淡了!来点让人尖叫的东西吧!

在下闲逛 CP,发现一篇好文,现在把它翻译出来,大家共同研究

(翻译的!不是我编的)

这是意大利人 Angelo Gattuso(evol76)2008 年 12 月 22 日发表的文章。


点击阅读原文

很遗憾,野比到目前为止都还没有联络到作者,所以等翻译完了以后有机会再找他。

-----关于废话的分割线-------



原文是 CPOL 许可的,所以本文也在 CPOL 许可下发布。

我们放弃了所有版权,但仍然具有对作品的著作权,以及作品本身在 CPOL(或其他任何 License)之下所

应享有的法律权益和需要承担的法律义务。所以还希望转载者不要切头切尾,把文章切了 jj 再拿去当自己的发表

呵呵,说的多了。前段时间和老外聊,老外说有个中国朋友看到有他的文章,但署名不是他。老外就把链接

发给我,我一看是我翻译的,但我的名字和原发站都没有。哈哈,就剩「人棍」,那哥们给切的光溜溜的。

其实说真的,我也觉得在中国老外的那些 License 都是防君子的。但好歹也要装一下吧?

哈哈,开玩笑,个人行为,个人负责。


-----下面不是废话了------


老规矩,源码 DEMO


点我下载

[size=16px]----------------

作者 Angelo Gattuso (evol76)




国籍 意大利


Angelo Gattuso(安吉罗·刚图索——译者按)2003 年 11 月毕业于都灵理工大学软件工程专业。

他目前从事软件工程师,开发和策划商业软件。在 ASP.NET 和三层架构软件方面都有涉足。

他喜欢音乐、读书还有烹饪——其实他更喜欢吃。


介绍

本文的点子是「把图形画到声音里去」,尤其是画到声音的频域之中。

声音可以用多种方式表示。通常,可以用「幅度 - 时间」图(波形)和「频率 - 时间」图(频谱)来表示。

下图显示了声音在时域中的幅度波形:





图中,X 轴为时间,Y 轴为声音幅度。第二类音频信号的显示方式是显示其不同的频率组成:





图中,X 轴为时间,Y 轴为频率。浅色(白)代表高该频率成分强度较高,深色(黑)表示强度较低。

可以从图中看到,声音是如何在频率和时间上变化的。


快速傅里叶变换

快速傅里叶变换是将信号(在这里,就是音频信号)变换到其频域的一种操作。

之后,可以看到输入信号的频率组成方式。快速傅里叶变换(FFT)是一种高效计算傅里叶变换的算法。







逆操作(IFFT,逆傅里叶变换)从频域获取数据,输出时域值。我们可以利用该算法将图形画到音频中。

我们将图形作为频域信号的输入,然后应用 IFFT 算法,就可以得到音频的波形用于生成输出的 wave 文件。

程序







图中的黑板是音频信号的「频率 - 时间」图。点击「开始(Start)」按钮左边的方框,

可以改变画笔颜色,然后可以用该种颜色在黑板上绘制图形。

使用较深的颜色(如深灰)可以获得较好的处理结果。

点击「开始(Start)」按钮,利用 IFFT 算法计算数据,并生成输出音频文件。

现在我们画点东西:






我们可以用 Cooledit 之类的程序来查看结果。

(下图显示的是一个 wav 文件的「频率 - 时间」图,而非我们通常见到的波形图——译者按)







代码

程序使用 C# 编写。这里我们用到了 2 个基础库:

·Garrett Hoofman 的
Wave File Library。该库用于产生 wav 输出文件
·任意 IFFT 算法库


using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WaveLibrary;

namespace Img2Wav
{
class Core_Img2Wav
{

private const double MAX_DATA = +50;
private const double MIN_DATA = -50;

private const String NoInputBitmap = "No input bitmap";

public Bitmap InputBitmap { get; set; }
public WaveFile OutputWav { get; set; }

public void Start()
{
int NumSamples = InputBitmap.Width * InputBitmap.Height;
byte[] Samples = new byte[NumSamples];
OutputWav = new WaveFile(1, 16, 44000);
if (InputBitmap == null) throw new Exception(NoInputBitmap);
double[] data = new double[InputBitmap.Height];

int w = 0;
for (int i = 0; i < InputBitmap.Width; i++)
{
for (int j = 0; j < InputBitmap.Height; j++)
{
Color C = InputBitmap.GetPixel(i,j);
data[j] = (C.R + C.G + C.B ) / 3;
}

FFT_Img2Wav.inverse(data);

for (int x = 0; x < data.Length; x++)
{
Samples[w] = (byte)(MAX_DATA * data[x]);
w++;
}
}

OutputWav.SetData(Samples,NumSamples);
}
}
}



许可

本文及相关源代码和文件,适用
The Code Project Open Licen (CPOL)


---------野比的分割线-----------


打完收工。





...全文
2071 71 打赏 收藏 转发到动态 举报
写回复
用AI写文章
71 条回复
切换为时间正序
请发表友善的回复…
发表回复
b8820230 2012-07-23
  • 打赏
  • 举报
回复
大牛
zz997788 2012-07-13
  • 打赏
  • 举报
回复
wavelibrary不可用, (野比)给的地址也不对
ddjdl 2012-07-12
  • 打赏
  • 举报
回复
拜读了。好东西。
落曦 2012-06-15
  • 打赏
  • 举报
回复
差一个东东运行不了。小菜路过
larissa523 2012-06-04
  • 打赏
  • 举报
回复
感谢分享。
  • 打赏
  • 举报
回复
其实一直想做个文件听起来是声音不是噪音,看起来是图片,读起来是文章,运行后还能干点啥事。。。。。重要的是一点也不多余一点也不浪费。但是我越学的多越觉得这不可能。。。。
Conmajia 2012-05-28
  • 打赏
  • 举报
回复
[Quote=引用 63 楼 的回复:]

wavelibrary不可用,谁能发一个上来
[/Quote]

随便找了个,没仔细看http://download.csdn.net/detail/enjoyfan/750384
kxyzjm62 2012-05-20
  • 打赏
  • 举报
回复
wavelibrary不可用,谁能发一个上来
udbsbukh 2012-05-19
  • 打赏
  • 举报
回复
真是有技术的人呀!强,向楼主学习!
Delta 2012-05-19
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

技术啊
[/Quote]来看年地。。。。
dragon_cheng 2012-05-19
  • 打赏
  • 举报
回复
不错的……
dragon_cheng 2012-05-19
  • 打赏
  • 举报
回复
不错的……
baichangle 2012-05-18
  • 打赏
  • 举报
回复
学习了
aby913 2012-05-18
  • 打赏
  • 举报
回复
牛人啊 就是不知道播放出来是什么效果
DonsyMo 2012-05-17
  • 打赏
  • 举报
回复
无所不能
叫我三三 2012-05-16
  • 打赏
  • 举报
回复
太牛X了 ,不知道播放出来效果如何
jhdxwj 2012-05-16
  • 打赏
  • 举报
回复
挺好,顶一个
yrnaaa 2012-05-16
  • 打赏
  • 举报
回复
不错的技术贴啊,顶起来
blackkettle 2012-05-16
  • 打赏
  • 举报
回复
这个有点意思
txzsp 2012-05-16
  • 打赏
  • 举报
回复
数字信号采集。
加载更多回复(39)

110,526

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧