首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ARM9(S3C2440)的IIS——理论知识及程序实例(2)

ARM9(S3C2440)的IIS——理论知识及程序实例(2)

一、综述
   
WAVE文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。
RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个字节便是“RIFF”。
WAVE文件是由若干个Chunk组成的。按照在文件中的出现位置包括:
1、RIFF WAVE Chunk,
2、Format Chunk,
3、Fact Chunk(可选),
4、Data Chunk。
具体见下图:
------------------------------------------------
|            
RIFF WAVE Chunk               |
|            
ID
= 'RIFF'                        
|
|            
RiffType = 'WAVE'               
|
------------------------------------------------
|            
Format Chunk                    
|
|            
ID = 'fmt '                     
    |
------------------------------------------------
|            
Fact Chunk(optional)          |
|            
ID = 'fact'                        
|
------------------------------------------------
|            
Data Chunk                     
|
|            
ID = 'data'                     
   |
------------------------------------------------
   
   
其中除了Fact Chunk外,其他三个Chunk是必须的。每个Chunk有各自的ID,位于Chunk最开始位置,作为标示,而且均为4个字节。并且紧跟在ID后面的是Chunk大
小(去除ID和Size所占的字节数后剩下的其他字节数目),4个字节表示,低字节表示数值低位,高字节表示数值高位。下面具体介绍各个Chunk内容。所有数值表示均为低字节表示低位,高字节表示高位。
二、具体介绍
RIFF WAVE Chunk
   
==================================
   
|      
|所占字节数|
具体内容  
|
   
==================================
   
| ID   
|
4 Bytes |  
'RIFF'   
|
   
----------------------------------
   
| Size
|
4 Bytes |            
|
   
----------------------------------
   
| Type
|
4 Bytes |  
'WAVE'   
|
   
----------------------------------
           
图2
RIFF WAVE Chunk
以'FIFF'作为标示,然后紧跟着为size字段,该size是整个wav文件大小减去ID和Size所占用的字节数,即FileLen - 8 = Size。然后是Type字段,为'WAVE',表示是wav文件。
结构定义如下:
struct RIFF_HEADER
{
  char szRiffID[4];  // 'R','I','F','F'
  DWORD dwRiffSize;
  char szRiffFormat[4]; // 'W','A','V','E'
};
Format Chunk
                                 
字节数        具体内容         
| ID           
|
4 Bytes
|  ‘fmt’
| Size         
|
4 Bytes
| 数值为16或18,18则最后又附加信息   
   
| FormatTag   
|
2 Bytes
| 编码方式,一般为0x000
   
| Channels     
|
2 Bytes
| 声道数目,1--单声道;2--双声道      
   
|SamplesPerSec |
4 Bytes
| 采样频率                  
| AvgBytesPerSec|
4 Bytes
| 每秒所需字节数  ===> WAVE_FORMAT
   | BlockAlign  |
2 Bytes | 数据块对齐单位(每个采样需要的字节数)   
| BitsPerSample |
2 Bytes
| 每个采样需要的bit数     
                     
      |
2 Bytes  
| 附加信息(可选通过Size来判断有无)
              
图3
Format Chunk
以'fmt '作为标示。一般情况下Size为16,此时最后附加信息没有;如果为18则最后多了2个字节的附加信息。主要由一些软件制成的wav格式中含有该2个字节的附加信息。

   
结构定义如下:
struct WAVE_FORMAT
{
  WORD wFormatTag;
  WORD wChannels;
  DWORD dwSamplesPerSec;
  DWORD dwAvgBytesPerSec;
  WORD wBlockAlign;
  WORD wBitsPerSample;
};
struct FMT_BLOCK
{
  char  szFmtID[4]; // 'f','m','t',' '
  DWORD  dwFmtSize;
  WAVE_FORMAT wavFormat;
};

Fact Chunk
   
==================================
   
|      
|所占字节数|
具体内容  
|
   
==================================
   
| ID   
|
4 Bytes |  
'fact'   
|
   
----------------------------------
   
| Size
|
4 Bytes |  
数值为4  
|
   
----------------------------------
   
| data
|
4 Bytes |            
|
   
----------------------------------
           
图4
Fact Chunk
   
Fact Chunk是可选字段,一般当wav文件由某些软件转化而成,则包含该Chunk。
   
结构定义如下:
struct FACT_BLOCK
{
  char  szFactID[4]; // 'f','a','c','t'
  DWORD  dwFactSize;
};

Data Chunk
   
==================================
   
|      
|所占字节数|
具体内容  
|
   
==================================
   
| ID   
|
4 Bytes |  
'data'   
|
   
----------------------------------
   
| Size
|
4 Bytes |            
|
   
----------------------------------
   
| data
|         
|            
|
   
----------------------------------
            
图5 Data Chunk
   
Data Chunk是真正保存wav数据的地方,以'data'作为该Chunk的标示。然后是
数据的大小。紧接着就是wav数据。根据Format Chunk中的声道数以及采样bit数,
wav数据的bit位置可以分成以下几种形式:
|  
单声道
|
取样1  
|   
取样2   
|   
取样3   
|   
取样4     
|
8bit量化 |   
声道0   
|   声道0 |   
声道0   
|   
声道0   

|  
双声道
|   
取样1     
        
|         
取样2
|
8bit量化 |
声道0(左) | 声道1(右) |
声道0(左) |
声道1(右)
   
         
      取样1            
|      
取样2         
|
   
|  
单声道
|
| 16bit量化 |   声道0  |
声道0   
|   
声道0   
|
声道0      
   
          |(低位字节)|(高位字节)
|(低位字节)|(高位字节)
   
                         取样1        
|  
双声道
|------------------------------------------------
   
| 16bit量化 | 声道0(左) | 声道0(左) |
声道1(右)
|
声道1(右)
               
|(低位字节) | (高位字节)
| (低位字节)
| (高位字节)
                        
图6 wav数据bit位置安排方式
   
Data Chunk头结构定义如下:
   
struct DATA_BLOCK
{
  char szDataID[4]; // 'd','a','t','a'
  DWORD dwDataSize;
};
看完上面这些我们应该要清楚在文件的开始地址偏移0x18(24)处是文件的采样频率,0x16(22)处是声道,0x2c(44)处才是真正的wave数据,也就是我们要播放的数据。


下面是UDA1314通过IIS接口的放音程序
#include"2440addr.h"
#include"WindowsXP_Wav.h"
#include"What_are_words.h"
#include"def.h"
//L3接口
#define L3C (1<<4)            
//GPB4 = L3CLOCK
#define L3D (1<<3)            
//GPB3 = L3DATA
#define L3M (1<<2)            
//GPB2 = L3MODE


//L3总线接口的写函数
//输入参数data为要写入的数据
//输入参数address,为1表示地址模式,为0表示数据传输模式
static void WriteL3(U8 data,U8 address)
{
      
int i,j;
      
if(address == 1)
            
rGPBDAT = rGPBDAT & ~(L3D | L3M | L3C) | L3C;      
//L3D=L, L3M=L(地址模式), L3C=H
      
else
            
rGPBDAT = rGPBDAT & ~(L3D | L3M | L3C) | (L3C | L3M);         
//L3M=H(数据传输模式)
      
for(i=0;i<10;i++)
            
;            
//等待一段时间

      
//并行数据转串行数据输出,以低位在前、高位在后的顺序
      
for(i=0;i<8;i++)   
      
{
            
if(data & 0x1)                     
// H
            
{
                    
rGPBDAT &= ~L3C;           
//L3C=L
                    
rGPBDAT |= L3D;               
//L3D=H            
                    
for(j=0;j<5;j++)
;                  
//等待一段时间
                    
rGPBDAT |= L3C;               
//L3C=H
                    
rGPBDAT |= L3D;               
//L3D=H
                    
for(j=0;j<5;j++)
;                  
//等待一段时间
              
}
            
else                     
// L
            
{
                    
rGPBDAT &= ~L3C;           
//L3C=L
                    
rGPBDAT &= ~L3D;           
//L3D=L
                    
for(j=0;j<5;j++)
;                  
//等待一段时间
                    
rGPBDAT |= L3C;               
//L3C=H
                    
rGPBDAT &= ~L3D;           
//L3D=L
                    
for(j=0;j<5;j++)
;                  
//等待一段时间         
            
}
            
data >>= 1;
      
}
      
rGPBDAT = rGPBDAT & ~(L3D | L3M | L3C) | (L3C | L3M);         
//L3M=H,L3C=H
}

继承事业,薪火相传
返回列表