#1236 - Vortex - Wed Jan 15, 2003 9:48 pm
I am working on a small sound program, based on the www.belogic.com sample code. Sometimes when a sound sample is played there is a clicking sound. From my Windows sound card programming experience I can conclude that at least one byte of sample data is being lost during the DMA transfer. The symptom is not consistent and it may be a problem with the emulator (VBA) or there is a high-priority interrupt which in some way causes data lost.
Your input will be appreciated.
Thanks
Your input will be appreciated.
Thanks
Code: |
#include "gba.h" #include "screenmode.h" #include "keypad.h" #include "sound21.c" #include "sound25.c" #define FIFO_A (0x040000A0) #define FIFO_B (0x040000A4) void InterruptProcess(void) __attribute__ ((section(".iwram"))); //the interrupt handler from crt0.s void InterruptProcess(void) { //sample finished!,stop Direct sound REG_TM0CNT_H = 0; //disable timer 0 REG_TM1CNT_H = 0; //disable timer 1 REG_DMA1CNT_H = 0; //stop DMA //clear the interrupt(s) REG_IF |= REG_IF; } void PlaySample( const u32* sound_data, u16 num_samples, u32 playbackFreq ) { const u32 cpuFreq = 16777216lu; //play a mono sound at 16khz //uses timer 0 as sampling rate source //uses timer 1 to count the samples played in order to stop the sound // Direct Sound Channel A REG_DMA1SAD = (unsigned long) sound_data; //dma1 source REG_DMA1DAD = FIFO_A; //write to FIFO A address REG_DMA1CNT_H = 0xb600; //dma control: DMA enabled+ start on FIFO+32bit+repeat+increment source&dest REG_DMA1CNT_L = 0; REG_TM1CNT_L = 0xFFFF - num_samples; //0xffff-the number of samples to play REG_TM1CNT_H = 0xC4; //enable timer1 + irq and cascade from timer 0 REG_IE = 0x10; //enable irq for timer 1 REG_IME = 1; //master enable interrupts //Formula for playback frequency is: 0xFFFF-round(cpuFreq/playbackFreq) REG_TM0CNT_L = 0xFFFF - (cpuFreq/playbackFreq); REG_TM0CNT_H = 0x0080; //enable timer0 } struct SountCntH { int Ch1to4OutputRatio : 2; int DSndAOutRatio : 1; int DSndBOutRatio : 1; int unused : 4; int EnableDSndAToRightSpeaker : 1; int EnableDSndAToLeftSpeaker : 1; int DSndASampleRateTimer : 1; int DSndAFIFOReset : 1; int EnableDSndBToRightSpeaker : 1; int EnableDSndBToLeftSpeaker : 1; int DSndBSampleRateTimer : 1; int DSndBFIFOReset : 1; }; void AgbMain (void) { u32 playbackFreq = 16384; // u32 SoundCntXMask = 0x080C0; struct SountCntH snd_ctrl; snd_ctrl.Ch1to4OutputRatio = 0; snd_ctrl.DSndAOutRatio = 1; // 100% snd_ctrl.DSndBOutRatio = 0; snd_ctrl.unused = 0; snd_ctrl.EnableDSndAToRightSpeaker = 1; snd_ctrl.EnableDSndAToLeftSpeaker = 1; snd_ctrl.DSndASampleRateTimer = 0; //Timer 0 snd_ctrl.DSndAFIFOReset = 1; snd_ctrl.EnableDSndBToRightSpeaker = 0; snd_ctrl.EnableDSndBToLeftSpeaker = 0; snd_ctrl.DSndBSampleRateTimer = 0; // Timer 0 snd_ctrl.DSndBFIFOReset = 0; //play a mono sound at 16khz //uses timer 0 as sampling rate source //uses timer 1 to count the samples played in order to stop the sound // REG_SOUNDCNT_H = 0x0b0F; //enable DS A&B + fifo reset + use timer0 + max volume to L and R // REG_SOUNDCNT_H = SoundCntXMask | ENABLE_DSA_TO_LEFT | ENABLE_DSB_TO_RIGHT; REG_SOUNDCNT_H = * (u16*) &snd_ctrl; REG_SOUNDCNT_X = 0x0080; //turn sound chip on SetMode( MODE_3 | BG2_ENABLE ); while(1) { if( REG_TM1CNT_H == 0 ) { if(!(*KEYS & KEY_A)) { while(!(*KEYS & KEY_A)); PlaySample((const u32*) SOUND25_DATA, SOUND25_LENGTH, playbackFreq ); } else if(!(*KEYS & KEY_B)) { while(!(*KEYS & KEY_B)); PlaySample((const u32*) SOUND21_DATA, SOUND21_LENGTH, playbackFreq ); } } if(!(*KEYS & KEY_UP)) { while(!(*KEYS & KEY_UP)); playbackFreq *= 2; } else if(!(*KEYS & KEY_DOWN)) { while(!(*KEYS & KEY_DOWN)); playbackFreq /= 2; } } } |