1 |
|
/* |
2 |
|
* SID.cpp - 6581 emulation |
3 |
|
* |
4 |
< |
* Frodo (C) 1994-1997,2002-2003 Christian Bauer |
4 |
> |
* Frodo Copyright (C) Christian Bauer |
5 |
|
* |
6 |
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
* it under the terms of the GNU General Public License as published by |
23 |
|
* ------------------ |
24 |
|
* |
25 |
|
* - Lots of empirically determined constants in the filter calculations |
26 |
– |
* - Voice 3 cannot be muted |
26 |
|
*/ |
27 |
|
|
28 |
|
#include "sysdeps.h" |
32 |
|
#include "Prefs.h" |
33 |
|
|
34 |
|
#ifdef __BEOS__ |
35 |
< |
#include <MediaKit.h> |
35 |
> |
#include <media/SoundPlayer.h> |
36 |
|
#endif |
37 |
|
|
38 |
|
#ifdef AMIGA |
348 |
|
// The following bit is set for the modulating |
349 |
|
// voice, not for the modulated one (as the SID bits) |
350 |
|
bool sync; // Sync modulation bit |
351 |
+ |
bool mute; // Voice muted (voice 3 only) |
352 |
|
}; |
353 |
|
|
354 |
|
// Renderer class |
355 |
|
class DigitalRenderer : public SIDRenderer { |
356 |
|
public: |
357 |
– |
#if defined(__BEOS__) || defined(__riscos__) |
357 |
|
DigitalRenderer(C64 *c64); |
359 |
– |
#else |
360 |
– |
DigitalRenderer(); |
361 |
– |
#endif |
358 |
|
virtual ~DigitalRenderer(); |
359 |
|
|
360 |
|
virtual void Reset(void); |
373 |
|
void calc_buffer(int16 *buf, long count); |
374 |
|
#endif |
375 |
|
|
376 |
+ |
C64 *the_c64; // Pointer to C64 object |
377 |
+ |
|
378 |
|
bool ready; // Flag: Renderer has initialized and is ready |
379 |
|
uint8 volume; // Master volume |
382 |
– |
bool v3_mute; // Voice 3 muted |
380 |
|
|
381 |
|
static uint16 TriTable[0x1000*2]; // Tables for certain waveforms |
382 |
|
static const uint16 TriSawTable[0x100]; |
415 |
|
int sample_in_ptr; // Index in sample_buf for writing |
416 |
|
|
417 |
|
#ifdef __BEOS__ |
418 |
< |
static bool stream_func(void *arg, char *buf, size_t count, void *header); |
419 |
< |
C64 *the_c64; // Pointer to C64 object |
420 |
< |
BDACStream *the_stream; // Pointer to stream |
424 |
< |
BSubscriber *the_sub; // Pointer to subscriber |
425 |
< |
bool in_stream; // Flag: Subscriber has entered stream |
418 |
> |
static void buffer_proc(void *cookie, void *buffer, size_t size, const media_raw_audio_format &format); |
419 |
> |
BSoundPlayer *the_player; // Pointer to sound player |
420 |
> |
bool player_stopped; // Flag: player stopped |
421 |
|
#endif |
422 |
|
|
423 |
|
#ifdef AMIGA |
446 |
|
int fd; |
447 |
|
audio_info status; |
448 |
|
uint_t sent_samples,delta_samples; |
449 |
< |
WORD *sound_calc_buf; |
449 |
> |
int16 *sound_calc_buf; |
450 |
|
#endif |
451 |
|
|
452 |
|
#ifdef __hpux |
453 |
|
int fd; |
454 |
|
audio_status status; |
455 |
< |
int16 * sound_calc_buf; |
455 |
> |
int16 *sound_calc_buf; |
456 |
|
int linecnt; |
457 |
|
#endif |
458 |
|
|
488 |
|
#ifdef __riscos__ |
489 |
|
int linecnt, sndbufsize; |
490 |
|
uint8 *sound_buffer; |
496 |
– |
C64 *the_c64; |
491 |
|
#endif |
492 |
|
}; |
493 |
|
|
818 |
|
* Constructor |
819 |
|
*/ |
820 |
|
|
827 |
– |
#if defined(__BEOS__) || defined(__riscos__) |
821 |
|
DigitalRenderer::DigitalRenderer(C64 *c64) : the_c64(c64) |
829 |
– |
#else |
830 |
– |
DigitalRenderer::DigitalRenderer() |
831 |
– |
#endif |
822 |
|
{ |
823 |
|
// Link voices together |
824 |
|
voice[0].mod_by = &voice[2]; |
867 |
|
void DigitalRenderer::Reset(void) |
868 |
|
{ |
869 |
|
volume = 0; |
880 |
– |
v3_mute = false; |
870 |
|
|
871 |
|
for (int v=0; v<3; v++) { |
872 |
|
voice[v].wave = WAVE_NONE; |
876 |
|
voice[v].eg_level = voice[v].s_level = 0; |
877 |
|
voice[v].a_add = voice[v].d_sub = voice[v].r_sub = EGTable[0]; |
878 |
|
voice[v].gate = voice[v].ring = voice[v].test = false; |
879 |
< |
voice[v].filter = voice[v].sync = false; |
879 |
> |
voice[v].filter = voice[v].sync = voice[v].mute = false; |
880 |
|
} |
881 |
|
|
882 |
|
f_type = FILT_NONE; |
955 |
|
voice[v].gate = byte & 1; |
956 |
|
voice[v].mod_by->sync = byte & 2; |
957 |
|
voice[v].ring = byte & 4; |
958 |
< |
if ((voice[v].test = byte & 8)) |
958 |
> |
if ((voice[v].test = byte & 8) != 0) |
959 |
|
voice[v].count = 0; |
960 |
|
break; |
961 |
|
|
994 |
|
|
995 |
|
case 24: |
996 |
|
volume = byte & 0xf; |
997 |
< |
v3_mute = byte & 0x80; |
997 |
> |
voice[2].mute = byte & 0x80; |
998 |
|
if (((byte >> 4) & 7) != f_type) { |
999 |
|
f_type = (byte >> 4) & 7; |
1000 |
|
#ifdef USE_FIXPOINT_MATHS |
1190 |
|
#ifdef __riscos__ // on RISC OS we have 8 bit logarithmic sound |
1191 |
|
DigitalRenderer_GetTables(&LinToLog, &LogScale); // get translation tables |
1192 |
|
#else |
1204 |
– |
#ifdef __BEOS__ |
1205 |
– |
count >>= 2; // 16 bit stereo output, count is in bytes |
1206 |
– |
#else |
1193 |
|
count >>= 1; // 16 bit mono output, count is in bytes |
1194 |
|
#endif |
1209 |
– |
#endif |
1195 |
|
while (count--) { |
1211 |
– |
int32 sum_output; |
1212 |
– |
int32 sum_output_filter = 0; |
1213 |
– |
|
1196 |
|
// Get current master volume from sample buffer, |
1197 |
|
// calculate sampled voice |
1198 |
|
uint8 master_volume = sample_buf[(sample_count >> 16) % SAMPLE_BUF_SIZE]; |
1199 |
|
sample_count += ((0x138 * 50) << 16) / SAMPLE_FREQ; |
1200 |
< |
sum_output = SampleTab[master_volume] << 8; |
1200 |
> |
int32 sum_output = SampleTab[master_volume] << 8; |
1201 |
> |
int32 sum_output_filter = 0; |
1202 |
|
|
1203 |
|
// Loop for all three voices |
1204 |
|
for (int j=0; j<3; j++) { |
1238 |
|
envelope = (v->eg_level * master_volume) >> 20; |
1239 |
|
|
1240 |
|
// Waveform generator |
1241 |
+ |
if (v->mute) |
1242 |
+ |
continue; |
1243 |
|
uint16 output; |
1244 |
|
|
1245 |
|
if (!v->test) |
1320 |
|
} |
1321 |
|
|
1322 |
|
// Write to buffer |
1323 |
< |
#ifdef __BEOS__ |
1339 |
< |
int16 audio_data = (sum_output + sum_output_filter) >> 10; |
1340 |
< |
int val = *buf + audio_data; |
1341 |
< |
if (val > 32767) |
1342 |
< |
val = 32767; |
1343 |
< |
if (val < -32768) |
1344 |
< |
val = -32768; |
1345 |
< |
*buf++ = val; |
1346 |
< |
val = *buf + audio_data; |
1347 |
< |
if (val > 32767) |
1348 |
< |
val = 32767; |
1349 |
< |
if (val < -32768) |
1350 |
< |
val = -32768; |
1351 |
< |
*buf++ = val; |
1352 |
< |
#elif defined(__riscos__) // lookup in 8k (13bit) translation table |
1323 |
> |
#if defined(__riscos__) // lookup in 8k (13bit) translation table |
1324 |
|
*buf++ = LinToLog[((sum_output + sum_output_filter) >> 13) & 0x1fff]; |
1325 |
|
#else |
1326 |
|
*buf++ = (sum_output + sum_output_filter) >> 10; |
1376 |
|
delete the_renderer; |
1377 |
|
|
1378 |
|
// Create new renderer |
1379 |
< |
if (new_type == SIDTYPE_DIGITAL) |
1409 |
< |
#if defined(__BEOS__) || defined(__riscos__) |
1379 |
> |
if (new_type == SIDTYPE_DIGITAL) { |
1380 |
|
the_renderer = new DigitalRenderer(the_c64); |
1411 |
– |
#else |
1412 |
– |
the_renderer = new DigitalRenderer(); |
1413 |
– |
#endif |
1381 |
|
#ifdef AMIGA |
1382 |
< |
else if (new_type == SIDTYPE_SIDCARD) |
1383 |
< |
the_renderer = new SIDCardRenderer(); |
1382 |
> |
} else if (new_type == SIDTYPE_SIDCARD) { |
1383 |
> |
the_renderer = new SIDCardRenderer; |
1384 |
|
#endif |
1385 |
< |
else |
1385 |
> |
#ifdef __linux__ |
1386 |
> |
} else if (new_type == SIDTYPE_SIDCARD) { |
1387 |
> |
the_renderer = new CatweaselRenderer; |
1388 |
> |
#endif |
1389 |
> |
} else { |
1390 |
|
the_renderer = NULL; |
1391 |
+ |
} |
1392 |
|
|
1393 |
|
// Stuff the current register values into the new renderer |
1394 |
|
if (the_renderer != NULL) |