GBA探索日记(9)(声音播放2)

这一节我们讨论如何正常结束声音播放的问题.不要觉得这是个小问题,当初这个小问题难倒了我们所有研究GBA的爱好者.我总觉得这一点似乎是GBA设计上的缺陷,但是最后我们可以通过使用VBlank中断还解决这个问题.本篇结束的时候,我还会给出完整声音播放的代码.这样,你甚至不必了解声音播放的细节就可以实现声音的播放功能了.

 

由于声音播放使用的DMA不能根据WORD COUNT来控制传输的数据量,同时又不能在传输完毕的时候产生DMA中断,所以我们无法知道什么时候DMA把我们的音频数据传输完毕.这样,我们必须自己另外加一计时器,来计算什么时候声音播放结束.当然,你可以使用Timer来做,但是另外再设置个Timer似乎就麻烦了点,而且Timer的精度过高,也不好计算长时间的声音播放.依照官方开发包中的做法,我们就拿VBlank中断作为声音播放的计时器.

 

VBlank中断是在硬件扫描屏幕V方向扫描线的时候产生的硬件中断.它是严格的每秒59.78次(接近60次/s)

 

下面我们来看看这段修改后的播放声音的代码.需要注意拿他和前一节的播放代码来比较一下,看看他们之间有什么不同.

 

这个PlayDirectSoundA的播发函数多了一个参数u32 time.它就是用来控制声音结束的时间参数.它的单位是秒(对于一般的声音播放来说,秒单位应该是足够精确了).

 

soundATime = time * 59.727;

这条代码是将实际播放时间的秒数转换成一共要产生VBlank的中断数.前面说过,我们将使用VBlank来判断我们的声音是否播放结束.而VBlank中断的频率是59.727Hz,也就是说一秒中要产生59.727次.比如说如果我们的这段声音要播放5秒钟,那么播放过程中一共要产生5*59.727次VBlank中断.这样,我们只要使用一个计数器,每次VBlank中断产生的时候计数器自加1,当它等于5*59.727的时候,那么声音也就应该结束了.

 

其它的代码就差不多和前一节的PlayDirectSoundA差不多了.

////////////////////////////////////PlayDirectSoundA/////////////////////////////////////

// time是播发时间,单位是秒数

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

{

       //Stop any previous sample

       soundAPlaying = 0;

    *(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;

 

       //Set sound A's current sound

       soundA = sound;

 

       //Set the length, looping, etc

       soundALength = length;

       // 讲time秒转换成V-Blank中断次数,V-Blank中断是59.727Hz

       soundATime = time * 59.727;

       soundACurrent = 0;

       soundASampleRate = sampleRate;

 

       //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;

 

       //The sound is playing

       soundAPlaying = 1;

}

 

在这里我们增加了一个函数UpdateDirectSoundA.它的作用是判断Direct Sound A是否播放完毕的函数.它的代码很简单.每调用它一次,当前计数器soundACurrent自加1,同时判断是否播放完毕.

/////////////////////////////////////UpdateDirectSoundA////////////////////////////////

void UpdateDirectSoundA(void)

{

      

       // if now is not playing sound A,return

       if(!soundAPlaying)

              return;

       // Increase the Current timer

       soundACurrent +=1;

       // If sound A play time is up,close the sound A

       if(soundACurrent >= soundATime)

              CloseDirectSoundA();

 

}

 

需要注意的是,这个函数的调用必须是放在VBlank中断的响应函数里.比如像下面一样,把它的调用放在Interrupt中处理VBlank的部分里.这样我们才能保证它是每1/59.727秒被调用一次.

关于中断的部分,请看看前面的<<GBA探索日记>>有关中断的部分.

void Interrupts(void)

{     

       u16 Int_Flag;

       REG_IME = 0x00;            // Disable interrupts

       Int_Flag = REG_IF;         // Read the interrupt flags

       if((REG_IF & 1) == 1)

       {

              UpdateDirectSoundA();

       }

       REG_IF = Int_Flag;          // Write back the interrupt flags

       REG_IME = 1;        // Re-Enable interrups

}

 

好了.这个如何控制声音播放结束的问题总算解决了.其实我们也可以使用Timer用同样的原理来控制声音播放的结束,不过至少我觉得Timer的中断产生频率太快,完全没有必要.下面我将把我播放声音的全部代码公布出来,你可以将它拷贝到libsound.c和libsound.h,然后就可以使用了.

 

随便在结束本节之前再说几句,我们关于GBA的基础部分也就结束.但是我们对于GBA开发的探索还没有结束.后面的GBA探索日记将介绍一些实际游戏开发过程中需要的技术,比如汉字显示,Tile模式下写点等问题.不过这些问题就和我们一直走的官方开发包没有关系(无论是日本人还是老美根本不会去考虑汉字显示的问题),但是这些技术在实际开发过程中是很有用的.特别是汉字显示和Tile下写点这两个问题,是很多朋友都在做的,现在应该说是比较成熟的,所以在后面的两篇日记里,我也将它们公布出来,希望对大家有所帮助.

 

 

//*************************************

//   文件名: libsound.h

//   GBA中Direct Sound处理函数或宏

//   tangl_99 创建于2003.2.7

//*************************************

 

#ifndef _SOUND_H

#define _SOUND_H

 

//////////////////////////Necessary Includes/////////////////////////////

 

 

//////////////////////////////Definitions/////////////////////////////////

#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

 

#define TIMER_CASCADE   BIT02

#define TIMER_IRQ       BIT06

#define TIMER_ENABLE    BIT07

#define DMA_ENABLE                              0x80000000

#define DMA_INTERUPT_ENABLE                     0x40000000

#define DMA_TIMEING_IMMEDIATE                   0x00000000

#define DMA_TIMEING_VBLANK                      0x10000000

#define DMA_TIMEING_HBLANK                      0x20000000

#define DMA_TIMEING_SYNC_TO_DISPLAY             0x30000000

#define DMA_16                                  0x00000000

#define DMA_32                                  0x04000000

#define DMA_REPEATE                             0x02000000

#define DMA_SOURCE_INCREMENT                    0x00000000

#define DMA_SOURCE_DECREMENT                    0x00800000

#define DMA_SOURCE_FIXED                        0x01000000

#define DMA_DEST_INCREMENT                      0x00000000

#define DMA_DEST_DECREMENT                      0x00200000

#define DMA_DEST_FIXED                          0x00400000

#define DMA_DEST_RELOAD                         0x00600000

 

#define RIGHT_VOLUME(n)                                 n

#define LEFT_VOLUME(n)                                  n<<4

#define SOUND_1_RIGHT_CHANNEL                   BIT08

#define SOUND_2_RIGHT_CHANNEL                   BIT09

#define SOUND_3_RIGHT_CHANNEL                   BIT10

#define SOUND_4_RIGHT_CHANNEL                   BIT11

#define SOUND_1_LEFT_CHANNEL                    BIT12

#define SOUND_2_LEFT_CHANNEL                    BIT13

#define SOUND_3_LEFT_CHANNEL                    BIT14

#define SOUND_4_LEFT_CHANNEL                    BIT15

 

//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

 

//SGCNT1

#define SOUND_1_ENABLE                                  BIT00

#define SOUND_2_ENABLE                                  BIT01

#define SOUND_3_ENABLE                                  BIT02

#define SOUND_4_ENABLE                                  BIT03

#define SOUND_MASTER_ENABLE                             BIT07

 

//SG10_L

#define S10L_NUM_SWEEP_SHIFTS(n)                n

#define S10L_SWEEP_INCREASE                             0

#define S10L_SWEEP_DECREASE                             BIT03

#define S10L_SWEEP_CHANGE_FREQ(n)               n<<4

 

//SG10_H

#define S10H_SOUND_LENGTH(n)                    n

#define S10H_WAVEFORM_CYCLE_12                  0

#define S10H_WAVEFORM_CYCLE_25                  BIT06

#define S10H_WAVEFORM_CYCLE_50                  BIT07

#define S10H_WAVEFROM_CYCLE_75                  BIT06 | BIT07

#define S10H_ENVELOPE_STEPS(n)                  n<<8

#define S10H_ENVELOPE_INCREASE                  0

#define S10H_ENVELOPE_DECREASE                  BIT11

#define S10H_ENVELOPE_START_VALUE(n)        n<<12

 

//SG20

#define S20_SOUND_LENGTH(n)                             n

#define S20_WAVEFORM_CYCLE_12                   0

#define S20_WAVEFORM_CYCLE_25                   BIT06

#define S20_WAVEFORM_CYCLE_50                   BIT07

#define S20_WAVEFROM_CYCLE_75                   BIT06 | BIT07

#define S20_ENVELOPE_STEPS(n)                   n<<8

#define S20_ENVELOPE_INCREASE                   0

#define S20_ENVELOPE_DECREASE                   BIT11

#define S20_ENVELOPE_START_VALUE(n)             n<<12

 

//SG21

#define S21_FREQUENCY(n)                                n

#define S21_CONTINOUS                                   0

#define S21_COUNTER                                             BIT14

#define S21_RESTART                                             BIT15

 

//SG30_L

#define S30L_32_STEP_WAVEFORM                   0

#define S30L_64_STEP_WAVEFORM                   BIT05

#define S30L_RAM_BANK_0                                 0

#define S30L_RAM_BANK_1                                 BIT06

#define S30L_ENABLE                                             BIT07

 

//SG30_H

#define S30H_SOUND_LENGTH(n)                    n

#define S30H_OUTPUT_MUTE                                0

#define S30H_OUTPUT_FULL                                BIT13

#define S30H_OUTPUT_1_2                                 BIT14

#define S30H_OUTPUT_1_4                                 BIT13 | BIT14

#define S30H_OUTPUT_3_4                                 BIT15

 

//SG31

#define S31_FREQUENCY(n)                                n

#define S31_CONTINOUS                                   0

#define S31_COUNTER                                             BIT14

#define S31_RESTART                                             BIT15

 

//SG40

#define S40_SOUND_LENGTH(n)                             n

#define S40_ENVELOPE_STEPS(n)                   n<<8

#define S40_ENVELOPE_INCREASE                   0

#define S40_ENVELOPE_DECREASE                   BIT11

#define S40_ENVELOPE_START_VALUE(n)             n<<12

 

//SG41

#define S41_DIVIDE_FREQ_2                               0

#define S41_DIVIDE_FREQ_1                               BIT00

#define S41_DIVIDE_FREQ_1_2                             BIT01

#define S41_DIVIDE_FREQ_1_3                             BIT00 | BIT01

#define S41_DIVIDE_FREQ_1_4                             BIT02

#define S41_DIVIDE_FREQ_1_5                             BIT00 | BIT02

#define S41_DIVIDE_FREQ_1_6                             BIT01 | BIT02

#define S41_DIVIDE_FREQ_1_7                             BIT00 | BIT01 | BIT02

#define S41_POLY_STEPS_15                               0

#define S41_POLY_STEPS_7                                BIT03

#define S41_POLY_SHIFT_FREQ(n)                  n<<4

#define S41_CONTINOUS                                   0

#define S41_COUNTER                                             BIT14

#define S41_RESTART                                             BIT15

 

#define REG_SGCNT0_L   0x4000080

#define REG_SGCNT0_H   0x4000082

#define REG_SGCNT1     0x4000084

 

extern u8 *soundA;                     //Sound A sample

extern u8 soundALoop;                     //Sound A loop parameter

extern u8 soundAPlaying;               //Sound A status

 

extern u32 soundACurrent;          //Sound A current location

extern u32 soundALength;               //Sound A sample length

extern u32 soundATime;                                     //Sound A sample time

extern u16 soundASampleRate;           //Sound A sample rate

 

 

extern u8 *soundB;                     //Sound B sample

extern u8 soundBLoop;                     //Sound B loop parameter

extern u8 soundBPlaying;               //Sound B status

 

extern u32 soundBLength;               //Sound B sample length

extern u32 soundBCurrent;          //Sound B current location

extern u32 soundBTime;                                     //Sound B sample time

extern u16 soundBSampleRate;           //Sound B sample rate

 

////////////////////////////////Function Prototypes//////////////////////////////

void PlaySound(u8 *sound, u16 sampleRate, u32 length,u32 time);

void UpdateDirectSound(void);

 

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

void PlayDirectSoundB(u8 *sound, u16 sampleRate, u32 length, u32 time);

 

void UpdateDirectSoundA(void);

void UpdateDirectSoundB(void);

 

void CloseDirectSoundA(void);

void CloseDirectSoundB(void);

 

void StopDirectSoundA(void);

void StopDirectSoundB(void);

 

void ResumeDirectSoundA(void);

void ResumeDirectSoundB(void);

 

#endif

 

//*************************************

//   文件名:libsound.c

//   GBA中Direct Sound处理函数或宏

//   tangl_99 创建于2003.2.7

//*************************************

#include <agb.h>

#include "libsound.h"

/////////////////////////////////////Globals/////////////////////////////////////

u8 *soundA;                     //Sound A sample

u8 soundALoop;                  //Sound A loop parameter

u8 soundAPlaying;               //Sound A status

 

u32 soundACurrent;          //Sound A current location

u32 soundALength;               //Sound A sample length

u32 soundATime;                                 //Sound A sample time

u16 soundASampleRate;           //Sound A sample rate

 

 

u8 *soundB;                     //Sound B sample

u8 soundBLoop;                  //Sound B loop parameter

u8 soundBPlaying;               //Sound B status

 

u32 soundBLength;               //Sound B sample length

u32 soundBCurrent;          //Sound B current location

u32 soundBTime;                                 //Sound B sample time

u16 soundBSampleRate;           //Sound B sample rate

 

 

////////////////////////////////////PlayDirectSoundA/////////////////////////////////////

// time是播发时间,单位是秒数

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

{

        //Stop any previous sample

        soundAPlaying = 0;

    *(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;

 

        //Set sound A's current sound

        soundA = sound;

 

        //Set the length, looping, etc

        soundALength = length;

        // 讲time秒转换成V-Blank中断次数,V-Blank中断是59.727Hz

        soundATime = time * 59.727;

        soundACurrent = 0;

        soundASampleRate = sampleRate;

 

        //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;

 

        //The sound is playing

        soundAPlaying = 1;

}

 

////////////////////////////////////PlayDirectSoundB/////////////////////////////////////

void PlayDirectSoundB(u8 *sound, u16 sampleRate, u32 length,u32 time)

{

        //Stop any previous sample

        soundBPlaying = 0;

        *(vu16 *)REG_TM1CNT_H  = 0;

        *(vu16 *)REG_TM1CNT_L = 0;

        *(vu32 *)REG_DMA2SAD = 0;

        *(vu16 *)REG_DMA2CNT_H = 0;

        *(vu32 *)REG_DMA2DAD = 0;

       

       

        //Output DirectSound B to right channel

        *(vu16 *)REG_SOUNDCNT_H |= DSOUND_B_RIGHT_CHANNEL | DSOUND_B_TIMER_1| DSOUND_B_LEFT_CHANNEL | DSOUND_B_FIFO_RESET | DSOUND_B_OUTPUT_FULL;

 

        //Enable all sound

        *(vu16 *)REG_SOUNDCNT_X |= SOUND_MASTER_ENABLE;

 

        //DMA1 Source Addresss

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

 

        //Set sound B's current sound

        soundB = sound;

 

        //Set the length and looping

        soundBLength = length;

        // 讲time秒转换成V-Blank中断次数,V-Blank中断是59.727Hz

        soundBTime = time * 59.727;

        soundBCurrent = 0;

        soundBSampleRate = sampleRate;

        soundBPlaying = 1;

 

        //DMA1 Destination Address (REG_SGFIFOB)

        *(vu32 *)REG_DMA2DAD = 0x40000A4;

 

        //Write 32 bits into 0x040000A4 (REG_SGFIF0B) every VSync

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

 

        //Sample Rate

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

 

        //Enable the timer

        *(vu16 *)REG_TM1CNT_H = TIMER_ENABLE | TIMER_IRQ;

}

 

/////////////////////////////////////UpdateDirectSoundA////////////////////////////////

void UpdateDirectSoundA(void)

{

       

        // if now is not playing sound A,return

        if(!soundAPlaying)

                return;

        // Increase the Current timer

    soundACurrent +=1;

        // If sound A play time is up,close the sound A

        if(soundACurrent >= soundATime)

                CloseDirectSoundA();

 

}

 

/////////////////////////////////////UpdateDirectSoundB////////////////////////////////

void UpdateDirectSoundB(void)

{

       

        // if now is not playing sound B,return

        if(!soundBPlaying)

                return;

        soundBCurrent +=1;

        // If sound B play time is up,close the sound B

        if(soundBCurrent >= soundBTime)

                CloseDirectSoundB();

 

}

 

void PlaySound(u8 *sound, u16 sampleRate, u32 length, u32 time)

{

PlayDirectSoundA(sound,sampleRate,length,time);

PlayDirectSoundB(sound,sampleRate,length,time);

 

}

 

void UpdateDirectSound()

{

UpdateDirectSoundA();

UpdateDirectSoundB();

}

 

void CloseDirectSoundA(void)

{

        soundAPlaying = 0;

        *(vu16 *)REG_TM0CNT_H = 0;

        *(vu16 *)REG_TM0CNT_L = 0;

        *(vu32 *)REG_DMA1SAD = 0;

        *(vu16 *)REG_DMA1CNT_H = 0;

        *(vu32 *)REG_DMA1DAD = 0;

}

 

void CloseDirectSoundB(void)

{

        soundBPlaying = 0;

        *(vu16 *)REG_TM1CNT_H = 0;

        *(vu16 *)REG_TM1CNT_L = 0;

        *(vu32 *)REG_DMA2SAD = 0;

        *(vu16 *)REG_DMA2CNT_H = 0;

        *(vu32 *)REG_DMA2DAD = 0;

}

 

void StopDirectSoundB(void)

{

        CloseDirectSoundB();

        // 用soundBCurrent来记录播放的时间,Resume的时候根据soundBCurrent/soundBtime,来判断sound data的入口

}

 

void StopDirectSoundA(void)

{

        CloseDirectSoundA();

        // 用soundACurrent来记录播放的时间,Resume的时候根据soundACurrent/soundAtime,来判断sound data的入口

}

 

void ResumeDirectSoundA(void)

{

        //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)(soundA+soundACurrent*soundALength/soundATime);

 

       

        //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/soundASampleRate);

 

        //Enable the timer

        *(vu16 *)REG_TM0CNT_H = TIMER_ENABLE | TIMER_IRQ;

 

        //The sound is playing

        soundAPlaying = 1;

}

 

 

void ResumeDirectSoundB(void)

{

        //Output DirectSound B to right channel

        *(vu16 *)REG_SOUNDCNT_H |= DSOUND_B_RIGHT_CHANNEL | DSOUND_B_TIMER_1| DSOUND_B_LEFT_CHANNEL | DSOUND_B_FIFO_RESET | DSOUND_B_OUTPUT_FULL;

 

        //Enable all sound

        *(vu16 *)REG_SOUNDCNT_X |= SOUND_MASTER_ENABLE;

 

        //DMA1 Source Addresss 需要计算重新开始的地址

        *(vu32 *)REG_DMA2SAD = (u32)(soundB+soundBCurrent*soundBLength/soundBTime);

       

        //DMA1 Destination Address (REG_SGFIFOB)

        *(vu32 *)REG_DMA2DAD = 0x40000A4;

 

        //Write 32 bits into 0x040000A4 (REG_SGFIF0B) every VSync

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

 

        //Sample Rate

        *(vu16 *)REG_TM1CNT_L = 65536 - (16777216/soundBSampleRate);

 

        //Enable the timer

        *(vu16 *)REG_TM1CNT_H = TIMER_ENABLE | TIMER_IRQ;

 

        soundBPlaying = 1;

 

}

金点 tangl_99

2003/4/19