#define PICO_SSH2_HZ ((int)(7670442.0 * 2.4))\r
\r
// sound.c\r
-extern void (*PsndMix_32_to_16l)(s16 *dest, s32 *src, int count);\r
+extern void (*PsndMix_32_to_16)(s16 *dest, s32 *src, int count);\r
void PsndRerate(int preserve_state);\r
\r
// media.c\r
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
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
#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)
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);
@ 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
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
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}
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
.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
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
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]
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}
int Period[4];\r
int Count[4];\r
int Output[4];\r
- int pad[1];\r
+ int Panning;\r
};\r
\r
static struct SN76496 ono_sn; // one and only SN76496\r
while (length > 0)\r
{\r
int vol[4];\r
- unsigned int out;\r
int left;\r
\r
\r
} while (left > 0 && R->Volume[3]);\r
if (R->Output[3]) vol[3] -= R->Count[3];\r
\r
- out = vol[0] * R->Volume[0] + vol[1] * R->Volume[1] +\r
+ length--;\r
+ if (R->Panning == 0xff || !stereo) {\r
+ unsigned int out =\r
+ vol[0] * R->Volume[0] + vol[1] * R->Volume[1] +\r
vol[2] * R->Volume[2] + vol[3] * R->Volume[3];\r
\r
- if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP;\r
-\r
- out /= STEP; // will be optimized to shift; max 0x4800 = 18432\r
- *buffer++ += out;\r
- if (stereo) *buffer++ += out;\r
-\r
- length--;\r
+ if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP;\r
+\r
+ out /= STEP; // will be optimized to shift; max 0x4800 = 18432\r
+ *buffer++ += out;\r
+ if (stereo) *buffer++ += out;\r
+ } else {\r
+#define P(n) !!(R->Panning & (1<<(n)))\r
+ unsigned int outl =\r
+ vol[0] * R->Volume[0] * P(4) + vol[1] * R->Volume[1] * P(5) +\r
+ vol[2] * R->Volume[2] * P(6) + vol[3] * R->Volume[3] * P(7);\r
+ unsigned int outr =\r
+ vol[0] * R->Volume[0] * P(0) + vol[1] * R->Volume[1] * P(1) +\r
+ vol[2] * R->Volume[2] * P(2) + vol[3] * R->Volume[3] * P(3);\r
+#undef P\r
+ if (outl > MAX_OUTPUT * STEP) outl = MAX_OUTPUT * STEP;\r
+ if (outr > MAX_OUTPUT * STEP) outr = MAX_OUTPUT * STEP;\r
+\r
+ outl /= STEP; // will be optimized to shift; max 0x4800 = 18432\r
+ outr /= STEP; // will be optimized to shift; max 0x4800 = 18432\r
+ *buffer++ += outl;\r
+ *buffer++ += outr;\r
+ }\r
}\r
}\r
\r
+void SN76496Config(int panning)\r
+{\r
+ struct SN76496 *R = &ono_sn;\r
+ R->Panning = panning & 0xff;\r
+}\r
+\r
\r
static void SN76496_set_clock(struct SN76496 *R,int clock)\r
{\r
\r
// added\r
SN76496_set_gain(R, 0);\r
+ R->Panning = 0xff;\r
\r
return 0;\r
}\r
\r
void SN76496Write(int data);\r
void SN76496Update(short *buffer,int length,int stereo);\r
+void SN76496Config(int panning);\r
int SN76496_init(int clock,int sample_rate);\r
\r
#endif\r
#include "resampler.h"\r
#include "mix.h"\r
\r
-void (*PsndMix_32_to_16l)(s16 *dest, s32 *src, int count) = mix_32_to_16l_stereo;\r
+void (*PsndMix_32_to_16)(s16 *dest, s32 *src, int count) = mix_32_to_16_stereo;\r
\r
// master int buffer to mix to\r
// +1 for a fill triggered by an instruction overhanging into the next scanline\r
PsndClear();\r
\r
// set mixer\r
- PsndMix_32_to_16l = (PicoIn.opt & POPT_EN_STEREO) ? mix_32_to_16l_stereo : mix_32_to_16_mono;\r
+ PsndMix_32_to_16 = (PicoIn.opt & POPT_EN_STEREO) ? mix_32_to_16_stereo : mix_32_to_16_mono;\r
mix_reset(PicoIn.opt & POPT_EN_SNDFILTER ? PicoIn.sndFilterAlpha : 0);\r
\r
if (PicoIn.AHW & PAHW_PICO)\r
if (PicoIn.opt & POPT_EN_STEREO) {\r
s16 *d = PicoIn.sndOut + pos*2;\r
// left channel only, mixed ro right channel in mixing phase\r
- *d++ += Pico.snd.dac_val2; d++;\r
- while (--len) *d++ += Pico.snd.dac_val, d++;\r
+ *d++ += Pico.snd.dac_val2, *d++ += Pico.snd.dac_val2;\r
+ while (--len) *d++ += Pico.snd.dac_val, *d++ += Pico.snd.dac_val;\r
} else {\r
s16 *d = PicoIn.sndOut + pos;\r
*d++ += Pico.snd.dac_val2;\r
if (Pico.m.hardware & PMS_HW_FMUSED) {\r
buf += pos;\r
PsndFMUpdate(buf32, len, 0, 0);\r
- while (len--) {\r
- *buf++ += *buf32++;\r
- buf += stereo;\r
- }\r
+ if (stereo) \r
+ while (len--) {\r
+ *buf++ += *buf32;\r
+ *buf++ += *buf32++;\r
+ }\r
+ else\r
+ while (len--) {\r
+ *buf++ += *buf32++;\r
+ }\r
}\r
}\r
\r
s16 *dacbuf = PicoIn.sndOut + (daclen << stereo);\r
Pico.snd.dac_pos += (length-daclen) << 20;\r
*dacbuf++ += Pico.snd.dac_val2;\r
- if (stereo) dacbuf++;\r
+ if (stereo) *dacbuf++ += Pico.snd.dac_val2;\r
for (daclen++; length-daclen > 0; daclen++) {\r
*dacbuf++ += Pico.snd.dac_val;\r
- if (stereo) dacbuf++;\r
+ if (stereo) *dacbuf++ += Pico.snd.dac_val;\r
}\r
Pico.snd.dac_val2 = Pico.snd.dac_val;\r
}\r
\r
// convert + limit to normal 16bit output\r
if (PicoIn.sndOut)\r
- PsndMix_32_to_16l(PicoIn.sndOut+(offset<<stereo), buf32, length-offset);\r
+ PsndMix_32_to_16(PicoIn.sndOut+(offset<<stereo), buf32, length-offset);\r
\r
pprof_end(sound);\r
\r
int len = (length-ym2413len);\r
if (Pico.m.hardware & PMS_HW_FMUSED) {\r
PsndFMUpdate(buf32, len, 0, 0);\r
- while (len--) {\r
- *ym2413buf++ += *buf32++;\r
- ym2413buf += stereo;\r
- }\r
+ if (stereo)\r
+ while (len--) {\r
+ *ym2413buf++ += *buf32;\r
+ *ym2413buf++ += *buf32++;\r
+ }\r
+ else\r
+ while (len--) {\r
+ *ym2413buf++ += *buf32++;\r
+ }\r
}\r
}\r
\r
- // upmix to "stereo" if needed\r
- if (PicoIn.opt & POPT_EN_STEREO) {\r
- int i;\r
- s16 *p;\r
- for (i = length, p = (s16 *)PicoIn.sndOut; i > 0; i--, p+=2)\r
- *(p + 1) = *p;\r
- }\r
-\r
pprof_end(sound);\r
\r
return length;\r
\r
/* set the right mixer func */\r
if (vol >= 5)\r
- PsndMix_32_to_16l = mix_32_to_16l_stereo;\r
+ PsndMix_32_to_16 = mix_32_to_16_stereo;\r
else {\r
- mix_32_to_16l_level = 5 - vol;\r
- PsndMix_32_to_16l = mix_32_to_16l_stereo_lvl;\r
+ mix_32_to_16_level = 5 - vol;\r
+ PsndMix_32_to_16 = mix_32_to_16_stereo_lvl;\r
}\r
}\r
\r