preliminary audio. only supports PSG (and handles all channels as such). drops out every once in a while.

This commit is contained in:
StapleButter
2017-04-06 22:38:46 +02:00
parent 8d66beba6b
commit 76c4e57608
2 changed files with 103 additions and 6 deletions

View File

@ -71,12 +71,11 @@ void Reset()
Channel::Channel(u32 num) Channel::Channel(u32 num)
{ {
// Num = num;
} }
Channel::~Channel() Channel::~Channel()
{ {
//
} }
void Channel::Reset() void Channel::Reset()
@ -88,28 +87,108 @@ void Channel::Reset()
Length = 0; Length = 0;
} }
void Channel::Start()
{
Timer = TimerReload;
Pos = 0;
// hax
NextSample_PSG();
}
void Channel::NextSample_PSG()
{
s16 psgtable[8][8] =
{
{-0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF},
{-0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF},
{-0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF},
{-0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF},
{-0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF},
{-0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF},
{-0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF},
{ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF}
};
CurSample = psgtable[(Cnt >> 24) & 0x7][Pos & 0x7];
}
void Channel::Run(s32* buf, u32 samples)
{
for (u32 s = 0; s < samples; s++)
buf[s] = 0;
if (!(Cnt & (1<<31))) return;
if (Num < 8) return;
if (!(Cnt & 0x7F)) return;
for (u32 s = 0; s < samples; s++)
{
Timer += 512; // 1 sample = 512 cycles at 16MHz
// will probably shit itself for very high-pitched sounds
while (Timer >> 16)
{
Timer = TimerReload + (Timer - 0x10000);
Pos++;
NextSample_PSG();
}
buf[s] = (s32)CurSample;
}
}
void Mix(u32 samples) void Mix(u32 samples)
{ {
s32 channelbuf[32];
s32 finalbuf[32];
for (u32 s = 0; s < samples; s++)
finalbuf[s] = 0;
for (int i = 0; i < 16; i++)
//int i = 8;
{
Channel* chan = Channels[i];
chan->Run(channelbuf, samples);
for (u32 s = 0; s < samples; s++)
{
finalbuf[s] += channelbuf[s];
}
}
// //
for (u32 s = 0; s < samples; s++)
{
s16 val = (s16)(finalbuf[s] >> 4);
// TODO panning! also volume and all
OutputBuffer[OutputWriteOffset] = val;
OutputBuffer[OutputWriteOffset + 1] = val;
OutputWriteOffset += 2;
OutputWriteOffset &= ((2*OutputBufferSize)-1);
}
NDS::ScheduleEvent(NDS::Event_SPU, true, 1024*16, Mix, 16); NDS::ScheduleEvent(NDS::Event_SPU, true, 1024*16, Mix, 16);
} }
void ReadOutput(s16* data, int samples) void ReadOutput(s16* data, int samples)
{ {u32 zarp = 0;
for (int i = 0; i < samples; i++) for (int i = 0; i < samples; i++)
{ {
*data++ = OutputBuffer[OutputReadOffset]; *data++ = OutputBuffer[OutputReadOffset];
*data++ = OutputBuffer[OutputReadOffset + 1]; *data++ = OutputBuffer[OutputReadOffset + 1];
if (OutputReadOffset != OutputWriteOffset) if (OutputReadOffset != OutputWriteOffset)
{ {zarp += 2;
OutputReadOffset += 2; OutputReadOffset += 2;
OutputReadOffset &= ((2*OutputBufferSize)-1); OutputReadOffset &= ((2*OutputBufferSize)-1);
} }
} }printf("read %d samples, took %d\n", samples, zarp);
} }

View File

@ -44,21 +44,39 @@ public:
~Channel(); ~Channel();
void Reset(); void Reset();
u32 Num;
u32 Cnt; u32 Cnt;
u32 SrcAddr; u32 SrcAddr;
u16 TimerReload; u16 TimerReload;
u32 LoopPos; u32 LoopPos;
u32 Length; u32 Length;
u32 Timer;
u32 Pos;
s16 CurSample;
void SetCnt(u32 val) void SetCnt(u32 val)
{ {
if ((val & (1<<31)) && !(Cnt & (1<<31)))
{
Start();
}
Cnt = val & 0xFF7F837F; Cnt = val & 0xFF7F837F;
//if(Num==8)printf("chan %d volume: %d\n", Num, val&0x7F);
} }
void SetSrcAddr(u32 val) { SrcAddr = val & 0x07FFFFFF; } void SetSrcAddr(u32 val) { SrcAddr = val & 0x07FFFFFF; }
void SetTimerReload(u32 val) { TimerReload = val & 0xFFFF; } void SetTimerReload(u32 val) { TimerReload = val & 0xFFFF;if(Num==8) printf("chan8 timer %04X\n", TimerReload);}
void SetLoopPos(u32 val) { LoopPos = (val & 0xFFFF) << 2; } void SetLoopPos(u32 val) { LoopPos = (val & 0xFFFF) << 2; }
void SetLength(u32 val) { Length = (val & 0x001FFFFF) << 2; } void SetLength(u32 val) { Length = (val & 0x001FFFFF) << 2; }
void Start();
void NextSample_PSG();
void Run(s32* buf, u32 samples);
}; };
} }