From 58dcda81b51fb17f3b6f3d6c08d05dd2e12a6793 Mon Sep 17 00:00:00 2001 From: bwmott Date: Mon, 5 Sep 2005 00:01:43 +0000 Subject: [PATCH] Removed unused TIASound emulation library. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@766 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- stella/src/emucore/TIASound.c | 713 -------------------------------- stella/src/emucore/TIASound.h | 67 --- stella/src/emucore/TIASound.txt | 297 ------------- 3 files changed, 1077 deletions(-) delete mode 100644 stella/src/emucore/TIASound.c delete mode 100644 stella/src/emucore/TIASound.h delete mode 100644 stella/src/emucore/TIASound.txt diff --git a/stella/src/emucore/TIASound.c b/stella/src/emucore/TIASound.c deleted file mode 100644 index 8bc605527..000000000 --- a/stella/src/emucore/TIASound.c +++ /dev/null @@ -1,713 +0,0 @@ -/*****************************************************************************/ -/* */ -/* Module: TIA Chip Sound Simulator */ -/* Purpose: To emulate the sound generation hardware of the Atari TIA chip. */ -/* Author: Ron Fries */ -/* */ -/* Revision History: */ -/* 10-Sep-96 - V1.0 - Initial Release */ -/* 14-Jan-97 - V1.1 - Cleaned up sound output by eliminating counter */ -/* reset. */ -/* */ -/*****************************************************************************/ -/* */ -/* License Information and Copyright Notice */ -/* ======================================== */ -/* */ -/* TiaSound is Copyright(c) 1996 by Ron Fries */ -/* */ -/* This library is free software; you can redistribute it and/or modify it */ -/* under the terms of version 2 of the GNU Library General Public License */ -/* as published by the Free Software Foundation. */ -/* */ -/* This library is distributed in the hope that it will be useful, but */ -/* WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library */ -/* General Public License for more details. */ -/* To obtain a copy of the GNU Library General Public License, write to the */ -/* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* */ -/* Any permitted reproduction of these routines, in whole or in part, must */ -/* bear this legend. */ -/* */ -/*****************************************************************************/ - -#ifdef SOUND_SUPPORT - -// For some braindead reason, Visual C++ won't let bspf.hxx be included -// here, so I have to redefine the following types (I hate Windows ...) -typedef signed char Int8; -typedef unsigned char uInt8; -typedef signed short Int16; -typedef unsigned short uInt16; -typedef signed int Int32; -typedef unsigned int uInt32; - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - -/* CONSTANT DEFINITIONS */ - -/* definitions for AUDCx (15, 16) */ -#define SET_TO_1 0x00 /* 0000 */ -#define POLY4 0x01 /* 0001 */ -#define DIV31_POLY4 0x02 /* 0010 */ -#define POLY5_POLY4 0x03 /* 0011 */ -#define PURE 0x04 /* 0100 */ -#define PURE2 0x05 /* 0101 */ -#define DIV31_PURE 0x06 /* 0110 */ -#define POLY5_2 0x07 /* 0111 */ -#define POLY9 0x08 /* 1000 */ -#define POLY5 0x09 /* 1001 */ -#define DIV31_POLY5 0x0a /* 1010 */ -#define POLY5_POLY5 0x0b /* 1011 */ -#define DIV3_PURE 0x0c /* 1100 */ -#define DIV3_PURE2 0x0d /* 1101 */ -#define DIV93_PURE 0x0e /* 1110 */ -#define DIV3_POLY5 0x0f /* 1111 */ - -#define DIV3_MASK 0x0c - -#define AUDC0 0x15 -#define AUDC1 0x16 -#define AUDF0 0x17 -#define AUDF1 0x18 -#define AUDV0 0x19 -#define AUDV1 0x1a - -/* the size (in entries) of the 4 polynomial tables */ -#define POLY4_SIZE 0x000f -#define POLY5_SIZE 0x001f -#define POLY9_SIZE 0x01ff - -/* channel definitions */ -#define CHAN1 0 -#define CHAN2 1 - -#define FALSE 0 -#define TRUE 1 - - -/* LOCAL GLOBAL VARIABLE DEFINITIONS */ - -/* structures to hold the 6 tia sound control bytes */ -static uInt8 AUDC[2]; /* AUDCx (15, 16) */ -static uInt8 AUDF[2]; /* AUDFx (17, 18) */ -static uInt8 AUDV[2]; /* AUDVx (19, 1A) */ - -static uInt8 Outvol[2]; /* last output volume for each channel */ - -static uInt32 volume; /* output sample volume percentage */ - -/* Initialze the bit patterns for the polynomials. */ - -/* The 4bit and 5bit patterns are the identical ones used in the tia chip. */ -/* Though the patterns could be packed with 8 bits per byte, using only a */ -/* single bit per byte keeps the math simple, which is important for */ -/* efficient processing. */ - -static uInt8 Bit4[POLY4_SIZE] = - { 1,1,0,1,1,1,0,0,0,0,1,0,1,0,0 }; - -static uInt8 Bit5[POLY5_SIZE] = - { 0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1 }; - -/* I've treated the 'Div by 31' counter as another polynomial because of */ -/* the way it operates. It does not have a 50% duty cycle, but instead */ -/* has a 13:18 ratio (of course, 13+18 = 31). This could also be */ -/* implemented by using counters. */ - -static uInt8 Div31[POLY5_SIZE] = - { 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0 }; - -/* Rather than have a table with 511 entries, I use a random number */ -/* generator. */ - -static uInt8 Bit9[POLY9_SIZE]; - -static uInt8 P4[2]; /* Position pointer for the 4-bit POLY array */ -static uInt8 P5[2]; /* Position pointer for the 5-bit POLY array */ -static uInt16 P9[2]; /* Position pointer for the 9-bit POLY array */ - -static uInt8 Div_n_cnt[2]; /* Divide by n counter. one for each channel */ -static uInt8 Div_n_max[2]; /* Divide by n maximum, one for each channel */ - - -/* In my routines, I treat the sample output as another divide by N counter. */ -/* For better accuracy, the Samp_n_cnt has a fixed binary decimal point */ -/* which has 8 binary digits to the right of the decimal point. */ - -static uInt16 Samp_n_max; /* Sample max, multiplied by 256 */ -static uInt16 Samp_n_cnt; /* Sample cnt. */ - - - -/*****************************************************************************/ -/* Module: Tia_sound_init() */ -/* Purpose: to handle the power-up initialization functions */ -/* these functions should only be executed on a cold-restart */ -/* */ -/* Author: Ron Fries */ -/* Date: September 10, 1996 */ -/* */ -/* Inputs: sample_freq - the value for the '30 Khz' Tia audio clock */ -/* playback_freq - the playback frequency in samples per second */ -/* */ -/* Outputs: Adjusts local globals - no return value */ -/* */ -/*****************************************************************************/ - -void Tia_sound_init (uInt16 sample_freq, uInt16 playback_freq) -{ - uInt8 chan; - Int16 n; - - /* fill the 9bit polynomial with random bits */ - for (n=0; n 1) - { - div_n_cnt0--; - } - else if (div_n_cnt0 == 1) - { - div_n_cnt0 = Div_n_max[0]; - - /* the P5 counter has multiple uses, so we inc it here */ - p5_0++; - if (p5_0 == POLY5_SIZE) - p5_0 = 0; - - /* check clock modifier for clock tick */ - if (((audc0 & 0x02) == 0) || - (((audc0 & 0x01) == 0) && Div31[p5_0]) || - (((audc0 & 0x01) == 1) && Bit5[p5_0])) - { - if (audc0 & 0x04) /* pure modified clock selected */ - { - if (outvol_0) /* if the output was set */ - outvol_0 = 0; /* turn it off */ - else - outvol_0 = audv0; /* else turn it on */ - } - else if (audc0 & 0x08) /* check for p5/p9 */ - { - if (audc0 == POLY9) /* check for poly9 */ - { - /* inc the poly9 counter */ - P9[0]++; - if (P9[0] == POLY9_SIZE) - P9[0] = 0; - - if (Bit9[P9[0]]) - outvol_0 = audv0; - else - outvol_0 = 0; - } - else /* must be poly5 */ - { - if (Bit5[p5_0]) - outvol_0 = audv0; - else - outvol_0 = 0; - } - } - else /* poly4 is the only remaining option */ - { - /* inc the poly4 counter */ - P4[0]++; - if (P4[0] == POLY4_SIZE) - P4[0] = 0; - - if (Bit4[P4[0]]) - outvol_0 = audv0; - else - outvol_0 = 0; - } - } - } - - - /* Process channel 1 */ - if (div_n_cnt1 > 1) - { - div_n_cnt1--; - } - else if (div_n_cnt1 == 1) - { - div_n_cnt1 = Div_n_max[1]; - - /* the P5 counter has multiple uses, so we inc it here */ - p5_1++; - if (p5_1 == POLY5_SIZE) - p5_1 = 0; - - /* check clock modifier for clock tick */ - if (((audc1 & 0x02) == 0) || - (((audc1 & 0x01) == 0) && Div31[p5_1]) || - (((audc1 & 0x01) == 1) && Bit5[p5_1])) - { - if (audc1 & 0x04) /* pure modified clock selected */ - { - if (outvol_1) /* if the output was set */ - outvol_1 = 0; /* turn it off */ - else - outvol_1 = audv1; /* else turn it on */ - } - else if (audc1 & 0x08) /* check for p5/p9 */ - { - if (audc1 == POLY9) /* check for poly9 */ - { - /* inc the poly9 counter */ - P9[1]++; - if (P9[1] == POLY9_SIZE) - P9[1] = 0; - - if (Bit9[P9[1]]) - outvol_1 = audv1; - else - outvol_1 = 0; - } - else /* must be poly5 */ - { - if (Bit5[p5_1]) - outvol_1 = audv1; - else - outvol_1 = 0; - } - } - else /* poly4 is the only remaining option */ - { - /* inc the poly4 counter */ - P4[1]++; - if (P4[1] == POLY4_SIZE) - P4[1] = 0; - - if (Bit4[P4[1]]) - outvol_1 = audv1; - else - outvol_1 = 0; - } - } - } - - /* decrement the sample counter - value is 256 since the lower - byte contains the fractional part */ - Samp_n_cnt -= 256; - - /* if the count down has reached zero */ - if (Samp_n_cnt < 256) - { - /* adjust the sample counter */ - Samp_n_cnt += Samp_n_max; - - /* calculate the latest output value and place in buffer - scale the volume by 128, since this is the default silence value - when using unsigned 8-bit samples in SDL */ - *(buffer++) = ((uInt8) ((((uInt32)outvol_0 + (uInt32)outvol_1) * volume) / 100))/2 + 128; - /* *(buffer++) = ((((uInt32)outvol_0 + (uInt32)outvol_1) * volume) / 100); */ - - /* and indicate one less byte to process */ - n--; - } - } - - /* save for next round */ - P5[0] = p5_0; - P5[1] = p5_1; - Outvol[0] = outvol_0; - Outvol[1] = outvol_1; - Div_n_cnt[0] = div_n_cnt0; - Div_n_cnt[1] = div_n_cnt1; -} - - -/*****************************************************************************/ -/* Module: Tia_get_registers() */ -/* Purpose: Returns the 6 TIA sound registers for use in state */ -/* loading and saving. */ -/* */ -/* Author: Stephen Anthony */ -/* Date: October 31, 2002 */ -/* */ -/* Inputs: reg .. reg6 - pointers to the variables where the registers */ -/* will be placed */ -/* */ -/*****************************************************************************/ - -void Tia_get_registers (unsigned char *reg1, unsigned char *reg2, unsigned char *reg3, - unsigned char *reg4, unsigned char *reg5, unsigned char *reg6) -{ - *reg1 = AUDC[0]; - *reg2 = AUDC[1]; - *reg3 = AUDF[0]; - *reg4 = AUDF[1]; - *reg5 = AUDV[0]; - *reg6 = AUDV[1]; -} - - -/*****************************************************************************/ -/* Module: Tia_set_registers() */ -/* Purpose: Sets the 6 TIA sound registers for use in state */ -/* loading and saving. */ -/* */ -/* Author: Stephen Anthony */ -/* Date: October 31, 2002 */ -/* */ -/* Inputs: reg .. reg6 - the registers to be set */ -/* */ -/*****************************************************************************/ - -void Tia_set_registers (unsigned char reg1, unsigned char reg2, unsigned char reg3, - unsigned char reg4, unsigned char reg5, unsigned char reg6) -{ - AUDC[0] = reg1; - AUDC[1] = reg2; - AUDF[0] = reg3; - AUDF[1] = reg4; - AUDV[0] = reg5; - AUDV[1] = reg6; -} - - -/*****************************************************************************/ -/* Module: Tia_clear_registers() */ -/* Purpose: Clears all TIA sound registers; soft reboot */ -/* */ -/* Author: Stephen Anthony */ -/* Date: May 12, 2005 */ -/* */ -/*****************************************************************************/ - -void Tia_clear_registers () -{ - uInt8 chan; - for (chan = CHAN1; chan <= CHAN2; chan++) - { - Outvol[chan] = 0; - Div_n_cnt[chan] = 0; - Div_n_max[chan] = 0; - AUDC[chan] = 0; - AUDF[chan] = 0; - AUDV[chan] = 0; - P4[chan] = 0; - P5[chan] = 0; - P9[chan] = 0; - } -} - - -/*****************************************************************************/ -/* Module: Tia_volume() */ -/* Purpose: Set volume to the specified percentage */ -/* */ -/* Author: Bradford W. Mott */ -/* Date: June 12, 2004 */ -/* */ -/*****************************************************************************/ -void Tia_volume (unsigned int percent) -{ - if((percent >= 0) && (percent <= 100)) - { - volume = percent; - } -} - -#ifdef __cplusplus -} -#endif - -#if 0 -/*****************************************************************************/ -/* Module: Tia_process_2() */ -/* Purpose: To fill the output buffer with the sound output based on the */ -/* tia chip parameters. This routine has not been optimized. */ -/* Though it is not used by the program, I've left it for reference.*/ -/* */ -/* Author: Ron Fries */ -/* Date: September 10, 1996 */ -/* */ -/* Inputs: *buffer - pointer to the buffer where the audio output will */ -/* be placed */ -/* n - size of the playback buffer */ -/* */ -/* Outputs: the buffer will be filled with n bytes of audio - no return val */ -/* */ -/*****************************************************************************/ - -void Tia_process_2 (register unsigned char *buffer, register uInt16 n) -{ - register uInt8 chan; - - /* loop until the buffer is filled */ - while (n) - { - /* loop through the channels */ - for (chan = CHAN1; chan <= CHAN2; chan++) - { - /* NOTE: this routine intentionally does not count down to zero */ - /* since 0 is used as a special case - no clock */ - - /* if the divide by N counter can count down */ - if (Div_n_cnt[chan] > 1) - { - /* decrement and loop */ - Div_n_cnt[chan]--; - } - /* otherwise if we've reached the bottom */ - else if (Div_n_cnt[chan] == 1) - { - /* reset the counter */ - Div_n_cnt[chan] = Div_n_max[chan]; - - /* the P5 counter has multiple uses, so we inc it here */ - P5[chan]++; - if (P5[chan] == POLY5_SIZE) - P5[chan] = 0; - - /* check clock modifier for clock tick */ - - /* if we're using pure tones OR - we're using DIV31 and the DIV31 bit is set OR - we're using POLY5 and the POLY5 bit is set */ - if (((AUDC[chan] & 0x02) == 0) || - (((AUDC[chan] & 0x01) == 0) && Div31[P5[chan]]) || - (((AUDC[chan] & 0x01) == 1) && Bit5[P5[chan]])) - { - if (AUDC[chan] & 0x04) /* pure modified clock selected */ - { - if (Outvol[chan]) /* if the output was set */ - Outvol[chan] = 0; /* turn it off */ - else - Outvol[chan] = AUDV[chan]; /* else turn it on */ - } - else if (AUDC[chan] & 0x08) /* check for p5/p9 */ - { - if (AUDC[chan] == POLY9) /* check for poly9 */ - { - /* inc the poly9 counter */ - P9[chan]++; - if (P9[chan] == POLY9_SIZE) - P9[chan] = 0; - - if (Bit9[P9[chan]]) /* if poly9 bit is set */ - Outvol[chan] = AUDV[chan]; - else - Outvol[chan] = 0; - } - else /* must be poly5 */ - { - if (Bit5[P5[chan]]) - Outvol[chan] = AUDV[chan]; - else - Outvol[chan] = 0; - } - } - else /* poly4 is the only remaining option */ - { - /* inc the poly4 counter */ - P4[chan]++; - if (P4[chan] == POLY4_SIZE) - P4[chan] = 0; - - if (Bit4[P4[chan]]) - Outvol[chan] = AUDV[chan]; - else - Outvol[chan] = 0; - } - } - } - } - - /* decrement the sample counter - value is 256 since the lower - byte contains the fractional part */ - Samp_n_cnt -= 256; - - /* if the count down has reached zero */ - if (Samp_n_cnt < 256) - { - /* adjust the sample counter */ - Samp_n_cnt += Samp_n_max; - - /* calculate the latest output value and place in buffer */ - *(buffer++) = Outvol[0] + Outvol[1]; - - /* and indicate one less byte to process */ - n--; - } - } -} -#endif - -#endif // SOUND_SUPPORT diff --git a/stella/src/emucore/TIASound.h b/stella/src/emucore/TIASound.h deleted file mode 100644 index 079a03154..000000000 --- a/stella/src/emucore/TIASound.h +++ /dev/null @@ -1,67 +0,0 @@ -/*****************************************************************************/ -/* */ -/* Module: TIA Chip Sound Simulator Includes, V1.1 */ -/* Purpose: Define global function prototypes and structures for the TIA */ -/* Chip Sound Simulator. */ -/* Author: Ron Fries */ -/* */ -/* Revision History: */ -/* 10-Sep-96 - V1.0 - Initial Release */ -/* 14-Jan-97 - V1.1 - Added compiler directives to facilitate compilation */ -/* on a C++ compiler. */ -/* */ -/*****************************************************************************/ -/* */ -/* License Information and Copyright Notice */ -/* ======================================== */ -/* */ -/* TiaSound is Copyright(c) 1997 by Ron Fries */ -/* */ -/* This library is free software; you can redistribute it and/or modify it */ -/* under the terms of version 2 of the GNU Library General Public License */ -/* as published by the Free Software Foundation. */ -/* */ -/* This library is distributed in the hope that it will be useful, but */ -/* WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library */ -/* General Public License for more details. */ -/* To obtain a copy of the GNU Library General Public License, write to the */ -/* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* */ -/* Any permitted reproduction of these routines, in whole or in part, must */ -/* bear this legend. */ -/* */ -/*****************************************************************************/ - -#ifndef _TIASOUND_H -#define _TIASOUND_H - -#ifdef SOUND_SUPPORT - -#ifdef __cplusplus -extern "C" { -#endif - -void Tia_sound_init (unsigned int sample_freq, unsigned int playback_freq); -void Update_tia_sound (unsigned int addr, unsigned char val); -void Tia_process_2 (register unsigned char *buffer, - register unsigned int n); -void Tia_process (register unsigned char *buffer, - register unsigned int n); - -void Tia_get_registers (unsigned char *reg1, unsigned char *reg2, unsigned char *reg3, - unsigned char *reg4, unsigned char *reg5, unsigned char *reg6); -void Tia_set_registers (unsigned char reg1, unsigned char reg2, unsigned char reg3, - unsigned char reg4, unsigned char reg5, unsigned char reg6); - -void Tia_clear_registers (void); - -void Tia_volume (unsigned int percent); - -#ifdef __cplusplus -} -#endif - -#endif // SOUND_SUPPORT - -#endif diff --git a/stella/src/emucore/TIASound.txt b/stella/src/emucore/TIASound.txt deleted file mode 100644 index 2819ef9ed..000000000 --- a/stella/src/emucore/TIASound.txt +++ /dev/null @@ -1,297 +0,0 @@ - TIASOUND.C - TIA SOUND EMULATION V1.0 - ===================================== - -As I'm sure you've already discovered, the Stella manual isn't always -correct. My observations show what I believe to be several discrepancies -in the description of the distortions. Of course, I could be wrong on a few -of these, so if some of the games don't sound right, please let me know -which ones. If possible, it would be best if you could send me a wave file -of what it is supposed to sound like, preferably at 44 KHz. Only a few -seconds should be necessary. - - -TIA AUDIO CIRCUITRY -=================== - - -THE HARDWARE ------------- - -In general, the sound hardware can be described as follows: - - -Selecting the Clock Modifier - Bits D0 and D1 ---------------------------------------------- - -Bits D0 and D1 select the output clock modifier: - - D1 D0 - ------- - 0 0 - direct clock (pure) - 0 1 - direct clock (pure) - 1 0 - divide by 31 - 1 1 - 5-bit polynomial - -The 'divide by 31' isn't simply the input clock divided by 31. It is, in -essence, a 5-bit polynomial with only two bits set. The resulting square -wave actually has a 13:18 ratio. This may be implemented in the hardware -as a pair of traps on a 5-bit counter. - - -Selecting the Source Pattern - Bits D2 and D3 ---------------------------------------------- - -Bits D2 and D3 select the source to be clocked: - - D3 D2 - ------- - 0 0 - 4-bit polynomial - 0 1 - pure (Q') - 1 0 - 5-bit polynomial - 1 1 - pure (Q') - -The 'pure' tones are generated by toggling the output. Whenever a clock -tick is received, the output will change states. I've used the notation Q' -to indicate the 'logical NOT of the last output'. Note that since the output -toggles, this can be thought of as a divide by 2 since the output frequency -will be half of the input frequency. This is only true for the pure tones. - - -Selecting the Source Clock - Bits D2 and D3 -------------------------------------------- - -When bits D2 and D3 are both set, it affects the source clock. I believe -the '30KHz' clock is actually the 3.58MHz clock divided by 114. When bits -D2 and D3 are set, the input source is switched to the 1.19MHz clock, so the -'30KHz' source clock is reduced to approximately 10KHz. - - -Exceptions - Selecting No Output or the 9-bit Polynomial --------------------------------------------------------- - -There are two exceptions that occur when bits D0-D2 are all 0. If AUDC is -zero (0000), then I believe the output is set equal to the volume. If AUDC is -equal to 8 (1000), the 9-bit polynomial is selected as the source to be -clocked. - - -Updated Detailed Functions for AUDC ------------------------------------ - -From my observations, I would describe the distortion selections as follows: - - HEX D3 D2 D1 D0 Clock Source Clock Modifier Source Pattern - --- ------------- -------------- ---------------- ---------------- - 0 0 0 0 0 3.58 MHz/114 -> none (pure) -> none - 1 0 0 0 1 3.58 MHz/114 -> none (pure) -> 4-bit poly - 2 0 0 1 0 3.58 MHz/114 -> divide by 31 -> 4-bit poly - 3 0 0 1 1 3.58 MHz/114 -> 5-bit poly -> 4-bit poly - 4 0 1 0 0 3.58 MHz/114 -> none (pure) -> pure (~Q) - 5 0 1 0 1 3.58 MHz/114 -> none (pure) -> pure (~Q) - 6 0 1 1 0 3.58 MHz/114 -> divide by 31 -> pure (~Q) - 7 0 1 1 1 3.58 MHz/114 -> 5-bit poly -> pure (~Q) - 8 1 0 0 0 3.58 MHz/114 -> none (pure) -> 9-bit poly - 9 1 0 0 1 3.58 MHz/114 -> none (pure) -> 5-bit poly - A 1 0 1 0 3.58 MHz/114 -> divide by 31 -> 5-bit poly - B 1 0 1 1 3.58 MHz/114 -> 5-bit poly -> 5-bit poly - C 1 1 0 0 1.19 MHz/114 -> none (pure) -> pure (~Q) - D 1 1 0 1 1.19 MHz/114 -> none (pure) -> pure (~Q) - E 1 1 1 0 1.19 MHz/114 -> divide by 31 -> pure (~Q) - F 1 1 1 1 1.19 MHz/114 -> 5-bit poly -> pure (~Q) - -For the most part, this follows the Stella manual, but there are a few -differences. Probably the most notable are hex entries 'A' and 'B', which -are listed in the Stella manual as 'div 31: pure tone' and 'set last 4 bits -to 1'. - -On entries 'A' and 'B', both the data source and the clock have the same -number of entries (31). Because of this, they will always align in the -same way. Entry 'A' will then reduce to a pure 'div by 31' output which -is identical to entry '6'. On 'B', both the source and the clock align -in such a way that the output will always be 1. - - - -THE POLYNOMIALS ---------------- - -The 4-bit, 5-bit, and 9-bit polynomials are essentially tables containing -a random series of bits (they are implemented in hardware as shift -registers). Because the tables are fixed in length, the 'random' pattern -will repeat periodically. - -The size of the table is described by its name. The actual size of the -table is 2^x - 1, where x is either the 4, 5 or 9. The 4-bit polynomial -has 15 entries, the 5-bit polynomial has 31 entries, and the 9-bit -polynomial has 511 entries. - -I've performed some analysis on the output of the actual Atari 2600, and -believe I have the actual 4-bit and 5-bit polynomials used by the Atari. -These have been encoded as byte arrays in my routines. For the 9-bit -polynomial, I use a random number generator which should produce -approximately the same results. - - -THE CLOCK ---------- - -I believe the input clock for the audio is a division of the main system -clock. With this assumption, I determined that the input clock for the -audio is equal to the 3.58MHz system clock divided by 114. Note that this -produces an actual audio clock of 31.4 KHz. This value closely matches the -frequencies I recorded from my unit. The Stella manual describes the Audio -Clock as approximately 30KHz, which I suppose is correct if you consider 5% -to be approximate. - -If both bits D2 and D3 of the AUDC register are set, I believe the TIA chip -uses the 1.19MHz clock for the base audio clock instead of the 3.58MHz. -This, of course, produces the 'divide by 3' functionality described in the -Stella manual. - - - -TIASOUND.C -========== - -The TIASOUND.C file is the heart of the TIA Sound Emulation program. -Although the routines in the file must work together, no other files are -modules are required for operation. A header file, 'TIASOUND.H', has -been included for use in other modules, and provides the necessary -function prototypes. I've attempted to make the routines as portable as -possible, so the file should compile on almost any compiler with little -or no modification. - -I have made some attempts at optimizing the routines, though I am sure -more optimization can be done. They are currently only available in 'C'. -I'll be happy to convert them to assembly language if desired. Please feel -free to send me e-mail (see below). - -The routines are easy to use. Detailed descriptions on the function calls -are listed below. - - -GENERAL OVERVIEW ----------------- - -On start-up of the system, a single call should be made to Tia_sound_init. -This routine will prepare the structures for sound output. This routine -can be called again if necessary during warm-start or other reset. - -Once in the main loop, there are two other functions that will be used. -Whenever the system needs to write to either the AUDC, AUDV or AUDF values, -a call should be made to the Update_tia_sound routine. This routine will -take care of updating the internal registers. It will pre-calculate several -values to help with optimization. - -The only other routine that is called is the Tia_process function. This -function will fill a audio buffer with a specified number of bytes. This -function should be called whenever a new audio buffer is required. - -For best results, I recommend using at least two output buffers. Using this -scheme, the sound card can be playing one buffer while the system is filling -the other. - - -DETAILED FUNCTION DESCRIPTIONS ------------------------------- - -Tia_sound_init(uint16 sample_freq, uint16 playback_freq) --------------------------------------------------------- - -This function initializes the structures used by the TiaSound.C routines. -This function takes two parameters: the sample frequency and the playback -frequency. The sample frequency is the frequency of the 30KHz source clock. -For my calculations, this clock is about 31.4 KHz, though any 16-bit -unsigned integer value can be used (1-65535). - -The playback frequency is the frequency of the sound playback (the frequency -used by the sound card). For best results, both the playback frequency and -the sample frequency should be identical. In the case where the sound card -cannot support 31.4 KHz (i.e. the original SB and many 'SB compatible' cards), -there are three options: - -1) Set the sample frequency to 31400 and the playback frequency to the - maximum possible (e.g. 22050). Though the system will reproduce all - output values, a significant amount of aliasing is introduced. - -2) Set the sample frequency and the playback frequency to the maximum possible - (e.g. 22050). In this case, all output values are reproduced with no - distortions; however, the pitch is about 2/3 of an octave low. - -3) Set the sample frequency to 31400 and the playback frequency to exactly - 1/2 of the sample frequency (15700). In this case, the output frequency - is correct and the aliasing is minimized. The aliasing is only - noticeable on the higher frequencies. Most notably, the highest pure tone - (AUDF = 0) is inaudible. - -Feel free to experiment to find other alternatives as well. - -This function has no return value (void). - - -Update_tia_sound (uint16 addr, uint8 val) ------------------------------------------ - -This function should be called each time an AUDC, AUDF or AUDV value -changes. This function takes two parameters: the address to change and -the new value. The address should be one of the following values: - - Addr Description - ---- ----------- - 0x15 AUDC0 - 0x16 AUDC1 - 0x17 AUDF0 - 0x18 AUDF1 - 0x19 AUDV0 - 0x1A AUDV1 - -Any values outside of this range will be ignored. - -The routine pre-calculates several values that are needed by the -processing function. This is done to optimize performance. - -This function has no return value (void). - - -Tia_process (unsigned char *buffer, uint16 n) ---------------------------------------------- - -This function calculates and fills a buffer with unsigned 8-bit mono audio. -This function takes two parameters: a pointer to the buffer to fill and -the size of the buffer (limited to 65535). This function fills the -buffer based on the requested size and returns. It automatically -updates the pointers for the next call, so subsequent calls to this function -will provide a continuous stream of data. - -The size of the buffer that is needed depends on the playback frequency. -It is best to keep the buffer as small as possible to maximize response time -to changes in the sound. Of course, the minimum size is dependent on -system and emulator performance. - -Selecting the correct buffer size is a careful balance. Selecting a buffer -size that is too small will produce noticeable clicks in the output, though -selecting a size that is too large will cause a poor response time and -possible delays in the system when the new buffer is filled. - -This function has no return value (void). - - -License Information and Copyright Notice -======================================== - -TiaSound is Copyright(c) 1996 by Ron Fries - -This library is free software; you can redistribute it and/or modify it under -the terms of version 2 of the GNU Library General Public License as published -by the Free Software Foundation. - -This library is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more -details. - -To obtain a copy of the GNU Library General Public License, write to the Free -Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -Any permitted reproduction of these routines, in whole or in part, must bear -this legend.