#77766 - ProblemBaby - Sun Apr 02, 2006 10:52 pm
Hello
Iam trying to write a software mixer but I dont get the correct sync. Ive no idea why it should work.
Some pseudo code:
Code: |
arm7vbank:
if (curBufFlag == 1)
curBuf = MixBuf
else
Start Play from the beginning of the MixBuf
|
Iam using the frequency: 31536hz with a buffersize of 528
Ive succeeded to do this on the gba (thanks dekutree64!) so it's something with the sync that doesnt work.
thanks
#77767 - HyperHacker - Sun Apr 02, 2006 10:53 pm
Should you be resetting curBufFlag? Hard to tell with so little code, especially when it's not even the actual source.
#77770 - ProblemBaby - Sun Apr 02, 2006 10:58 pm
Yeah, Ive no idea why I didnt show u the real source=)
Code: |
Arm7VBlank:
if (CurrentBuffer)
{
g_dsipc->Sound.CurrentMixingBuffer = g_dsipc->Sound.MixingBuffer;
CurrentBuffer = 0;
}
else
{
REG_SOUNDCHNCNT(0) = 0
REG_SOUNDCHNCNT(1) = 0;
REG_SOUNDCHNTMR(0) = -0x1000000 / 31536;
REG_SOUNDCHNTMR(1) = -0x1000000 / 31536;
REG_SOUNDCHNLEN(0) = (528 * 4) / 4;
REG_SOUNDCHNLEN(1) = (528 * 4) / 4;
REG_SOUNDCHNPNT(0) = 0;
REG_SOUNDCHNPNT(1) = 0;
REG_SOUNDCHNSAD(0) = (u32)&g_dsipc->Sound.MixingBuffer[0 * 528];
REG_SOUNDCHNSAD(1) = (u32)&g_dsipc->Sound.MixingBuffer[2 * 528];
REG_SOUNDCHNCNT(0) = SOUNDCHNCNT_ENABLED | SOUNDCHNCNT_REPEATMODE_LOOP | SOUNDCHNCNT_FORMAT_PCM16 | SOUNDCHNCNT_PANNING(0x00) | SOUNDCHNCNT_VOLUME(0x7F);
REG_SOUNDCHNCNT(1) = SOUNDCHNCNT_ENABLED | SOUNDCHNCNT_REPEATMODE_LOOP | SOUNDCHNCNT_FORMAT_PCM16 | SOUNDCHNCNT_PANNING(0x7F) | SOUNDCHNCNT_VOLUME(0x7F);
CurrentBuffer = 1;
}
// Some terrible written mix code. in Arm9
u32 i, j;
BIOSCpuSetZero32(TempMixingBuffer, 528 * 2);
for (i = 0; i < 32; i++)
{
if (Chn[i].pData)
{
for (j = 0; j < 528; j++)
{
TempMixingBuffer[j*2+0] = Chn[i].pData[Chn[i].Position] * Chn[i].LeftVolume;
TempMixingBuffer[j*2+1] = Chn[i].pData[Chn[i].Position] * Chn[i].RightVolume;
Chn[i].Position++;
//while (Chn[i].Position >= Chn[i].Length)
// Chn[i].Position -= Chn[i].LoopLength;
}
}
}
for (i = 0; i < 528; i++)
{
if (TempMixingBuffer[i*2+0] > 32767)
TempMixingBuffer[i*2+0] = 32767;
else if (TempMixingBuffer[i*2+0] < -32768)
TempMixingBuffer[i*2+0] = -32768;
if (TempMixingBuffer[i*2+1] > 32767)
TempMixingBuffer[i*2+1] = 32767;
else if (TempMixingBuffer[i*2+1] < -32768)
TempMixingBuffer[i*2+1] = -32768;
g_dsipc->Sound.CurrentMixingBuffer[528 * 2] = TempMixingBuffer[i*2+1];
g_dsipc->Sound.CurrentMixingBuffer[0] = TempMixingBuffer[i*2+0];
g_dsipc->Sound.CurrentMixingBuffer++;
}
|
#77773 - DekuTree64 - Sun Apr 02, 2006 11:26 pm
Those mixing rate/buffer size settings only work on the GBA, because it runs at 280896 clocks/vblank. According to this, DS runs at 560190 clocks/vblank, which when plugged into tepples' sample rate calculator, doesn't come up with anything.
So, you'll need to use a timer to count samples, instead of VBlank. What I've done before is set the sound channel to loop, set one CPU timer to run at the same rate as the sound channel's timer, and cascade another timer off that. Each VBlank, I read the cascade timer and take the difference since last frame (remember to handle wrap around), and mix that many samples. Store the value you read from the cascade timer for getting the difference next frame.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku
#77775 - ProblemBaby - Sun Apr 02, 2006 11:43 pm
I tested the sample rate calculater myself (to be sure) and actually it comes up with some. When setting Fetch witdth = 2.
And I don't have to care about the fetch witdth for DS, right?
I tried to put in the new values, it still doesnt work but shouldnt those values work?
#77776 - DekuTree64 - Sun Apr 02, 2006 11:49 pm
I'm not sure what the DS's fetch width is. What kind of problem are you getting? Clicking during the restart, or like it's not filling the buffer properly or something?
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku
#77779 - ProblemBaby - Sun Apr 02, 2006 11:58 pm
hmm hard to describe...
The sound is played incorrectly all the time through, I think its a sync problem, cause I can't see something wrong in the Mix function.
The sample seems to be restarted each time, like it just copies the data the first time, then just let it loop around.
#77784 - tepples - Mon Apr 03, 2006 12:04 am
ProblemBaby wrote: |
Iam trying to write a software mixer but I dont get the correct sync. Ive no idea why it should work.
[...]Iam using the frequency: 31536hz with a buffersize of 528 |
You will want to use frequency 32768 Hz on the DS, with timer based switching instead of vblank based switching.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#77786 - ProblemBaby - Mon Apr 03, 2006 12:08 am
It isnt played at all if the Play Once is enabled (instead of loop).
tepples wrote: |
You will want to use frequency 32768 Hz on the DS, with timer based switching instead of vblank based switching.
|
Yeah probably Ive too, but I want to try some more, cause I think its better to have vblank based switching when it comes to synced video/audio/input effects.
#77855 - ProblemBaby - Mon Apr 03, 2006 4:47 pm
DekuTree64 wrote: |
So, you'll need to use a timer to count samples, instead of VBlank. What I've done before is set the sound channel to loop, set one CPU timer to run at the same rate as the sound channel's timer, and cascade another timer off that. Each VBlank, I read the cascade timer and take the difference since last frame (remember to handle wrap around), and mix that many samples. Store the value you read from the cascade timer for getting the difference next frame.
|
I don't understand. At which CPU is what done?, Do you just start the two channels in the audio init code? Is the actual mix code in VBlank?
Sorry that iam so slow in understanding
#77869 - DekuTree64 - Mon Apr 03, 2006 6:45 pm
ProblemBaby wrote: |
At which CPU is what done?, Do you just start the two channels in the audio init code? Is the actual mix code in VBlank? |
Either CPU, yes, yes.
If you want to mix on the ARM9, getting the sound channels and timers started at the same time is pretty tricky. I set up a little CPU communication system using the FIFO registers, to send across start/stop mixer commands, and wait until they finish processing before starting the timers on ARM9.
Another thing I forgot to mention for this style, you have to mix to a ring buffer instead of swapping between 2 equal size buffers. Basically that means you need to check if mixing your full batch will run past the end of the buffer, and if so, split it in two. Mix right to the end, set the buffer position back to the start, and mix the rest.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku
#77872 - ProblemBaby - Mon Apr 03, 2006 7:00 pm
Just have to ask, if you've tried this.. what speed did you come up with? The main reason for me to do this is to be able to support 32 channels, linear interpolation, volume ramps, Play from ROM and no length/loopstart restrictions. But if this end up in 50+ cpu usage it isnt worth it.
So I just want to make sure that its worth it before I start, what speed do you think I'll will end up in.