工作总结 年终总结 实习报告 毕业论文
四项监督制度心得体会 | 学习廉政准则心得体会 | 创先争优 | 警察纪律条令心得体会 | 三查三看
演讲致辞 竞聘演讲 | 会议发言 | 爱国演讲 | 就职演说 | 开业开幕 汇报体会 心得体会 | 企业文化 | 思想学习 | 征文演讲 | 经验材料 | 演讲稿 |调查报告
报告总结 工作总结 | 述职报告 | 调研报告 | 计划规划 | 工作汇报 公文处理 申报材料 | 企划文案 | 规则方案 | 技巧经验 | 模板范例 | 和谐社会| 晚会文艺
领导讲话 思想宣传 | 经济工作 | 工作报告 | 组织人事 | 反腐倡廉 党建工会 慰问贺电 | 事迹材料 | 思想汇报 | 入党相关 | 党会发言 | 个人简历| 实习报告 | 入党思想汇报
房地产范文 可研评估报告| 项目建议书| 设计文件| 招投标文件| 造价预算 计划书 商业计划书 | 策划书 | 合同文件| 企划方案 | 工程质量 | 党性分析| 入党申请书
|免费论文 | 证券金融 | 经 济 学 | 会计 / 审计 | 工商经济管理 | 财政税收 | 财务管理 | 公共管理 | 管 理 学 | 文 化 | 艺 术 学 | 社 会 学 | 教 育 学 | 工 科 | 理 科 | 计 算 机 | 文 学 | 哲 学 | 政 治 | 医 学 | 法学 / 法律 | 毕业论文格式 | 毕业论文范文 |
您现在的位置: 工作总结--范文网 >> 论文 >> 计算机论文 >> 计算机应用 >> 正文

在DOS下的DSP播音的编程

关键字:在DOS下的DSP播音的编程

 
作者:佚名    范文来源:本站原创    点击数:    更新时间:2010-6-1

在DOS下的DSP播音的编程

摘要 该文介绍了DSP编程的基本原则和方法,并给出程序实例帮助理解,读者可以此为基础来拓展、生成自己的实用程序。
在DOS下编程,将声音转化为数据记录下来,或将数据转化为声音,通过声卡上配置的喇叭回放出来,是一项很有实用价值和开发魅力的技术。时下流行的声卡,如Sound Blaster Pro及其兼容卡,都配有数字声音处理器DSP芯片(Digital Sound Processor),专门用于对声音进行数字记录及回放,是声音数字处理的基础硬件。而WAV文件、VOC文件等,则都是这些数据记载的具体形式。Creative公司为了方便用户,提供了一组CT-Voice驱动程序,专门针对VOC文件,作为开发利用DSP功能的软接口,使用比较方便。但是,也造成了某些限制。对于开发者而言,直接对DSP硬件编程,实现其功能,也许是更有吸引力的。
声音,无论是从扬声器输出的,还是从话筒输入的,都是模拟量。
而数据,无论是内存里操作的,还是磁盘上存储的都是数字量。因此,微机处理声音,大多离不开ADC与DAC两种转换。由于声音数据的数据量比较大,在声音的数字处理中,除直接由CPU进行传输外,批量数据常采用DMA方式传输,以节省较多的CPU时间。
总括起来,ADC与DAC两种转换方式,直接传输和DMA传输这两种传输方式,再加上不同的压缩方式,如喇叭控制、静寂等等,所有这些的不同组合,就构成了DSP的各种功能。根据DSP的硬件原理,其各种功能都规定了一定的操作步骤。

一、DSP编程要点
在DSP编程中,主要注意命令与端口两个层次的操作。

1.DSP命令。DSP的功能一般以一个操作码(称作命令号)的写操作为中心,按规定的步骤,配合若干必要的辅助操作,构成一串操作的组合,称为DSP命令。如8位直接播放功能命令号为10h,8位直接录音功能命令号为20h,喇叭的通断功能命令号分别为d1h与d3h等等。

2.端口操作。DSP命令主要靠端口操作来实现。端口操作包括DSP初始化、写DSP命令(即发DSP命令)、读DSP状态参数、DSP中断等。所涉及的端口地址及相应的用途如表1。
表1 DSP端口及用途
端口地址由基址2x0h加6、0ah、0ch、0eh等形成,其中,x可取值1、2、3、4、5、6等,具体情况随硬件设置而定,多数卡在出厂被默认设置为2,即基址为220h。通过跳线,可改变此值,避免与其它设备口地址冲突。

二、编程实例
DSP的功能是比较丰富的,限于篇幅,本文只简要介绍其中的8位直接播放功能,由此举一反三,其它功能的用法不难得知。各功能的规定操作可参考文献1和2。

1.命令操作步骤。8位直接播放功能的操作步骤如下:
·写命令号10h;
·写数据字节(即播放声音的8位数据);
·按采样率所需时间周期延时。
以此三步操作为循环体,进行n次循环,即完成播放。其中,n为声音数据字节数。

2.2xch端口写操作。在DSP编程中,无论是发送命令,还是发送数据,都是通过写端口2xch来完成的。在写端口2xch之前,应先读此端口,直到所得值的bit7为0,这才表明此端口处于可写状态,才能进行写操作。此过程的c语言形式如下:
while (inportb(0x22c)&0x80);
outportb(0x22c,byte);
这里假定端口基址为220h。句中byte可以是命令号,也可以是数据。

3.定时器。为使播放按一定的采样率进行,需对数据发送进行定时控制。这一般是借用主机定时中断int8,将其调用频率提高到与采样率相当的程度,利用其监视、控制数据发送的时间,来满足播音频率的要求。关于定时中断的编程技术已有过许多介绍,限于篇幅,不再赘述,读读文后的程序清单,即一目了然。应该说明的是,对于CPU较慢的机型如386,由于计时代码本身的执行时间可能已经超过采样率对应的时间周期,定时控制就达不到预期的效果。这种情况下,用一个空循环来定时,调整循环次数,即可满足频率要求。此法的缺点是定时精度差,参数因CPU速度而异。所幸的是,目前多数配置多媒体的PC机,其CPU都在486以上。

 


4.内存利用。人耳可辨声音的最高频率可达20kHz以上,因此DSP的采样率至少也要达到与此相当的水平,而为了容纳立体声双声道信息,采样率还要再翻一倍。常见的WAV声音的采样率有44100、22050、11025等。在这么高的采样率下,声音的数据量自然很大,如44k采样率下,20秒的录音数据长达800多k。为在DOS常规内存内处理这种规模的数据,实例程序采取了分块处理的方式,将数据分成以当前剩余自由内存大小为单位的块,将其逐次读入,逐次处理。同时,由于C语言的read()函数每次读操作的字节数最多不过64k-1,因此,每一个分块又需分
若干次读入。实例表明,经此法处理的播放程序不受WAV文件长度的限制,笔者在Windows下录制的长达5M多的WAV文件(11k采样率,约8分钟)也照播不误。

5.声音文件。本文提供的程序实例其声音数据取自WAV文件,其实,对于VOC文件,本播放技术也一样适用,只不过数据的读取格式有所不同而已。关于WAV文件的格式,可参考文献3,VOC文件的格式参考献1和2。
实例程序用Borland C++ 3.1编译,在配置OPTI 386主板、海洋48
6主板及多种与SoundBlaster Pro兼容声卡的兼容机上运行通过。

三、源程序清单
#include
#include
#include
#include
#include
#include
#include
#include
#include"timer.h"
#define n1 20
#define n2 100
struct WavHead
{
char riff[4];
long size0;
char wavefmt[8];
long size1;
int fmttag;
int channel;
long samplespersec;
long bytespersec;
int blockalign;
int bitspersample;
char flg[4];
}whead;
unsigned Port=0x210;
char Found=0;
unsigned cnt1,cnt2;
void PortReset();
void outwave(un

signed char huge *,long);
void WritePortC(unsigned char);
void errexit(char *);
void main()
{

int fp;

unsigned n,r,nn,i,j;
char name[32];
long fermem,rr,datasize;
unsigned char huge *data,huge *p;
if(argc<2)errexit("miss file name\n");
strcpy(name,argv[1]);strcat(name,".wav");
fp=-open(name,0-RDONLY);if(fp=-1)errexit("Error open fil
e\n");
-read(fp,&whead,sizeof(WavHead));
if(whead.blockalign=1 && strncmp(whead.flg,"data",4)==0)
{
-read(fp,&datasize,4);//单声道WAV数据
}
else if(whead.blockalign=2 && strncmp(whead.flg,"fact"
,4)==0)
{
lseek(fp,12l,1);
-read(fp,&datasize,4);//双声道WAV数据
}
else errexit("Error file struct\n");
farmem=farcoreleft();
PortReset();//初始化DSP端口
Counter=0;//开始计时
SetTimer(NewTimer,44100);//调整时间中断频率
WritePortC(0xd1);//接通喇叭
if(farmem≥datasize)//数据量不超过内存容量
{
p=data=(unsigned char huge *)farmalloc(datasize);
n=datasize/32768;r=datasize%32768;
for(i=0;i-read(fp,p,r);
outwave(data,datasize);
}
else//数据量超过内存容量
{
nn=datasize/farmem;//分块操作的块数
rr=datasize%farmem;//最后一块的大小
n=farmem/32768;//每块read次数
r=farmem%32768;//read余零尾数
data=(unsigned char huge *)farmalloc(farmem);
for(i=0;i{
p=data;
for(j=0;j-read(fp,p,r);
//读入内存
outwave(data,farmem);//发送声音数据
}
p=data;
n=rr/32768;r=rr%32768;//最后块的操作
for(i=0;i-read(fp,p,r);
//读入
outwave(data,rr);//发送
}
WritePortC(0xd3);//断开喇叭
RestoreTimer();//恢复时间中断
farfree(data);
-close(fp);
}
void PortReset()//初始化DSP端口
{
cnt1=n1;

 


while(Port≤0x260)&&!Found)
{//测端口基址
outportb(Port+6,1);
outportb(Port+6,0);
cnt2=n2;
while(cnt2>2 && inportb(Port+0xe)<128)--cnt2;
if(cnt2=0||inportb(Port+0xa)!=oxaa)
{
--cnt1;
if(cnt1==0)
{
cnt1=n1;
Port=Port+0x10;
}
}
else Found=1;//找到基址
}
if(!Found)errexit("Reset failed\n");//找不到基址
}
void outwave(unsigned char huge *p,long len)
{//发送声音数据
long i;
int smpl;
smpl=44100/whead.samplespersec/whead.blockalign;
//采样周期系数
for(i=0;i{
WritePortC(0x10);//发送命令
WritePortC(p[i]);//发送数据
while(Counter}
}
void WritePortC(unsigned char v)
{
while(inportb(Port+0xc)&0x80);//等待写有效状态
outportb(Port+0xc,v);//写端口(发送)
}
void errexit(char *msg)
{
-AX=3;
asm int 10h
printf(msg);
exit(0);
}
//Timer.h
#includ
#define OldTimerInt 0x60
unsigned long Counter;
unsigned CounterInt8,fpI8;
void SetTimer(void interrupt(*Rout)(…),unsigned freq)
{//设置新频率的定时中断
int ICnt;
fpI8=(freq+9)/18;//新旧频率的倍数
asm cli
ICnt=1193180/freq;
outportb(0x43,0x36);
outportb(0x40,ICnt & 255);
outportb(0x40,ICnt》8);
setvect(OldTimerInt,getvect(

8));//保存旧定时中断
setvect(8,rout);//置新的定时中断
sam sti;
}
void RestoreTimer()
{
asm cli
outportb(0x43,0x36);
outportb(0x40,0);
outportb(0x40,0);
setvect(8,getvect(OldTimerInt));//恢复原定时中断
asm sti
}
void interrupt NewTimer(…)
{//新定时中断
REGPACK R;
Counter++;//给应用程序提供新频率的计数
if(--CounterInt8=0)
{
intr(OldTimerInt,&R);//按原频率走动时钟
CounterInt8=fpI8;//用新旧频率的倍数分频
}
else outportb(0x20,0x20);//退出中断
}


 

本站所有内容均来源于互联网和会员交流,仅供用户免费测试使用,著作权、版权归原著作权、版权人所有。如果您认为我们的某些文章侵犯了您的权利,请您来信通知我们,我们将尽快删除。
范文录入:wangtong    责任编辑:wangtong 
  • 上一篇范文:

  • 下一篇范文: 没有了
  • 七一 端午 圣诞 艾滋 老人 重阳 国庆 中秋 教师 八一 父亲 儿童
    母亲 护士 青年 劳动 清明 植树 妇女 元宵 春节 元旦 部长 站长
    秘书 队长 所长 馆长 团委 编辑 营销 干部 市委 业务 助理 工人
    省长 警察 护士 医生 律师 院长 行长 社长 店长 厂长 学生 班长
    校长 经理 董事 主管 主席 书记 股长 村长 组长 科长 乡长 镇长
    主任 处长 局长 区长 县长 厅长 市长 民警 整改 和谐 先进 安全
    文明 驻村 扶贫 招商 审计 统计 保先 创新 旅游 稽查 城管 城建
    消防 燃气 民营 县域 经济 科技 药品 医院 卫生 烟草 农业 林业
    残联 档案 保密 房产 国土 机关 药监 妇联 财务 综治 普法 廉政
    人事 组工 会计 财政 水利 行政 广电 电力 工厂 酒店 乡镇 学校
    社区 石油 煤矿 公司 宣传 工会 银行 税务 工商 邮政 电信 通信
    交通 公路 公安 司法 政协 人大 计生 检察 信访 教育 党委 党建
    安监
    新农村 读后感 收费站 大学生 开发区 幼儿园
    青少年 办公室 信用社 工程师 班主任 公务员 供销社
     
    热门推荐
    普通范文 网吧的组建及相关技术
    普通范文 网上购物之路--浅析购物网站的经营要素
    普通范文 网络技术在分布式测试系统上的应用
    普通范文 关于IT渠道扁平化的研究
    普通范文 VB中创建超长时间计时器对象
    普通范文 电子商务的经济分析
    普通范文 IT增值渠道(VAC)发展研究
    普通范文 基于WWW的协同式CAI软件的Java实现
    普通范文 基于ASP技术开发Web数据库检索程序
    普通范文 图书馆管理系统
    普通范文 Windows NT中的登记项及其完整性
    普通范文 微机UNIX直接视频图形程序设计
    普通范文 数据加密技术
    普通范文 详解加密技术概念、加密方法以及应用
    普通范文 信息技术对高校图书馆工作的影响
    普通范文 知识管理、电子商务与商务模式
    普通范文 基于Client/Server 的课件系统的设计与实现
    普通范文 基于WWW的协同式CAI软件的Java实现
    普通范文 VB中创建超长时间计时器对象
    普通范文 脉冲功率装置能源计算机控制技术
    普通范文 基层金融机构加强计算机管理的探索
    普通范文 实时性远程答疑系统
    普通范文 在DOS下的DSP播音的编程
    | 设为首页 | 加入收藏 | 联系我们 | 友情链接 | 版权申明 |
    京ICP备05019101号 北京市通信管理局
    Copyright ? 2000-2010 范文在线网 www.fanwen114.com -- 北京奇迹创业科技发展有限公司
    联系地址:北京市朝阳区南湖南路15号院(金隅丽港城)1号楼0905室 邮政编码:100102
    本站所有内容均来源于互联网和会员交流,仅供用户免费测试使用,著作权、版权归原著作权、版权人所有。
    如果您认为我们的某些文章侵犯了您的权利,请您来信通知我们,我们将尽快删除。
    caohaijun77#126.com(如发邮件请将"#"改为"@")