Skip to content

Commit

Permalink
core, implement GG stereo
Browse files Browse the repository at this point in the history
  • Loading branch information
irixxxx committed Jan 23, 2024
1 parent fa4e053 commit 70efc52
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 82 deletions.
2 changes: 1 addition & 1 deletion pico/pico.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ void Pico32xSetClocks(int msh2_hz, int ssh2_hz);
#define PICO_SSH2_HZ ((int)(7670442.0 * 2.4))

// sound.c
extern void (*PsndMix_32_to_16l)(s16 *dest, s32 *src, int count);
extern void (*PsndMix_32_to_16)(s16 *dest, s32 *src, int count);
void PsndRerate(int preserve_state);

// media.c
Expand Down
2 changes: 2 additions & 0 deletions pico/sms.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ static void z80_sms_out(unsigned short a, unsigned char d)
case 0x00:
if ((PicoIn.AHW & PAHW_GG) && a < 0x8) // GG I/O area
Pico.ms.io_gg[a] = d;
if ((PicoIn.AHW & PAHW_GG) && a == 0x6)
SN76496Config(d);
break;
case 0x01:
if ((PicoIn.AHW & PAHW_GG) && a < 0x8) { // GG I/O area
Expand Down
21 changes: 11 additions & 10 deletions pico/sound/mix.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
val -= val >> 3; /* reduce level to avoid clipping */ \
if ((s16)val != val) val = (val < 0 ? MINOUT : MAXOUT)

int mix_32_to_16l_level;
int mix_32_to_16_level;

static struct iir {
int alpha; // alpha for EMA low pass
Expand Down Expand Up @@ -63,33 +63,34 @@ static inline int filter_null(struct iir *fi2, int x)

#define filter filter_band

#define mix_32_to_16l_stereo_core(dest, src, count, lv, fl) { \
#define mix_32_to_16_stereo_core(dest, src, count, lv, fl) { \
int l, r; \
struct iir lf = lfi2, rf = rfi2; \
\
for (; count > 0; count--) \
{ \
l = r = *dest; \
l = *dest; \
l += *src++ >> lv; \
r += *src++ >> lv; \
l = fl(&lf, l); \
r = fl(&rf, r); \
Limit16(l); \
Limit16(r); \
*dest++ = l; \
r = *dest; \
r += *src++ >> lv; \
r = fl(&rf, r); \
Limit16(r); \
*dest++ = r; \
} \
lfi2 = lf, rfi2 = rf; \
}

void mix_32_to_16l_stereo_lvl(s16 *dest, s32 *src, int count)
void mix_32_to_16_stereo_lvl(s16 *dest, s32 *src, int count)
{
mix_32_to_16l_stereo_core(dest, src, count, mix_32_to_16l_level, filter);
mix_32_to_16_stereo_core(dest, src, count, mix_32_to_16_level, filter);
}

void mix_32_to_16l_stereo(s16 *dest, s32 *src, int count)
void mix_32_to_16_stereo(s16 *dest, s32 *src, int count)
{
mix_32_to_16l_stereo_core(dest, src, count, 0, filter);
mix_32_to_16_stereo_core(dest, src, count, 0, filter);
}

void mix_32_to_16_mono(s16 *dest, s32 *src, int count)
Expand Down
6 changes: 3 additions & 3 deletions pico/sound/mix.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ void mix_16h_to_32_s2(s32 *dest, s16 *src, int count);

void mix_16h_to_32_resample_stereo(s32 *dest, s16 *src, int count, int fac16);
void mix_16h_to_32_resample_mono(s32 *dest, s16 *src, int count, int fac16);
void mix_32_to_16l_stereo(s16 *dest, s32 *src, int count);
void mix_32_to_16_stereo(s16 *dest, s32 *src, int count);
void mix_32_to_16_mono(s16 *dest, s32 *src, int count);

extern int mix_32_to_16l_level;
void mix_32_to_16l_stereo_lvl(s16 *dest, s32 *src, int count);
extern int mix_32_to_16_level;
void mix_32_to_16_stereo_lvl(s16 *dest, s32 *src, int count);
void mix_reset(int alpha_q16);
66 changes: 34 additions & 32 deletions pico/sound/mix_arm.S
Original file line number Diff line number Diff line change
Expand Up @@ -282,29 +282,29 @@ m16_32_rsm_end:

@ mix 32bit audio (with 16bits really used, upper bits indicate overflow) with normal 16 bit audio with left channel only
@ warning: this function assumes dest is word aligned
.global mix_32_to_16l_stereo @ short *dest, int *src, int count
.global mix_32_to_16_stereo @ short *dest, int *src, int count

mix_32_to_16l_stereo:
mix_32_to_16_stereo:
stmfd sp!, {r4-r8,r10-r11,lr}

mov r2, r2, lsl #1
subs r2, r2, #4
bmi m32_16l_st_end
bmi m32_16_st_end

ldr r12, =filter
ldr r8, [r12], #4
ldmia r12, {r3,r10-r11,lr}
str r8, [sp, #-4]!

m32_16l_st_loop:
m32_16_st_loop:
ldmia r0, {r8,r12}
ldmia r1!, {r4-r7}
add r5, r5, r8, asr #16
add r7, r7, r12,asr #16
mov r8, r8, lsl #16
mov r12,r12,lsl #16
add r4, r4, r8, asr #16
add r5, r5, r8, asr #16
add r6, r6, r12,asr #16
add r7, r7, r12,asr #16
ldr r12,[sp]
LPfilt r4, r3
LPfilt r5, lr
Expand All @@ -323,16 +323,17 @@ m32_16l_st_loop:
orr r4, r5, r4, lsr #16
orr r5, r7, r6, lsr #16
stmia r0!, {r4,r5}
bpl m32_16l_st_loop
bpl m32_16_st_loop

m32_16l_st_end:
m32_16_st_end:
@ check for remaining bytes to convert
tst r2, #2
beq m32_16l_st_no_unal2
ldrsh r6, [r0]
beq m32_16_st_no_unal2
ldr r6, [r0]
ldmia r1!,{r4,r5}
add r4, r4, r6
add r5, r5, r6
add r5, r5, r6, asr #16
mov r6, r6, lsl #16
add r4, r4, r6, asr #16
ldr r12,[sp]
LPfilt r4, r3
LPfilt r5, lr
Expand All @@ -344,7 +345,7 @@ m32_16l_st_end:
orr r4, r5, r4, lsr #16
str r4, [r0], #4

m32_16l_st_no_unal2:
m32_16_st_no_unal2:
ldr r12, =filter
add r12,r12, #4
stmia r12, {r3,r10-r11,lr}
Expand Down Expand Up @@ -386,10 +387,10 @@ m32_16_mo_loop:
ldmia r0, {r8,r12}
ldmia r1!, {r4-r7}
add r5, r5, r8, asr #16
mov r8, r8, lsl #16
add r4, r4, r8, asr #16
add r7, r7, r12,asr #16
mov r8, r8, lsl #16
mov r12,r12,lsl #16
add r4, r4, r8, asr #16
add r6, r6, r12,asr #16
ldr r12,[sp]
LPfilt r4, r11
Expand Down Expand Up @@ -458,20 +459,20 @@ m32_16_mo_no_unal:
.data
.align 4

.global mix_32_to_16l_level
mix_32_to_16l_level:
.global mix_32_to_16_level
mix_32_to_16_level:
.word 0

.text
.align 4

@ same as mix_32_to_16l_stereo, but with additional shift
.global mix_32_to_16l_stereo_lvl @ short *dest, int *src, int count
@ same as mix_32_to_16_stereo, but with additional shift
.global mix_32_to_16_stereo_lvl @ short *dest, int *src, int count

mix_32_to_16l_stereo_lvl:
mix_32_to_16_stereo_lvl:
stmfd sp!, {r4-r11,lr}

ldr r9, =mix_32_to_16l_level
ldr r9, =mix_32_to_16_level
mov lr, #1
ldr r9, [r9]
ldr r12, =filter
Expand All @@ -481,17 +482,17 @@ mix_32_to_16l_stereo_lvl:

mov r2, r2, lsl #1
subs r2, r2, #4
bmi m32_16l_st_l_end
bmi m32_16_st_l_end

m32_16l_st_l_loop:
m32_16_st_l_loop:
ldmia r0, {r8,r12}
ldmia r1!, {r4-r7}
add r5, r5, r8, asr #16
add r7, r7, r12,asr #16
mov r8, r8, lsl #16
mov r12,r12,lsl #16
add r4, r4, r8, asr #16
add r5, r5, r8, asr #16
add r6, r6, r12,asr #16
add r7, r7, r12,asr #16
mov r4, r4, asr r9
mov r5, r5, asr r9
mov r6, r6, asr r9
Expand All @@ -514,16 +515,17 @@ m32_16l_st_l_loop:
orr r4, r5, r4, lsr #16
orr r5, r7, r6, lsr #16
stmia r0!, {r4,r5}
bpl m32_16l_st_l_loop
bpl m32_16_st_l_loop

m32_16l_st_l_end:
m32_16_st_l_end:
@ check for remaining bytes to convert
tst r2, #2
beq m32_16l_st_l_no_unal2
ldrsh r6, [r0]
beq m32_16_st_l_no_unal2
ldr r6, [r0]
ldmia r1!,{r4,r5}
add r4, r4, r6
add r5, r5, r6
add r5, r5, r6, asr #16
mov r6, r6, lsl #16
add r4, r4, r6, asr #16
mov r4, r4, asr r9
mov r5, r5, asr r9
ldr r12,[sp]
Expand All @@ -537,7 +539,7 @@ m32_16l_st_l_end:
orr r4, r5, r4, lsr #16
str r4, [r0], #4

m32_16l_st_l_no_unal2:
m32_16_st_l_no_unal2:
ldr r12, =filter
add r12,r12, #4
stmia r12, {r3,r10-r11,lr}
Expand Down
44 changes: 34 additions & 10 deletions pico/sound/sn76496.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ struct SN76496
int Period[4];
int Count[4];
int Output[4];
int pad[1];
int Panning;
};

static struct SN76496 ono_sn; // one and only SN76496
Expand Down Expand Up @@ -135,7 +135,6 @@ void SN76496Update(short *buffer, int length, int stereo)
while (length > 0)
{
int vol[4];
unsigned int out;
int left;


Expand Down Expand Up @@ -203,19 +202,43 @@ void SN76496Update(short *buffer, int length, int stereo)
} while (left > 0 && R->Volume[3]);
if (R->Output[3]) vol[3] -= R->Count[3];

out = vol[0] * R->Volume[0] + vol[1] * R->Volume[1] +
length--;
if (R->Panning == 0xff || !stereo) {
unsigned int out =
vol[0] * R->Volume[0] + vol[1] * R->Volume[1] +
vol[2] * R->Volume[2] + vol[3] * R->Volume[3];

if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP;

out /= STEP; // will be optimized to shift; max 0x4800 = 18432
*buffer++ += out;
if (stereo) *buffer++ += out;

length--;
if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP;

out /= STEP; // will be optimized to shift; max 0x4800 = 18432
*buffer++ += out;
if (stereo) *buffer++ += out;
} else {
#define P(n) !!(R->Panning & (1<<(n)))
unsigned int outl =
vol[0] * R->Volume[0] * P(4) + vol[1] * R->Volume[1] * P(5) +
vol[2] * R->Volume[2] * P(6) + vol[3] * R->Volume[3] * P(7);
unsigned int outr =
vol[0] * R->Volume[0] * P(0) + vol[1] * R->Volume[1] * P(1) +
vol[2] * R->Volume[2] * P(2) + vol[3] * R->Volume[3] * P(3);
#undef P
if (outl > MAX_OUTPUT * STEP) outl = MAX_OUTPUT * STEP;
if (outr > MAX_OUTPUT * STEP) outr = MAX_OUTPUT * STEP;

outl /= STEP; // will be optimized to shift; max 0x4800 = 18432
outr /= STEP; // will be optimized to shift; max 0x4800 = 18432
*buffer++ += outl;
*buffer++ += outr;
}
}
}

void SN76496Config(int panning)
{
struct SN76496 *R = &ono_sn;
R->Panning = panning & 0xff;
}


static void SN76496_set_clock(struct SN76496 *R,int clock)
{
Expand Down Expand Up @@ -286,6 +309,7 @@ int SN76496_init(int clock,int sample_rate)

// added
SN76496_set_gain(R, 0);
R->Panning = 0xff;

return 0;
}
Expand Down
1 change: 1 addition & 0 deletions pico/sound/sn76496.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

void SN76496Write(int data);
void SN76496Update(short *buffer,int length,int stereo);
void SN76496Config(int panning);
int SN76496_init(int clock,int sample_rate);

#endif
Loading

0 comments on commit 70efc52

Please sign in to comment.