掌上游戏机开发指南GBA探索日记(8)(转)

掌上游戏机开发指南GBA探索日记(8)(转)[@more@]

  有了前几篇关于中断和Timer,DMA传输的介绍后,现在我们可以进入GBA声音播放的部分了.GBA一共有6个声道,从Sound 1-4加上两个Direct Sound A(and)B.GBA中对声音的播放应该是最困难的部分.至少我是这么认为,因为这里面涉及到太多的技术细节.所以我在这里只能告诉大家怎么在GBA中播放声音,至于内部的细节,我就无可奉告了.

  

  如果你手上有任天堂的官方开发包AgbLib3.0,那么看看AgbLib3.0中有关声音的播放部分.任天堂公司在官方开发包里提供了个mediaPlayer2000来实现GBA声音的播放.那个mediaPlayer2000是个十分复杂的东西,需要配置很复杂的ini配置文件.光是看配置ini文件的帮助文件都够我们看几天了.为此,在官方开发包里面还专门附加了mediaPlyaer2000的帮助部分.不过最大的问题是,它的mediaPlayer2000播放声音的库文件无法在一般的GCC下在编译.或许是我所得到的官方开发包不完整(只有个AgbLib,GCC是另外自己搭配的),总之,那个mediaPlayer2000是不能用了.

  

  前面的<>都是以官方开发包为基础而写的,内容是十分贴近AgbLib.但是这一节由于官方开发包里的mediaPlayer2000无法使用,所以我们就必须另开辟一条道路来走了.还好,这条路我已经走通了,大家也可以顺着这个方向前进.

  

  这一部分关于声音播放的内容你也可以跳过前面的理论讲解.在后面我会直接把所有的声音播放的代码完整得公布在下一篇的探索日记中.如果你觉得麻烦,也可以直接看后面怎么使用这些播放库函数就可以了.

  

  我们首先看看这张有关声道的内部结构图:

  
  2005.1.5.17.59.46.1.gif

  这里我们看到,Sound 1-4跟Direct Sound A和B有着不同的播放渠道.Direct Sound播放是需要通过DMA实现声音数据的传输.而传输速度就必须由Timer来控制.这也就是为什么我要在前面几节讲解DMA和Timer了.

  

  我们这里主要看Direct Sound的声音播放.因为它的功能是最强大的.而Sound 1-4各个播放的声音数据都不同,而且使用起来很复杂,所以这里不讲了,如果你有兴趣,可以参考官方开发包.

  

  Direct Sounds A and B 播放的是8位线性的音频数据

  

  它们的数据入口就是两个寄存器SGFIFOA(B)_L和SGFIFOA(B)_H

  
  2005.1.5.17.59.56.2.gif

  每个Direct Sound一次可以接受4个字节的数据.

  

  然后我们看看声音播放的控制寄存器

  
2005.1.5.18.0.5.3.gif

  很复杂吧.其实我已经不只一次地给出这样的寄存器图表了.这些图片都是官方开发包里面的.它的说明都是很齐全的.不过我还是要说几句.

  

  Direct Sound的播放一定要和Timer0或者1,DMA联系在一起.其中

  

  Timer Selection for Direct Sound A或者B

  

  就是指定该Direct Sound所使用的Timer了.而Timer只能是Timer 1或者Timer 0.

  

  Output of Direct Sound A或者B

  

  是选择每个Direct Sound左右声道的使用.其实这个选择没有多大用处.我试过,无论你选哪个,在GBA上播放的效果都差不多.所以我们一般都是把每个Direct Sound左右声道都开起.

  

  Direct Sound FIFO A(B) Clear and Sequencer Reset

  

  一般是初始化Direct Sound时候使用.FIFO是指先进先出接口.

  

  下面让我们来做个实例来看看具体要做的步骤.

  

  首先,我们要有个转换工具wav2gbac.exe. 它可以把我们电脑上的*.wav文件转换成一个*.h头文件.但是得注意,你的*.wav文件最好是8位音频,因为GBA上的Direct Sound只能播放8位的音频.即使8位以上的wav文件,但是播放出来还是只有8位的效果.

  

  wav2gbac.exe这个工具可以在www.gbadev.org上下载.是个DOS下的程序.

  

  我们在dos提示符下输入:

  

  wav2gbac xxx.wav xxx.h

  

  这样它就把xxx.wav音频数据转换到xxx.h里的一个大数组里了.

  

  好了,我们已经得到转换后的音频数据.下面我们来看看如何写我们的声音播放函数.

  

  void PlayDirectSoundA(u8 *sound, u16 sampleRate, u32 length)

  

  {

  

  //Stop any previous sample

  

  *(vu16 *)REG_TM0CNT_H = 0;

  

  *(vu16 *)REG_TM0CNT_L = 0;

  

  *(vu32 *)REG_DMA1SAD = 0;

  

  *(vu16 *)REG_DMA1CNT_H = 0;

  

  *(vu32 *)REG_DMA1DAD = 0;

  

  //Output DirectSound A to right channel

  

  *(vu16 *)REG_SOUNDCNT_H |= DSOUND_A_RIGHT_CHANNEL| DSOUND_A_TIMER_0 | DSOUND_A_LEFT_CHANNEL | DSOUND_A_FIFO_RESET | DSOUND_A_OUTPUT_FULL;

  

  //Enable all sound

  

  *(vu16 *)REG_SOUNDCNT_X |= SOUND_MASTER_ENABLE;

  

  //DMA1 Source Addresss

  

  *(vu32 *)REG_DMA1SAD = (u32)sound;

  

  //DMA1 Destination Address (REG_SGFIFOA)

  

  *(vu32 *)REG_DMA1DAD = 0x40000A0;

  

  //Write 32 bits into 0x040000A0 (REG_SGFIF0A) every VSync

  

  *(vu32 *)REG_DMA1CNT = DMA_DEST_FIXED | DMA_REPEATE | DMA_32 | DMA_TIMEING_SYNC_TO_DISPLAY | DMA_ENABLE;

  

  //Sample Rate

  

  *(vu16 *)REG_TM0CNT_L = 65536 - (16777216/sampleRate);

  

  //Enable the timer

  

  *(vu16 *)REG_TM0CNT_H = TIMER_ENABLE | TIMER_IRQ;

  

  }

  

  这是个播放Direct Sound A声道的播放函数.

  

  首先我们来看函数的参数,u8 *sound,u16 sampleRate,u32 length这些都是我们的声音转换工具wav2gbac.exe自动创建了的.你只要简单地把声音文件xxx.h的参数传递过来就可以了.

  

  在播放声音之前,我们得先重至一次所需要的一切资源.这就是下面的代码完成的功能:

  

  //Stop any previous sample

  

  *(vu16 *)REG_TM0CNT_H = 0;

  

  *(vu16 *)REG_TM0CNT_L = 0;

  

  *(vu32 *)REG_DMA1SAD = 0;

  

  *(vu16 *)REG_DMA1CNT_H = 0;

  

  *(vu32 *)REG_DMA1DAD = 0;

  

  我使用了Timer0,DMA1作为我们播放Direct Sound A的辅助工具.这里的Timer,DMA都是可以自己选择的.但是需要注意的是Timer只能是Timer0或者Timer1,DMA也只能是DMA1或者DMA2.我们一般让Timer0,DMA1作为Direct Sound A的辅助控制,Timer1,DMA2作为Direct Sound B的辅助控制.

  

  //Output DirectSound A to right channel

  

  *(vu16 *)REG_SOUNDCNT_H |= DSOUND_A_RIGHT_CHANNEL| DSOUND_A_TIMER_0 | DSOUND_A_LEFT_CHANNEL | DSOUND_A_FIFO_RESET | DSOUND_A_OUTPUT_FULL;

  

  这是设置前面已经讲到的声音播放的控制寄存器.你可以根据前面的图表来自己设置.不过一般我们都使用上面代码的设置.如果你搞不清楚,在后面我会把完整的Direct Sound库函数给出来.下面是上面使用到的参数定义(其实就是C语言中的宏)

  

  #define BIT00 1

  

  #define BIT01 2

  

  #define BIT02 4

  

  #define BIT03 8

  

  #define BIT04 16

  

  #define BIT05 32

  

  #define BIT06 64

  

  #define BIT07 128

  

  #define BIT08 256

  

  #define BIT09 512

  

  #define BIT10 1024

  

  #define BIT11 2048

  

  #define BIT12 4096

  

  #define BIT13 8192

  

  #define BIT14 16384

  

  #define BIT15 32768

  

  //SGCNT0_H

  

  #define SOUND_OUTPUT_1_4                     0

  

  #define SOUND_OUTPUT_1_2                     BIT00

  

  #define SOUND_OUTPUT_FULL                    BIT01

  

  #define DSOUND_A_OUTPUT_HALF                 0

  

  #define DSOUND_A_OUTPUT_FULL                 BIT02

  

  #define DSOUND_B_OUTPUT_HALF                 0

  

  #define DSOUND_B_OUTPUT_FULL                 BIT03

  

  #define DSOUND_A_RIGHT_CHANNEL               BIT08

  

  #define DSOUND_A_LEFT_CHANNEL                BIT09

  

  #define DSOUND_A_TIMER_0                     0

  

  #define DSOUND_A_TIMER_1                     BIT10

  

  #define DSOUND_A_FIFO_RESET                        BIT11

  

  #define DSOUND_B_RIGHT_CHANNEL                BIT12

  

  #define DSOUND_B_LEFT_CHANNEL                 BIT13

  

  #define DSOUND_B_TIMER_0                     0

  

  #define DSOUND_B_TIMER_1                     BIT14

  

  #define DSOUND_B_FIFO_RESET                   BIT15

  

  接下来,我们开起声音播放的总开关

  

  #define SOUND_MASTER_ENABLE 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/8225414/viewspace-951681/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/8225414/viewspace-951681/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值