mirror of
https://github.com/libretro/RACE.git
synced 2025-02-18 16:01:02 +00:00
700 lines
18 KiB
C++
700 lines
18 KiB
C++
// Flavor modified sound.c and sound.h from NEOPOP
|
|
// which was originally based on sn76496.c from MAME
|
|
// some ideas also taken from NeoPop-SDL code
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Originally from
|
|
// NEOPOP : Emulator as in Dreamland
|
|
//
|
|
// Copyright (c) 2001-2002 by neopop_uk
|
|
//---------------------------------------------------------------------------
|
|
|
|
//---------------------------------------------------------------------------
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version. See also the license.txt file for
|
|
// additional informations.
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
/************************************************************************
|
|
* *
|
|
* Portions, but not all of this source file are based on MAME v0.60 *
|
|
* File "sn76496.c". All copyright goes to the original author. *
|
|
* The remaining parts, including DAC processing, by neopop_uk *
|
|
* *
|
|
************************************************************************/
|
|
|
|
#ifndef __GP32__
|
|
#include "StdAfx.h"
|
|
#endif
|
|
|
|
#include "neopopsound.h"
|
|
|
|
|
|
#include "main.h"
|
|
#include "memory.h"
|
|
//#include "menu.h"
|
|
|
|
|
|
//=============================================================================
|
|
|
|
SoundChip toneChip;
|
|
SoundChip noiseChip;
|
|
|
|
//==== DAC
|
|
#ifdef TARGET_WIN
|
|
#define DAC_BUFFERSIZE (2560 * 1024) //at (256 * 1024) the PC version will crash on MS2 intro
|
|
#else
|
|
#define DAC_BUFFERSIZE (256 * 1024) //at (256 * 1024) the PC version will crash on MS2 intro
|
|
#endif
|
|
|
|
int dacLBufferRead, dacLBufferWrite, dacLBufferCount;
|
|
_u16 dacBufferL[DAC_BUFFERSIZE];
|
|
int fixsoundmahjong;
|
|
|
|
#if !defined(__GP32__) && !defined(__LIBRETRO__)
|
|
|
|
int volume = SDL_MIX_MAXVOLUME;//SDL_MIX_MAXVOLUME / 2;
|
|
|
|
void increaseVolume()
|
|
{
|
|
if(volume < SDL_MIX_MAXVOLUME)
|
|
volume++;
|
|
}
|
|
|
|
void decreaseVolume()
|
|
{
|
|
if(volume > 0)
|
|
volume--;
|
|
}
|
|
|
|
#endif
|
|
|
|
//=============================================================================
|
|
|
|
#define SOUNDCHIPCLOCK (3072000) //Unverified / sounds correct
|
|
|
|
#define MAX_OUTPUT 0x7fff
|
|
#define STEP 0x10000 //Fixed point adjuster
|
|
|
|
#define MAX_OUTPUT_STEP 0x7fff0000
|
|
#define STEP_SHIFT 16
|
|
|
|
static _u32 VolTable[16];
|
|
static _u32 UpdateStep = 0; //Number of steps during one sample.
|
|
|
|
/* Formulas for noise generator */
|
|
/* bit0 = output */
|
|
|
|
/* noise feedback for white noise mode (verified on real SN76489 by John Kortink) */
|
|
#define FB_WNOISE 0x14002 /* (16bits) bit16 = bit0(out) ^ bit2 ^ bit15 */
|
|
|
|
/* noise feedback for periodic noise mode */
|
|
#define FB_PNOISE 0x08000 /* 15bit rotate */
|
|
|
|
/* noise generator start preset (for periodic noise) */
|
|
#define NG_PRESET 0x0f35
|
|
|
|
#define max(a,b) (a>b?a:b)
|
|
#define min(a,b) (a<b?a:b)
|
|
|
|
//=============================================================================
|
|
|
|
static _u16 sample_chip_tone(void)
|
|
{
|
|
int i;
|
|
|
|
int vol[3];
|
|
unsigned int out;
|
|
int left;
|
|
|
|
/* vol[] keeps track of how long each square wave stays */
|
|
/* in the 1 position during the sample period. */
|
|
vol[0] = vol[1] = vol[2] = /*vol[3] = */ 0;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
if (toneChip.Output[i]) vol[i] += toneChip.Count[i];
|
|
toneChip.Count[i] -= STEP;
|
|
|
|
/* Period[i] is the half period of the square wave. Here, in each */
|
|
/* loop I add Period[i] twice, so that at the end of the loop the */
|
|
/* square wave is in the same status (0 or 1) it was at the start. */
|
|
/* vol[i] is also incremented by Period[i], since the wave has been 1 */
|
|
/* exactly half of the time, regardless of the initial position. */
|
|
/* If we exit the loop in the middle, Output[i] has to be inverted */
|
|
/* and vol[i] incremented only if the exit status of the square */
|
|
/* wave is 1. */
|
|
|
|
while (toneChip.Count[i] <= 0)
|
|
{
|
|
toneChip.Count[i] += toneChip.Period[i];
|
|
if (toneChip.Count[i] > 0)
|
|
{
|
|
toneChip.Output[i] ^= 1;
|
|
if (toneChip.Output[i]) vol[i] += toneChip.Period[i];
|
|
break;
|
|
}
|
|
toneChip.Count[i] += toneChip.Period[i];
|
|
vol[i] += toneChip.Period[i];
|
|
}
|
|
if (toneChip.Output[i]) vol[i] -= toneChip.Count[i];
|
|
}
|
|
/*
|
|
left = STEP;
|
|
do
|
|
{
|
|
int nextevent;
|
|
|
|
if (toneChip.Count[3] < left) nextevent = toneChip.Count[3];
|
|
else nextevent = left;
|
|
|
|
if (toneChip.Output[3]) vol[3] += toneChip.Count[3];
|
|
toneChip.Count[3] -= nextevent;
|
|
if (toneChip.Count[3] <= 0)
|
|
{
|
|
if (toneChip.RNG & 1) toneChip.RNG ^= toneChip.NoiseFB;
|
|
toneChip.RNG >>= 1;
|
|
toneChip.Output[3] = toneChip.RNG & 1;
|
|
toneChip.Count[3] += toneChip.Period[3];
|
|
if (toneChip.Output[3]) vol[3] += toneChip.Period[3];
|
|
}
|
|
if (toneChip.Output[3]) vol[3] -= toneChip.Count[3];
|
|
|
|
left -= nextevent;
|
|
} while (left > 0);
|
|
*/
|
|
|
|
out = vol[0] * toneChip.Volume[0] + vol[1] * toneChip.Volume[1] +
|
|
vol[2] * toneChip.Volume[2];
|
|
|
|
//if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP;
|
|
if (out > MAX_OUTPUT_STEP) out = MAX_OUTPUT_STEP;
|
|
|
|
return out>>STEP_SHIFT;//out / STEP;
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
static _u16 sample_chip_noise(void)
|
|
{
|
|
int i;
|
|
|
|
//int vol[4];
|
|
int vol3 = 0;
|
|
unsigned int out;
|
|
int left;
|
|
|
|
/* vol[] keeps track of how long each square wave stays */
|
|
/* in the 1 position during the sample period. */
|
|
/*
|
|
vol[0] = vol[1] = vol[2] = vol[3] = 0;
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
if (noiseChip.Output[i]) vol[i] += noiseChip.Count[i];
|
|
noiseChip.Count[i] -= STEP;
|
|
|
|
// Period[i] is the half period of the square wave. Here, in each
|
|
// loop I add Period[i] twice, so that at the end of the loop the
|
|
// square wave is in the same status (0 or 1) it was at the start.
|
|
// vol[i] is also incremented by Period[i], since the wave has been 1
|
|
// exactly half of the time, regardless of the initial position.
|
|
// If we exit the loop in the middle, Output[i] has to be inverted
|
|
// and vol[i] incremented only if the exit status of the square
|
|
// wave is 1.
|
|
|
|
while (noiseChip.Count[i] <= 0)
|
|
{
|
|
noiseChip.Count[i] += noiseChip.Period[i];
|
|
if (noiseChip.Count[i] > 0)
|
|
{
|
|
noiseChip.Output[i] ^= 1;
|
|
if (noiseChip.Output[i]) vol[i] += noiseChip.Period[i];
|
|
break;
|
|
}
|
|
noiseChip.Count[i] += noiseChip.Period[i];
|
|
vol[i] += noiseChip.Period[i];
|
|
}
|
|
if (noiseChip.Output[i]) vol[i] -= noiseChip.Count[i];
|
|
}
|
|
*/
|
|
if (noiseChip.Volume[3])
|
|
{
|
|
left = STEP;
|
|
do
|
|
{
|
|
int nextevent = min(noiseChip.Count[3],left);
|
|
|
|
//if (noiseChip.Count[3] < left) nextevent = noiseChip.Count[3];
|
|
//else nextevent = left;
|
|
|
|
if (noiseChip.Output[3]) vol3 += noiseChip.Count[3];
|
|
noiseChip.Count[3] -= nextevent;
|
|
if (noiseChip.Count[3] <= 0)
|
|
{
|
|
if (noiseChip.RNG & 1) noiseChip.RNG ^= noiseChip.NoiseFB;
|
|
noiseChip.RNG >>= 1;
|
|
noiseChip.Output[3] = noiseChip.RNG & 1;
|
|
noiseChip.Count[3] += noiseChip.Period[3];
|
|
if (noiseChip.Output[3]) vol3 += noiseChip.Period[3];
|
|
}
|
|
if (noiseChip.Output[3]) vol3 -= noiseChip.Count[3];
|
|
|
|
left -= nextevent;
|
|
} while (left > 0);
|
|
}
|
|
out = vol3 * noiseChip.Volume[3];
|
|
|
|
//if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP;
|
|
if (out > MAX_OUTPUT_STEP) out = MAX_OUTPUT_STEP;
|
|
|
|
return out>>STEP_SHIFT;//out / STEP;
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
void sound_update(_u16* chip_buffer, int length_bytes)
|
|
{
|
|
length_bytes >>= 1;//turn it into words
|
|
while (length_bytes)
|
|
{
|
|
//Mix a mono track out of: (Tone + Noise) >> 1
|
|
//Write it to the sound buffer
|
|
*(chip_buffer++) = (sample_chip_tone() + sample_chip_noise()) >> 1;
|
|
|
|
length_bytes--;
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
void WriteSoundChip(SoundChip* chip, _u8 data)
|
|
{
|
|
#if !defined(__GP32__) && !defined(__LIBRETRO__)
|
|
SDL_LockAudio();
|
|
#endif
|
|
//Command
|
|
if (data & 0x80)
|
|
{
|
|
int r = (data & 0x70) >> 4;
|
|
int c = r>>1;//r/2;
|
|
|
|
chip->LastRegister = r;
|
|
chip->Register[r] = (chip->Register[r] & 0x3f0) | (data & 0x0f);
|
|
|
|
switch(r)
|
|
{
|
|
case 0: /* tone 0 : frequency */
|
|
case 2: /* tone 1 : frequency */
|
|
case 4: /* tone 2 : frequency */
|
|
chip->Period[c] = UpdateStep * chip->Register[r];
|
|
if (chip->Period[c] == 0) chip->Period[c] = UpdateStep;
|
|
if (r == 4)
|
|
{
|
|
/* update noise shift frequency */
|
|
if ((chip->Register[6] & 0x03) == 0x03)
|
|
chip->Period[3] = chip->Period[2]<<1;
|
|
}
|
|
break;
|
|
|
|
case 1: /* tone 0 : volume */
|
|
case 3: /* tone 1 : volume */
|
|
case 5: /* tone 2 : volume */
|
|
case 7: /* noise : volume */
|
|
#ifdef NEOPOP_DEBUG
|
|
if (filter_sound)
|
|
{
|
|
if (chip == &toneChip)
|
|
system_debug_message("sound (T): Set Tone %d Volume to %d (0 = min, 15 = max)", c, 15 - (data & 0xF));
|
|
else
|
|
system_debug_message("sound (N): Set Tone %d Volume to %d (0 = min, 15 = max)", c, 15 - (data & 0xF));
|
|
}
|
|
#endif
|
|
chip->Volume[c] = VolTable[data & 0xF];
|
|
break;
|
|
|
|
case 6: /* noise : frequency, mode */
|
|
{
|
|
int n = chip->Register[6];
|
|
#ifdef NEOPOP_DEBUG
|
|
if (filter_sound)
|
|
{
|
|
char *pm, *nm = "White";
|
|
if ((n & 4)) nm = "Periodic";
|
|
|
|
switch(n & 3)
|
|
{
|
|
case 0: pm = "N/512"; break;
|
|
case 1: pm = "N/1024"; break;
|
|
case 2: pm = "N/2048"; break;
|
|
case 3: pm = "Tone#2"; break;
|
|
}
|
|
|
|
if (chip == &toneChip)
|
|
system_debug_message("sound (T): Set Noise Mode to %s, Period = %s", nm, pm);
|
|
else
|
|
system_debug_message("sound (N): Set Noise Mode to %s, Period = %s", nm, pm);
|
|
}
|
|
#endif
|
|
chip->NoiseFB = (n & 4) ? FB_WNOISE : FB_PNOISE;
|
|
n &= 3;
|
|
/* N/512,N/1024,N/2048,Tone #2 output */
|
|
chip->Period[3] = (n == 3) ? 2 * chip->Period[2] : (UpdateStep << (5+n));
|
|
|
|
/* reset noise shifter */
|
|
chip->RNG = NG_PRESET;
|
|
chip->Output[3] = chip->RNG & 1;
|
|
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int r = chip->LastRegister;
|
|
int c = r/2;
|
|
|
|
switch (r)
|
|
{
|
|
case 0: /* tone 0 : frequency */
|
|
case 2: /* tone 1 : frequency */
|
|
case 4: /* tone 2 : frequency */
|
|
chip->Register[r] = (chip->Register[r] & 0x0f) | ((data & 0x3f) << 4);
|
|
chip->Period[c] = UpdateStep * chip->Register[r];
|
|
if (chip->Period[c] == 0) chip->Period[c] = UpdateStep;
|
|
if (r == 4)
|
|
{
|
|
/* update noise shift frequency */
|
|
if ((chip->Register[6] & 0x03) == 0x03)
|
|
chip->Period[3] = chip->Period[2]<<1;
|
|
}
|
|
#ifdef NEOPOP_DEBUG
|
|
if (filter_sound)
|
|
{
|
|
if (chip == &toneChip)
|
|
system_debug_message("sound (T): Set Tone %d Frequency to %d", c, chip->Register[r]);
|
|
else
|
|
system_debug_message("sound (N): Set Tone %d Frequency to %d", c, chip->Register[r]);
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
#if !defined(__GP32__) && !defined(__LIBRETRO__)
|
|
SDL_UnlockAudio();
|
|
#endif
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
//#ifdef __LIBRETRO__
|
|
void dac_writeL(unsigned char data)
|
|
{
|
|
static int conv=5;
|
|
#if !defined(__GP32__) && !defined(__LIBRETRO__)
|
|
SDL_LockAudio();
|
|
#endif
|
|
|
|
#ifdef __LIBRETRO__
|
|
//pretend that conv=5.5 (44100/8000) conversion factor
|
|
|
|
if(conv==5)
|
|
conv=6;
|
|
else
|
|
{
|
|
conv=5;
|
|
|
|
//Arregla el sonido del Super Real Mahjong
|
|
if (fixsoundmahjong>500)
|
|
conv=3;
|
|
}
|
|
|
|
#else
|
|
conv=1;
|
|
#endif
|
|
|
|
for(int i=0;i<conv;i++)
|
|
{
|
|
//Write to buffer
|
|
dacBufferL[dacLBufferWrite++] = (data-0x80)<<8;
|
|
|
|
//dacLBufferWrite++;
|
|
if (dacLBufferWrite == DAC_BUFFERSIZE)
|
|
dacLBufferWrite = 0;
|
|
|
|
//Overflow?
|
|
dacLBufferCount++;
|
|
if (dacLBufferCount == DAC_BUFFERSIZE)
|
|
{
|
|
//dbg_printf("dac_write: DAC buffer overflow\nPlease report this to the author.");
|
|
dacLBufferCount = 0;
|
|
}
|
|
}
|
|
|
|
#if !defined(__GP32__) && !defined(__LIBRETRO__)
|
|
SDL_UnlockAudio();
|
|
#endif
|
|
}
|
|
//#endif
|
|
|
|
/*void dac_writeR(unsigned char data)
|
|
{
|
|
SDL_LockAudio();
|
|
//Write to buffer
|
|
dacBufferR[dacRBufferWrite] = data;
|
|
dacRBufferWrite++;
|
|
if (dacRBufferWrite == DAC_BUFFERSIZE)
|
|
dacRBufferWrite = 0;
|
|
|
|
//Overflow?
|
|
dacRBufferCount++;
|
|
if (dacRBufferCount == DAC_BUFFERSIZE)
|
|
{
|
|
dbg_printf("dac_write: DAC buffer overflow\nPlease report this to the author.");
|
|
dacRBufferCount = 0;
|
|
}
|
|
SDL_UnlockAudio();
|
|
}*/
|
|
|
|
void dac_mixer(_u16* stream, int length_bytes)
|
|
{
|
|
#if !defined(__GP32__) && !defined(__LIBRETRO__)
|
|
int length_words = length_bytes>>1;
|
|
length_bytes &= 0xFFFFFFFE; //make sure it's 16bit safe
|
|
|
|
if(dacLBufferRead+length_words >= DAC_BUFFERSIZE)
|
|
{
|
|
SDL_MixAudio((Uint8*)stream, (Uint8*)&dacBufferL[dacLBufferRead], (DAC_BUFFERSIZE-dacLBufferRead)*2, volume); //mix it to the buffer
|
|
SDL_MixAudio((Uint8*)&stream[DAC_BUFFERSIZE-dacLBufferRead], (Uint8*)dacBufferL, length_bytes-((DAC_BUFFERSIZE-dacLBufferRead)*2), volume); //mix it to the buffer
|
|
dacLBufferRead = length_words-(DAC_BUFFERSIZE-dacLBufferRead);
|
|
}
|
|
else
|
|
{
|
|
SDL_MixAudio((Uint8*)stream, (Uint8*)&dacBufferL[dacLBufferRead], length_bytes, volume); //mix it to the buffer
|
|
dacLBufferRead += length_words;
|
|
}
|
|
|
|
dacLBufferCount -= length_words; //need it in 16bits
|
|
#endif
|
|
}
|
|
|
|
|
|
void dac_update(_u16* dac_buffer, int length_bytes)
|
|
{
|
|
while (length_bytes > 1)
|
|
{
|
|
//Copy then clear DAC data
|
|
#ifdef __LIBRETRO__
|
|
*(dac_buffer++) |= dacBufferL[dacLBufferRead];
|
|
#else
|
|
*(dac_buffer++) = dacBufferL[dacLBufferRead];
|
|
#endif
|
|
dacBufferL[dacLBufferRead] = 0; //silence?
|
|
|
|
length_bytes -= 2; // 1 byte = 8 bits
|
|
|
|
if (dacLBufferCount > 0)
|
|
{
|
|
dacLBufferCount--;
|
|
|
|
//Advance the DAC read
|
|
// dacLBufferRead++;
|
|
if (++dacLBufferRead == DAC_BUFFERSIZE)
|
|
dacLBufferRead = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
#ifdef __GP32__
|
|
volatile int soundON = 0;
|
|
#endif
|
|
|
|
//Resets the sound chips, also used whenever sound options are changed
|
|
void sound_init(int SampleRate)
|
|
{
|
|
int i;
|
|
double out;
|
|
|
|
/* the base clock for the tone generators is the chip clock divided by 16; */
|
|
/* for the noise generator, it is clock / 256. */
|
|
/* Here we calculate the number of steps which happen during one sample */
|
|
/* at the given sample rate. No. of events = sample rate / (clock/16). */
|
|
/* STEP is a multiplier used to turn the fraction into a fixed point */
|
|
/* number. */
|
|
UpdateStep = (_u32)(((double)STEP * SampleRate * 16) / SOUNDCHIPCLOCK);
|
|
|
|
//Initialise Left Chip
|
|
memset(&toneChip, 0, sizeof(SoundChip));
|
|
|
|
//Initialise Right Chip
|
|
memset(&noiseChip, 0, sizeof(SoundChip));
|
|
|
|
//Default register settings
|
|
for (i = 0;i < 8;i+=2)
|
|
{
|
|
toneChip.Register[i] = 0;
|
|
toneChip.Register[i + 1] = 0x0f; /* volume = 0 */
|
|
noiseChip.Register[i] = 0;
|
|
noiseChip.Register[i + 1] = 0x0f; /* volume = 0 */
|
|
}
|
|
|
|
for (i = 0;i < 4;i++)
|
|
{
|
|
toneChip.Output[i] = 0;
|
|
toneChip.Period[i] = toneChip.Count[i] = UpdateStep;
|
|
noiseChip.Output[i] = 0;
|
|
noiseChip.Period[i] = noiseChip.Count[i] = UpdateStep;
|
|
}
|
|
|
|
//Build the volume table
|
|
out = MAX_OUTPUT / 3;
|
|
|
|
/* build volume table (2dB per step) */
|
|
for (i = 0;i < 15;i++)
|
|
{
|
|
VolTable[i] = (_u32)out;
|
|
out /= 1.258925412; /* = 10 ^ (2/20) = 2dB */
|
|
}
|
|
VolTable[15] = 0;
|
|
|
|
|
|
//Clear the DAC buffer
|
|
for (i = 0; i < DAC_BUFFERSIZE; i++)
|
|
dacBufferL[i] = 0;
|
|
|
|
dacLBufferCount = 0;
|
|
dacLBufferRead = 0;
|
|
dacLBufferWrite = 0;
|
|
|
|
#ifdef __GP32__
|
|
soundON = 1;
|
|
#endif
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
|
|
#ifdef __LIBRETRO__
|
|
#define NGPC_CHIP_FREQUENCY 44100
|
|
#else
|
|
#define NGPC_CHIP_FREQUENCY 8000
|
|
#endif
|
|
int chip_freq=NGPC_CHIP_FREQUENCY;//what we'd prefer
|
|
|
|
#define CHIPBUFFERLENGTH 35280
|
|
|
|
#define UNDEFINED 0xFFFFFF
|
|
|
|
// ====== Chip sound =========
|
|
//static LPDIRECTSOUNDBUFFER chipBuffer = NULL; // Chip Buffer
|
|
static int lastChipWrite = 0, chipWrite = UNDEFINED; //Write Cursor
|
|
|
|
// ====== DAC sound =========
|
|
//static LPDIRECTSOUNDBUFFER dacBuffer = NULL; // DAC Buffer
|
|
static int lastDacWrite = 0, dacWrite = UNDEFINED; //Write Cursor
|
|
|
|
|
|
_u8 blockSound[CHIPBUFFERLENGTH], blockDAC[CHIPBUFFERLENGTH]; // Gets filled with sound data.
|
|
unsigned int blockSoundWritePtr = 0;
|
|
unsigned int blockSoundReadPtr = 0;
|
|
|
|
void system_sound_chipreset(void)
|
|
{
|
|
//Initialises sound chips, matching frequncies
|
|
sound_init(chip_freq);
|
|
}
|
|
|
|
#ifdef __GP32__
|
|
|
|
int audioCallback(unsigned short* sndBuf,int len) {
|
|
int i,smp;
|
|
if (soundON==0)
|
|
return 0;
|
|
for (i=0;i<len;i++)
|
|
{
|
|
smp = (sample_chip_tone() + sample_chip_noise()) >> 1;
|
|
smp = (smp + dacBufferL[dacLBufferRead]) >> 1;
|
|
|
|
*(sndBuf++) = smp;
|
|
*(sndBuf++) = smp; // stereo ?
|
|
dacBufferL[dacLBufferRead] = 0; //silence?
|
|
if (dacLBufferCount > 0)
|
|
{
|
|
dacLBufferCount--;
|
|
if (++dacLBufferRead == DAC_BUFFERSIZE)
|
|
dacLBufferRead = 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifndef __LIBRETRO__
|
|
void mixaudioCallback(void *userdata, Uint8 *stream, int len)
|
|
{
|
|
#ifndef __GP32__
|
|
sound_update((_u16*)blockSound, len); //Get sound data
|
|
// memcpy(stream, blockSound, len); //put it in the buffer
|
|
SDL_MixAudio(stream, blockSound, len, volume); //mix it to the buffer
|
|
|
|
if(dacLBufferCount >= len)
|
|
{
|
|
//dac_update((_u16*)blockDAC, len); //Get DAC data
|
|
//SDL_MixAudio(stream, blockDAC, len, volume); //mix it to the buffer
|
|
|
|
dac_mixer((_u16*)stream, len); //Get DAC data
|
|
}
|
|
#endif
|
|
}
|
|
#endif /* __LIBRETRO__ */
|
|
|
|
int sound_system_init()
|
|
{
|
|
#if !defined(__GP32__) && !defined(__LIBRETRO__)
|
|
//set up SDL sound here?
|
|
SDL_AudioSpec fmt, retFmt;
|
|
|
|
fmt.freq = chip_freq; //11025 is good for dac_ sound
|
|
fmt.format = AUDIO_S16;
|
|
fmt.channels = 1;
|
|
#ifdef __LIBRETRO__
|
|
fmt.samples = 512;
|
|
#else
|
|
fmt.samples = 512;
|
|
#endif
|
|
fmt.callback = mixaudioCallback;
|
|
fmt.userdata = NULL;
|
|
|
|
/* Open the audio device and start playing sound! */
|
|
if ( SDL_OpenAudio(&fmt, &retFmt) < 0 ) {
|
|
fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError());
|
|
exit(1);
|
|
}
|
|
|
|
chip_freq = retFmt.freq;
|
|
|
|
system_sound_chipreset(); //Resets chips
|
|
|
|
SDL_PauseAudio(0);
|
|
#else
|
|
system_sound_chipreset(); //Resets chips
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
|
|
//call this every so often to update the sound output
|
|
void system_sound_update(int nframes)
|
|
{
|
|
}
|
|
|
|
|
|
|