gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Audio > my simple DMA sound routine doesn?t work ; ( why???

#2016 - rome - Mon Jan 27, 2003 7:55 pm

here a simple code to play a song on the gba. this code just set DMA and play (dont stop to playing)
but i cant heard anything.... what?s wrong on this code??? anybody can help me? thanks!

Code:

#define u32 unsigned int
#define u16 unsigned short
#define s8  char



////////////////////////////////////////////////////////////////////////////////
// Gunfire.h
////////////////////////////////////////////////////////////////////////////////
const s8 GunfireRawAudio[] =
{
      2,   4,   0,  -4,  ... this song continues...
                           (of course i wont list here)
};

#define SOUND_FREQ 22050

#define GBA_FREQ 16777216  //GBA runs at 16,7 MHz


// master registers

#define REG_SOUNDCNT_X *(u32*)0x04000084 // control all hardware chip sound of GBA
#define REG_SOUNDCNT_H *(u32*)0x04000082 // control directsound channels
#define REG_SOUNDCNT_L *(u32*)0x04000080 // control sound channels 1-4 (NOT USED BY US)

  // DMA channel 1 register definitions
   #define REG_DMA1CNT         *(u32*)0x40000C4 //  control register
   #define REG_DMA1SAD         *(u32*)0x40000BC //  source address
   #define REG_DMA1DAD         *(u32*)0x40000C0 //  destination address

   // DMA flags
    #define WORD_DMA            0x04000000
    #define HALF_WORD_DMA       0x00000000
    #define ENABLE_DMA          0x80000000
    #define START_ON_FIFO_EMPTY 0x30000000
    #define DMA_REPEAT          0x02000000
    #define DEST_REG_SAME       0x00400000

   //  Timer 0 register definitions
     #define REG_TM0D            *(u16*)0x4000100
     #define REG_TM0CNT          *(u16*)0x4000102

   //   Timer flags
      #define TIMER_ENABLED       0x0080

    //   FIFO address defines
       #define REG_FIFO_A          0x040000A0
       #define REG_FIFO_B          0x040000A4




      //  flags defined
        #define SND_ENABLED           0x00000080 // enable sound circuit
        #define SND_OUTPUT_RATIO_25   0x0000 // general output sound volume (25 %)
        #define SND_OUTPUT_RATIO_50   0x0001 // general output sound volume (25 %)
        #define SND_OUTPUT_RATIO_100  0x0002  // general output sound volume (25 %)
        #define DSA_OUTPUT_RATIO_50   0x0000  // output sound volume in channel A (25 %)
        #define DSA_OUTPUT_RATIO_100  0x0004 // output sound volume in channel A
        #define DSA_OUTPUT_TO_RIGHT   0x0100     // set output of channel A in right speaker
        #define DSA_OUTPUT_TO_LEFT    0x0200     // set output of channel A in left speaker
        #define DSA_OUTPUT_TO_BOTH    0x0300     // set output of channel A in both speakers
        #define DSA_TIMER0            0x0000     // tell to GBA use timer0 to DirectSound A
        #define DSA_TIMER1            0x0400     // tell to GBA use timer1 to DirectSound A
        #define DSA_FIFO_RESET        0x0800     // reset FIFO to DirectSound A
        #define DSB_OUTPUT_RATIO_50   0x0000     // flag to output sound volume in channel B (25 %)
        #define DSB_OUTPUT_RATIO_100  0x0008     // flag to output sound volume in channel B (25 %)
        #define DSB_OUTPUT_TO_RIGHT   0x1000     // set output of channel B in right speaker
        #define DSB_OUTPUT_TO_LEFT    0x2000     // set output of channel B in left speaker
        #define DSB_OUTPUT_TO_BOTH    0x3000     // set output of channel B in both speakers
        #define DSB_TIMER0            0x0000     // tell to GBA use timer0 to DirectSound B
        #define DSB_TIMER1            0x4000     // tell to GBA use timer1 to DirectSound B
        #define DSB_FIFO_RESET        0x8000     // reset FIFO to DirectSound B


// timer interval to refresh the FIFO
#define TIMER_INTERVAL      (0xFFFF - GBA_FREQ/SOUND_FREQ)

int main(void)
{
   // enable sound circuit
 REG_SOUNDCNT_X = SND_ENABLED;


// we don`t want to mess with sound channels 1-4
 REG_SOUNDCNT_L = 0;

 
//  enable and reset Direct Sound channel A, at full volume, using
//   Timer 0 to determine frequency
REG_SOUNDCNT_H = SND_OUTPUT_RATIO_100 |
                                DSA_OUTPUT_RATIO_100 |
                                   DSA_OUTPUT_TO_BOTH |
                                                   DSA_TIMER0 |
                                             DSA_FIFO_RESET;



  //  set the timer to overflow at the appropriate frequency and start it
    REG_TM0D   = TIMER_INTERVAL;
    REG_TM0CNT = TIMER_ENABLED;

//start the DMA transfer (assume that GunfireRawAudio is a (signed char*)
//     pointer to the buffer containing our sound data)

   REG_DMA1SAD = (u32)(GunfireRawAudio);
   REG_DMA1DAD = (u32)REG_FIFO_A;
   REG_DMA1CNT = ENABLE_DMA |
              START_ON_FIFO_EMPTY |
                               WORD_DMA |
                              DMA_REPEAT;

 while (1)
 {

 }
   return 0;
}

#2033 - darkcloud - Tue Jan 28, 2003 1:52 am

Your TIMER_INTERVAL isn't being defined as anything.
_________________
Maybe in order to understand mankind, we have to look at the word itself: "Mankind". Basically, it's made up of two separate words - "mank" and "ind". What do these words mean ? It's a mystery, and that's why so is mankind.

#2036 - Splam - Tue Jan 28, 2003 2:34 am

#define TIMER_INTERVAL (0xFFFF - GBA_FREQ/SOUND_FREQ)

Just take a look here

http://www.belogic.com/gba/directsound.shtml

See what you might have missed, just ignore the 2nd timer for the sample end interrupt.


Last edited by Splam on Tue Jan 28, 2003 2:40 am; edited 1 time in total

#2037 - darkcloud - Tue Jan 28, 2003 2:37 am

oh lol whoops didn't see that
_________________
Maybe in order to understand mankind, we have to look at the word itself: "Mankind". Basically, it's made up of two separate words - "mank" and "ind". What do these words mean ? It's a mystery, and that's why so is mankind.

#2038 - darkcloud - Tue Jan 28, 2003 2:47 am

ok well i think i learned how to do sound from the same place you did because i have that same code. I put the code into a function, and I also created a struct called SAMPLE, SAMPLE's a pointer to the sound data, and an int telling how large the sample is. Here's my function:

Code:

void init_sfx_system(const SAMPLE *pSample, int timeInt)
{
    // turn on the sound chip
    REG_SOUNDCNT_X = SND_ENABLED;

    // make sure sound channels 1-4 are turned off
    REG_SOUNDCNT_L = 0;

    // set the direct sound output control register
    REG_SOUNDCNT_H = SND_OUTPUT_RATIO_100 | // 100% sound output
                     DSA_OUTPUT_RATIO_100 | // 100% direct sound A output
                     DSA_OUTPUT_TO_BOTH |   // output Direct Sound A to both right and left speakers
                     DSA_TIMER0 |           // use timer 0 to determine the playback frequency of Direct Sound A
                     DSA_FIFO_RESET;        // reset the FIFO for Direct Sound A
                     
    REG_TM0D   = timeInt;
    REG_TM0CNT = TIMER_ENABLED;
    REG_DMA1SAD = (u32)(pSample->pData);
   REG_DMA1DAD = (u32)REG_FIFO_A;
    REG_DMA1CNT = ENABLE_DMA | START_ON_FIFO_EMPTY | WORD_DMA | DMA_REPEAT;
}


That's exactly how I do it.
_________________
Maybe in order to understand mankind, we have to look at the word itself: "Mankind". Basically, it's made up of two separate words - "mank" and "ind". What do these words mean ? It's a mystery, and that's why so is mankind.