Annotation of hatari/src/sound.c, revision 1.1.1.19

1.1       root        1: /*
1.1.1.5   root        2:   Hatari - sound.c
                      3: 
1.1.1.19! root        4:   This file is distributed under the GNU General Public License, version 2
        !             5:   or at your option any later version. Read the file gpl.txt for details.
1.1       root        6: 
1.1.1.11  root        7:   This is where we emulate the YM2149. To obtain cycle-accurate timing we store
                      8:   the current cycle time and this is incremented during each instruction.
                      9:   When a write occurs in the PSG registers we take the difference in time and
                     10:   generate this many samples using the previous register data.
                     11:   Now we begin again from this point. To make sure we always have 1/50th of
                     12:   samples we update the buffer generation every 1/50th second, just in case no
                     13:   write took place on the PSG.
                     14:   NOTE: If the emulator runs slower than 50fps it cannot update the buffers,
                     15:   but the sound thread still needs some data to play to prevent a 'pop'. The
                     16:   ONLY feasible solution is to play the same buffer again. I have tried all
                     17:   kinds of methods to play the sound 'slower', but this produces un-even timing
                     18:   in the sound and it simply doesn't work. If the emulator cannot keep the
                     19:   speed, users will have to turn off the sound - that's it.
1.1.1.12  root       20: 
                     21:   The new version of the sound core uses some code/ideas from the following GPL projects :
1.1.1.15  root       22:     - tone and noise steps computations are from StSound 1.2 by Arnaud CarrĂ© (Leonard/Oxygene)
1.1.1.12  root       23:     - 5 bits volume table and 16*16*16 combinations of all volume are from Sc68 by Benjamin Gerard
                     24:     - 4 bits to 5 bits volume interpolation from 16*16*16 to 32*32*32 from YM blep synthesis by Antti Lankila
                     25: 
1.1.1.16  root       26:   Special case for per==0 : as measured on a real STF, when tone/noise/env's per==0, we get
                     27:   the same sound output as when per==1.
                     28: 
                     29: 
1.1       root       30: */
1.1.1.12  root       31: 
                     32: /* 2008/05/05  [NP]    Fix case where period is 0 for noise, sound or envelope.        */
                     33: /*                     In that case, a real ST sounds as if period was in fact 1.      */
                     34: /*                     (fix buggy sound replay in ESwat that set volume<0 and trigger  */
                     35: /*                     a badly initialised envelope with envper=0).                    */
                     36: /* 2008/07/27  [NP]    Better separation between accesses to the YM hardware registers */
                     37: /*                     and the sound rendering routines. Use Sound_WriteReg() to pass  */
                     38: /*                     all writes to the sound rendering functions. This allows to     */
1.1.1.19! root       39: /*                     have sound.c independent of psg.c (to ease replacement of       */
1.1.1.12  root       40: /*                     sound.c by another rendering method).                           */
                     41: /* 2008/08/02  [NP]    Initial convert of Ym2149Ex.cpp from C++ to C.                  */
                     42: /*                     Remove unused part of the code (StSound specific).              */
                     43: /* 2008/08/09  [NP]    Complete integration of StSound routines into sound.c           */
                     44: /*                     Set EnvPer=3 if EnvPer<3 (ESwat buggy replay).                  */
                     45: /* 2008/08/13  [NP]    StSound was generating samples in the range 0-32767, instead    */
                     46: /*                     of really signed samples between -32768 and 32767, which could  */
                     47: /*                     give incorrect results in many case.                            */
                     48: /* 2008/09/06  [NP]    Use sc68 volumes table for a more accurate mixing of the voices */
                     49: /*                     All volumes are converted to 5 bits and the table contains      */
                     50: /*                     32*32*32 values. Samples are signed and centered to get the     */
                     51: /*                     biggest amplitude possible.                                     */
                     52: /*                     Faster mixing routines for tone+volume+envelope (don't use      */
                     53: /*                     StSound's version anymore, it gave problem with some GCC).      */
                     54: /* 2008/09/17  [NP]    Add ym_normalise_5bit_table to normalise the 32*32*32 table and */
                     55: /*                     to optionally center 16 bit signed sample.                      */
                     56: /*                     Possibility to mix volumes using a table measured on ST or a    */
                     57: /*                     linear mean of the 3 channels' volume.                          */
                     58: /*                     Default mixing set to YM_LINEAR_MIXING.                         */
                     59: /* 2008/10/14  [NP]    Full support for 5 bits volumes : envelopes are generated with  */
                     60: /*                     32 volumes per pattern as on a real YM-2149. Fixed volumes      */
                     61: /*                     on 4 bits are converted to their 5 bits equivalent. This should */
                     62: /*                     give the maximum accuracy possible when computing volumes.      */
                     63: /*                     New version of Ym2149_EnvStepCompute to handle 5 bits volumes.  */
                     64: /*                     Function YM2149_EnvBuild to compute the 96 volumes that define  */
                     65: /*                     a single envelope (32 initial volumes, then 64 repeated values).*/
                     66: /* 2008/10/26  [NP]    Correctly save/restore all necessary variables in               */
                     67: /*                     Sound_MemorySnapShot_Capture.                                   */
                     68: /* 2008/11/23  [NP]    Clean source, remove old sound core.                            */
1.1.1.17  root       69: /* 2011/11/03  [DS]    Stereo DC filtering which accounts for DMA sound.               */
1.1.1.12  root       70: 
                     71: 
                     72: 
1.1.1.14  root       73: const char Sound_fileid[] = "Hatari sound.c : " __DATE__ " " __TIME__;
1.1.1.5   root       74: 
                     75: #include <SDL_types.h>
1.1       root       76: 
                     77: #include "main.h"
                     78: #include "audio.h"
1.1.1.10  root       79: #include "cycles.h"
1.1.1.15  root       80: #include "configuration.h"
1.1.1.9   root       81: #include "dmaSnd.h"
1.1.1.15  root       82: #include "crossbar.h"
1.1       root       83: #include "file.h"
1.1.1.15  root       84: #include "cycInt.h"
1.1.1.8   root       85: #include "log.h"
1.1       root       86: #include "memorySnapShot.h"
                     87: #include "psg.h"
                     88: #include "sound.h"
1.1.1.16  root       89: #include "screen.h"
1.1       root       90: #include "video.h"
                     91: #include "wavFormat.h"
                     92: #include "ymFormat.h"
1.1.1.15  root       93: #include "avi_record.h"
1.1.1.16  root       94: #include "clocks_timings.h"
1.1       root       95: 
                     96: 
                     97: 
1.1.1.12  root       98: /*--------------------------------------------------------------*/
                     99: /* Definition of the possible envelopes shapes (using 5 bits)  */
                    100: /*--------------------------------------------------------------*/
                    101: 
                    102: #define        ENV_GODOWN      0               /* 31 ->  0 */
                    103: #define        ENV_GOUP        1               /*  0 -> 31 */
                    104: #define        ENV_DOWN        2               /*  0 ->  0 */
                    105: #define        ENV_UP          3               /* 31 -> 31 */
                    106: 
                    107: /* To generate an envelope, we first use block 0, then we repeat blocks 1 and 2 */
                    108: static const int YmEnvDef[ 16 ][ 3 ] = {
                    109:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 0 \___ */
                    110:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 1 \___ */
                    111:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 2 \___ */
                    112:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 3 \___ */
                    113:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 4 /___ */
                    114:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 5 /___ */
                    115:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 6 /___ */
                    116:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 7 /___ */
                    117:        { ENV_GODOWN,   ENV_GODOWN, ENV_GODOWN } ,      /* 8 \\\\ */
                    118:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 9 \___ */
                    119:        { ENV_GODOWN,   ENV_GOUP, ENV_GODOWN } ,        /* A \/\/ */
                    120:        { ENV_GODOWN,   ENV_UP, ENV_UP } ,              /* B \--- */
                    121:        { ENV_GOUP,     ENV_GOUP, ENV_GOUP } ,          /* C //// */
                    122:        { ENV_GOUP,     ENV_UP, ENV_UP } ,              /* D /--- */
                    123:        { ENV_GOUP,     ENV_GODOWN, ENV_GOUP } ,        /* E /\/\ */
                    124:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* F /___ */
                    125:        };
                    126: 
                    127: 
                    128: /* Buffer to store the 16 envelopes built from YmEnvDef */
                    129: static ymu16   YmEnvWaves[ 16 ][ 32 * 3 ];             /* 16 envelopes with 3 blocks of 32 volumes */
1.1.1.3   root      130: 
1.1       root      131: 
1.1.1.12  root      132: 
                    133: /*--------------------------------------------------------------*/
                    134: /* Definition of the volumes tables (using 5 bits) and of the  */
                    135: /* mixing parameters for the 3 voices.                         */
                    136: /*--------------------------------------------------------------*/
                    137: 
                    138: /* Table of unsigned 5 bit D/A output level for 1 channel as measured on a real ST (expanded from 4 bits to 5 bits) */
                    139: /* Vol 0 should be 310 when measuread as a voltage, but we set it to 0 in order to have a volume=0 matching */
                    140: /* the 0 level of a 16 bits unsigned sample (no sound output) */
                    141: static const ymu16 ymout1c5bit[ 32 ] =
                    142: {
                    143:   0 /*310*/,  369,  438,  521,  619,  735,  874, 1039,
                    144:  1234, 1467, 1744, 2072, 2463, 2927, 3479, 4135,
                    145:  4914, 5841, 6942, 8250, 9806,11654,13851,16462,
                    146: 19565,23253,27636,32845,39037,46395,55141,65535
1.1       root      147: };
                    148: 
1.1.1.12  root      149: /* Convert a constant 4 bits volume to the internal 5 bits value : */
1.1.1.18  root      150: /* volume5=volume4*2+1, except for volumes 0 and 1 which remain 0 and 1, */
1.1.1.12  root      151: /* in order to map [0,15] into [0,31] (O must remain 0, and 15 must give 31) */
1.1.1.18  root      152: static const ymu16 YmVolume4to5[ 16 ] = { 0,1,5,7,9,11,13,15,17,19,21,23,25,27,29,31 };
1.1       root      153: 
1.1.1.12  root      154: /* Table of unsigned 4 bit D/A output level for 3 channels as measured on a real ST */
1.1.1.18  root      155: static ymu16 volumetable_original[16][16][16] =
1.1.1.12  root      156: #include "ym2149_fixed_vol.h"
1.1.1.5   root      157: 
1.1.1.12  root      158: /* Corresponding table interpolated to 5 bit D/A output level (16 bits unsigned) */
1.1.1.18  root      159: static ymu16 ymout5_u16[32][32][32];
1.1.1.12  root      160: 
                    161: /* Same table, after conversion to signed results (same pointer, with different type) */
                    162: static yms16 *ymout5 = (yms16 *)ymout5_u16;
                    163: 
                    164: 
                    165: 
                    166: /*--------------------------------------------------------------*/
                    167: /* Other constants / macros                                    */
                    168: /*--------------------------------------------------------------*/
                    169: 
                    170: /* Number of generated samples per frame (eg. 44Khz=882) */
1.1.1.16  root      171: #define SAMPLES_PER_FRAME  (nAudioFrequency/nScreenRefreshRate)
1.1.1.12  root      172: 
                    173: /* Current sound replay freq (usually 44100 Hz) */
1.1.1.14  root      174: #define YM_REPLAY_FREQ   nAudioFrequency
1.1.1.12  root      175: 
1.1.1.16  root      176: /* YM-2149 clock on all Atari models is 2 MHz */
                    177: #define YM_ATARI_CLOCK         (MachineClocks.YM_Freq)
1.1.1.12  root      178: 
                    179: 
                    180: /* Merge/read the 3 volumes in a single integer (5 bits per volume) */
                    181: #define        YM_MERGE_VOICE(C,B,A)   ( (C)<<10 | (B)<<5 | A )
                    182: #define        YM_MASK_1VOICE          0x1f
                    183: #define YM_MASK_A              0x1f
                    184: #define YM_MASK_B              (0x1f<<5)
                    185: #define YM_MASK_C              (0x1f<<10)
                    186: 
                    187: 
                    188: /* Constants for YM2149_Normalise_5bit_Table */
                    189: #define        YM_OUTPUT_LEVEL                 0x7fff          /* amplitude of the final signal (0..65535 if centered, 0..32767 if not) */
1.1.1.14  root      190: #define YM_OUTPUT_CENTERED             false
1.1.1.12  root      191: 
                    192: 
                    193: 
                    194: /*--------------------------------------------------------------*/
                    195: /* Variables for the YM2149 emulator (need to be saved and     */
                    196: /* restored in memory snapshots)                               */
                    197: /*--------------------------------------------------------------*/
                    198: 
                    199: static ymu32   stepA , stepB , stepC;
                    200: static ymu32   posA , posB , posC;
                    201: static ymu32   mixerTA , mixerTB , mixerTC;
                    202: static ymu32   mixerNA , mixerNB , mixerNC;
                    203: 
                    204: static ymu32   noiseStep;
                    205: static ymu32   noisePos;
                    206: static ymu32   currentNoise;
                    207: static ymu32   RndRack;                                /* current random seed */
                    208: 
                    209: static ymu32   envStep;
                    210: static ymu32   envPos;
                    211: static int     envShape;
                    212: 
                    213: static ymu16   EnvMask3Voices = 0;                     /* mask is 0x1f for voices having an active envelope */
                    214: static ymu16   Vol3Voices = 0;                         /* volume 0-0x1f for voices having a constant volume */
                    215:                                                        /* volume is set to 0 if voice has an envelope in EnvMask3Voices */
                    216: 
                    217: 
                    218: /* Global variables that can be changed/read from other parts of Hatari */
                    219: Uint8          SoundRegs[ 14 ];
                    220: 
1.1.1.16  root      221: int            YmVolumeMixing = YM_TABLE_MIXING;
1.1.1.14  root      222: bool           UseLowPassFilter = false;
1.1.1.12  root      223: 
                    224: bool           bEnvelopeFreqFlag;                      /* Cleared each frame for YM saving */
                    225: 
                    226: Sint16         MixBuffer[MIXBUFFER_SIZE][2];
                    227: int            nGeneratedSamples;                      /* Generated samples since audio buffer update */
                    228: static int     ActiveSndBufIdx;                        /* Current working index into above mix buffer */
1.1.1.16  root      229: static int     ActiveSndBufIdxAvi;                     /* Current working index to save an AVI audio frame */
                    230: 
                    231: static yms64   SamplesPerFrame_unrounded = 0;          /* Number of samples for the current VBL, with simulated fractional part */
                    232: static int     SamplesPerFrame;                        /* Number of samples to generate for the current VBL */
                    233: static int     CurrentSamplesNb = 0;                   /* Number of samples already generated for the current VBL */
1.1.1.12  root      234: 
1.1.1.16  root      235: bool           Sound_BufferIndexNeedReset = false;
1.1.1.12  root      236: 
                    237: 
                    238: /*--------------------------------------------------------------*/
                    239: /* Local functions prototypes                                  */
                    240: /*--------------------------------------------------------------*/
                    241: 
1.1.1.17  root      242: static ymsample        LowPassFilter           (ymsample x0);
1.1.1.18  root      243: static ymsample        PWMaliasFilter          (ymsample x0);
1.1.1.12  root      244: 
1.1.1.18  root      245: static void    interpolate_volumetable (ymu16 volumetable[32][32][32]);
1.1.1.12  root      246: 
1.1.1.18  root      247: static void    YM2149_BuildModelVolumeTable(ymu16 volumetable[32][32][32]);
                    248: static void    YM2149_BuildLinearVolumeTable(ymu16 volumetable[32][32][32]);
1.1.1.12  root      249: static void    YM2149_Normalise_5bit_Table(ymu16 *in_5bit , yms16 *out_5bit, unsigned int Level, bool DoCenter);
                    250: 
                    251: static void    YM2149_EnvBuild         (void);
1.1.1.16  root      252: static void    Ym2149_BuildVolumeTable (void);
1.1.1.12  root      253: static void    Ym2149_Init             (void);
                    254: static void    Ym2149_Reset            (void);
                    255: 
                    256: static ymu32   YM2149_RndCompute       (void);
                    257: static ymu32   Ym2149_ToneStepCompute  (ymu8 rHigh , ymu8 rLow);
                    258: static ymu32   Ym2149_NoiseStepCompute (ymu8 rNoise);
                    259: static ymu32   Ym2149_EnvStepCompute   (ymu8 rHigh , ymu8 rLow);
                    260: static ymsample        YM2149_NextSample       (void);
                    261: 
1.1.1.16  root      262: static int     Sound_SetSamplesPassed(bool FillFrame);
                    263: static void    Sound_GenerateSamples(int SamplesToGenerate);
1.1.1.12  root      264: 
                    265: 
                    266: 
                    267: /*--------------------------------------------------------------*/
1.1.1.17  root      268: /* DC Adjuster                                                 */
1.1.1.12  root      269: /*--------------------------------------------------------------*/
                    270: 
1.1.1.17  root      271: /**
                    272:  * 6dB/octave first order HPF fc = (1.0-0.998)*44100/(2.0*pi)
                    273:  * Z pole = 0.99804 --> FS = 44100 Hz : fc=13.7 Hz (11 Hz meas)
                    274:  * a = (int32_t)(32768.0*(1.0 - pole)) :       a = 64 !!!
                    275:  * Input range: -32768 to 32767  Maximum step: +65536 or -65472
                    276:  */
                    277: ymsample       Subsonic_IIR_HPF_Left(ymsample x0)
1.1.1.12  root      278: {
1.1.1.17  root      279:        static  yms32   x1 = 0, y1 = 0, y0 = 0;
1.1.1.14  root      280: 
1.1.1.17  root      281:        y1 += ((x0 - x1)<<15) - (y0<<6);  /*  64*y0  */
                    282:        y0 = y1>>15;
                    283:        x1 = x0;
1.1.1.12  root      284: 
1.1.1.17  root      285:        return y0;
1.1.1.12  root      286: }
                    287: 
                    288: 
1.1.1.17  root      289: ymsample       Subsonic_IIR_HPF_Right(ymsample x0)
1.1       root      290: {
1.1.1.17  root      291:        static  yms32   x1 = 0, y1 = 0, y0 = 0;
1.1.1.12  root      292: 
1.1.1.17  root      293:        y1 += ((x0 - x1)<<15) - (y0<<6);  /*  64*y0  */
                    294:        y0 = y1>>15;
                    295:        x1 = x0;
1.1.1.12  root      296: 
1.1.1.17  root      297:        return y0;
1.1.1.12  root      298: }
                    299: 
                    300: 
1.1.1.17  root      301: /*--------------------------------------------------------------*/
                    302: /* Low Pass Filter routines.                                   */
                    303: /*--------------------------------------------------------------*/
1.1.1.12  root      304: 
1.1.1.17  root      305: /**
                    306:  * Get coefficients for different Fs (C10 is in ST only):
                    307:  * Wc = 2*M_PI*4895.1;
                    308:  * Fs = 44100;
                    309:  * warp = Wc/tanf((Wc/2)/Fs);
                    310:  * b = Wc/(warp+Wc);
                    311:  * a = (Wc-warp)/(warp+Wc);
                    312:  *
                    313:  * #define B_z (yms32)( 0.2667*(1<<15))
                    314:  * #define A_z (yms32)(-0.4667*(1<<15))
                    315:  *
                    316:  * y0 = (B_z*(x0 + x1) - A_z*y0) >> 15;
                    317:  * x1 = x0;
                    318:  *
                    319:  * The Lowpass Filter formed by C10 = 0.1 uF
                    320:  * and
1.1.1.18  root      321:  * R8=1k // 1k*(65119-46602)/65119 // R9=10k // R10=5.1k //
1.1.1.17  root      322:  * (R12=470)*(100=Q1_HFE) = 206.865 ohms when YM2149 is High
                    323:  * and
                    324:  * R8=1k // R9=10k // R10=5.1k // (R12=470)*(100=Q1_HFE)
                    325:  *                        = 759.1   ohms when YM2149 is Low
                    326:  * High corner is 1/(2*pi*(0.1*10e-6)*206.865) fc = 7693.7 Hz
                    327:  * Low  corner is 1/(2*pi*(0.1*10e-6)*795.1)   fc = 2096.6 Hz
                    328:  * Notes:
                    329:  * - using STF reference designators R8 R9 R10 C10 (from dec 1986 schematics)
                    330:  * - using corresponding numbers from psgstrep and psgquart
                    331:  * - 65119 is the largest value in Paulo's psgstrep table
                    332:  * - 46602 is the largest value in Paulo's psgquart table
                    333:  * - this low pass filter uses the highest cutoff frequency
                    334:  *   on the STf (a slightly lower frequency is reasonable).
                    335:  *
                    336:  * A first order lowpass filter with a high cutoff frequency
                    337:  * is used when the YM2149 pulls high, and a lowpass filter
                    338:  * with a low cutoff frequency is used when R8 pulls low.
                    339:  */
                    340: static ymsample        LowPassFilter(ymsample x0)
                    341: {
                    342:        static  yms32 y0 = 0, x1 = 0;
                    343: 
                    344:        if (x0 >= y0)
                    345:        /* YM Pull up:   fc = 7586.1 Hz (44.1 KHz), fc = 8257.0 Hz (48 KHz) */
                    346:                y0 = (3*(x0 + x1) + (y0<<1)) >> 3;
                    347:        else
                    348:        /* R8 Pull down: fc = 1992.0 Hz (44.1 KHz), fc = 2168.0 Hz (48 KHz) */
                    349:                y0 = ((x0 + x1) + (6*y0)) >> 3;
1.1.1.12  root      350: 
1.1.1.17  root      351:        x1 = x0;
                    352:        return y0;
1.1.1.12  root      353: }
                    354: 
1.1.1.18  root      355: /**
                    356:  * This piecewise selective filter works by filtering the falling
                    357:  * edge of a sampled pulse-wave differently from the rising edge.
                    358:  *
                    359:  * Piecewise selective filtering is effective because harmonics on
                    360:  * one part of a wave partially define harmonics on other portions.
                    361:  *
                    362:  * Piecewise selective filtering can efficiently reduce aliasing
                    363:  * with minimal harmonic removal.
                    364:  *
                    365:  * I disclose this information into the public domain so that it
                    366:  * cannot be patented. May 23 2012 David Savinkoff.
                    367:  */
                    368: static ymsample        PWMaliasFilter(ymsample x0)
                    369: {
                    370:        static  yms32 y0 = 0, x1 = 0;
                    371: 
                    372:        if (x0 >= y0)
                    373:        /* YM Pull up   */
                    374:                y0 = x0;
                    375:        else
                    376:        /* R8 Pull down */
                    377:                y0 = (3*(x0 + x1) + (y0<<1)) >> 3;
                    378: 
                    379:        x1 = x0;
                    380:        return y0;
                    381: }
                    382: 
1.1.1.12  root      383: 
                    384: 
                    385: /*--------------------------------------------------------------*/
                    386: /* Build the volume conversion table used to simulate the      */
                    387: /* behaviour of DAC used with the YM2149 in the atari ST.      */
                    388: /* The final 32*32*32 table is built using a 16*16*16 table    */
                    389: /* of all possible fixed volume combinations on a ST.          */
                    390: /*--------------------------------------------------------------*/
                    391: 
1.1.1.18  root      392: static void    interpolate_volumetable(ymu16 volumetable[32][32][32])
1.1.1.12  root      393: {
1.1.1.18  root      394:        int     i, j, k;
1.1.1.12  root      395: 
1.1.1.18  root      396:        for (i = 1; i < 32; i += 2) { /* Copy 16 Panels to make a Block */
                    397:                for (j = 1; j < 32; j += 2) { /* Copy 16 Rows to make a Panel */
                    398:                        for (k = 1; k < 32; k += 2) { /* Copy 16 Elements to make a Row */
                    399:                                volumetable[i][j][k] = volumetable_original[(i-1)/2][(j-1)/2][(k-1)/2];
1.1.1.12  root      400:                        }
1.1.1.18  root      401:                        volumetable[i][j][0] = volumetable[i][j][1]; /* Move 0th Element */
                    402:                        volumetable[i][j][1] = volumetable[i][j][3]; /* Move 1st Element */
                    403:                        /* Interpolate 3rd Element */
                    404:                        volumetable[i][j][3] = (ymu16)(0.5 + sqrt((double)volumetable[i][j][1] * volumetable[i][j][5]));
                    405:                        for (k = 2; k < 32; k += 2) /* Interpolate Even Elements */
                    406:                                volumetable[i][j][k] = (ymu16)(0.5 + sqrt((double)volumetable[i][j][k-1] * volumetable[i][j][k+1]));
1.1.1.12  root      407:                }
1.1.1.18  root      408:                for (k = 0; k < 32; k++) {
                    409:                        volumetable[i][0][k] = volumetable[i][1][k]; /* Move 0th Row */
                    410:                        volumetable[i][1][k] = volumetable[i][3][k]; /* Move 1st Row */
                    411:                        /* Interpolate 3rd Row */
                    412:                        volumetable[i][3][k] = (ymu16)(0.5 + sqrt((double)volumetable[i][1][k] * volumetable[i][5][k]));
                    413:                }
                    414:                for (j = 2; j < 32; j += 2) /* Interpolate Even Rows */
                    415:                        for (k = 0; k < 32; k++)
                    416:                                volumetable[i][j][k] = (ymu16)(0.5 + sqrt((double)volumetable[i][j-1][k] * volumetable[i][j+1][k]));
1.1.1.11  root      417:        }
1.1.1.18  root      418:        for (j = 0; j < 32; j++)
                    419:                for (k = 0; k < 32; k++) {
                    420:                        volumetable[0][j][k] = volumetable[1][j][k]; /* Move 0th Panel */
                    421:                        volumetable[1][j][k] = volumetable[3][j][k]; /* Move 1st Panel */
                    422:                        /* Interpolate 3rd Panel */
                    423:                        volumetable[3][j][k] = (ymu16)(0.5 + sqrt((double)volumetable[1][j][k] * volumetable[5][j][k]));
                    424:                }
                    425:        for (i = 2; i < 32; i += 2) /* Interpolate Even Panels */
                    426:                for (j = 0; j < 32; j++) /* Interpolate Even Panels */
                    427:                        for (k = 0; k < 32; k++)
                    428:                                volumetable[i][j][k] = (ymu16)(0.5 + sqrt((double)volumetable[i-1][j][k] * volumetable[i+1][j][k]));
1.1       root      429: }
                    430: 
1.1.1.5   root      431: 
1.1.1.12  root      432: 
                    433: 
1.1.1.2   root      434: /*-----------------------------------------------------------------------*/
1.1.1.11  root      435: /**
1.1.1.12  root      436:  * Build a linear version of the conversion table.
                    437:  * We use the mean of the 3 volumes converted to 16 bit values
                    438:  * (each value of ymout1c5bit is in [0,65535])
1.1.1.11  root      439:  */
1.1.1.12  root      440: 
1.1.1.18  root      441: static void    YM2149_BuildLinearVolumeTable(ymu16 volumetable[32][32][32])
1.1       root      442: {
1.1.1.12  root      443:        int     i, j, k;
                    444: 
                    445:        for (i = 0; i < 32; i++)
                    446:                for (j = 0; j < 32; j++)
                    447:                        for (k = 0; k < 32; k++)
1.1.1.18  root      448:                                volumetable[i][j][k] = (ymu16)( ((ymu32)ymout1c5bit[i] + ymout1c5bit[j] + ymout1c5bit[k]) / 3);
1.1.1.12  root      449: }
                    450: 
                    451: 
                    452: 
1.1       root      453: 
1.1.1.12  root      454: /*-----------------------------------------------------------------------*/
                    455: /**
1.1.1.17  root      456:  * Build a circuit analysed version of the conversion table.
                    457:  * David Savinkoff designed this algorithm by analysing data
                    458:  * measured by Paulo Simoes and Benjamin Gerard.
                    459:  * The numbers are arrived at by assuming a current steering
                    460:  * resistor ladder network and using the voltage divider rule.
1.1.1.18  root      461:  *
                    462:  * If one looks at the ST schematic of the YM2149, one sees
                    463:  * three sound pins tied together and attached to a 1000 ohm
                    464:  * resistor (1k) that has the other end grounded.
                    465:  * The 1k resistor is also in parallel with a 0.1 microfarad
                    466:  * capacitor (on the Atari ST, not STE or others). The voltage
                    467:  * developed across the 1K resistor is the output voltage which
                    468:  * I call Vout.
                    469:  *
1.1.1.19! root      470:  * The output of the YM2149 is modelled well as pullup resistors.
1.1.1.18  root      471:  * Thus, the three sound pins are seen as three parallel
                    472:  * computer-controlled, adjustable pull-up resistors.
                    473:  * To emulate the output of the YM2149, one must determine the
                    474:  * resistance values of the YM2149 relative to the 1k resistor,
                    475:  * which is done by the 'math model'.
                    476:  *
                    477:  * The AC + DC math model is:
                    478:  *
                    479:  * (MaxVol*WARP) / (1.0 + 1.0/(conductance_[i]+conductance_[j]+conductance_[k]))
                    480:  * or
                    481:  * (MaxVol*WARP) / (1.0 + 1.0/( 1/Ra +1/Rb  +1/Rc )) , Ra = channel A resistance
                    482:  *
                    483:  * Note that the first 1.0 in the formula represents the
                    484:  * normalized 1k resistor (1.0 * 1000 ohms = 1k).
                    485:  *
                    486:  * The YM2149 DC component model represents the output voltage
                    487:  * filtered of high frequency AC component, but DC component
                    488:  * remains.
                    489:  * The YM2149 DC component mode treats the voltage exactly as if
                    490:  * it were low pass filtered. This is more than what is required
                    491:  * to make 'quartet mode sound'. Simplicity leads to Generality!
                    492:  *
                    493:  * The DC component model model is:
                    494:  *
                    495:  * (MaxVol*WARP) / (2.0 + 1.0/( 1/Ra + 1/Rb  + 1/Rc))
                    496:  * or
                    497:  * (MaxVol*WARP*0.5) / (1.0 + 0.5/( 1/Ra + 1/Rb  + 1/Rc))
                    498:  *
                    499:  * Note that the 1.0 represents the normalized 1k resistor.
                    500:  * 0.5 represents 50% duty cycle for the parallel resistors
                    501:  * being summed (this effectively doubles the pull-up resistance).
1.1.1.17  root      502:  */
                    503: 
1.1.1.18  root      504: static void    YM2149_BuildModelVolumeTable(ymu16 volumetable[32][32][32])
1.1.1.17  root      505: {
1.1.1.18  root      506: #define MaxVol  65535.0               /* Normal Mode Maximum value in table */
                    507: #define FOURTH2 1.19                  /* Fourth root of two from YM2149 */
                    508: #define WARP    1.666666666666666667  /* measured as 1.65932 from 46602 */
1.1.1.17  root      509: 
                    510:        double conductance;
                    511:        double conductance_[32];
                    512:        int     i, j, k;
                    513: 
                    514: /**
                    515:  * YM2149 and R8=1k follows (2^-1/4)^(n-31) better when 2 voices are
                    516:  * summed (A+B or B+C or C+A) rather than individually (A or B or C):
1.1.1.18  root      517:  *   conductance = 2.0/3.0/(1.0-1.0/WARP)-2.0/3.0;
1.1.1.17  root      518:  * When taken into consideration with three voices.
                    519:  *
                    520:  * Note that the YM2149 does not use laser trimmed resistances, thus
                    521:  * has offsets that are added and/or multiplied with (2^-1/4)^(n-31).
                    522:  */
1.1.1.18  root      523:        conductance = 2.0/3.0/(1.0-1.0/WARP)-2.0/3.0; /* conductance = 1.0 */
1.1.1.17  root      524: 
                    525: /**
                    526:  * Because the YM current output (voltage source with series resistances)
                    527:  * is connected to a grounded resistor to develop the output voltage
                    528:  * (instead of a current to voltage converter), the output transfer
                    529:  * function is not linear. Thus:
                    530:  * 2.0*conductance_[n] = 1.0/(1.0-1.0/FOURTH2/(1.0/conductance + 1.0))-1.0;
                    531:  */
                    532:        for (i = 31; i >= 1; i--)
                    533:        {
                    534:                conductance_[i] = conductance/2.0;
                    535:                conductance = 1.0/(1.0-1.0/FOURTH2/(1.0/conductance + 1.0))-1.0;
                    536:        }
1.1.1.18  root      537:        conductance_[0] = 1.0e-8; /* Avoid divide by zero */
1.1.1.17  root      538: 
1.1.1.18  root      539: /**
                    540:  * YM2149 AC + DC components model:
                    541:  * (Note that Maxvol is 65119 in Simoes' table, 65535 in Gerard's)
                    542:  *
                    543:  * Sum the conductances as a function of a voltage divider:
                    544:  * Vout=Vin*Rout/(Rout+Rin)
                    545:  */
1.1.1.17  root      546:        for (i = 0; i < 32; i++)
                    547:                for (j = 0; j < 32; j++)
                    548:                        for (k = 0; k < 32; k++)
                    549:                        {
1.1.1.18  root      550:                                volumetable[i][j][k] = (ymu16)(0.5+(MaxVol*WARP)/(1.0 +
1.1.1.17  root      551:                                        1.0/(conductance_[i]+conductance_[j]+conductance_[k])));
                    552:                        }
1.1.1.18  root      553: 
                    554: /**
                    555:  * YM2149 DC component model:
                    556:  * R8=1k (pulldown) + YM//1K (pullup) with YM 50% duty PWM
                    557:  * (Note that MaxVol is 46602 in Paulo Simoes Quartet mode table)
                    558:  *
                    559:  *     for (i = 0; i < 32; i++)
                    560:  *             for (j = 0; j < 32; j++)
                    561:  *                     for (k = 0; k < 32; k++)
                    562:  *                     {
                    563:  *                             volumetable[i][j][k] = (ymu16)(0.5+(MaxVol*WARP)/(1.0 +
                    564:  *                                     2.0/(conductance_[i]+conductance_[j]+conductance_[k])));
                    565:  *                     }
                    566:  */
1.1.1.17  root      567: }
                    568: 
                    569: 
                    570: 
                    571: 
                    572: /*-----------------------------------------------------------------------*/
                    573: /**
1.1.1.12  root      574:  * Normalise and optionally center the volume table used to
                    575:  * convert the 3 volumes to a final signed 16 bit sample.
                    576:  * This allows to adapt the amplitude/volume of the samples and
                    577:  * to convert unsigned values to signed values.
                    578:  * - in_5bit contains 32*32*32 unsigned values in the range
                    579:  *     [0,65535].
                    580:  * - out_5bit will contain signed values
                    581:  * Possible values are :
                    582:  *     Level=65535 and DoCenter=TRUE -> [-32768,32767]
1.1.1.14  root      583:  *     Level=32767 and DoCenter=false -> [0,32767]
1.1.1.19! root      584:  *     Level=16383 and DoCenter=false -> [0,16383] (to avoid overflow with DMA sound on STe)
1.1.1.12  root      585:  */
                    586: 
                    587: static void    YM2149_Normalise_5bit_Table(ymu16 *in_5bit , yms16 *out_5bit, unsigned int Level, bool DoCenter)
                    588: {
                    589:        if ( Level )
1.1.1.11  root      590:        {
1.1.1.14  root      591:                int h;
1.1.1.12  root      592:                int Max = in_5bit[0x7fff];
1.1.1.19! root      593:                int Center = (Level+1)>>1;
1.1.1.14  root      594:                //fprintf ( stderr , "level %d max %d center %d\n" , Level, Max, Center );
                    595: 
1.1.1.12  root      596:                /* Change the amplitude of the signal to 'level' : [0,max] -> [0,level] */
                    597:                /* Then optionally center the signal around Level/2 */
                    598:                /* This means we go from sthg like [0,65535] to [-32768, 32767] if Level=65535 and DoCenter=TRUE */
                    599:                for (h=0; h<32*32*32; h++)
                    600:                {
                    601:                        int tmp = in_5bit[h], res;
                    602:                        res = tmp * Level / Max;
1.1.1.14  root      603: 
1.1.1.12  root      604:                        if ( DoCenter )
                    605:                                res -= Center;
                    606: 
                    607:                        out_5bit[h] = res;
1.1.1.14  root      608:                        //fprintf ( stderr , "h %d in %d out %d\n" , h , tmp , res );
1.1.1.12  root      609:                }
1.1.1.11  root      610:        }
1.1       root      611: }
                    612: 
1.1.1.5   root      613: 
1.1.1.12  root      614: 
                    615: 
1.1.1.2   root      616: /*-----------------------------------------------------------------------*/
1.1.1.11  root      617: /**
1.1.1.12  root      618:  * Precompute all 16 possible envelopes.
                    619:  * Each envelope is made of 3 blocks of 32 volumes.
1.1.1.11  root      620:  */
1.1.1.12  root      621: 
                    622: static void    YM2149_EnvBuild ( void )
1.1       root      623: {
1.1.1.12  root      624:        int     env;
                    625:        int     block;
                    626:        int     vol=0 , inc=0;
                    627:        int     i;
1.1       root      628: 
1.1.1.12  root      629: 
                    630:        for ( env=0 ; env<16 ; env++ )                          /* 16 possible envelopes */
                    631:                for ( block=0 ; block<3 ; block++ )             /* 3 blocks to define an envelope */
                    632:                {
1.1.1.14  root      633:                        switch ( YmEnvDef[ env ][ block ] )
                    634:                        {
1.1.1.12  root      635:                                case ENV_GODOWN :       vol=31 ; inc=-1 ; break;
                    636:                                case ENV_GOUP :         vol=0  ; inc=1 ; break;
                    637:                                case ENV_DOWN :         vol=0  ; inc=0 ; break;
                    638:                                case ENV_UP :           vol=31 ; inc=0 ; break;
1.1.1.14  root      639:                        }
                    640: 
1.1.1.12  root      641:                        for ( i=0 ; i<32 ; i++ )                /* 32 volumes per block */
                    642:                        {
                    643:                                YmEnvWaves[ env ][ block*32 + i ] = YM_MERGE_VOICE ( vol , vol , vol );
                    644:                                vol += inc;
                    645:                        }
                    646:                }
                    647: }
                    648: 
                    649: 
                    650: 
                    651: /*-----------------------------------------------------------------------*/
                    652: /**
1.1.1.16  root      653:  * Depending on the YM mixing method, build the table used to convert
                    654:  * the 3 YM volumes into a single sample.
1.1.1.12  root      655:  */
                    656: 
1.1.1.16  root      657: static void    Ym2149_BuildVolumeTable(void)
1.1.1.12  root      658: {
                    659:        /* Depending on the volume mixing method, we use a table based on real measures */
                    660:        /* or a table based on a linear volume mixing. */
1.1.1.17  root      661:        if ( YmVolumeMixing == YM_MODEL_MIXING )
                    662:                YM2149_BuildModelVolumeTable(ymout5_u16);       /* create 32*32*32 circuit analysed model of the volume table */
                    663:        else if ( YmVolumeMixing == YM_TABLE_MIXING )
1.1.1.16  root      664:                interpolate_volumetable(ymout5_u16);            /* expand the 16*16*16 values in volumetable_original to 32*32*32 */
1.1.1.12  root      665:        else
                    666:                YM2149_BuildLinearVolumeTable(ymout5_u16);      /* combine the 32 possible volumes */
                    667: 
                    668:        /* Normalise/center the values (convert from u16 to s16) */
1.1.1.19! root      669:        /* On STE/TT, we use YM_OUTPUT_LEVEL>>1 to avoid overflow with DMA sound */
        !           670:        if ( (ConfigureParams.System.nMachineType == MACHINE_STE) || (ConfigureParams.System.nMachineType == MACHINE_MEGA_STE)
        !           671:                || (ConfigureParams.System.nMachineType == MACHINE_TT) )
        !           672:                YM2149_Normalise_5bit_Table ( ymout5_u16[0][0] , ymout5 , (YM_OUTPUT_LEVEL>>1) , YM_OUTPUT_CENTERED );
        !           673:        else
        !           674:                YM2149_Normalise_5bit_Table ( ymout5_u16[0][0] , ymout5 , YM_OUTPUT_LEVEL , YM_OUTPUT_CENTERED );
1.1.1.16  root      675: }
                    676: 
                    677: 
                    678: 
                    679: /*-----------------------------------------------------------------------*/
                    680: /**
                    681:  * Init some internal tables for faster results (env, volume)
                    682:  * and reset the internal states.
                    683:  */
                    684: 
                    685: static void    Ym2149_Init(void)
                    686: {
                    687:        /* Build the 16 envelope shapes */
                    688:        YM2149_EnvBuild();
                    689: 
                    690:        /* Build the volume conversion table */
                    691:        Ym2149_BuildVolumeTable();
1.1.1.12  root      692: 
                    693:        /* Reset YM2149 internal states */
                    694:        Ym2149_Reset();
                    695: }
                    696: 
                    697: 
                    698: 
                    699: /*-----------------------------------------------------------------------*/
                    700: /**
1.1.1.16  root      701:  * Reset all ym registers as well as the internal variables
1.1.1.12  root      702:  */
                    703: 
                    704: static void    Ym2149_Reset(void)
                    705: {
                    706:        int     i;
1.1.1.14  root      707: 
1.1.1.12  root      708:        for ( i=0 ; i<14 ; i++ )
                    709:                Sound_WriteReg ( i , 0 );
                    710: 
                    711:        Sound_WriteReg ( 7 , 0xff );
                    712: 
1.1.1.16  root      713:        posA = 0;
                    714:        posB = 0;
                    715:        posC = 0;
                    716: 
1.1.1.12  root      717:        currentNoise = 0xffff;
1.1.1.14  root      718: 
1.1.1.12  root      719:        RndRack = 1;
1.1.1.14  root      720: 
1.1.1.12  root      721:        envShape = 0;
                    722:        envPos = 0;
                    723: }
                    724: 
                    725: 
                    726: 
                    727: /*-----------------------------------------------------------------------*/
                    728: /**
                    729:  * Returns a pseudo random value, used to generate white noise.
1.1.1.19! root      730:  * As measured by David Savinkoff, the YM2149 uses a 17 stage LSFR with
        !           731:  * 2 taps (17,14)
1.1.1.12  root      732:  */
                    733: 
                    734: static ymu32   YM2149_RndCompute(void)
                    735: {
1.1.1.19! root      736:        /*  17 stage, 2 taps (17, 14) LFSR */
        !           737:        if (RndRack & 1)
        !           738:        {
        !           739:                RndRack = RndRack>>1 ^ 0x12000;         /* bits 17 and 14 are ones */
        !           740:                return 0xffff;
        !           741:        }
        !           742:        else
        !           743:        {       RndRack >>= 1;
        !           744:                return 0;
        !           745:        }
1.1.1.12  root      746: }
                    747: 
                    748: 
                    749: 
                    750: /*-----------------------------------------------------------------------*/
                    751: /**
1.1.1.16  root      752:  * Compute tone's step based on the input period.
                    753:  * Although for tone we should have the same result when per==0 and per==1,
                    754:  * this gives some very sharp and unpleasant sounds in the emulation.
                    755:  * To get a better sound, we consider all per<=5 to give step=0, which will
                    756:  * produce a constant output at value '1'. This should be handled with some
                    757:  * proper filters to remove high frequencies as on a real ST (where per<=9
                    758:  * gives nearly no audible sound).
                    759:  * A common replay freq of 44.1 kHz will also not be high enough to correctly
                    760:  * render possible tone's freq of 125 or 62.5 kHz (when per==1 or per==2)
1.1.1.12  root      761:  */
                    762: 
1.1.1.16  root      763: #define NEWSTEP
                    764: #ifndef NEWSTEP
1.1.1.12  root      765: static ymu32   Ym2149_ToneStepCompute(ymu8 rHigh , ymu8 rLow)
                    766: {
                    767:        int     per;
1.1.1.14  root      768:        yms64   step;
1.1.1.12  root      769: 
                    770:        per = rHigh&15;
                    771:        per = (per<<8)+rLow;
1.1.1.18  root      772: 
                    773:        if  (per <= (int)(YM_ATARI_CLOCK/(YM_REPLAY_FREQ*7)) )
1.1.1.12  root      774:                return 0;
                    775: 
1.1.1.14  root      776:        step = YM_ATARI_CLOCK;
1.1.1.12  root      777:        step <<= (15+16-3);
                    778:        step /= (per * YM_REPLAY_FREQ);
                    779: 
                    780:        return step;
                    781: }
1.1.1.16  root      782: #else
                    783: static ymu32   Ym2149_ToneStepCompute(ymu8 rHigh , ymu8 rLow)
                    784: {
                    785:        int     per;
                    786:        yms64   step;
                    787: 
                    788:        per = rHigh&15;
                    789:        per = (per<<8)+rLow;
                    790: 
                    791: #if 0                                                  /* need some high freq filters for this to work correctly */
                    792:        if ( per == 0 )
                    793:                per = 1;                                /* result for Per=0 is the same as for Per=1 */ 
                    794: #else
1.1.1.18  root      795:        if  (per <= (int)(YM_ATARI_CLOCK/(YM_REPLAY_FREQ*7)) )
                    796:                return 0;                               /* discard frequencies higher than 80% of nyquist rate. */
1.1.1.16  root      797: #endif
                    798: 
                    799:        step = YM_ATARI_CLOCK;
                    800:        step <<= 24;
                    801: 
                    802:        step /= (per * 8 * YM_REPLAY_FREQ);             /* 0x5ab9 < step < 0x5ab3f46 at 44.1 kHz */
                    803: 
                    804:        return step;
                    805: }
                    806: #endif
1.1.1.12  root      807: 
1.1.1.16  root      808: /*-----------------------------------------------------------------------*/
                    809: /**
                    810:  * Compute noise's step based on the input period.
                    811:  * On a real STF, we get the same result when per==0 and per==1.
                    812:  * A common replay freq of 44.1 kHz will not be high enough to correctly
                    813:  * render possible noise's freq of 125 or 62.5 kHz (when per==1 or per==2).
                    814:  * With a random wave such as noise, this means that with a replay freq
                    815:  * of 44.1 kHz, per==1 and per==2 (as well as per==3) will sound the same :
                    816:  *     per==1   step=0x2d59fa3   freq=125 kHz
                    817:  *     per==2   step=0x16acfd1   freq=62.5 kHz
                    818:  *     per==3   step=0x0f1dfe1   freq=41.7 kHz
                    819:  */
1.1.1.12  root      820: 
1.1.1.16  root      821: #ifndef NEWSTEP
1.1.1.12  root      822: static ymu32   Ym2149_NoiseStepCompute(ymu8 rNoise)
                    823: {
                    824:        int     per;
1.1.1.14  root      825:        yms64   step;
1.1.1.12  root      826: 
                    827:        per = (rNoise&0x1f);
                    828:        if (per<3)
                    829:                return 0;
                    830: 
1.1.1.14  root      831:        step = YM_ATARI_CLOCK;
1.1.1.12  root      832:        step <<= (16-1-3);
                    833:        step /= (per * YM_REPLAY_FREQ);
                    834: 
                    835:        return step;
1.1       root      836: }
1.1.1.16  root      837: #else
                    838: static ymu32   Ym2149_NoiseStepCompute(ymu8 rNoise)
                    839: {
                    840:        int     per;
                    841:        yms64   step;
                    842: 
                    843:        per = (rNoise&0x1f);
1.1       root      844: 
1.1.1.16  root      845:        if ( per == 0 )
                    846:                per = 1;                                /* result for Per=0 is the same as for Per=1 */ 
                    847: 
                    848:        step = YM_ATARI_CLOCK;
                    849:        step <<= 24;
                    850: 
                    851:        step /= (per * 16 * YM_REPLAY_FREQ);            /* 0x17683f < step < 0x2d59fa3 at 44.1 kHz */
                    852: 
                    853:        return step;
                    854: }
                    855: #endif
1.1.1.5   root      856: 
1.1.1.2   root      857: /*-----------------------------------------------------------------------*/
1.1.1.11  root      858: /**
1.1.1.12  root      859:  * Compute envelope's step. The envelope is made of different patterns
                    860:  * of 32 volumes. In each pattern, the volume is changed at frequency
                    861:  * Fe = MasterClock / ( 8 * EnvPer ).
                    862:  * In our case, we use a lower replay freq ; between 2 consecutive calls
                    863:  * to envelope's generation, the internal counter will advance 'step'
                    864:  * units, where step = MasterClock / ( 8 * EnvPer * YM_REPLAY_FREQ )
                    865:  * As 'step' requires floating point to be stored, we use left shifting
                    866:  * to multiply 'step' by a fixed amount. All operations are made with
                    867:  * shifted values ; to get the final value, we must right shift the
                    868:  * result. We use '<<24', which gives 8 bits for the integer part, and
                    869:  * the equivalent of 24 bits for the fractional part.
                    870:  * Since we're using large numbers, we temporarily use 64 bits integer
                    871:  * to avoid overflow and keep largest precision possible.
1.1.1.16  root      872:  * On a real STF, we get the same result when per==0 and per==1.
1.1.1.11  root      873:  */
1.1.1.12  root      874: 
                    875: static ymu32   Ym2149_EnvStepCompute(ymu8 rHigh , ymu8 rLow)
1.1       root      876: {
1.1.1.12  root      877:        yms64   per;
1.1.1.14  root      878:        yms64   step;
1.1       root      879: 
1.1.1.12  root      880:        per = rHigh;
                    881:        per = (per<<8)+rLow;
                    882: 
1.1.1.14  root      883:        step = YM_ATARI_CLOCK;
1.1.1.12  root      884:        step <<= 24;
1.1.1.16  root      885: 
                    886:        if ( per == 0 )
                    887:                per = 1;                                /* result for Per=0 is the same as for Per=1 */ 
                    888: 
                    889:        step /= (8 * per * YM_REPLAY_FREQ);             /* 0x5ab < step < 0x5ab3f46 at 44.1 kHz */
1.1.1.12  root      890: 
                    891:        return step;
                    892: }
                    893: 
                    894: 
                    895: 
                    896: /*-----------------------------------------------------------------------*/
                    897: /**
                    898:  * Main function : compute the value of the next sample.
                    899:  * Mixes all 3 voices with tone+noise+env and apply low pass
                    900:  * filter if needed.
1.1.1.16  root      901:  * All operations are done with integer math, using <<24 to simulate
                    902:  * floating point precision : upper 8 bits are the integer part, lower 24
                    903:  * are the fractional part.
                    904:  * Tone is a square wave with 2 states 0 or 1. If integer part of posX is
                    905:  * even (bit24=0) we consider output is 0, else (bit24=1) we consider
                    906:  * output is 1. This gives the value of bt for one voice after extending it
                    907:  * to all 0 bits or all 1 bits using a '-'
1.1.1.12  root      908:  */
                    909: 
1.1.1.16  root      910: #ifndef NEWSTEP
1.1.1.12  root      911: static ymsample        YM2149_NextSample(void)
                    912: {
                    913:        ymsample        sample;
                    914:        int             bt;
                    915:        ymu32           bn;
                    916:        ymu16           Env3Voices;
                    917:        ymu16           Tone3Voices;
                    918: 
                    919: 
                    920:        /* Noise value : 0 or 0xffff */
                    921:        if ( noisePos&0xffff0000 )
                    922:        {
1.1.1.19! root      923:                currentNoise = YM2149_RndCompute();
1.1.1.12  root      924:                noisePos &= 0xffff;
                    925:        }
                    926:        bn = currentNoise;                              /* 0 or 0xffff */
                    927: 
                    928:        /* Get the 5 bits volume corresponding to the current envelope's position */
                    929:        Env3Voices = YmEnvWaves[ envShape ][ envPos>>24 ];      /* integer part of envPos is in bits 24-31 */
                    930:        Env3Voices &= EnvMask3Voices;                   /* only keep volumes for voices using envelope */
                    931: 
                    932: //fprintf ( stderr , "env %x %x %x\n" , Env3Voices , envStep , envPos );
                    933: 
                    934:        /* Tone3Voices will contain the output state of each voice : 0 or 0x1f */
                    935:        bt = ((((yms32)posA)>>31) | mixerTA) & (bn | mixerNA);  /* 0 or 0xffff */
                    936:        Tone3Voices = bt & YM_MASK_1VOICE;                      /* 0 or 0x1f */
                    937:        bt = ((((yms32)posB)>>31) | mixerTB) & (bn | mixerNB);
                    938:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 5;
                    939:        bt = ((((yms32)posC)>>31) | mixerTC) & (bn | mixerNC);
                    940:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 10;
                    941: 
                    942:        /* Combine fixed volumes and envelope volumes and keep the resulting */
                    943:        /* volumes depending on the output state of each voice (0 or 0x1f) */
                    944:        Tone3Voices &= ( Env3Voices | Vol3Voices );
                    945: 
1.1.1.18  root      946:        /* When a step period is 0, the represented frequency was filtered from the */
                    947:        /* ouput of the YM2149. Thus, use the transient DC component of the sample. */
                    948:        /* Note that the "-1" table offset is a "good fit" for the DC component.    */
                    949: 
                    950:        if (stepA == 0  &&  (Tone3Voices & YM_MASK_A) > 1)
                    951:                Tone3Voices -= 1;     /* Voice A AC component removed; Transient DC component remains */
                    952: 
                    953:        if (stepB == 0  &&  (Tone3Voices & YM_MASK_B) > 1<<5)
                    954:                Tone3Voices -= 1<<5;  /* Voice B AC component removed; Transient DC component remains */
                    955: 
                    956:        if (stepC == 0  &&  (Tone3Voices & YM_MASK_C) > 1<<10)
                    957:                Tone3Voices -= 1<<10; /* Voice C AC component removed; Transient DC component remains */
                    958: 
1.1.1.12  root      959:        /* D/A conversion of the 3 volumes into a sample using a precomputed conversion table */
1.1.1.18  root      960: 
1.1.1.12  root      961:        sample = ymout5[ Tone3Voices ];                 /* 16 bits signed value */
                    962: 
                    963: 
                    964:        /* Increment positions */
                    965:        posA += stepA;
                    966:        posB += stepB;
                    967:        posC += stepC;
                    968:        noisePos += noiseStep;
1.1.1.14  root      969: 
1.1.1.12  root      970:        envPos += envStep;
                    971:        if ( envPos >= (3*32) << 24 )                   /* blocks 0, 1 and 2 were used (envPos 0 to 95) */
                    972:                envPos -= (2*32) << 24;                 /* replay/loop blocks 1 and 2 (envPos 32 to 95) */
                    973: 
                    974:        /* Apply low pass filter ? */
                    975:        if ( UseLowPassFilter )
1.1.1.18  root      976:                return LowPassFilter(sample);
                    977:        else
                    978:                return PWMaliasFilter(sample);
1.1       root      979: }
1.1.1.16  root      980: #else
                    981: static ymsample        YM2149_NextSample(void)
                    982: {
                    983:        ymsample        sample;
                    984:        ymu32           bt;
                    985:        ymu32           bn;
                    986:        ymu16           Env3Voices;                     /* 0x00CCBBAA */
                    987:        ymu16           Tone3Voices;                    /* 0x00CCBBAA */
1.1       root      988: 
                    989: 
1.1.1.16  root      990:        /* Noise value : 0 or 0xffff */
                    991:        if ( noisePos&0xff000000 )                      /* integer part > 0 */
                    992:        {
1.1.1.19! root      993:                currentNoise = YM2149_RndCompute();
1.1.1.16  root      994:                noisePos &= 0xffffff;                   /* keep fractional part of noisePos */
                    995:        }
                    996:        bn = currentNoise;                              /* 0 or 0xffff */
                    997: 
                    998:        /* Get the 5 bits volume corresponding to the current envelope's position */
                    999:        Env3Voices = YmEnvWaves[ envShape ][ envPos>>24 ];      /* integer part of envPos is in bits 24-31 */
                   1000:        Env3Voices &= EnvMask3Voices;                   /* only keep volumes for voices using envelope */
                   1001: 
                   1002: //fprintf ( stderr , "env %x %x %x\n" , Env3Voices , envStep , envPos );
                   1003: 
                   1004:        /* Tone3Voices will contain the output state of each voice : 0 or 0x1f */
                   1005:        bt = -( (posA>>24) & 1);                        /* 0 if bit24=0 or 0xffffffff if bit24=1 */
                   1006:        bt = (bt | mixerTA) & (bn | mixerNA);           /* 0 or 0xffff */
                   1007:        Tone3Voices = bt & YM_MASK_1VOICE;              /* 0 or 0x1f */
                   1008:        bt = -( (posB>>24) & 1);
                   1009:        bt = (bt | mixerTB) & (bn | mixerNB);
                   1010:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 5;
                   1011:        bt = -( (posC>>24) & 1);
                   1012:        bt = (bt | mixerTC) & (bn | mixerNC);
                   1013:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 10;
                   1014: 
                   1015:        /* Combine fixed volumes and envelope volumes and keep the resulting */
                   1016:        /* volumes depending on the output state of each voice (0 or 0x1f) */
                   1017:        Tone3Voices &= ( Env3Voices | Vol3Voices );
                   1018: 
                   1019:        /* D/A conversion of the 3 volumes into a sample using a precomputed conversion table */
1.1.1.18  root     1020: 
                   1021:        if (stepA == 0  &&  (Tone3Voices & YM_MASK_A) > 1)
                   1022:                Tone3Voices -= 1;     /* Voice A AC component removed; Transient DC component remains */
                   1023: 
                   1024:        if (stepB == 0  &&  (Tone3Voices & YM_MASK_B) > 1<<5)
                   1025:                Tone3Voices -= 1<<5;  /* Voice B AC component removed; Transient DC component remains */
                   1026: 
                   1027:        if (stepC == 0  &&  (Tone3Voices & YM_MASK_C) > 1<<10)
                   1028:                Tone3Voices -= 1<<10; /* Voice C AC component removed; Transient DC component remains */
                   1029: 
1.1.1.16  root     1030:        sample = ymout5[ Tone3Voices ];                 /* 16 bits signed value */
                   1031: 
                   1032: 
                   1033:        /* Increment positions */
                   1034:        posA += stepA;
                   1035:        posB += stepB;
                   1036:        posC += stepC;
                   1037:        noisePos += noiseStep;
                   1038: 
                   1039:        envPos += envStep;
                   1040:        if ( envPos >= (3*32) << 24 )                   /* blocks 0, 1 and 2 were used (envPos 0 to 95) */
                   1041:                envPos -= (2*32) << 24;                 /* replay/loop blocks 1 and 2 (envPos 32 to 95) */
                   1042: 
                   1043:        /* Apply low pass filter ? */
                   1044:        if ( UseLowPassFilter )
1.1.1.18  root     1045:                return LowPassFilter(sample);
                   1046:        else
                   1047:                return PWMaliasFilter(sample);
1.1.1.16  root     1048: }
                   1049: #endif
                   1050: 
1.1.1.12  root     1051: 
1.1.1.2   root     1052: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1053: /**
1.1.1.12  root     1054:  * Update internal variables (steps, volume masks, ...) each
                   1055:  * time an YM register is changed.
1.1.1.11  root     1056:  */
1.1.1.16  root     1057: #ifndef NEWSTEP
                   1058: #define BIT_SHIFT 31
                   1059: #else
                   1060: #define BIT_SHIFT 24
                   1061: #endif
1.1.1.12  root     1062: void   Sound_WriteReg( int reg , Uint8 data )
1.1.1.7   root     1063: {
1.1.1.12  root     1064:        switch (reg)
                   1065:        {
                   1066:                case 0:
                   1067:                        SoundRegs[0] = data;
                   1068:                        stepA = Ym2149_ToneStepCompute ( SoundRegs[1] , SoundRegs[0] );
1.1.1.16  root     1069:                        if (!stepA) posA = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root     1070:                        break;
                   1071: 
                   1072:                case 1:
                   1073:                        SoundRegs[1] = data & 0x0f;
                   1074:                        stepA = Ym2149_ToneStepCompute ( SoundRegs[1] , SoundRegs[0] );
1.1.1.16  root     1075:                        if (!stepA) posA = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root     1076:                        break;
                   1077: 
                   1078:                case 2:
                   1079:                        SoundRegs[2] = data;
                   1080:                        stepB = Ym2149_ToneStepCompute ( SoundRegs[3] , SoundRegs[2] );
1.1.1.16  root     1081:                        if (!stepB) posB = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root     1082:                        break;
1.1.1.7   root     1083: 
1.1.1.12  root     1084:                case 3:
                   1085:                        SoundRegs[3] = data & 0x0f;
                   1086:                        stepB = Ym2149_ToneStepCompute ( SoundRegs[3] , SoundRegs[2] );
1.1.1.16  root     1087:                        if (!stepB) posB = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root     1088:                        break;
                   1089: 
                   1090:                case 4:
                   1091:                        SoundRegs[4] = data;
                   1092:                        stepC = Ym2149_ToneStepCompute ( SoundRegs[5] , SoundRegs[4] );
1.1.1.16  root     1093:                        if (!stepC) posC = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root     1094:                        break;
                   1095: 
                   1096:                case 5:
                   1097:                        SoundRegs[5] = data & 0x0f;
                   1098:                        stepC = Ym2149_ToneStepCompute ( SoundRegs[5] , SoundRegs[4] );
1.1.1.16  root     1099:                        if (!stepC) posC = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root     1100:                        break;
                   1101: 
                   1102:                case 6:
                   1103:                        SoundRegs[6] = data & 0x1f;
                   1104:                        noiseStep = Ym2149_NoiseStepCompute ( SoundRegs[6] );
                   1105:                        if (!noiseStep)
                   1106:                        {
                   1107:                                noisePos = 0;
                   1108:                                currentNoise = 0xffff;
                   1109:                        }
                   1110:                        break;
                   1111: 
                   1112:                case 7:
                   1113:                        SoundRegs[7] = data & 0x3f;                     /* ignore bits 6 and 7 */
                   1114:                        mixerTA = (data&(1<<0)) ? 0xffff : 0;
                   1115:                        mixerTB = (data&(1<<1)) ? 0xffff : 0;
                   1116:                        mixerTC = (data&(1<<2)) ? 0xffff : 0;
                   1117:                        mixerNA = (data&(1<<3)) ? 0xffff : 0;
                   1118:                        mixerNB = (data&(1<<4)) ? 0xffff : 0;
                   1119:                        mixerNC = (data&(1<<5)) ? 0xffff : 0;
                   1120:                        break;
                   1121: 
                   1122:                case 8:
                   1123:                        SoundRegs[8] = data & 0x1f;
                   1124:                        if ( data & 0x10 )
                   1125:                        {
                   1126:                                EnvMask3Voices |= YM_MASK_A;            /* env ON */
                   1127:                                Vol3Voices &= ~YM_MASK_A;               /* fixed vol OFF */
                   1128:                        }
                   1129:                        else
                   1130:                        {
                   1131:                                EnvMask3Voices &= ~YM_MASK_A;           /* env OFF */
                   1132:                                Vol3Voices &= ~YM_MASK_A;               /* clear previous vol */
                   1133:                                Vol3Voices |= YmVolume4to5[ SoundRegs[8] ];     /* fixed vol ON */
                   1134:                        }
                   1135:                        break;
1.1.1.14  root     1136: 
1.1.1.12  root     1137:                case 9:
                   1138:                        SoundRegs[9] = data & 0x1f;
                   1139:                        if ( data & 0x10 )
                   1140:                        {
                   1141:                                EnvMask3Voices |= YM_MASK_B;            /* env ON */
                   1142:                                Vol3Voices &= ~YM_MASK_B;               /* fixed vol OFF */
                   1143:                        }
                   1144:                        else
                   1145:                        {
                   1146:                                EnvMask3Voices &= ~YM_MASK_B;           /* env OFF */
                   1147:                                Vol3Voices &= ~YM_MASK_B;               /* clear previous vol */
                   1148:                                Vol3Voices |= ( YmVolume4to5[ SoundRegs[9] ] ) << 5;    /* fixed vol ON */
                   1149:                        }
                   1150:                        break;
1.1.1.14  root     1151: 
1.1.1.12  root     1152:                case 10:
                   1153:                        SoundRegs[10] = data & 0x1f;
                   1154:                        if ( data & 0x10 )
                   1155:                        {
                   1156:                                EnvMask3Voices |= YM_MASK_C;            /* env ON */
                   1157:                                Vol3Voices &= ~YM_MASK_C;               /* fixed vol OFF */
                   1158:                        }
                   1159:                        else
                   1160:                        {
                   1161:                                EnvMask3Voices &= ~YM_MASK_C;           /* env OFF */
                   1162:                                Vol3Voices &= ~YM_MASK_C;               /* clear previous vol */
                   1163:                                Vol3Voices |= ( YmVolume4to5[ SoundRegs[10] ] ) << 10;  /* fixed vol ON */
                   1164:                        }
                   1165:                        break;
                   1166: 
                   1167:                case 11:
                   1168:                        SoundRegs[11] = data;
                   1169:                        envStep = Ym2149_EnvStepCompute ( SoundRegs[12] , SoundRegs[11] );
                   1170:                        break;
                   1171: 
                   1172:                case 12:
                   1173:                        SoundRegs[12] = data;
                   1174:                        envStep = Ym2149_EnvStepCompute ( SoundRegs[12] , SoundRegs[11] );
                   1175:                        break;
                   1176: 
                   1177:                case 13:
                   1178:                        SoundRegs[13] = data & 0xf;
                   1179:                        envPos = 0;                                     /* when writing to EnvShape, we must reset the EnvPos */
                   1180:                        envShape = SoundRegs[13];
1.1.1.14  root     1181:                        bEnvelopeFreqFlag = true;                       /* used for YmFormat saving */
1.1.1.12  root     1182:                        break;
                   1183: 
                   1184:        }
                   1185: }
                   1186: 
                   1187: 
                   1188: 
                   1189: /*-----------------------------------------------------------------------*/
                   1190: /**
                   1191:  * Init random generator, sound tables and envelopes
                   1192:  * (called only once when Hatari starts)
                   1193:  */
                   1194: void Sound_Init(void)
                   1195: {
                   1196:        /* Build volume/env tables, ... */
                   1197:        Ym2149_Init();
1.1.1.14  root     1198: 
1.1.1.11  root     1199:        Sound_Reset();
1.1.1.7   root     1200: }
                   1201: 
                   1202: 
                   1203: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1204: /**
1.1.1.12  root     1205:  * Reset the sound emulation (called from Reset_ST() in reset.c)
1.1.1.11  root     1206:  */
1.1.1.7   root     1207: void Sound_Reset(void)
                   1208: {
1.1.1.11  root     1209:        /* Lock audio system before accessing variables which are used by the
                   1210:         * callback function, too! */
                   1211:        Audio_Lock();
1.1.1.9   root     1212: 
1.1.1.11  root     1213:        /* Clear sound mixing buffer: */
1.1.1.12  root     1214:        memset(MixBuffer, 0, sizeof(MixBuffer));
1.1.1.7   root     1215: 
1.1.1.11  root     1216:        /* Clear cycle counts, buffer index and register '13' flags */
                   1217:        Cycles_SetCounter(CYCLES_COUNTER_SOUND, 0);
1.1.1.14  root     1218:        bEnvelopeFreqFlag = false;
                   1219: 
1.1.1.11  root     1220:        CompleteSndBufIdx = 0;
                   1221:        /* We do not start with 0 here to fake some initial samples: */
                   1222:        nGeneratedSamples = SoundBufferSize + SAMPLES_PER_FRAME;
                   1223:        ActiveSndBufIdx = nGeneratedSamples % MIXBUFFER_SIZE;
1.1.1.16  root     1224:        SamplesPerFrame = SAMPLES_PER_FRAME;
                   1225:        CurrentSamplesNb = 0;
                   1226:        ActiveSndBufIdxAvi = ActiveSndBufIdx;
1.1.1.15  root     1227: //fprintf ( stderr , "Sound_Reset SoundBufferSize %d SAMPLES_PER_FRAME %d nGeneratedSamples %d , ActiveSndBufIdx %d\n" ,
                   1228: //     SoundBufferSize , SAMPLES_PER_FRAME, nGeneratedSamples , ActiveSndBufIdx );
1.1.1.7   root     1229: 
1.1.1.12  root     1230:        Ym2149_Reset();
1.1.1.9   root     1231: 
1.1.1.11  root     1232:        Audio_Unlock();
1.1.1.7   root     1233: }
                   1234: 
                   1235: 
                   1236: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1237: /**
                   1238:  * Reset the sound buffer index variables.
1.1.1.16  root     1239:  * Very important : this function should only be called by setting
                   1240:  * Sound_BufferIndexNeedReset=true ; sound buffer index should be reset
                   1241:  * only after the sound for the whole VBL was updated (CurrentSamplesNb returns to 0)
                   1242:  * else it will alter the value of DMA Frame Count ($ff8909/0b/0d) and
                   1243:  * could cause crashes in some programs.
1.1.1.11  root     1244:  */
1.1.1.9   root     1245: void Sound_ResetBufferIndex(void)
1.1.1.7   root     1246: {
1.1.1.11  root     1247:        Audio_Lock();
                   1248:        nGeneratedSamples = SoundBufferSize + SAMPLES_PER_FRAME;
                   1249:        ActiveSndBufIdx =  (CompleteSndBufIdx + nGeneratedSamples) % MIXBUFFER_SIZE;
1.1.1.16  root     1250:        SamplesPerFrame = SAMPLES_PER_FRAME;
                   1251:        CurrentSamplesNb = 0;
                   1252:        ActiveSndBufIdxAvi = ActiveSndBufIdx;
1.1.1.15  root     1253: //fprintf ( stderr , "Sound_ResetBufferIndex SoundBufferSize %d SAMPLES_PER_FRAME %d nGeneratedSamples %d , ActiveSndBufIdx %d\n" ,
                   1254: //     SoundBufferSize , SAMPLES_PER_FRAME, nGeneratedSamples , ActiveSndBufIdx );
1.1.1.11  root     1255:        Audio_Unlock();
1.1.1.7   root     1256: }
                   1257: 
                   1258: 
                   1259: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1260: /**
                   1261:  * Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                   1262:  */
1.1.1.12  root     1263: void Sound_MemorySnapShot_Capture(bool bSave)
1.1.1.7   root     1264: {
1.1.1.11  root     1265:        /* Save/Restore details */
1.1.1.12  root     1266:        MemorySnapShot_Store(&stepA, sizeof(stepA));
                   1267:        MemorySnapShot_Store(&stepB, sizeof(stepB));
                   1268:        MemorySnapShot_Store(&stepC, sizeof(stepC));
                   1269:        MemorySnapShot_Store(&posA, sizeof(posA));
                   1270:        MemorySnapShot_Store(&posB, sizeof(posB));
                   1271:        MemorySnapShot_Store(&posC, sizeof(posC));
                   1272: 
                   1273:        MemorySnapShot_Store(&mixerTA, sizeof(mixerTA));
                   1274:        MemorySnapShot_Store(&mixerTB, sizeof(mixerTB));
                   1275:        MemorySnapShot_Store(&mixerTC, sizeof(mixerTC));
                   1276:        MemorySnapShot_Store(&mixerNA, sizeof(mixerNA));
                   1277:        MemorySnapShot_Store(&mixerNB, sizeof(mixerNB));
                   1278:        MemorySnapShot_Store(&mixerNC, sizeof(mixerNC));
                   1279: 
                   1280:        MemorySnapShot_Store(&noiseStep, sizeof(noiseStep));
                   1281:        MemorySnapShot_Store(&noisePos, sizeof(noisePos));
                   1282:        MemorySnapShot_Store(&currentNoise, sizeof(currentNoise));
                   1283:        MemorySnapShot_Store(&RndRack, sizeof(RndRack));
                   1284: 
                   1285:        MemorySnapShot_Store(&envStep, sizeof(envStep));
                   1286:        MemorySnapShot_Store(&envPos, sizeof(envPos));
                   1287:        MemorySnapShot_Store(&envShape, sizeof(envShape));
1.1.1.14  root     1288: 
1.1.1.12  root     1289:        MemorySnapShot_Store(&EnvMask3Voices, sizeof(EnvMask3Voices));
                   1290:        MemorySnapShot_Store(&Vol3Voices, sizeof(Vol3Voices));
1.1.1.14  root     1291: 
1.1.1.12  root     1292:        MemorySnapShot_Store(SoundRegs, sizeof(SoundRegs));
                   1293: 
1.1.1.14  root     1294:        // MemorySnapShot_Store(&YmVolumeMixing, sizeof(YmVolumeMixing));
                   1295:        // MemorySnapShot_Store(&UseLowPassFilter, sizeof(UseLowPassFilter));
1.1.1.7   root     1296: }
                   1297: 
                   1298: 
                   1299: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1300: /**
                   1301:  * Find how many samples to generate and store in 'nSamplesToGenerate'
                   1302:  * Also update sound cycles counter to store how many we actually did
                   1303:  * so generates set amount each frame.
1.1.1.16  root     1304:  * If FillFrame is true, this means we reach the end of the VBL and me must
                   1305:  * add as many samples as necessary to get a total of SamplesPerFrame
                   1306:  * for this VBL.
1.1.1.11  root     1307:  */
1.1.1.16  root     1308: static int Sound_SetSamplesPassed(bool FillFrame)
1.1       root     1309: {
1.1.1.11  root     1310:        int nSoundCycles;
1.1.1.16  root     1311:        int SamplesToGenerate;                          /* How many samples are needed for this time-frame */
                   1312: 
                   1313:        nSoundCycles = Cycles_GetCounter(CYCLES_COUNTER_VIDEO);
1.1.1.11  root     1314: 
1.1.1.16  root     1315:        /* example : 160256 cycles per VBL, 44Khz = 882 samples per VBL at 50 Hz */
                   1316:        /* 882/160256 samples per cpu clock cycle */
1.1.1.11  root     1317: 
1.1.1.16  root     1318:        /* Total number of samples that we should have at this point of the VBL */
                   1319:        SamplesToGenerate = nSoundCycles * SamplesPerFrame
                   1320:                / ClocksTimings_GetCyclesPerVBL ( ConfigureParams.System.nMachineType , nScreenRefreshRate );
1.1.1.11  root     1321: 
1.1.1.16  root     1322: //if (SamplesToGenerate > SamplesPerFrame )
                   1323: //fprintf ( stderr , "over run %d %d\n" , SamplesPerFrame , SamplesToGenerate );
1.1.1.11  root     1324: 
1.1.1.16  root     1325:        if (SamplesToGenerate > SamplesPerFrame)
                   1326:                SamplesToGenerate = SamplesPerFrame;
                   1327: 
                   1328:        SamplesToGenerate -= CurrentSamplesNb;          /* don't count samples that were already generated up to now */
                   1329:        if ( SamplesToGenerate < 0 )
                   1330:                SamplesToGenerate = 0;
                   1331: 
                   1332: 
                   1333:        /* If we're called from the VBL interrupt (FillFrame==true), we must ensure we have */
                   1334:        /* an exact total of SamplesPerFrame samples during a full VBL (we take into account */
                   1335:        /* the samples that were already generated during this VBL) */
                   1336:        if ( FillFrame )
                   1337:        {
                   1338:                SamplesToGenerate = SamplesPerFrame - CurrentSamplesNb; /* how many samples are missing to reach SamplesPerFrame */
                   1339:                if ( SamplesToGenerate < 0 )
                   1340:                        SamplesToGenerate = 0;
                   1341:        }
1.1.1.11  root     1342: 
1.1.1.16  root     1343:        /* Check we don't fill the sound's ring buffer before it's played by Audio_Callback()   */
                   1344:        /* This should never happen, except if the system suffers major slowdown due to other   */
                   1345:        /* processes or if we run in fast forward mode.                                         */
                   1346:        /* In the case of slowdown, we set Sound_BufferIndexNeedReset to "resync" the working   */
                   1347:        /* buffer's index ActiveSndBufIdx with the system buffer's index CompleteSndBufIdx.     */
                   1348:        /* In the case of fast forward, we do nothing here, Sound_BufferIndexNeedReset will be  */
                   1349:        /* set when the user exits fast forward mode.                                           */
                   1350:        if ( ( SamplesToGenerate > MIXBUFFER_SIZE - nGeneratedSamples ) && ( ConfigureParams.System.bFastForward == false )
                   1351:            && ( ConfigureParams.Sound.bEnableSound == true ) )
1.1.1.11  root     1352:        {
1.1.1.16  root     1353:                Log_Printf ( LOG_WARN , "Your system is too slow, some sound samples were not correctly emulated\n" );
                   1354:                Sound_BufferIndexNeedReset = true;
1.1.1.11  root     1355:        }
1.1.1.16  root     1356: 
                   1357: //fprintf ( stderr , "vbl %d hbl %d samp_gen %d / %d frac %lx\n" , nVBLs , nHBL , SamplesToGenerate , SamplesPerFrame , (long int)SamplesPerFrame_unrounded );
                   1358: 
                   1359:        return SamplesToGenerate;
1.1       root     1360: }
                   1361: 
1.1.1.5   root     1362: 
1.1.1.2   root     1363: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1364: /**
                   1365:  * Generate samples for all channels during this time-frame
                   1366:  */
1.1.1.16  root     1367: static void Sound_GenerateSamples(int SamplesToGenerate)
1.1       root     1368: {
1.1.1.12  root     1369:        int     i;
                   1370:        int     idx;
1.1.1.14  root     1371: 
1.1.1.16  root     1372:        if (SamplesToGenerate <= 0)
1.1.1.12  root     1373:                return;
1.1.1.14  root     1374: 
1.1.1.15  root     1375:        if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
1.1.1.11  root     1376:        {
1.1.1.16  root     1377:                for (i = 0; i < SamplesToGenerate; i++)
1.1.1.15  root     1378:                {
                   1379:                        idx = (ActiveSndBufIdx + i) % MIXBUFFER_SIZE;
1.1.1.17  root     1380:                        MixBuffer[idx][0] = MixBuffer[idx][1] = Subsonic_IIR_HPF_Left( YM2149_NextSample() );
1.1.1.15  root     1381:                }
                   1382:                /* If Falcon emulation, crossbar does the job */
1.1.1.16  root     1383:                Crossbar_GenerateSamples(ActiveSndBufIdx, SamplesToGenerate);
1.1.1.11  root     1384:        }
1.1.1.15  root     1385:        else if (ConfigureParams.System.nMachineType != MACHINE_ST)
                   1386:        {
1.1.1.16  root     1387:                for (i = 0; i < SamplesToGenerate; i++)
1.1.1.15  root     1388:                {
                   1389:                        idx = (ActiveSndBufIdx + i) % MIXBUFFER_SIZE;
1.1.1.18  root     1390:                        MixBuffer[idx][0] = MixBuffer[idx][1] = YM2149_NextSample();
1.1.1.15  root     1391:                }
1.1.1.17  root     1392:                /* If Ste or TT emulation, DmaSnd does mixing and filtering */
1.1.1.16  root     1393:                DmaSnd_GenerateSamples(ActiveSndBufIdx, SamplesToGenerate);
1.1.1.15  root     1394:        }
                   1395:        else if (ConfigureParams.System.nMachineType == MACHINE_ST)
                   1396:        {
1.1.1.16  root     1397:                for (i = 0; i < SamplesToGenerate; i++)
1.1.1.15  root     1398:                {
                   1399:                        idx = (ActiveSndBufIdx + i) % MIXBUFFER_SIZE;
1.1.1.17  root     1400:                        MixBuffer[idx][0] = MixBuffer[idx][1] = Subsonic_IIR_HPF_Left( YM2149_NextSample() );
1.1.1.15  root     1401:                }
                   1402:        }
1.1.1.12  root     1403: 
1.1.1.16  root     1404:        ActiveSndBufIdx = (ActiveSndBufIdx + SamplesToGenerate) % MIXBUFFER_SIZE;
                   1405:        nGeneratedSamples += SamplesToGenerate;
                   1406:        CurrentSamplesNb += SamplesToGenerate;                          /* number of samples generated for current VBL */
1.1       root     1407: }
                   1408: 
1.1.1.5   root     1409: 
1.1.1.2   root     1410: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1411: /**
                   1412:  * This is called to built samples up until this clock cycle
1.1.1.16  root     1413:  * Sound_Update can be called several times during a VBL ; we must ensure
                   1414:  * that we generate exactly SamplesPerFrame samples between 2 calls
                   1415:  * to Sound_Update_VBL.
1.1.1.11  root     1416:  */
1.1.1.16  root     1417: void Sound_Update(bool FillFrame)
1.1       root     1418: {
1.1.1.11  root     1419:        int OldSndBufIdx = ActiveSndBufIdx;
1.1.1.16  root     1420:        int SamplesToGenerate;
1.1.1.5   root     1421: 
1.1.1.11  root     1422:        /* Make sure that we don't interfere with the audio callback function */
                   1423:        Audio_Lock();
1.1.1.6   root     1424: 
1.1.1.16  root     1425:        /* Find how many samples to generate */
                   1426:        SamplesToGenerate = Sound_SetSamplesPassed( FillFrame );
                   1427: 
1.1.1.11  root     1428:        /* And generate */
1.1.1.16  root     1429:        Sound_GenerateSamples( SamplesToGenerate );
1.1       root     1430: 
1.1.1.11  root     1431:        /* Allow audio callback function to occur again */
                   1432:        Audio_Unlock();
1.1.1.6   root     1433: 
1.1.1.11  root     1434:        /* Save to WAV file, if open */
                   1435:        if (bRecordingWav)
1.1.1.16  root     1436:                WAVFormat_Update(MixBuffer, OldSndBufIdx, SamplesToGenerate);
1.1       root     1437: }
                   1438: 
1.1.1.5   root     1439: 
1.1.1.2   root     1440: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1441: /**
1.1.1.16  root     1442:  * On the end of each VBL, complete audio buffer to reach SamplesPerFrame samples.
                   1443:  * As Sound_Update(false) could be called several times during the VBL, the audio
                   1444:  * buffer might be already partially filled.
                   1445:  * We must first complete the buffer using the same value of SamplesPerFrame
                   1446:  * by calling Sound_Update(true) ; then we can compute a new value for
                   1447:  * SamplesPerFrame that will be used for the next VBL to come.
1.1.1.11  root     1448:  */
1.1.1.5   root     1449: void Sound_Update_VBL(void)
1.1       root     1450: {
1.1.1.16  root     1451:        Sound_Update(true);                                     /* generate as many samples as needed to fill this VBL */
                   1452: //fprintf ( stderr , "vbl done %d %d\n" , SamplesPerFrame , CurrentSamplesNb );
1.1.1.5   root     1453: 
1.1.1.16  root     1454:        CurrentSamplesNb = 0;                                   /* VBL is complete, reset counter for next VBL */
                   1455: 
                   1456:        /*Compute a fractional equivalent of SamplesPerFrame for the next VBL, to avoid rounding propagation */
                   1457:        SamplesPerFrame_unrounded += (yms64) ClocksTimings_GetSamplesPerVBL ( ConfigureParams.System.nMachineType ,
                   1458:                        nScreenRefreshRate , nAudioFrequency );
                   1459:        SamplesPerFrame = SamplesPerFrame_unrounded >> 28;              /* use integer part */
                   1460:        SamplesPerFrame_unrounded &= 0x0fffffff;                        /* keep fractional part in the lower 28 bits */
                   1461: 
                   1462:        /* Reset sound buffer if needed (after pause, fast forward, slow system, ...) */
                   1463:        if ( Sound_BufferIndexNeedReset )
                   1464:        {
                   1465:                Sound_ResetBufferIndex ();
                   1466:                Sound_BufferIndexNeedReset = false;
                   1467:        }
                   1468:        
                   1469:        /* Record AVI audio frame is necessary */
1.1.1.15  root     1470:        if ( bRecordingAvi )
                   1471:        {
1.1.1.16  root     1472:                int Len;
1.1.1.15  root     1473: 
1.1.1.16  root     1474:                Len = ActiveSndBufIdx - ActiveSndBufIdxAvi;     /* number of generated samples for this frame */
                   1475:                if ( Len < 0 )
                   1476:                        Len += MIXBUFFER_SIZE;                  /* end of ring buffer was reached */
1.1.1.15  root     1477: 
1.1.1.16  root     1478:                Avi_RecordAudioStream ( MixBuffer , ActiveSndBufIdxAvi , Len );
1.1.1.15  root     1479:        }
                   1480: 
1.1.1.16  root     1481:        ActiveSndBufIdxAvi = ActiveSndBufIdx;                   /* save new position for next AVI audio frame */
                   1482: 
1.1.1.11  root     1483:        /* Clear write to register '13', used for YM file saving */
1.1.1.14  root     1484:        bEnvelopeFreqFlag = false;
1.1       root     1485: }
                   1486: 
                   1487: 
1.1.1.2   root     1488: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1489: /**
                   1490:  * Start recording sound, as .YM or .WAV output
                   1491:  */
1.1.1.12  root     1492: bool Sound_BeginRecording(char *pszCaptureFileName)
1.1       root     1493: {
1.1.1.12  root     1494:        bool bRet;
1.1.1.7   root     1495: 
1.1.1.11  root     1496:        if (!pszCaptureFileName || strlen(pszCaptureFileName) <= 3)
                   1497:        {
                   1498:                Log_Printf(LOG_ERROR, "Illegal sound recording file name!\n");
1.1.1.14  root     1499:                return false;
1.1.1.11  root     1500:        }
                   1501: 
                   1502:        /* Did specify .YM or .WAV? If neither report error */
                   1503:        if (File_DoesFileExtensionMatch(pszCaptureFileName,".ym"))
                   1504:                bRet = YMFormat_BeginRecording(pszCaptureFileName);
                   1505:        else if (File_DoesFileExtensionMatch(pszCaptureFileName,".wav"))
                   1506:                bRet = WAVFormat_OpenFile(pszCaptureFileName);
                   1507:        else
                   1508:        {
                   1509:                Log_AlertDlg(LOG_ERROR, "Unknown Sound Recording format.\n"
                   1510:                             "Please specify a .YM or .WAV output file.");
1.1.1.14  root     1511:                bRet = false;
1.1.1.11  root     1512:        }
                   1513: 
                   1514:        return bRet;
1.1       root     1515: }
                   1516: 
1.1.1.5   root     1517: 
1.1.1.2   root     1518: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1519: /**
                   1520:  * End sound recording
                   1521:  */
1.1.1.7   root     1522: void Sound_EndRecording(void)
1.1       root     1523: {
1.1.1.11  root     1524:        /* Stop sound recording and close files */
                   1525:        if (bRecordingYM)
                   1526:                YMFormat_EndRecording();
                   1527:        if (bRecordingWav)
                   1528:                WAVFormat_CloseFile();
1.1       root     1529: }
                   1530: 
1.1.1.6   root     1531: 
1.1.1.2   root     1532: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1533: /**
                   1534:  * Are we recording sound data?
                   1535:  */
1.1.1.12  root     1536: bool Sound_AreWeRecording(void)
1.1       root     1537: {
1.1.1.11  root     1538:        return (bRecordingYM || bRecordingWav);
1.1       root     1539: }
1.1.1.12  root     1540: 
1.1.1.16  root     1541: 
                   1542: /*-----------------------------------------------------------------------*/
                   1543: /**
                   1544:  * Rebuild volume conversion table
                   1545:  */
                   1546: void Sound_SetYmVolumeMixing(void)
                   1547: {
                   1548:        /* Build the volume conversion table */
                   1549:        Ym2149_BuildVolumeTable();
                   1550: }
                   1551: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.