kopia lustrzana https://github.com/Jean-MarcHarvengt/MCUME
544 wiersze
18 KiB
C++
544 wiersze
18 KiB
C++
#include "dcastaway.h"
|
|
|
|
#ifndef NO_SOUND
|
|
|
|
#include<stdio.h>
|
|
#include<stdlib.h>
|
|
#include<string.h>
|
|
|
|
#include<Arduino.h>
|
|
|
|
#include "st.h"
|
|
#include "mem.h"
|
|
#include "m68k_intrf.h"
|
|
#include "sound.h"
|
|
|
|
#define LONGLONG long long
|
|
|
|
#define ENVELOPE_PERIOD(Fine,Coarse) (((unsigned long)Coarse)<<8) + (unsigned long)Fine
|
|
#define NOISE_PERIOD(Freq) ((((unsigned long)Freq)&0x1f)<<11)
|
|
#define TONE_PERIOD(Fine,Coarse) ((((unsigned long)Coarse)&0x0f)<<8) + (unsigned long)Fine
|
|
#define MIXTABLE_SIZE (256*8) /* Large table, so don't overflow */
|
|
#define TONEFREQ_SHIFT 28 /* 4.28 fixed point */
|
|
#define NOISEFREQ_SHIFT 28 /* 4.28 fixed point */
|
|
#define ENVFREQ_SHIFT 16 /* 16.16 fixed */
|
|
|
|
#define SAMPLES_BUFFER_SIZE 1024
|
|
/* Number of generated samples per frame (eg. 44Khz=882) : */
|
|
#define SAMPLES_PER_FRAME ((SOUND_FREQ*2)/50) //((SOUND_FREQ+35)/50)
|
|
/* Frequency of generated samples: */
|
|
#define SAMPLES_FREQ (SOUND_FREQ)
|
|
#define YM_FREQ (2000000/SAMPLES_FREQ) /* YM Frequency 2Mhz */
|
|
|
|
/* Original wave samples */
|
|
/* Shape x Length(repeat 3rd/4th entries) */
|
|
#include "tab_EnvelopeShapeValues.h"
|
|
//static const int EnvelopeShapeValues[16*1024] = { 1,2 };
|
|
/* Use table to convert from (A+B+C) to clipped 'unsigned char' for sound buffer */
|
|
/* -ve and +ve range */
|
|
#include "tab_MixTable.h"
|
|
//static const char MixTable[MIXTABLE_SIZE] = { 1,2 };
|
|
static const char *pMixTable = &MixTable[MIXTABLE_SIZE/2]; /* Signed index into above */
|
|
/* LogTable */
|
|
#include "tab_LogTable.h"
|
|
//static const int LogTable[256] = { 1,2 };
|
|
#include "tab_LogTable16.h"
|
|
//static const int LogTable16[16] = { 1,2 };
|
|
static const int *pEnvelopeLogTable = &LogTable[128];
|
|
|
|
/* Current sample for this time period */
|
|
static int Envelope[SAMPLES_BUFFER_SIZE];
|
|
static int Noise[SAMPLES_BUFFER_SIZE];
|
|
char MixBuffer[MIXBUFFER_SIZE];
|
|
|
|
|
|
|
|
/* Frequency and time period samples */
|
|
static unsigned long ChannelFreq[3], EnvelopeFreq, NoiseFreq; /* Current frequency of each channel A,B,C,Envelope and Noise */
|
|
static int ChannelAmpDecayTime[3]; /* Store counter to show if amplitude is changed to generate 'samples' */
|
|
/* Output channel data */
|
|
static int Channel_A_Buffer[SAMPLES_BUFFER_SIZE],Channel_B_Buffer[SAMPLES_BUFFER_SIZE],Channel_C_Buffer[SAMPLES_BUFFER_SIZE];
|
|
static int ActiveSndBufIdx; /* Current working index into above mix buffer */
|
|
static int nSamplesToGenerate; /* How many samples are needed for this time-frame */
|
|
|
|
/* global values */
|
|
bool bWriteEnvelopeFreq; /* Did write to register '13' - causes frequency reset */
|
|
bool bWriteChannelAAmp, bWriteChannelBAmp, bWriteChannelCAmp; /* Did write to amplitude registers? */
|
|
bool bEnvelopeFreqFlag; /* As above, but cleared each frame for YM saving */
|
|
/* Buffer to store circular samples */
|
|
int nGeneratedSamples; /* Generated samples since audio buffer update */
|
|
int SoundCycles;
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/* Envelope shape table */
|
|
typedef struct
|
|
{
|
|
int WaveStart[4], WaveDelta[4];
|
|
} ENVSHAPE;
|
|
|
|
|
|
/* Square wave look up table */
|
|
static const int SquareWave[16] = { 127,127,127,127,127,127,127,127, -128,-128,-128,-128,-128,-128,-128,-128 };
|
|
|
|
|
|
static long RandomNum;
|
|
|
|
static __inline__ long Misc_NextLongRand(long Seed)
|
|
{
|
|
unsigned long Lo, Hi;
|
|
|
|
Lo = 16807 * (long)(Seed & 0xffff);
|
|
Hi = 16807 * (long)((unsigned long)Seed >> 16);
|
|
Lo += (Hi & 0x7fff) << 16;
|
|
if (Lo > 2147483647L) {
|
|
Lo &= 2147483647L;
|
|
++Lo;
|
|
}
|
|
Lo += Hi >> 15;
|
|
if (Lo > 2147483647L) {
|
|
Lo &= 2147483647L;
|
|
++Lo;
|
|
}
|
|
return((long)Lo);
|
|
}
|
|
|
|
static __inline__ long Misc_GetRandom(void)
|
|
{
|
|
RandomNum = Misc_NextLongRand(RandomNum);
|
|
if (!RandomNum)
|
|
{
|
|
RandomNum++;
|
|
return 0;
|
|
}
|
|
return(RandomNum);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/*
|
|
Init sound tables and envelopes
|
|
*/
|
|
void Sound_Init(void)
|
|
{
|
|
Sound_Reset();
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/*
|
|
Reset the sound emulation
|
|
*/
|
|
void Sound_Reset(void)
|
|
{
|
|
int i;
|
|
|
|
Sound_ClearMixBuffer(); /* Clear buffer */
|
|
|
|
/* Clear cycle counts, buffer index and register '13' flags */
|
|
SoundCycles = 0;
|
|
bEnvelopeFreqFlag = FALSE;
|
|
bWriteEnvelopeFreq = FALSE;
|
|
bWriteChannelAAmp = bWriteChannelBAmp = bWriteChannelCAmp = FALSE;
|
|
|
|
/* Lock audio system before accessing variables that are also use by the callback function! */
|
|
Audio_Lock();
|
|
CompleteSndBufIdx = 0;
|
|
ActiveSndBufIdx = (SOUND_BUFFER_SIZE + SAMPLES_PER_FRAME) % MIXBUFFER_SIZE;
|
|
nGeneratedSamples = 0;
|
|
Audio_Unlock();
|
|
|
|
/* Clear frequency counter */
|
|
for(i=0; i<3; i++)
|
|
{
|
|
ChannelFreq[i] =
|
|
ChannelAmpDecayTime[i] = 0;
|
|
}
|
|
EnvelopeFreq = NoiseFreq = 0;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/*
|
|
Clear mixer buffer, where samples are stored ready to pass to sound player
|
|
*/
|
|
void Sound_ClearMixBuffer(void)
|
|
{
|
|
Audio_Lock();
|
|
|
|
Memory_Clear(MixBuffer, MIXBUFFER_SIZE); /* Clear buffer */
|
|
|
|
Audio_Unlock();
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/*
|
|
Find how many samples to generate and store in 'nSamplesToGenerate'
|
|
Also update 'SoundCycles' to store how many we actually did so generates set amount each frame
|
|
*/
|
|
static void Sound_SetSamplesPassed(void)
|
|
{
|
|
int nSampleCycles;
|
|
int nSamplesPerFrame;
|
|
int Dec=1;
|
|
|
|
/* Check how many cycles have passed, as we use this to help find out if we are playing sample data */
|
|
|
|
/* First, add decay to channel amplitude variables */
|
|
if (SoundCycles>(CYCLES_PER_FRAME/4))
|
|
Dec = 16; /* Been long time between sound writes, must be normal tone sound */
|
|
|
|
if (!bWriteChannelAAmp) /* Not written to amplitude, decay value */
|
|
{
|
|
ChannelAmpDecayTime[0]-=Dec;
|
|
if (ChannelAmpDecayTime[0]<0) ChannelAmpDecayTime[0] = 0;
|
|
}
|
|
if (!bWriteChannelBAmp)
|
|
{
|
|
ChannelAmpDecayTime[1]-=Dec;
|
|
if (ChannelAmpDecayTime[1]<0) ChannelAmpDecayTime[1] = 0;
|
|
}
|
|
if (!bWriteChannelCAmp)
|
|
{
|
|
ChannelAmpDecayTime[2]-=Dec;
|
|
if (ChannelAmpDecayTime[2]<0) ChannelAmpDecayTime[2] = 0;
|
|
}
|
|
|
|
/* 160256 cycles per VBL, 44Khz = 882 samples per VBL */
|
|
/* 882/160256 samples per clock cycle */
|
|
nSamplesPerFrame = SAMPLES_PER_FRAME;
|
|
#if 0 /* Use floats for calculation */
|
|
nSamplesToGenerate = (int)( (float)SoundCycles * ((float)nSamplesPerFrame/(float)CYCLES_PER_FRAME) );
|
|
if (nSamplesToGenerate > nSamplesPerFrame)
|
|
nSamplesToGenerate = nSamplesPerFrame;
|
|
|
|
nSampleCycles = (int)( (float)nSamplesToGenerate / ((float)nSamplesPerFrame/(float)CYCLES_PER_FRAME) );
|
|
SoundCycles -= nSampleCycles;
|
|
#else /* Use integers for calculation - both of these calculations should fit into 32-bit int */
|
|
nSamplesToGenerate = SoundCycles * nSamplesPerFrame / CYCLES_PER_FRAME;
|
|
//printf("nSamplesToGenerate=%i , SoundCycles=%i\n",nSamplesToGenerate,SoundCycles);
|
|
if (nSamplesToGenerate > nSamplesPerFrame)
|
|
nSamplesToGenerate = nSamplesPerFrame;
|
|
|
|
nSampleCycles = nSamplesToGenerate * CYCLES_PER_FRAME / nSamplesPerFrame;
|
|
SoundCycles -= nSampleCycles;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/*
|
|
Generate envelope wave for this time-frame
|
|
*/
|
|
static void Sound_GenerateEnvelope(unsigned char EnvShape, unsigned char Fine, unsigned char Coarse)
|
|
{
|
|
const int *pEnvelopeValues;
|
|
unsigned long EnvelopePeriod,EnvelopeFreqDelta;
|
|
int i;
|
|
|
|
/* Find envelope details */
|
|
if (bWriteEnvelopeFreq)
|
|
EnvelopeFreq = 0;
|
|
pEnvelopeValues = &EnvelopeShapeValues[ (EnvShape&0x0f)*1024 ]; /* Envelope shape values */
|
|
EnvelopePeriod = ENVELOPE_PERIOD((unsigned long)Fine,(unsigned long)Coarse);
|
|
|
|
if (EnvelopePeriod==0) /* Handle div by zero */
|
|
EnvelopeFreqDelta = 0;
|
|
else
|
|
EnvelopeFreqDelta = ((LONGLONG)YM_FREQ<<ENVFREQ_SHIFT) / (EnvelopePeriod); /* 16.16 fixed point */
|
|
|
|
/* Create envelope from current shape and frequency */
|
|
for(i=0; i<nSamplesToGenerate; i++)
|
|
{
|
|
Envelope[i] = pEnvelopeValues[EnvelopeFreq>>ENVFREQ_SHIFT]; /* Store envelope wave, already applied 'log' function */
|
|
EnvelopeFreq += EnvelopeFreqDelta;
|
|
if (EnvelopeFreq&0xfe000000)
|
|
EnvelopeFreq = 0x02000000 | (EnvelopeFreq&0x01ffffff); /* Keep in range 512-1024 once past 511! */
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/*
|
|
Generate nosie for this time-frame
|
|
*/
|
|
static void Sound_GenerateNoise(unsigned char MixerControl, unsigned char NoiseGen)
|
|
{
|
|
int NoiseValue;
|
|
unsigned long NoisePeriod,NoiseFreqDelta;
|
|
int i;
|
|
|
|
NoisePeriod = NOISE_PERIOD((unsigned long)NoiseGen);
|
|
|
|
if (NoisePeriod==0) /* Handle div by zero */
|
|
NoiseFreqDelta = 0;
|
|
else
|
|
NoiseFreqDelta = (((LONGLONG)YM_FREQ)<<NOISEFREQ_SHIFT) / NoisePeriod; /* 4.28 fixed point */
|
|
|
|
/* Generate noise samples */
|
|
for(i=0; i<nSamplesToGenerate; i++)
|
|
{
|
|
NoiseValue = (unsigned int)Misc_GetRandom()%96; /* Get random value */
|
|
if (SquareWave[NoiseFreq>>NOISEFREQ_SHIFT]<=0) /* Add to square wave at given frequency */
|
|
NoiseValue = -NoiseValue;
|
|
|
|
Noise[i] = NoiseValue;
|
|
NoiseFreq += NoiseFreqDelta;
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/*
|
|
Generate channel of samples for this time-frame
|
|
*/
|
|
static void Sound_GenerateChannel(int *pBuffer, unsigned char ToneFine, unsigned char ToneCoarse,unsigned char Amplitude,unsigned char MixerControl,unsigned long *pChannelFreq,int MixMask)
|
|
{
|
|
int *pNoise = Noise, *pEnvelope = Envelope;
|
|
unsigned long ToneFreq=*pChannelFreq;
|
|
unsigned long TonePeriod;
|
|
unsigned long ToneFreqDelta;
|
|
int i,Amp,Mix;
|
|
int ToneOutput,NoiseOutput,MixerOutput,EnvelopeOutput,AmplitudeOutput;
|
|
|
|
TonePeriod = TONE_PERIOD((unsigned long)ToneFine,(unsigned long)ToneCoarse);
|
|
/* Find frequency of channel */
|
|
if (TonePeriod==0)
|
|
ToneFreqDelta = 0; /* Handle div by zero */
|
|
else
|
|
ToneFreqDelta = (((LONGLONG)YM_FREQ)<<TONEFREQ_SHIFT) / TonePeriod; /* 4.28 fixed point */
|
|
Amp = LogTable16[(Amplitude&0x0f)];
|
|
Mix = (MixerControl>>MixMask)&9; /* Read I/O Mixer */
|
|
|
|
/* Check if we are trying to play a 'sample' - we need to up the volume on these as they tend to be rather quiet */
|
|
if ((Amplitude&0x10)==0) /* Fixed level amplitude? */
|
|
{
|
|
ChannelAmpDecayTime[MixMask]++; /* Increment counter to find out if we are playing samples... */
|
|
if (ChannelAmpDecayTime[MixMask]>16)
|
|
ChannelAmpDecayTime[MixMask] = 16; /* And limit */
|
|
}
|
|
|
|
for(i=0; i<nSamplesToGenerate; i++)
|
|
{
|
|
/* Output from Tone Generator(0-255) */
|
|
ToneOutput = SquareWave[ToneFreq>>TONEFREQ_SHIFT];
|
|
|
|
/* Output from Noise Generator(0-255) */
|
|
NoiseOutput = *pNoise++;
|
|
/* Output from Mixer(combines Tone+Noise) */
|
|
switch (Mix) {
|
|
case 0: /* Has Noise and Tone */
|
|
MixerOutput = NoiseOutput+ToneOutput;
|
|
break;
|
|
case 1: /* Has Noise */
|
|
MixerOutput = NoiseOutput;
|
|
break;
|
|
case 8: /* Has Tone */
|
|
MixerOutput = ToneOutput;
|
|
break;
|
|
|
|
default: /* This is used to emulate samples - should give no output, but ST gives set tone!!?? */
|
|
/* MixerControl gets set to give a continuous tone and then then Amplitude */
|
|
/* of channels A,B and C get changed with all other registers in the PSG */
|
|
/* staying as zero's. This produces the sounds from Quartet, Speech, NoiseTracker etc...! */
|
|
MixerOutput = 127;
|
|
}
|
|
|
|
EnvelopeOutput = pEnvelopeLogTable[*pEnvelope++];
|
|
|
|
if ((Amplitude&0x10)==0)
|
|
{
|
|
AmplitudeOutput = Amp; /* Fixed level amplitude */
|
|
|
|
/* As with most emulators, sample playback is always 'quiet'. We check to see if */
|
|
/* the amplitude of a channel is repeatedly changing and when this is detected we */
|
|
/* scale the volume accordingly */
|
|
if (ChannelAmpDecayTime[MixMask]>8)
|
|
AmplitudeOutput <<= 1; /* Scale up by a factor of 2 */
|
|
}
|
|
else
|
|
AmplitudeOutput = EnvelopeOutput;
|
|
|
|
*pBuffer++ = (MixerOutput*AmplitudeOutput)>>8;
|
|
|
|
ToneFreq+=ToneFreqDelta;
|
|
}
|
|
|
|
/* Store back incremented frequency, for next call */
|
|
*pChannelFreq = ToneFreq;
|
|
}
|
|
|
|
#ifdef XXX
|
|
/*-----------------------------------------------------------------------*/
|
|
/*
|
|
Generate samples for all channels during this time-frame
|
|
*/
|
|
static void Sound_GenerateSamples(void)
|
|
{
|
|
int *pChannelA=Channel_A_Buffer, *pChannelB=Channel_B_Buffer, *pChannelC=Channel_C_Buffer;
|
|
int i;
|
|
|
|
/* Anything to do? */
|
|
if (nSamplesToGenerate>0)
|
|
{
|
|
/* Generate envelope/noise samples for this time */
|
|
Sound_GenerateEnvelope(psg[PSG_REG_ENV_SHAPE],psg[PSG_REG_ENV_FINE],psg[PSG_REG_ENV_COARSE]);
|
|
Sound_GenerateNoise(psg[PSG_REG_MIXER_CONTROL],psg[PSG_REG_NOISE_GENERATOR]);
|
|
|
|
/* Generate 3 channels, store to separate buffer so can mix/clip */
|
|
Sound_GenerateChannel(pChannelA,psg[PSG_REG_CHANNEL_A_FINE],psg[PSG_REG_CHANNEL_A_COARSE],psg[PSG_REG_CHANNEL_A_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[0],0);
|
|
Sound_GenerateChannel(pChannelB,psg[PSG_REG_CHANNEL_B_FINE],psg[PSG_REG_CHANNEL_B_COARSE],psg[PSG_REG_CHANNEL_B_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[1],1);
|
|
Sound_GenerateChannel(pChannelC,psg[PSG_REG_CHANNEL_C_FINE],psg[PSG_REG_CHANNEL_C_COARSE],psg[PSG_REG_CHANNEL_C_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[2],2);
|
|
|
|
/* Mix channels together, using table to clip and also convert to 'unsigned char' */
|
|
for(i=0; i<nSamplesToGenerate; i++)
|
|
MixBuffer[(i+ActiveSndBufIdx)%MIXBUFFER_SIZE] = pMixTable[(*pChannelA++) + (*pChannelB++) + (*pChannelC++)];
|
|
|
|
ActiveSndBufIdx = (ActiveSndBufIdx + nSamplesToGenerate) % MIXBUFFER_SIZE;
|
|
nGeneratedSamples += nSamplesToGenerate;
|
|
|
|
/* Reset the write to register '13' flag */
|
|
bWriteEnvelopeFreq = FALSE;
|
|
/* And amplitude write flags */
|
|
bWriteChannelAAmp = bWriteChannelBAmp = bWriteChannelCAmp = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/*
|
|
This is called to built samples up until this clock cycle
|
|
*/
|
|
void Sound_Update(void)
|
|
{
|
|
int OldSndBufIdx = ActiveSndBufIdx;
|
|
|
|
|
|
/* Find how many to generate */
|
|
Sound_SetSamplesPassed();
|
|
/* And generate */
|
|
Sound_GenerateSamples();
|
|
|
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/*
|
|
This is called from the audio callback function to create enough samples
|
|
to fill the current sound buffer.
|
|
*/
|
|
void Sound_UpdateFromAudioCallBack(void)
|
|
{
|
|
/* If there are already enough samples or if we are recording, we should
|
|
* not generate more samples here! */
|
|
if(nGeneratedSamples >= SOUND_BUFFER_SIZE)
|
|
return;
|
|
|
|
nSamplesToGenerate = SOUND_BUFFER_SIZE - nGeneratedSamples;
|
|
|
|
Sound_GenerateSamples();
|
|
Serial.println("vvv");
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
void Sound_Update(void)
|
|
{
|
|
int Dec=1;
|
|
|
|
/* Check how many cycles have passed, as we use this to help find out if we are playing sample data */
|
|
|
|
/* First, add decay to channel amplitude variables */
|
|
if (SoundCycles>(CYCLES_PER_FRAME/4))
|
|
Dec = 16; /* Been long time between sound writes, must be normal tone sound */
|
|
|
|
if (!bWriteChannelAAmp) /* Not written to amplitude, decay value */
|
|
{
|
|
ChannelAmpDecayTime[0]-=Dec;
|
|
if (ChannelAmpDecayTime[0]<0) ChannelAmpDecayTime[0] = 0;
|
|
}
|
|
if (!bWriteChannelBAmp)
|
|
{
|
|
ChannelAmpDecayTime[1]-=Dec;
|
|
if (ChannelAmpDecayTime[1]<0) ChannelAmpDecayTime[1] = 0;
|
|
}
|
|
if (!bWriteChannelCAmp)
|
|
{
|
|
ChannelAmpDecayTime[2]-=Dec;
|
|
if (ChannelAmpDecayTime[2]<0) ChannelAmpDecayTime[2] = 0;
|
|
}
|
|
|
|
//Sound_Update();
|
|
|
|
/* Clear write to register '13', used for YM file saving */
|
|
//bEnvelopeFreqFlag = FALSE;
|
|
|
|
/* Reset the write to register '13' flag */
|
|
bWriteEnvelopeFreq = FALSE;
|
|
/* And amplitude write flags */
|
|
bWriteChannelAAmp = bWriteChannelBAmp = bWriteChannelCAmp = FALSE;
|
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/*
|
|
On each VBL (50fps) complete samples.
|
|
*/
|
|
void Sound_Update_VBL(void)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
void Sound_UpdateFromCallBack16(short *pBuffer, int len)
|
|
{
|
|
len = len >> 1;
|
|
|
|
int *pChannelA=Channel_A_Buffer, *pChannelB=Channel_B_Buffer, *pChannelC=Channel_C_Buffer;
|
|
int i;
|
|
nSamplesToGenerate = len;
|
|
|
|
/* Generate envelope/noise samples for this time */
|
|
Sound_GenerateEnvelope(psg[PSG_REG_ENV_SHAPE],psg[PSG_REG_ENV_FINE],psg[PSG_REG_ENV_COARSE]);
|
|
Sound_GenerateNoise(psg[PSG_REG_MIXER_CONTROL],psg[PSG_REG_NOISE_GENERATOR]);
|
|
|
|
/* Generate 3 channels, store to separate buffer so can mix/clip */
|
|
Sound_GenerateChannel(pChannelA,psg[PSG_REG_CHANNEL_A_FINE],psg[PSG_REG_CHANNEL_A_COARSE],psg[PSG_REG_CHANNEL_A_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[0],0);
|
|
Sound_GenerateChannel(pChannelB,psg[PSG_REG_CHANNEL_B_FINE],psg[PSG_REG_CHANNEL_B_COARSE],psg[PSG_REG_CHANNEL_B_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[1],1);
|
|
Sound_GenerateChannel(pChannelC,psg[PSG_REG_CHANNEL_C_FINE],psg[PSG_REG_CHANNEL_C_COARSE],psg[PSG_REG_CHANNEL_C_AMP],psg[PSG_REG_MIXER_CONTROL],&ChannelFreq[2],2);
|
|
|
|
/* Mix channels together, using table to clip and also convert to 'unsigned char' */
|
|
for(i=0; i<len; i++) {
|
|
//short s = ((*pChannelA++) +(*pChannelB++) + (*pChannelC++))<<4;
|
|
//*pBuffer++ = s;
|
|
//*pBuffer++ = s;
|
|
//char s = pMixTable[(*pChannelA++) + (*pChannelB++) + (*pChannelC++)];
|
|
short s = (*pChannelA++) + (*pChannelB++) + (*pChannelC++);
|
|
*pBuffer++ = (short)s << 7;
|
|
s = (*pChannelA++) + (*pChannelB++) + (*pChannelC++);
|
|
|
|
// s = pMixTable[(*pChannelA++) + (*pChannelB++) + (*pChannelC++)];
|
|
*pBuffer++ = (short)s << 7;
|
|
//*pBuffer++ = (short)s << 8;
|
|
//*pBuffer++ = 0;
|
|
//
|
|
}
|
|
|
|
bWriteEnvelopeFreq = FALSE;
|
|
/* And amplitude write flags */
|
|
bWriteChannelAAmp = bWriteChannelBAmp = bWriteChannelCAmp = FALSE;
|
|
|
|
}
|
|
|
|
#else
|
|
#warning NO_SOUND
|
|
#warning NO_SOUND
|
|
#warning NO_SOUND
|
|
#warning NO_SOUND
|
|
#warning NO_SOUND
|
|
#warning NO_SOUND
|
|
#endif
|