前几天上微博的时候发现了个牛人主页http://bellard.org/ ,此牛人编写的软件耳熟能详,比如FFmpeg、TCC、Qemu等等,还有前一段时间在网络上非常流行,javascript实现的一个虚拟机,可以在浏览器中启动一个linux。这个linux中也带了此牛人自己写的tcc,所以简单的编译程序也不成问题。

来到这个主页,有一行非常显眼

... A PC emulator in Javascript: how much time takes your browser to boot Linux ?

2700 billion decimal digits of Pi computed with a desktop computer.

Analog and Digital TV (DVB-T) signal generation by displaying an image on a PC display. ...

模拟与数字电视信号产生...是用PC的VGA输出产生一个可以被电视识别并显示的信号。看到这个的第一眼并没有感觉到这有什么特别的,因为VGA原本就是用来输出视频信号的嘛。但是继续往下看,就发现了事情和原本认为的不一样。

  • A DVB-T set-top box able to receive VHF signals with a bandwidth of 8 MHz (unfortunately most decoders sold in UK only receive UHF signals). You can use French DVB-T receivers which accept VHF and UHF RF signals.

  • A PC with a recent VGA card able to display in resolutions up to 4096x2048 with 8 bit per pixel with a pixel clock of exactly 76.5 MHz. ATI Radeon 9200SE are reported to work (their PLL can generate every frequency which is a multiple of 2.25 MHz up to 400 MHz). Other VGA cards may work too. If your card cannot generate a 76.5 MHz pixel clock, I can provide alternate images to do some testing.

  • A cable connecting the VGA output to the set-top box RF input. It is possible to use antennas, but since the transmit power is very low, it is better to begin with a cable connection.

15 pin VGA connector 9.5mm RF connector

------------------- -----------------------

1 (red signal) <-----> RF signal (central pin)

6 (red ground) <-----> GND

这分明是用VGA产生任意信号嘛!

为了了解情况,我去Wiki搜索了一下VGA,发现这种15-pin的VGA端口包括了这么几种端子,接地线、红绿蓝信号、同步信号还有就是一个I²C的ID bit。其中的红绿蓝信号是模拟信号输出,也就是说,屏幕上的一个像素点会在一次扫描周期中,以RS-343标准定义的电压范围在相应三个颜色端子进行输出。

以我的笔记本为例,我的windows系统可以在“Windows移动中心”里设置,把液晶屏上的内容复制给VGA输出。我设置的分辨率是1366×768,刷新率为60Hz。这样,每一帧屏幕内容都在VGA输出端口上形成一个1366×768次采样的波形,如果可以每秒切换60次以上的屏幕内容,就可以在VGA的输出得到预设的波形。

简单计算一下,按照我现在的屏幕设置,1366×768×60=62,945,280SPS。可以设置的最大输出,2048×1536×75=235,929,600SPS,这个频率已经足够做短波广播了。

我从最简单的情况入手,尝试输出一个1K左右的正弦信号。在宿舍做这些东西很悲催啊!没有示波器,只好先用最简单的方法来测试。音频信号比较方便,只需要拿来一副普通耳机就OK了。整个过程很顺利,生成一幅图片,并全屏显示就顺利的听到了声音。不过有一点很不爽的是,在声音中一直都有很大的噗噗声,黑屏与白屏的情况也有,也许是VGA的特殊时序吧!

既然声音已经听到了,那么不妨用VGA的颜色分量来输出一首歌?Challenge accepted!

要做到这一步并没有太难逾越的技术难题,主要就是在快速生成一幅图片并显示。60fps的更新频率,单纯使用GDI的方式显示不太靠谱。更何况,生成能听的音频也需要保证“声音”和屏幕刷新输出是同步的。普通的显示方法不够用了,只好拿来OpenGL。

OpenGL和DirectX在win中都可以用,考虑到以后点OpenGL科技树的概率要大得多,还是用OpenGL了,顺便熟悉一下。

下载好glut,.dll、.h、.lib分别就位之后就可以继续下一步。首先就是生成一个全屏窗体,启用双缓冲(需要用到双缓冲和SwapBuffers实现垂直同步)。这段代码较长且没什么内容,就略去了。

pos=0;
fp=fopen("c:\\a.wav","rb");
fseek(fp, 0, SEEK_END);
flen=ftell(fp);
fseek(fp, 0, SEEK_SET );
filep=(char *)malloc(flen*sizeof(char));
fread(filep,sizeof(char),flen,fp);
fclose(fp);
content=(char*)malloc(1366*768*4);

这一段代码不需要注释,其中的a.wav是用软件转换出来的8位单声道无压缩的wav文件,不考虑文件头几十字节的“噪音”数据,直接读取输出这个文件本身即可。我用到的音频采样率是44100,文件头相比来说小的过头了。

然后就是处理输出。我没有用glut自己的那个主循环,不够灵活。代码结构是这样:

while(1)
{//TODO: 处理消息//TODO: 填充一帧数据glDrawPixels(...);SwapBuffers(hDC);
}

这里的代码也比较简单,google了很多网页,貌似SwapBuffers可以实现垂直同步。后来的实验这里也没有出现问题。

声音每秒有44100个采样数据,而VGA每秒有62945280个采样数据,所以62945280/44100约1427个像素点取相同的DAC数值。我没有只给某个单色赋值,红绿蓝三色取了相同的数值,alpha通道取最大值255,很简单的循环就完成了数据填充。

for (i=0;i<1366*768;i++)
{if (pos<flen)t=filep[pos];else{t=0;    //读到数据结尾则从开头开始读pos=0;}content[4*i]=t;content[4*i+1]=t;content[4*i+2]=t;content[4*i+3]=255;if(tmp>1427)    //1427点取相同DAC数值{pos++;tmp=0;}tmp++;
}

这里的代码速度可以优化,VS2010的编译器优化已经足够,所以就没有再继续。

编译运行,听到了音乐声,Challenge Passed!

利用VGA输出音频信号相关推荐

  1. php编程输出心形图案_利用php输出不同的心形图案,php心形图案_PHP教程

    利用php输出不同的心形图案,php心形图案 首先为大家分享php输出心形曲线的代码,代码如下 效果如下: 利用php输出笛卡尔心形图案,代码如下 复制代码 代码如下:$width = 600; $h ...

  2. php 实现心芯图案,利用php输出不同的心形图案

    首先为大家分享php输出心形曲线的代码,代码如下 效果如下: 利用php输出笛卡尔心形图案,代码如下 复制代码 代码如下: $width = 600; $height = 650; header(&q ...

  3. 成功解决利用pandas输出DataFrame格式数据表时没有最左边的索引编号(我去,这个问题折腾了我半个多小时)

    成功解决利用pandas输出DataFrame格式数据表时没有最左边的索引编号(我去,这个问题折腾了我半个多小时) 导读:首先,关于这个问题,博主想骂街,经过各种查询,没找到类似问题,然后博主自己不断 ...

  4. C语言学习之利用指针输出二维数组任一行任一列元素的值

    利用指针输出二维数组任一行任一列元素的值. int main(){int a[3][4];int i,j,x,y;int (*p)[4];//指针变量p指向包含4个整型元素的一维数组printf(&q ...

  5. 如何利用NLog输出结构化日志,并在Kibana优雅分析日志?

    上文我们演示了使用NLog向ElasticSearch写日志的基本过程(输出的是普通文本日志),今天我们来看下如何向ES输出结构化日志.在Kibana中分析日志. 什么是结构化日志? 当前互联网.物联 ...

  6. 利用循环输出如下图形

    利用循环输出如下图形. [cpp] view plain copy * ** *** **** ***** #include<stdio.h> void main() { int i,j; ...

  7. mips汇编之利用syscall输出结果

    作者:非妃是公主 专栏:<汇编> 个性签:顺境不惰,逆境不馁,以心制境,万事可成.--曾国藩 转载请标明,原文链接:https://blog.csdn.net/myf_666/articl ...

  8. C++:利用printf 输出string

    目录 1. 要点 2. c_str() 1. 要点 在c++中直接利用printf("%s",s) 是不允许的,因此c++中提供了一个函数c_str()对字符串进行转换,接着再利用 ...

  9. ubuntu添加自定义vga输出分辨率

    最近在调试一个视频采集芯片的驱动,主要是接收vga输入和hdmi输入,在实验的过程中遇到了一个恼火的问题,就是同一台电脑(我的联想笔记本y400),在win8的vga输出的1360768分辨率我的采集 ...

  10. 利用STC15输出两路互补SPWM波形

    利用STC15输出两路互补SPWM波形

最新文章

  1. python解释器环境中、用于表示上一次_大工20秋《数据挖掘》在线作业3 【标准答案】...
  2. Android特色开发之Google MAP
  3. 3D CNN框架结构各层计算
  4. AngularJS依赖注入
  5. spring整合springmvc案例
  6. Java工作笔记-@Value注解的使用(可用于配置文件)
  7. 收藏 | 有没有什么可以节省大量时间的 Deep Learning 效率神器?
  8. 统计局:去年12月天然气、电力生产增长较快
  9. 在哪里学python-python的强项在哪里
  10. 【看别人的,学习】文本增强,再也不怕用户要修改标准界面的字段描述了
  11. 机器学习之推荐算法分类
  12. 计算机为什么找不到网络打印机,电脑找不到网络打印机怎么办
  13. php计算距离商家距离,php 计算3公里内所以用户的距离
  14. 2019_WSDM_Session-Based Social Recommendation via Dynamic Graph Attention Networks
  15. ARM DS-5 Development Studio 5.28.1 破解激活教程
  16. php利用七牛云的对象存储完成图片上传-高效管理图片(用php搭建一个自己的图床) nice!!!
  17. 2018乌镇峰会 -- 完美世界萧泓论道互联网与文化交流
  18. 台式电脑 在哪找到计算机名,win7电脑的投屏功能在哪?教你找到!
  19. [2021]Linux下C语言qrencode二维码生成库的基本使用和ARM开发板移植
  20. ID号自动生成,补缺功能

热门文章

  1. Oracle优化新常态 前半生
  2. 小电托——1-1磁路的基本概念和基本定律
  3. Python3 百度图片 美女 下载 爬虫 多线程
  4. 【夏虫语冰】visio2013安装出错,无法打开注册表,错误码1402
  5. 【每周论文阅读-第四周】proposal-level 特征聚合视频目标检测方法01
  6. 计算机图形学--方法篇(凹多边形的识别与判定方法)
  7. 黑马程序员—我的面试,我的学习,我的经历
  8. 物联网毕业设计 单片机智能温控风扇设计与实现
  9. 世界淡水资源占水资源的多少_全球的淡水资源占水资源比例为多少
  10. Linux系统内核升级