95 lines
2.2 KiB
Objective-C
95 lines
2.2 KiB
Objective-C
/* class A2Computer (category Audio)
|
|
*/
|
|
#import "LibAppleII-Priv.h"
|
|
|
|
@implementation A2Computer (Audio)
|
|
//---------------------------------------------------------------------------
|
|
|
|
static struct
|
|
{
|
|
int silence; // = 0 or 128
|
|
double FIR[kFilterSize]; // partial sums of FIR coefficients
|
|
|
|
} g =
|
|
{
|
|
.silence = 128,
|
|
};
|
|
|
|
|
|
static double Sinc(double x)
|
|
{ return x? sin(x)/x : 1.; }
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
+ (void)_InitAudio
|
|
{/*
|
|
Called once at startup, from '+initialize'. Prepares the digital filter
|
|
coefficients, and sets a default volume level.
|
|
*/
|
|
const double pi = 4. * atan(1.),
|
|
c = pi * 0.4 / kFilterRes;
|
|
double psum = 0.,
|
|
norm = 0.;
|
|
|
|
for (int j = kFilterSize; --j >= 0;)
|
|
{
|
|
int i = 2*j - kFilterSize + 1;
|
|
double h = Sinc(c * i);
|
|
// double x = i * (pi / kFilterSize);
|
|
|
|
// h *= 42 + 50*cos(x) + 8*cos(2*x); // Blackman
|
|
// h *= 54 + 46*cos(x); // Hamming
|
|
// h *= 50 + 50*cos(x); // Hann
|
|
|
|
norm += ( g.FIR[j] = h );
|
|
// NSLog(@"h[%4d] = %f", j, h);
|
|
}
|
|
|
|
for (int j = kFilterSize; --j >= 0;)
|
|
g.FIR[j] = ( psum += (g.FIR[j] / norm) );
|
|
|
|
[A2Computer SetAudioVolume:40];
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
+ (void)SetAudioVolume:(unsigned)volume
|
|
{/*
|
|
Sets the volume level for audio production. Parameter 'volume' should
|
|
be between 0 and 100.
|
|
*/
|
|
if (volume > 100)
|
|
volume = 100;
|
|
A2T.audio.flat = (g.silence - volume - 1L) << 24;
|
|
|
|
long range = -256L * (2 * (int)volume + 1);
|
|
|
|
for (int i = kFilterSize; --i >= 0;)
|
|
A2T.audio.delta[i] =
|
|
((long)(g.FIR[i] * range + 0.5)) << 16;
|
|
|
|
#if 0
|
|
for (int i = LENGTH(gSpkrOut); --i >= 0;)
|
|
gSpkrOut[i] = A2T.audio.flat; //??
|
|
#endif
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
- (void)_DefaultAudio:(uint8_t [])audioOut :(unsigned)nSamples
|
|
{
|
|
if (mHalts & kfHaltNoPower) // then power is off; emit hiss
|
|
{
|
|
for (int i = nSamples/4; --i >= 0;)
|
|
((uint32_t*)audioOut)[i] = 0x01010101 *
|
|
( (g.silence - 8) + (A2Random16() & 15) );
|
|
}
|
|
else // power is on, but execution still halted; emit silence
|
|
{
|
|
memset(audioOut, g.silence, nSamples);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
@end
|