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

1.1       root        1: /*
1.1.1.5   root        2:   Hatari - sound.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   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     */
                     39: /*                     have sound.c independant of psg.c (to ease replacement of       */
                     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:  *
        !           470:  * The output of the YM2149 is modeled well as pullup resistors.
        !           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.12  root      584:  */
                    585: 
                    586: static void    YM2149_Normalise_5bit_Table(ymu16 *in_5bit , yms16 *out_5bit, unsigned int Level, bool DoCenter)
                    587: {
                    588:        if ( Level )
1.1.1.11  root      589:        {
1.1.1.14  root      590:                int h;
1.1.1.12  root      591:                int Max = in_5bit[0x7fff];
                    592:                int Center = Level>>1;
1.1.1.14  root      593:                //fprintf ( stderr , "level %d max %d center %d\n" , Level, Max, Center );
                    594: 
1.1.1.12  root      595:                /* Change the amplitude of the signal to 'level' : [0,max] -> [0,level] */
                    596:                /* Then optionally center the signal around Level/2 */
                    597:                /* This means we go from sthg like [0,65535] to [-32768, 32767] if Level=65535 and DoCenter=TRUE */
                    598:                for (h=0; h<32*32*32; h++)
                    599:                {
                    600:                        int tmp = in_5bit[h], res;
                    601:                        res = tmp * Level / Max;
1.1.1.14  root      602: 
1.1.1.12  root      603:                        if ( DoCenter )
                    604:                                res -= Center;
                    605: 
                    606:                        out_5bit[h] = res;
1.1.1.14  root      607:                        //fprintf ( stderr , "h %d in %d out %d\n" , h , tmp , res );
1.1.1.12  root      608:                }
1.1.1.11  root      609:        }
1.1       root      610: }
                    611: 
1.1.1.5   root      612: 
1.1.1.12  root      613: 
                    614: 
1.1.1.2   root      615: /*-----------------------------------------------------------------------*/
1.1.1.11  root      616: /**
1.1.1.12  root      617:  * Precompute all 16 possible envelopes.
                    618:  * Each envelope is made of 3 blocks of 32 volumes.
1.1.1.11  root      619:  */
1.1.1.12  root      620: 
                    621: static void    YM2149_EnvBuild ( void )
1.1       root      622: {
1.1.1.12  root      623:        int     env;
                    624:        int     block;
                    625:        int     vol=0 , inc=0;
                    626:        int     i;
1.1       root      627: 
1.1.1.12  root      628: 
                    629:        for ( env=0 ; env<16 ; env++ )                          /* 16 possible envelopes */
                    630:                for ( block=0 ; block<3 ; block++ )             /* 3 blocks to define an envelope */
                    631:                {
1.1.1.14  root      632:                        switch ( YmEnvDef[ env ][ block ] )
                    633:                        {
1.1.1.12  root      634:                                case ENV_GODOWN :       vol=31 ; inc=-1 ; break;
                    635:                                case ENV_GOUP :         vol=0  ; inc=1 ; break;
                    636:                                case ENV_DOWN :         vol=0  ; inc=0 ; break;
                    637:                                case ENV_UP :           vol=31 ; inc=0 ; break;
1.1.1.14  root      638:                        }
                    639: 
1.1.1.12  root      640:                        for ( i=0 ; i<32 ; i++ )                /* 32 volumes per block */
                    641:                        {
                    642:                                YmEnvWaves[ env ][ block*32 + i ] = YM_MERGE_VOICE ( vol , vol , vol );
                    643:                                vol += inc;
                    644:                        }
                    645:                }
                    646: }
                    647: 
                    648: 
                    649: 
                    650: /*-----------------------------------------------------------------------*/
                    651: /**
1.1.1.16  root      652:  * Depending on the YM mixing method, build the table used to convert
                    653:  * the 3 YM volumes into a single sample.
1.1.1.12  root      654:  */
                    655: 
1.1.1.16  root      656: static void    Ym2149_BuildVolumeTable(void)
1.1.1.12  root      657: {
                    658:        /* Depending on the volume mixing method, we use a table based on real measures */
                    659:        /* or a table based on a linear volume mixing. */
1.1.1.17  root      660:        if ( YmVolumeMixing == YM_MODEL_MIXING )
                    661:                YM2149_BuildModelVolumeTable(ymout5_u16);       /* create 32*32*32 circuit analysed model of the volume table */
                    662:        else if ( YmVolumeMixing == YM_TABLE_MIXING )
1.1.1.16  root      663:                interpolate_volumetable(ymout5_u16);            /* expand the 16*16*16 values in volumetable_original to 32*32*32 */
1.1.1.12  root      664:        else
                    665:                YM2149_BuildLinearVolumeTable(ymout5_u16);      /* combine the 32 possible volumes */
                    666: 
                    667:        /* Normalise/center the values (convert from u16 to s16) */
1.1.1.18! root      668:        YM2149_Normalise_5bit_Table ( ymout5_u16[0][0] , ymout5 , YM_OUTPUT_LEVEL , YM_OUTPUT_CENTERED );
1.1.1.16  root      669: }
                    670: 
                    671: 
                    672: 
                    673: /*-----------------------------------------------------------------------*/
                    674: /**
                    675:  * Init some internal tables for faster results (env, volume)
                    676:  * and reset the internal states.
                    677:  */
                    678: 
                    679: static void    Ym2149_Init(void)
                    680: {
                    681:        /* Build the 16 envelope shapes */
                    682:        YM2149_EnvBuild();
                    683: 
                    684:        /* Build the volume conversion table */
                    685:        Ym2149_BuildVolumeTable();
1.1.1.12  root      686: 
                    687:        /* Reset YM2149 internal states */
                    688:        Ym2149_Reset();
                    689: }
                    690: 
                    691: 
                    692: 
                    693: /*-----------------------------------------------------------------------*/
                    694: /**
1.1.1.16  root      695:  * Reset all ym registers as well as the internal variables
1.1.1.12  root      696:  */
                    697: 
                    698: static void    Ym2149_Reset(void)
                    699: {
                    700:        int     i;
1.1.1.14  root      701: 
1.1.1.12  root      702:        for ( i=0 ; i<14 ; i++ )
                    703:                Sound_WriteReg ( i , 0 );
                    704: 
                    705:        Sound_WriteReg ( 7 , 0xff );
                    706: 
1.1.1.16  root      707:        posA = 0;
                    708:        posB = 0;
                    709:        posC = 0;
                    710: 
1.1.1.12  root      711:        currentNoise = 0xffff;
1.1.1.14  root      712: 
1.1.1.12  root      713:        RndRack = 1;
1.1.1.14  root      714: 
1.1.1.12  root      715:        envShape = 0;
                    716:        envPos = 0;
                    717: }
                    718: 
                    719: 
                    720: 
                    721: /*-----------------------------------------------------------------------*/
                    722: /**
                    723:  * Returns a pseudo random value, used to generate white noise.
                    724:  */
                    725: 
                    726: static ymu32   YM2149_RndCompute(void)
                    727: {
                    728:        ymu32   bit;
1.1.1.14  root      729: 
1.1.1.12  root      730:        bit = (RndRack&1) ^ ((RndRack>>2)&1);
                    731:        RndRack = (RndRack>>1) | (bit<<16);
                    732:        return (bit ? 0 : 0xffff);
                    733: }
                    734: 
                    735: 
                    736: 
                    737: /*-----------------------------------------------------------------------*/
                    738: /**
1.1.1.16  root      739:  * Compute tone's step based on the input period.
                    740:  * Although for tone we should have the same result when per==0 and per==1,
                    741:  * this gives some very sharp and unpleasant sounds in the emulation.
                    742:  * To get a better sound, we consider all per<=5 to give step=0, which will
                    743:  * produce a constant output at value '1'. This should be handled with some
                    744:  * proper filters to remove high frequencies as on a real ST (where per<=9
                    745:  * gives nearly no audible sound).
                    746:  * A common replay freq of 44.1 kHz will also not be high enough to correctly
                    747:  * render possible tone's freq of 125 or 62.5 kHz (when per==1 or per==2)
1.1.1.12  root      748:  */
                    749: 
1.1.1.16  root      750: #define NEWSTEP
                    751: #ifndef NEWSTEP
1.1.1.12  root      752: static ymu32   Ym2149_ToneStepCompute(ymu8 rHigh , ymu8 rLow)
                    753: {
                    754:        int     per;
1.1.1.14  root      755:        yms64   step;
1.1.1.12  root      756: 
                    757:        per = rHigh&15;
                    758:        per = (per<<8)+rLow;
1.1.1.18! root      759: 
        !           760:        if  (per <= (int)(YM_ATARI_CLOCK/(YM_REPLAY_FREQ*7)) )
1.1.1.12  root      761:                return 0;
                    762: 
1.1.1.14  root      763:        step = YM_ATARI_CLOCK;
1.1.1.12  root      764:        step <<= (15+16-3);
                    765:        step /= (per * YM_REPLAY_FREQ);
                    766: 
                    767:        return step;
                    768: }
1.1.1.16  root      769: #else
                    770: static ymu32   Ym2149_ToneStepCompute(ymu8 rHigh , ymu8 rLow)
                    771: {
                    772:        int     per;
                    773:        yms64   step;
                    774: 
                    775:        per = rHigh&15;
                    776:        per = (per<<8)+rLow;
                    777: 
                    778: #if 0                                                  /* need some high freq filters for this to work correctly */
                    779:        if ( per == 0 )
                    780:                per = 1;                                /* result for Per=0 is the same as for Per=1 */ 
                    781: #else
1.1.1.18! root      782:        if  (per <= (int)(YM_ATARI_CLOCK/(YM_REPLAY_FREQ*7)) )
        !           783:                return 0;                               /* discard frequencies higher than 80% of nyquist rate. */
1.1.1.16  root      784: #endif
                    785: 
                    786:        step = YM_ATARI_CLOCK;
                    787:        step <<= 24;
                    788: 
                    789:        step /= (per * 8 * YM_REPLAY_FREQ);             /* 0x5ab9 < step < 0x5ab3f46 at 44.1 kHz */
                    790: 
                    791:        return step;
                    792: }
                    793: #endif
1.1.1.12  root      794: 
1.1.1.16  root      795: /*-----------------------------------------------------------------------*/
                    796: /**
                    797:  * Compute noise's step based on the input period.
                    798:  * On a real STF, we get the same result when per==0 and per==1.
                    799:  * A common replay freq of 44.1 kHz will not be high enough to correctly
                    800:  * render possible noise's freq of 125 or 62.5 kHz (when per==1 or per==2).
                    801:  * With a random wave such as noise, this means that with a replay freq
                    802:  * of 44.1 kHz, per==1 and per==2 (as well as per==3) will sound the same :
                    803:  *     per==1   step=0x2d59fa3   freq=125 kHz
                    804:  *     per==2   step=0x16acfd1   freq=62.5 kHz
                    805:  *     per==3   step=0x0f1dfe1   freq=41.7 kHz
                    806:  */
1.1.1.12  root      807: 
1.1.1.16  root      808: #ifndef NEWSTEP
1.1.1.12  root      809: static ymu32   Ym2149_NoiseStepCompute(ymu8 rNoise)
                    810: {
                    811:        int     per;
1.1.1.14  root      812:        yms64   step;
1.1.1.12  root      813: 
                    814:        per = (rNoise&0x1f);
                    815:        if (per<3)
                    816:                return 0;
                    817: 
1.1.1.14  root      818:        step = YM_ATARI_CLOCK;
1.1.1.12  root      819:        step <<= (16-1-3);
                    820:        step /= (per * YM_REPLAY_FREQ);
                    821: 
                    822:        return step;
1.1       root      823: }
1.1.1.16  root      824: #else
                    825: static ymu32   Ym2149_NoiseStepCompute(ymu8 rNoise)
                    826: {
                    827:        int     per;
                    828:        yms64   step;
                    829: 
                    830:        per = (rNoise&0x1f);
1.1       root      831: 
1.1.1.16  root      832:        if ( per == 0 )
                    833:                per = 1;                                /* result for Per=0 is the same as for Per=1 */ 
                    834: 
                    835:        step = YM_ATARI_CLOCK;
                    836:        step <<= 24;
                    837: 
                    838:        step /= (per * 16 * YM_REPLAY_FREQ);            /* 0x17683f < step < 0x2d59fa3 at 44.1 kHz */
                    839: 
                    840:        return step;
                    841: }
                    842: #endif
1.1.1.5   root      843: 
1.1.1.2   root      844: /*-----------------------------------------------------------------------*/
1.1.1.11  root      845: /**
1.1.1.12  root      846:  * Compute envelope's step. The envelope is made of different patterns
                    847:  * of 32 volumes. In each pattern, the volume is changed at frequency
                    848:  * Fe = MasterClock / ( 8 * EnvPer ).
                    849:  * In our case, we use a lower replay freq ; between 2 consecutive calls
                    850:  * to envelope's generation, the internal counter will advance 'step'
                    851:  * units, where step = MasterClock / ( 8 * EnvPer * YM_REPLAY_FREQ )
                    852:  * As 'step' requires floating point to be stored, we use left shifting
                    853:  * to multiply 'step' by a fixed amount. All operations are made with
                    854:  * shifted values ; to get the final value, we must right shift the
                    855:  * result. We use '<<24', which gives 8 bits for the integer part, and
                    856:  * the equivalent of 24 bits for the fractional part.
                    857:  * Since we're using large numbers, we temporarily use 64 bits integer
                    858:  * to avoid overflow and keep largest precision possible.
1.1.1.16  root      859:  * On a real STF, we get the same result when per==0 and per==1.
1.1.1.11  root      860:  */
1.1.1.12  root      861: 
                    862: static ymu32   Ym2149_EnvStepCompute(ymu8 rHigh , ymu8 rLow)
1.1       root      863: {
1.1.1.12  root      864:        yms64   per;
1.1.1.14  root      865:        yms64   step;
1.1       root      866: 
1.1.1.12  root      867:        per = rHigh;
                    868:        per = (per<<8)+rLow;
                    869: 
1.1.1.14  root      870:        step = YM_ATARI_CLOCK;
1.1.1.12  root      871:        step <<= 24;
1.1.1.16  root      872: 
                    873:        if ( per == 0 )
                    874:                per = 1;                                /* result for Per=0 is the same as for Per=1 */ 
                    875: 
                    876:        step /= (8 * per * YM_REPLAY_FREQ);             /* 0x5ab < step < 0x5ab3f46 at 44.1 kHz */
1.1.1.12  root      877: 
                    878:        return step;
                    879: }
                    880: 
                    881: 
                    882: 
                    883: /*-----------------------------------------------------------------------*/
                    884: /**
                    885:  * Main function : compute the value of the next sample.
                    886:  * Mixes all 3 voices with tone+noise+env and apply low pass
                    887:  * filter if needed.
1.1.1.16  root      888:  * All operations are done with integer math, using <<24 to simulate
                    889:  * floating point precision : upper 8 bits are the integer part, lower 24
                    890:  * are the fractional part.
                    891:  * Tone is a square wave with 2 states 0 or 1. If integer part of posX is
                    892:  * even (bit24=0) we consider output is 0, else (bit24=1) we consider
                    893:  * output is 1. This gives the value of bt for one voice after extending it
                    894:  * to all 0 bits or all 1 bits using a '-'
1.1.1.12  root      895:  */
                    896: 
1.1.1.16  root      897: #ifndef NEWSTEP
1.1.1.12  root      898: static ymsample        YM2149_NextSample(void)
                    899: {
                    900:        ymsample        sample;
                    901:        int             bt;
                    902:        ymu32           bn;
                    903:        ymu16           Env3Voices;
                    904:        ymu16           Tone3Voices;
                    905: 
                    906: 
                    907:        /* Noise value : 0 or 0xffff */
                    908:        if ( noisePos&0xffff0000 )
                    909:        {
                    910:                currentNoise ^= YM2149_RndCompute();
                    911:                noisePos &= 0xffff;
                    912:        }
                    913:        bn = currentNoise;                              /* 0 or 0xffff */
                    914: 
                    915:        /* Get the 5 bits volume corresponding to the current envelope's position */
                    916:        Env3Voices = YmEnvWaves[ envShape ][ envPos>>24 ];      /* integer part of envPos is in bits 24-31 */
                    917:        Env3Voices &= EnvMask3Voices;                   /* only keep volumes for voices using envelope */
                    918: 
                    919: //fprintf ( stderr , "env %x %x %x\n" , Env3Voices , envStep , envPos );
                    920: 
                    921:        /* Tone3Voices will contain the output state of each voice : 0 or 0x1f */
                    922:        bt = ((((yms32)posA)>>31) | mixerTA) & (bn | mixerNA);  /* 0 or 0xffff */
                    923:        Tone3Voices = bt & YM_MASK_1VOICE;                      /* 0 or 0x1f */
                    924:        bt = ((((yms32)posB)>>31) | mixerTB) & (bn | mixerNB);
                    925:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 5;
                    926:        bt = ((((yms32)posC)>>31) | mixerTC) & (bn | mixerNC);
                    927:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 10;
                    928: 
                    929:        /* Combine fixed volumes and envelope volumes and keep the resulting */
                    930:        /* volumes depending on the output state of each voice (0 or 0x1f) */
                    931:        Tone3Voices &= ( Env3Voices | Vol3Voices );
                    932: 
1.1.1.18! root      933:        /* When a step period is 0, the represented frequency was filtered from the */
        !           934:        /* ouput of the YM2149. Thus, use the transient DC component of the sample. */
        !           935:        /* Note that the "-1" table offset is a "good fit" for the DC component.    */
        !           936: 
        !           937:        if (stepA == 0  &&  (Tone3Voices & YM_MASK_A) > 1)
        !           938:                Tone3Voices -= 1;     /* Voice A AC component removed; Transient DC component remains */
        !           939: 
        !           940:        if (stepB == 0  &&  (Tone3Voices & YM_MASK_B) > 1<<5)
        !           941:                Tone3Voices -= 1<<5;  /* Voice B AC component removed; Transient DC component remains */
        !           942: 
        !           943:        if (stepC == 0  &&  (Tone3Voices & YM_MASK_C) > 1<<10)
        !           944:                Tone3Voices -= 1<<10; /* Voice C AC component removed; Transient DC component remains */
        !           945: 
1.1.1.12  root      946:        /* D/A conversion of the 3 volumes into a sample using a precomputed conversion table */
1.1.1.18! root      947: 
1.1.1.12  root      948:        sample = ymout5[ Tone3Voices ];                 /* 16 bits signed value */
                    949: 
                    950: 
                    951:        /* Increment positions */
                    952:        posA += stepA;
                    953:        posB += stepB;
                    954:        posC += stepC;
                    955:        noisePos += noiseStep;
1.1.1.14  root      956: 
1.1.1.12  root      957:        envPos += envStep;
                    958:        if ( envPos >= (3*32) << 24 )                   /* blocks 0, 1 and 2 were used (envPos 0 to 95) */
                    959:                envPos -= (2*32) << 24;                 /* replay/loop blocks 1 and 2 (envPos 32 to 95) */
                    960: 
                    961:        /* Apply low pass filter ? */
                    962:        if ( UseLowPassFilter )
1.1.1.18! root      963:                return LowPassFilter(sample);
        !           964:        else
        !           965:                return PWMaliasFilter(sample);
1.1       root      966: }
1.1.1.16  root      967: #else
                    968: static ymsample        YM2149_NextSample(void)
                    969: {
                    970:        ymsample        sample;
                    971:        ymu32           bt;
                    972:        ymu32           bn;
                    973:        ymu16           Env3Voices;                     /* 0x00CCBBAA */
                    974:        ymu16           Tone3Voices;                    /* 0x00CCBBAA */
1.1       root      975: 
                    976: 
1.1.1.16  root      977:        /* Noise value : 0 or 0xffff */
                    978:        if ( noisePos&0xff000000 )                      /* integer part > 0 */
                    979:        {
                    980:                currentNoise ^= YM2149_RndCompute();
                    981:                noisePos &= 0xffffff;                   /* keep fractional part of noisePos */
                    982:        }
                    983:        bn = currentNoise;                              /* 0 or 0xffff */
                    984: 
                    985:        /* Get the 5 bits volume corresponding to the current envelope's position */
                    986:        Env3Voices = YmEnvWaves[ envShape ][ envPos>>24 ];      /* integer part of envPos is in bits 24-31 */
                    987:        Env3Voices &= EnvMask3Voices;                   /* only keep volumes for voices using envelope */
                    988: 
                    989: //fprintf ( stderr , "env %x %x %x\n" , Env3Voices , envStep , envPos );
                    990: 
                    991:        /* Tone3Voices will contain the output state of each voice : 0 or 0x1f */
                    992:        bt = -( (posA>>24) & 1);                        /* 0 if bit24=0 or 0xffffffff if bit24=1 */
                    993:        bt = (bt | mixerTA) & (bn | mixerNA);           /* 0 or 0xffff */
                    994:        Tone3Voices = bt & YM_MASK_1VOICE;              /* 0 or 0x1f */
                    995:        bt = -( (posB>>24) & 1);
                    996:        bt = (bt | mixerTB) & (bn | mixerNB);
                    997:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 5;
                    998:        bt = -( (posC>>24) & 1);
                    999:        bt = (bt | mixerTC) & (bn | mixerNC);
                   1000:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 10;
                   1001: 
                   1002:        /* Combine fixed volumes and envelope volumes and keep the resulting */
                   1003:        /* volumes depending on the output state of each voice (0 or 0x1f) */
                   1004:        Tone3Voices &= ( Env3Voices | Vol3Voices );
                   1005: 
                   1006:        /* D/A conversion of the 3 volumes into a sample using a precomputed conversion table */
1.1.1.18! root     1007: 
        !          1008:        if (stepA == 0  &&  (Tone3Voices & YM_MASK_A) > 1)
        !          1009:                Tone3Voices -= 1;     /* Voice A AC component removed; Transient DC component remains */
        !          1010: 
        !          1011:        if (stepB == 0  &&  (Tone3Voices & YM_MASK_B) > 1<<5)
        !          1012:                Tone3Voices -= 1<<5;  /* Voice B AC component removed; Transient DC component remains */
        !          1013: 
        !          1014:        if (stepC == 0  &&  (Tone3Voices & YM_MASK_C) > 1<<10)
        !          1015:                Tone3Voices -= 1<<10; /* Voice C AC component removed; Transient DC component remains */
        !          1016: 
1.1.1.16  root     1017:        sample = ymout5[ Tone3Voices ];                 /* 16 bits signed value */
                   1018: 
                   1019: 
                   1020:        /* Increment positions */
                   1021:        posA += stepA;
                   1022:        posB += stepB;
                   1023:        posC += stepC;
                   1024:        noisePos += noiseStep;
                   1025: 
                   1026:        envPos += envStep;
                   1027:        if ( envPos >= (3*32) << 24 )                   /* blocks 0, 1 and 2 were used (envPos 0 to 95) */
                   1028:                envPos -= (2*32) << 24;                 /* replay/loop blocks 1 and 2 (envPos 32 to 95) */
                   1029: 
                   1030:        /* Apply low pass filter ? */
                   1031:        if ( UseLowPassFilter )
1.1.1.18! root     1032:                return LowPassFilter(sample);
        !          1033:        else
        !          1034:                return PWMaliasFilter(sample);
1.1.1.16  root     1035: }
                   1036: #endif
                   1037: 
1.1.1.12  root     1038: 
1.1.1.2   root     1039: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1040: /**
1.1.1.12  root     1041:  * Update internal variables (steps, volume masks, ...) each
                   1042:  * time an YM register is changed.
1.1.1.11  root     1043:  */
1.1.1.16  root     1044: #ifndef NEWSTEP
                   1045: #define BIT_SHIFT 31
                   1046: #else
                   1047: #define BIT_SHIFT 24
                   1048: #endif
1.1.1.12  root     1049: void   Sound_WriteReg( int reg , Uint8 data )
1.1.1.7   root     1050: {
1.1.1.12  root     1051:        switch (reg)
                   1052:        {
                   1053:                case 0:
                   1054:                        SoundRegs[0] = data;
                   1055:                        stepA = Ym2149_ToneStepCompute ( SoundRegs[1] , SoundRegs[0] );
1.1.1.16  root     1056:                        if (!stepA) posA = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root     1057:                        break;
                   1058: 
                   1059:                case 1:
                   1060:                        SoundRegs[1] = data & 0x0f;
                   1061:                        stepA = Ym2149_ToneStepCompute ( SoundRegs[1] , SoundRegs[0] );
1.1.1.16  root     1062:                        if (!stepA) posA = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root     1063:                        break;
                   1064: 
                   1065:                case 2:
                   1066:                        SoundRegs[2] = data;
                   1067:                        stepB = Ym2149_ToneStepCompute ( SoundRegs[3] , SoundRegs[2] );
1.1.1.16  root     1068:                        if (!stepB) posB = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root     1069:                        break;
1.1.1.7   root     1070: 
1.1.1.12  root     1071:                case 3:
                   1072:                        SoundRegs[3] = data & 0x0f;
                   1073:                        stepB = Ym2149_ToneStepCompute ( SoundRegs[3] , SoundRegs[2] );
1.1.1.16  root     1074:                        if (!stepB) posB = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root     1075:                        break;
                   1076: 
                   1077:                case 4:
                   1078:                        SoundRegs[4] = data;
                   1079:                        stepC = Ym2149_ToneStepCompute ( SoundRegs[5] , SoundRegs[4] );
1.1.1.16  root     1080:                        if (!stepC) posC = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root     1081:                        break;
                   1082: 
                   1083:                case 5:
                   1084:                        SoundRegs[5] = data & 0x0f;
                   1085:                        stepC = Ym2149_ToneStepCompute ( SoundRegs[5] , SoundRegs[4] );
1.1.1.16  root     1086:                        if (!stepC) posC = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root     1087:                        break;
                   1088: 
                   1089:                case 6:
                   1090:                        SoundRegs[6] = data & 0x1f;
                   1091:                        noiseStep = Ym2149_NoiseStepCompute ( SoundRegs[6] );
                   1092:                        if (!noiseStep)
                   1093:                        {
                   1094:                                noisePos = 0;
                   1095:                                currentNoise = 0xffff;
                   1096:                        }
                   1097:                        break;
                   1098: 
                   1099:                case 7:
                   1100:                        SoundRegs[7] = data & 0x3f;                     /* ignore bits 6 and 7 */
                   1101:                        mixerTA = (data&(1<<0)) ? 0xffff : 0;
                   1102:                        mixerTB = (data&(1<<1)) ? 0xffff : 0;
                   1103:                        mixerTC = (data&(1<<2)) ? 0xffff : 0;
                   1104:                        mixerNA = (data&(1<<3)) ? 0xffff : 0;
                   1105:                        mixerNB = (data&(1<<4)) ? 0xffff : 0;
                   1106:                        mixerNC = (data&(1<<5)) ? 0xffff : 0;
                   1107:                        break;
                   1108: 
                   1109:                case 8:
                   1110:                        SoundRegs[8] = data & 0x1f;
                   1111:                        if ( data & 0x10 )
                   1112:                        {
                   1113:                                EnvMask3Voices |= YM_MASK_A;            /* env ON */
                   1114:                                Vol3Voices &= ~YM_MASK_A;               /* fixed vol OFF */
                   1115:                        }
                   1116:                        else
                   1117:                        {
                   1118:                                EnvMask3Voices &= ~YM_MASK_A;           /* env OFF */
                   1119:                                Vol3Voices &= ~YM_MASK_A;               /* clear previous vol */
                   1120:                                Vol3Voices |= YmVolume4to5[ SoundRegs[8] ];     /* fixed vol ON */
                   1121:                        }
                   1122:                        break;
1.1.1.14  root     1123: 
1.1.1.12  root     1124:                case 9:
                   1125:                        SoundRegs[9] = data & 0x1f;
                   1126:                        if ( data & 0x10 )
                   1127:                        {
                   1128:                                EnvMask3Voices |= YM_MASK_B;            /* env ON */
                   1129:                                Vol3Voices &= ~YM_MASK_B;               /* fixed vol OFF */
                   1130:                        }
                   1131:                        else
                   1132:                        {
                   1133:                                EnvMask3Voices &= ~YM_MASK_B;           /* env OFF */
                   1134:                                Vol3Voices &= ~YM_MASK_B;               /* clear previous vol */
                   1135:                                Vol3Voices |= ( YmVolume4to5[ SoundRegs[9] ] ) << 5;    /* fixed vol ON */
                   1136:                        }
                   1137:                        break;
1.1.1.14  root     1138: 
1.1.1.12  root     1139:                case 10:
                   1140:                        SoundRegs[10] = data & 0x1f;
                   1141:                        if ( data & 0x10 )
                   1142:                        {
                   1143:                                EnvMask3Voices |= YM_MASK_C;            /* env ON */
                   1144:                                Vol3Voices &= ~YM_MASK_C;               /* fixed vol OFF */
                   1145:                        }
                   1146:                        else
                   1147:                        {
                   1148:                                EnvMask3Voices &= ~YM_MASK_C;           /* env OFF */
                   1149:                                Vol3Voices &= ~YM_MASK_C;               /* clear previous vol */
                   1150:                                Vol3Voices |= ( YmVolume4to5[ SoundRegs[10] ] ) << 10;  /* fixed vol ON */
                   1151:                        }
                   1152:                        break;
                   1153: 
                   1154:                case 11:
                   1155:                        SoundRegs[11] = data;
                   1156:                        envStep = Ym2149_EnvStepCompute ( SoundRegs[12] , SoundRegs[11] );
                   1157:                        break;
                   1158: 
                   1159:                case 12:
                   1160:                        SoundRegs[12] = data;
                   1161:                        envStep = Ym2149_EnvStepCompute ( SoundRegs[12] , SoundRegs[11] );
                   1162:                        break;
                   1163: 
                   1164:                case 13:
                   1165:                        SoundRegs[13] = data & 0xf;
                   1166:                        envPos = 0;                                     /* when writing to EnvShape, we must reset the EnvPos */
                   1167:                        envShape = SoundRegs[13];
1.1.1.14  root     1168:                        bEnvelopeFreqFlag = true;                       /* used for YmFormat saving */
1.1.1.12  root     1169:                        break;
                   1170: 
                   1171:        }
                   1172: }
                   1173: 
                   1174: 
                   1175: 
                   1176: /*-----------------------------------------------------------------------*/
                   1177: /**
                   1178:  * Init random generator, sound tables and envelopes
                   1179:  * (called only once when Hatari starts)
                   1180:  */
                   1181: void Sound_Init(void)
                   1182: {
                   1183:        /* Build volume/env tables, ... */
                   1184:        Ym2149_Init();
1.1.1.14  root     1185: 
1.1.1.11  root     1186:        Sound_Reset();
1.1.1.7   root     1187: }
                   1188: 
                   1189: 
                   1190: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1191: /**
1.1.1.12  root     1192:  * Reset the sound emulation (called from Reset_ST() in reset.c)
1.1.1.11  root     1193:  */
1.1.1.7   root     1194: void Sound_Reset(void)
                   1195: {
1.1.1.11  root     1196:        /* Lock audio system before accessing variables which are used by the
                   1197:         * callback function, too! */
                   1198:        Audio_Lock();
1.1.1.9   root     1199: 
1.1.1.11  root     1200:        /* Clear sound mixing buffer: */
1.1.1.12  root     1201:        memset(MixBuffer, 0, sizeof(MixBuffer));
1.1.1.7   root     1202: 
1.1.1.11  root     1203:        /* Clear cycle counts, buffer index and register '13' flags */
                   1204:        Cycles_SetCounter(CYCLES_COUNTER_SOUND, 0);
1.1.1.14  root     1205:        bEnvelopeFreqFlag = false;
                   1206: 
1.1.1.11  root     1207:        CompleteSndBufIdx = 0;
                   1208:        /* We do not start with 0 here to fake some initial samples: */
                   1209:        nGeneratedSamples = SoundBufferSize + SAMPLES_PER_FRAME;
                   1210:        ActiveSndBufIdx = nGeneratedSamples % MIXBUFFER_SIZE;
1.1.1.16  root     1211:        SamplesPerFrame = SAMPLES_PER_FRAME;
                   1212:        CurrentSamplesNb = 0;
                   1213:        ActiveSndBufIdxAvi = ActiveSndBufIdx;
1.1.1.15  root     1214: //fprintf ( stderr , "Sound_Reset SoundBufferSize %d SAMPLES_PER_FRAME %d nGeneratedSamples %d , ActiveSndBufIdx %d\n" ,
                   1215: //     SoundBufferSize , SAMPLES_PER_FRAME, nGeneratedSamples , ActiveSndBufIdx );
1.1.1.7   root     1216: 
1.1.1.12  root     1217:        Ym2149_Reset();
1.1.1.9   root     1218: 
1.1.1.11  root     1219:        Audio_Unlock();
1.1.1.7   root     1220: }
                   1221: 
                   1222: 
                   1223: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1224: /**
                   1225:  * Reset the sound buffer index variables.
1.1.1.16  root     1226:  * Very important : this function should only be called by setting
                   1227:  * Sound_BufferIndexNeedReset=true ; sound buffer index should be reset
                   1228:  * only after the sound for the whole VBL was updated (CurrentSamplesNb returns to 0)
                   1229:  * else it will alter the value of DMA Frame Count ($ff8909/0b/0d) and
                   1230:  * could cause crashes in some programs.
1.1.1.11  root     1231:  */
1.1.1.9   root     1232: void Sound_ResetBufferIndex(void)
1.1.1.7   root     1233: {
1.1.1.11  root     1234:        Audio_Lock();
                   1235:        nGeneratedSamples = SoundBufferSize + SAMPLES_PER_FRAME;
                   1236:        ActiveSndBufIdx =  (CompleteSndBufIdx + nGeneratedSamples) % MIXBUFFER_SIZE;
1.1.1.16  root     1237:        SamplesPerFrame = SAMPLES_PER_FRAME;
                   1238:        CurrentSamplesNb = 0;
                   1239:        ActiveSndBufIdxAvi = ActiveSndBufIdx;
1.1.1.15  root     1240: //fprintf ( stderr , "Sound_ResetBufferIndex SoundBufferSize %d SAMPLES_PER_FRAME %d nGeneratedSamples %d , ActiveSndBufIdx %d\n" ,
                   1241: //     SoundBufferSize , SAMPLES_PER_FRAME, nGeneratedSamples , ActiveSndBufIdx );
1.1.1.11  root     1242:        Audio_Unlock();
1.1.1.7   root     1243: }
                   1244: 
                   1245: 
                   1246: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1247: /**
                   1248:  * Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                   1249:  */
1.1.1.12  root     1250: void Sound_MemorySnapShot_Capture(bool bSave)
1.1.1.7   root     1251: {
1.1.1.11  root     1252:        /* Save/Restore details */
1.1.1.12  root     1253:        MemorySnapShot_Store(&stepA, sizeof(stepA));
                   1254:        MemorySnapShot_Store(&stepB, sizeof(stepB));
                   1255:        MemorySnapShot_Store(&stepC, sizeof(stepC));
                   1256:        MemorySnapShot_Store(&posA, sizeof(posA));
                   1257:        MemorySnapShot_Store(&posB, sizeof(posB));
                   1258:        MemorySnapShot_Store(&posC, sizeof(posC));
                   1259: 
                   1260:        MemorySnapShot_Store(&mixerTA, sizeof(mixerTA));
                   1261:        MemorySnapShot_Store(&mixerTB, sizeof(mixerTB));
                   1262:        MemorySnapShot_Store(&mixerTC, sizeof(mixerTC));
                   1263:        MemorySnapShot_Store(&mixerNA, sizeof(mixerNA));
                   1264:        MemorySnapShot_Store(&mixerNB, sizeof(mixerNB));
                   1265:        MemorySnapShot_Store(&mixerNC, sizeof(mixerNC));
                   1266: 
                   1267:        MemorySnapShot_Store(&noiseStep, sizeof(noiseStep));
                   1268:        MemorySnapShot_Store(&noisePos, sizeof(noisePos));
                   1269:        MemorySnapShot_Store(&currentNoise, sizeof(currentNoise));
                   1270:        MemorySnapShot_Store(&RndRack, sizeof(RndRack));
                   1271: 
                   1272:        MemorySnapShot_Store(&envStep, sizeof(envStep));
                   1273:        MemorySnapShot_Store(&envPos, sizeof(envPos));
                   1274:        MemorySnapShot_Store(&envShape, sizeof(envShape));
1.1.1.14  root     1275: 
1.1.1.12  root     1276:        MemorySnapShot_Store(&EnvMask3Voices, sizeof(EnvMask3Voices));
                   1277:        MemorySnapShot_Store(&Vol3Voices, sizeof(Vol3Voices));
1.1.1.14  root     1278: 
1.1.1.12  root     1279:        MemorySnapShot_Store(SoundRegs, sizeof(SoundRegs));
                   1280: 
1.1.1.14  root     1281:        // MemorySnapShot_Store(&YmVolumeMixing, sizeof(YmVolumeMixing));
                   1282:        // MemorySnapShot_Store(&UseLowPassFilter, sizeof(UseLowPassFilter));
1.1.1.7   root     1283: }
                   1284: 
                   1285: 
                   1286: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1287: /**
                   1288:  * Find how many samples to generate and store in 'nSamplesToGenerate'
                   1289:  * Also update sound cycles counter to store how many we actually did
                   1290:  * so generates set amount each frame.
1.1.1.16  root     1291:  * If FillFrame is true, this means we reach the end of the VBL and me must
                   1292:  * add as many samples as necessary to get a total of SamplesPerFrame
                   1293:  * for this VBL.
1.1.1.11  root     1294:  */
1.1.1.16  root     1295: static int Sound_SetSamplesPassed(bool FillFrame)
1.1       root     1296: {
1.1.1.11  root     1297:        int nSoundCycles;
1.1.1.16  root     1298:        int SamplesToGenerate;                          /* How many samples are needed for this time-frame */
                   1299: 
                   1300:        nSoundCycles = Cycles_GetCounter(CYCLES_COUNTER_VIDEO);
1.1.1.11  root     1301: 
1.1.1.16  root     1302:        /* example : 160256 cycles per VBL, 44Khz = 882 samples per VBL at 50 Hz */
                   1303:        /* 882/160256 samples per cpu clock cycle */
1.1.1.11  root     1304: 
1.1.1.16  root     1305:        /* Total number of samples that we should have at this point of the VBL */
                   1306:        SamplesToGenerate = nSoundCycles * SamplesPerFrame
                   1307:                / ClocksTimings_GetCyclesPerVBL ( ConfigureParams.System.nMachineType , nScreenRefreshRate );
1.1.1.11  root     1308: 
1.1.1.16  root     1309: //if (SamplesToGenerate > SamplesPerFrame )
                   1310: //fprintf ( stderr , "over run %d %d\n" , SamplesPerFrame , SamplesToGenerate );
1.1.1.11  root     1311: 
1.1.1.16  root     1312:        if (SamplesToGenerate > SamplesPerFrame)
                   1313:                SamplesToGenerate = SamplesPerFrame;
                   1314: 
                   1315:        SamplesToGenerate -= CurrentSamplesNb;          /* don't count samples that were already generated up to now */
                   1316:        if ( SamplesToGenerate < 0 )
                   1317:                SamplesToGenerate = 0;
                   1318: 
                   1319: 
                   1320:        /* If we're called from the VBL interrupt (FillFrame==true), we must ensure we have */
                   1321:        /* an exact total of SamplesPerFrame samples during a full VBL (we take into account */
                   1322:        /* the samples that were already generated during this VBL) */
                   1323:        if ( FillFrame )
                   1324:        {
                   1325:                SamplesToGenerate = SamplesPerFrame - CurrentSamplesNb; /* how many samples are missing to reach SamplesPerFrame */
                   1326:                if ( SamplesToGenerate < 0 )
                   1327:                        SamplesToGenerate = 0;
                   1328:        }
1.1.1.11  root     1329: 
1.1.1.16  root     1330:        /* Check we don't fill the sound's ring buffer before it's played by Audio_Callback()   */
                   1331:        /* This should never happen, except if the system suffers major slowdown due to other   */
                   1332:        /* processes or if we run in fast forward mode.                                         */
                   1333:        /* In the case of slowdown, we set Sound_BufferIndexNeedReset to "resync" the working   */
                   1334:        /* buffer's index ActiveSndBufIdx with the system buffer's index CompleteSndBufIdx.     */
                   1335:        /* In the case of fast forward, we do nothing here, Sound_BufferIndexNeedReset will be  */
                   1336:        /* set when the user exits fast forward mode.                                           */
                   1337:        if ( ( SamplesToGenerate > MIXBUFFER_SIZE - nGeneratedSamples ) && ( ConfigureParams.System.bFastForward == false )
                   1338:            && ( ConfigureParams.Sound.bEnableSound == true ) )
1.1.1.11  root     1339:        {
1.1.1.16  root     1340:                Log_Printf ( LOG_WARN , "Your system is too slow, some sound samples were not correctly emulated\n" );
                   1341:                Sound_BufferIndexNeedReset = true;
1.1.1.11  root     1342:        }
1.1.1.16  root     1343: 
                   1344: //fprintf ( stderr , "vbl %d hbl %d samp_gen %d / %d frac %lx\n" , nVBLs , nHBL , SamplesToGenerate , SamplesPerFrame , (long int)SamplesPerFrame_unrounded );
                   1345: 
                   1346:        return SamplesToGenerate;
1.1       root     1347: }
                   1348: 
1.1.1.5   root     1349: 
1.1.1.2   root     1350: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1351: /**
                   1352:  * Generate samples for all channels during this time-frame
                   1353:  */
1.1.1.16  root     1354: static void Sound_GenerateSamples(int SamplesToGenerate)
1.1       root     1355: {
1.1.1.12  root     1356:        int     i;
                   1357:        int     idx;
1.1.1.14  root     1358: 
1.1.1.16  root     1359:        if (SamplesToGenerate <= 0)
1.1.1.12  root     1360:                return;
1.1.1.14  root     1361: 
1.1.1.15  root     1362:        if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
1.1.1.11  root     1363:        {
1.1.1.16  root     1364:                for (i = 0; i < SamplesToGenerate; i++)
1.1.1.15  root     1365:                {
                   1366:                        idx = (ActiveSndBufIdx + i) % MIXBUFFER_SIZE;
1.1.1.17  root     1367:                        MixBuffer[idx][0] = MixBuffer[idx][1] = Subsonic_IIR_HPF_Left( YM2149_NextSample() );
1.1.1.15  root     1368:                }
                   1369:                /* If Falcon emulation, crossbar does the job */
1.1.1.16  root     1370:                Crossbar_GenerateSamples(ActiveSndBufIdx, SamplesToGenerate);
1.1.1.11  root     1371:        }
1.1.1.15  root     1372:        else if (ConfigureParams.System.nMachineType != MACHINE_ST)
                   1373:        {
1.1.1.16  root     1374:                for (i = 0; i < SamplesToGenerate; i++)
1.1.1.15  root     1375:                {
                   1376:                        idx = (ActiveSndBufIdx + i) % MIXBUFFER_SIZE;
1.1.1.18! root     1377:                        MixBuffer[idx][0] = MixBuffer[idx][1] = YM2149_NextSample();
1.1.1.15  root     1378:                }
1.1.1.17  root     1379:                /* If Ste or TT emulation, DmaSnd does mixing and filtering */
1.1.1.16  root     1380:                DmaSnd_GenerateSamples(ActiveSndBufIdx, SamplesToGenerate);
1.1.1.15  root     1381:        }
                   1382:        else if (ConfigureParams.System.nMachineType == MACHINE_ST)
                   1383:        {
1.1.1.16  root     1384:                for (i = 0; i < SamplesToGenerate; i++)
1.1.1.15  root     1385:                {
                   1386:                        idx = (ActiveSndBufIdx + i) % MIXBUFFER_SIZE;
1.1.1.17  root     1387:                        MixBuffer[idx][0] = MixBuffer[idx][1] = Subsonic_IIR_HPF_Left( YM2149_NextSample() );
1.1.1.15  root     1388:                }
                   1389:        }
1.1.1.12  root     1390: 
1.1.1.16  root     1391:        ActiveSndBufIdx = (ActiveSndBufIdx + SamplesToGenerate) % MIXBUFFER_SIZE;
                   1392:        nGeneratedSamples += SamplesToGenerate;
                   1393:        CurrentSamplesNb += SamplesToGenerate;                          /* number of samples generated for current VBL */
1.1       root     1394: }
                   1395: 
1.1.1.5   root     1396: 
1.1.1.2   root     1397: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1398: /**
                   1399:  * This is called to built samples up until this clock cycle
1.1.1.16  root     1400:  * Sound_Update can be called several times during a VBL ; we must ensure
                   1401:  * that we generate exactly SamplesPerFrame samples between 2 calls
                   1402:  * to Sound_Update_VBL.
1.1.1.11  root     1403:  */
1.1.1.16  root     1404: void Sound_Update(bool FillFrame)
1.1       root     1405: {
1.1.1.11  root     1406:        int OldSndBufIdx = ActiveSndBufIdx;
1.1.1.16  root     1407:        int SamplesToGenerate;
1.1.1.5   root     1408: 
1.1.1.11  root     1409:        /* Make sure that we don't interfere with the audio callback function */
                   1410:        Audio_Lock();
1.1.1.6   root     1411: 
1.1.1.16  root     1412:        /* Find how many samples to generate */
                   1413:        SamplesToGenerate = Sound_SetSamplesPassed( FillFrame );
                   1414: 
1.1.1.11  root     1415:        /* And generate */
1.1.1.16  root     1416:        Sound_GenerateSamples( SamplesToGenerate );
1.1       root     1417: 
1.1.1.11  root     1418:        /* Allow audio callback function to occur again */
                   1419:        Audio_Unlock();
1.1.1.6   root     1420: 
1.1.1.11  root     1421:        /* Save to WAV file, if open */
                   1422:        if (bRecordingWav)
1.1.1.16  root     1423:                WAVFormat_Update(MixBuffer, OldSndBufIdx, SamplesToGenerate);
1.1       root     1424: }
                   1425: 
1.1.1.5   root     1426: 
1.1.1.2   root     1427: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1428: /**
1.1.1.16  root     1429:  * On the end of each VBL, complete audio buffer to reach SamplesPerFrame samples.
                   1430:  * As Sound_Update(false) could be called several times during the VBL, the audio
                   1431:  * buffer might be already partially filled.
                   1432:  * We must first complete the buffer using the same value of SamplesPerFrame
                   1433:  * by calling Sound_Update(true) ; then we can compute a new value for
                   1434:  * SamplesPerFrame that will be used for the next VBL to come.
1.1.1.11  root     1435:  */
1.1.1.5   root     1436: void Sound_Update_VBL(void)
1.1       root     1437: {
1.1.1.16  root     1438:        Sound_Update(true);                                     /* generate as many samples as needed to fill this VBL */
                   1439: //fprintf ( stderr , "vbl done %d %d\n" , SamplesPerFrame , CurrentSamplesNb );
1.1.1.5   root     1440: 
1.1.1.16  root     1441:        CurrentSamplesNb = 0;                                   /* VBL is complete, reset counter for next VBL */
                   1442: 
                   1443:        /*Compute a fractional equivalent of SamplesPerFrame for the next VBL, to avoid rounding propagation */
                   1444:        SamplesPerFrame_unrounded += (yms64) ClocksTimings_GetSamplesPerVBL ( ConfigureParams.System.nMachineType ,
                   1445:                        nScreenRefreshRate , nAudioFrequency );
                   1446:        SamplesPerFrame = SamplesPerFrame_unrounded >> 28;              /* use integer part */
                   1447:        SamplesPerFrame_unrounded &= 0x0fffffff;                        /* keep fractional part in the lower 28 bits */
                   1448: 
                   1449:        /* Reset sound buffer if needed (after pause, fast forward, slow system, ...) */
                   1450:        if ( Sound_BufferIndexNeedReset )
                   1451:        {
                   1452:                Sound_ResetBufferIndex ();
                   1453:                Sound_BufferIndexNeedReset = false;
                   1454:        }
                   1455:        
                   1456:        /* Record AVI audio frame is necessary */
1.1.1.15  root     1457:        if ( bRecordingAvi )
                   1458:        {
1.1.1.16  root     1459:                int Len;
1.1.1.15  root     1460: 
1.1.1.16  root     1461:                Len = ActiveSndBufIdx - ActiveSndBufIdxAvi;     /* number of generated samples for this frame */
                   1462:                if ( Len < 0 )
                   1463:                        Len += MIXBUFFER_SIZE;                  /* end of ring buffer was reached */
1.1.1.15  root     1464: 
1.1.1.16  root     1465:                Avi_RecordAudioStream ( MixBuffer , ActiveSndBufIdxAvi , Len );
1.1.1.15  root     1466:        }
                   1467: 
1.1.1.16  root     1468:        ActiveSndBufIdxAvi = ActiveSndBufIdx;                   /* save new position for next AVI audio frame */
                   1469: 
1.1.1.11  root     1470:        /* Clear write to register '13', used for YM file saving */
1.1.1.14  root     1471:        bEnvelopeFreqFlag = false;
1.1       root     1472: }
                   1473: 
                   1474: 
1.1.1.2   root     1475: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1476: /**
                   1477:  * Start recording sound, as .YM or .WAV output
                   1478:  */
1.1.1.12  root     1479: bool Sound_BeginRecording(char *pszCaptureFileName)
1.1       root     1480: {
1.1.1.12  root     1481:        bool bRet;
1.1.1.7   root     1482: 
1.1.1.11  root     1483:        if (!pszCaptureFileName || strlen(pszCaptureFileName) <= 3)
                   1484:        {
                   1485:                Log_Printf(LOG_ERROR, "Illegal sound recording file name!\n");
1.1.1.14  root     1486:                return false;
1.1.1.11  root     1487:        }
                   1488: 
                   1489:        /* Did specify .YM or .WAV? If neither report error */
                   1490:        if (File_DoesFileExtensionMatch(pszCaptureFileName,".ym"))
                   1491:                bRet = YMFormat_BeginRecording(pszCaptureFileName);
                   1492:        else if (File_DoesFileExtensionMatch(pszCaptureFileName,".wav"))
                   1493:                bRet = WAVFormat_OpenFile(pszCaptureFileName);
                   1494:        else
                   1495:        {
                   1496:                Log_AlertDlg(LOG_ERROR, "Unknown Sound Recording format.\n"
                   1497:                             "Please specify a .YM or .WAV output file.");
1.1.1.14  root     1498:                bRet = false;
1.1.1.11  root     1499:        }
                   1500: 
                   1501:        return bRet;
1.1       root     1502: }
                   1503: 
1.1.1.5   root     1504: 
1.1.1.2   root     1505: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1506: /**
                   1507:  * End sound recording
                   1508:  */
1.1.1.7   root     1509: void Sound_EndRecording(void)
1.1       root     1510: {
1.1.1.11  root     1511:        /* Stop sound recording and close files */
                   1512:        if (bRecordingYM)
                   1513:                YMFormat_EndRecording();
                   1514:        if (bRecordingWav)
                   1515:                WAVFormat_CloseFile();
1.1       root     1516: }
                   1517: 
1.1.1.6   root     1518: 
1.1.1.2   root     1519: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1520: /**
                   1521:  * Are we recording sound data?
                   1522:  */
1.1.1.12  root     1523: bool Sound_AreWeRecording(void)
1.1       root     1524: {
1.1.1.11  root     1525:        return (bRecordingYM || bRecordingWav);
1.1       root     1526: }
1.1.1.12  root     1527: 
1.1.1.16  root     1528: 
                   1529: /*-----------------------------------------------------------------------*/
                   1530: /**
                   1531:  * Rebuild volume conversion table
                   1532:  */
                   1533: void Sound_SetYmVolumeMixing(void)
                   1534: {
                   1535:        /* Build the volume conversion table */
                   1536:        Ym2149_BuildVolumeTable();
                   1537: }
                   1538: 

unix.superglobalmegacorp.com

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