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

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 :
                     22:     - tone and noise steps computations are from StSound 1.2 by Arnaud Carr� (Leonard/Oxygene)
                     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       root       26: */
1.1.1.12  root       27: 
                     28: /* 2008/05/05  [NP]    Fix case where period is 0 for noise, sound or envelope.        */
                     29: /*                     In that case, a real ST sounds as if period was in fact 1.      */
                     30: /*                     (fix buggy sound replay in ESwat that set volume<0 and trigger  */
                     31: /*                     a badly initialised envelope with envper=0).                    */
                     32: /* 2008/07/27  [NP]    Better separation between accesses to the YM hardware registers */
                     33: /*                     and the sound rendering routines. Use Sound_WriteReg() to pass  */
                     34: /*                     all writes to the sound rendering functions. This allows to     */
                     35: /*                     have sound.c independant of psg.c (to ease replacement of       */
                     36: /*                     sound.c by another rendering method).                           */
                     37: /* 2008/08/02  [NP]    Initial convert of Ym2149Ex.cpp from C++ to C.                  */
                     38: /*                     Remove unused part of the code (StSound specific).              */
                     39: /* 2008/08/09  [NP]    Complete integration of StSound routines into sound.c           */
                     40: /*                     Set EnvPer=3 if EnvPer<3 (ESwat buggy replay).                  */
                     41: /* 2008/08/13  [NP]    StSound was generating samples in the range 0-32767, instead    */
                     42: /*                     of really signed samples between -32768 and 32767, which could  */
                     43: /*                     give incorrect results in many case.                            */
                     44: /* 2008/09/06  [NP]    Use sc68 volumes table for a more accurate mixing of the voices */
                     45: /*                     All volumes are converted to 5 bits and the table contains      */
                     46: /*                     32*32*32 values. Samples are signed and centered to get the     */
                     47: /*                     biggest amplitude possible.                                     */
                     48: /*                     Faster mixing routines for tone+volume+envelope (don't use      */
                     49: /*                     StSound's version anymore, it gave problem with some GCC).      */
                     50: /* 2008/09/17  [NP]    Add ym_normalise_5bit_table to normalise the 32*32*32 table and */
                     51: /*                     to optionally center 16 bit signed sample.                      */
                     52: /*                     Possibility to mix volumes using a table measured on ST or a    */
                     53: /*                     linear mean of the 3 channels' volume.                          */
                     54: /*                     Default mixing set to YM_LINEAR_MIXING.                         */
                     55: /* 2008/10/14  [NP]    Full support for 5 bits volumes : envelopes are generated with  */
                     56: /*                     32 volumes per pattern as on a real YM-2149. Fixed volumes      */
                     57: /*                     on 4 bits are converted to their 5 bits equivalent. This should */
                     58: /*                     give the maximum accuracy possible when computing volumes.      */
                     59: /*                     New version of Ym2149_EnvStepCompute to handle 5 bits volumes.  */
                     60: /*                     Function YM2149_EnvBuild to compute the 96 volumes that define  */
                     61: /*                     a single envelope (32 initial volumes, then 64 repeated values).*/
                     62: /* 2008/10/26  [NP]    Correctly save/restore all necessary variables in               */
                     63: /*                     Sound_MemorySnapShot_Capture.                                   */
                     64: /* 2008/11/23  [NP]    Clean source, remove old sound core.                            */
                     65: 
                     66: 
                     67: 
1.1.1.14! root       68: const char Sound_fileid[] = "Hatari sound.c : " __DATE__ " " __TIME__;
1.1.1.5   root       69: 
                     70: #include <SDL_types.h>
1.1       root       71: 
                     72: #include "main.h"
                     73: #include "audio.h"
1.1.1.10  root       74: #include "cycles.h"
1.1.1.9   root       75: #include "dmaSnd.h"
1.1       root       76: #include "file.h"
                     77: #include "int.h"
1.1.1.8   root       78: #include "log.h"
1.1       root       79: #include "memorySnapShot.h"
                     80: #include "psg.h"
                     81: #include "sound.h"
                     82: #include "video.h"
                     83: #include "wavFormat.h"
                     84: #include "ymFormat.h"
                     85: 
                     86: 
                     87: 
1.1.1.12  root       88: /*--------------------------------------------------------------*/
                     89: /* Definition of the possible envelopes shapes (using 5 bits)  */
                     90: /*--------------------------------------------------------------*/
                     91: 
                     92: #define        ENV_GODOWN      0               /* 31 ->  0 */
                     93: #define        ENV_GOUP        1               /*  0 -> 31 */
                     94: #define        ENV_DOWN        2               /*  0 ->  0 */
                     95: #define        ENV_UP          3               /* 31 -> 31 */
                     96: 
                     97: /* To generate an envelope, we first use block 0, then we repeat blocks 1 and 2 */
                     98: static const int YmEnvDef[ 16 ][ 3 ] = {
                     99:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 0 \___ */
                    100:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 1 \___ */
                    101:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 2 \___ */
                    102:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 3 \___ */
                    103:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 4 /___ */
                    104:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 5 /___ */
                    105:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 6 /___ */
                    106:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 7 /___ */
                    107:        { ENV_GODOWN,   ENV_GODOWN, ENV_GODOWN } ,      /* 8 \\\\ */
                    108:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 9 \___ */
                    109:        { ENV_GODOWN,   ENV_GOUP, ENV_GODOWN } ,        /* A \/\/ */
                    110:        { ENV_GODOWN,   ENV_UP, ENV_UP } ,              /* B \--- */
                    111:        { ENV_GOUP,     ENV_GOUP, ENV_GOUP } ,          /* C //// */
                    112:        { ENV_GOUP,     ENV_UP, ENV_UP } ,              /* D /--- */
                    113:        { ENV_GOUP,     ENV_GODOWN, ENV_GOUP } ,        /* E /\/\ */
                    114:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* F /___ */
                    115:        };
                    116: 
                    117: 
                    118: /* Buffer to store the 16 envelopes built from YmEnvDef */
                    119: static ymu16   YmEnvWaves[ 16 ][ 32 * 3 ];             /* 16 envelopes with 3 blocks of 32 volumes */
1.1.1.3   root      120: 
1.1       root      121: 
1.1.1.12  root      122: 
                    123: /*--------------------------------------------------------------*/
                    124: /* Definition of the volumes tables (using 5 bits) and of the  */
                    125: /* mixing parameters for the 3 voices.                         */
                    126: /*--------------------------------------------------------------*/
                    127: 
                    128: /* 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) */
                    129: /* Vol 0 should be 310 when measuread as a voltage, but we set it to 0 in order to have a volume=0 matching */
                    130: /* the 0 level of a 16 bits unsigned sample (no sound output) */
                    131: static const ymu16 ymout1c5bit[ 32 ] =
                    132: {
                    133:   0 /*310*/,  369,  438,  521,  619,  735,  874, 1039,
                    134:  1234, 1467, 1744, 2072, 2463, 2927, 3479, 4135,
                    135:  4914, 5841, 6942, 8250, 9806,11654,13851,16462,
                    136: 19565,23253,27636,32845,39037,46395,55141,65535
1.1       root      137: };
                    138: 
1.1.1.12  root      139: /* Convert a constant 4 bits volume to the internal 5 bits value : */
                    140: /* volume5=volume4*2+1, except for volumes 0 and 1 which become 0 and 2, */
                    141: /* in order to map [0,15] into [0,31] (O must remain 0, and 15 must give 31) */
                    142: static const ymu16 YmVolume4to5[ 16 ] = { 0,2,5,7,9,11,13,15,17,19,21,23,25,27,29,31 };
1.1       root      143: 
1.1.1.12  root      144: /* Table of unsigned 4 bit D/A output level for 3 channels as measured on a real ST */
                    145: static ymu16 volumetable_original[ 16 * 16 * 16 ] =
                    146: #include "ym2149_fixed_vol.h"
1.1.1.5   root      147: 
1.1.1.12  root      148: /* Corresponding table interpolated to 5 bit D/A output level (16 bits unsigned) */
                    149: static ymu16 ymout5_u16[ 32 * 32 * 32 ];
                    150: 
                    151: /* Same table, after conversion to signed results (same pointer, with different type) */
                    152: static yms16 *ymout5 = (yms16 *)ymout5_u16;
                    153: 
                    154: 
                    155: 
                    156: /*--------------------------------------------------------------*/
                    157: /* Other constants / macros                                    */
                    158: /*--------------------------------------------------------------*/
                    159: 
                    160: /* Number of generated samples per frame (eg. 44Khz=882) */
1.1.1.14! root      161: #define SAMPLES_PER_FRAME  ((nAudioFrequency+35)/nScreenRefreshRate)
1.1.1.12  root      162: 
                    163: /* Current sound replay freq (usually 44100 Hz) */
1.1.1.14! root      164: #define YM_REPLAY_FREQ   nAudioFrequency
1.1.1.12  root      165: 
                    166: /* YM-2149 clock on Atari ST is 2 MHz */
                    167: #define YM_ATARI_CLOCK                 2000000
                    168: 
                    169: 
                    170: /* Merge/read the 3 volumes in a single integer (5 bits per volume) */
                    171: #define        YM_MERGE_VOICE(C,B,A)   ( (C)<<10 | (B)<<5 | A )
                    172: #define        YM_MASK_1VOICE          0x1f
                    173: #define YM_MASK_A              0x1f
                    174: #define YM_MASK_B              (0x1f<<5)
                    175: #define YM_MASK_C              (0x1f<<10)
                    176: 
                    177: 
                    178: /* Constants for YM2149_Normalise_5bit_Table */
                    179: #define        YM_OUTPUT_LEVEL                 0x7fff          /* amplitude of the final signal (0..65535 if centered, 0..32767 if not) */
1.1.1.14! root      180: #define YM_OUTPUT_CENTERED             false
1.1.1.12  root      181: 
                    182: 
                    183: 
                    184: /*--------------------------------------------------------------*/
                    185: /* Variables for the DC adjuster / Low Pass Filter             */
                    186: /*--------------------------------------------------------------*/
                    187: #define DC_ADJUST_BUFFERLEN            512             /* must be a power of 2 */
                    188: 
                    189: static ymsample        dc_buffer[DC_ADJUST_BUFFERLEN];
                    190: static int     dc_pos;
                    191: static int     dc_sum;
                    192: static ymsample        m_lowPassFilter[2];
                    193: 
                    194: 
                    195: 
                    196: /*--------------------------------------------------------------*/
                    197: /* Variables for the YM2149 emulator (need to be saved and     */
                    198: /* restored in memory snapshots)                               */
                    199: /*--------------------------------------------------------------*/
                    200: 
                    201: static ymu32   stepA , stepB , stepC;
                    202: static ymu32   posA , posB , posC;
                    203: static ymu32   mixerTA , mixerTB , mixerTC;
                    204: static ymu32   mixerNA , mixerNB , mixerNC;
                    205: 
                    206: static ymu32   noiseStep;
                    207: static ymu32   noisePos;
                    208: static ymu32   currentNoise;
                    209: static ymu32   RndRack;                                /* current random seed */
                    210: 
                    211: static ymu32   envStep;
                    212: static ymu32   envPos;
                    213: static int     envShape;
                    214: 
                    215: static ymu16   EnvMask3Voices = 0;                     /* mask is 0x1f for voices having an active envelope */
                    216: static ymu16   Vol3Voices = 0;                         /* volume 0-0x1f for voices having a constant volume */
                    217:                                                        /* volume is set to 0 if voice has an envelope in EnvMask3Voices */
                    218: 
                    219: 
                    220: /* Global variables that can be changed/read from other parts of Hatari */
                    221: Uint8          SoundRegs[ 14 ];
                    222: 
                    223: int            YmVolumeMixing = YM_LINEAR_MIXING;
1.1.1.14! root      224: bool           UseLowPassFilter = false;
1.1.1.12  root      225: 
                    226: bool           bEnvelopeFreqFlag;                      /* Cleared each frame for YM saving */
                    227: 
                    228: Sint16         MixBuffer[MIXBUFFER_SIZE][2];
                    229: int            nGeneratedSamples;                      /* Generated samples since audio buffer update */
                    230: int            nSamplesToGenerate;                     /* How many samples are needed for this time-frame */
                    231: static int     ActiveSndBufIdx;                        /* Current working index into above mix buffer */
                    232: 
                    233: 
                    234: 
                    235: /*--------------------------------------------------------------*/
                    236: /* Local functions prototypes                                  */
                    237: /*--------------------------------------------------------------*/
                    238: 
                    239: static void    DcAdjuster_Reset        (void);
                    240: static void    DcAdjuster_AddSample    (ymsample sample);
                    241: static ymsample        DcAdjuster_GetDcLevel   (void);
                    242: static void    LowPassFilter_Reset     (void);
                    243: static ymsample        LowPassFilter           (ymsample in);
                    244: 
                    245: static int     volumetable_get         (int i, int j, int k);
                    246: static void    volumetable_set         (ymu16 *volumetable, int i, int j, int k, int val);
                    247: static int     volumetable_interpolate (int y1, int y2);
                    248: static void    interpolate_volumetable (ymu16 *out);
                    249: 
                    250: static void    YM2149_BuildLinearVolumeTable(ymu16 *out);
                    251: static void    YM2149_Normalise_5bit_Table(ymu16 *in_5bit , yms16 *out_5bit, unsigned int Level, bool DoCenter);
                    252: 
                    253: static void    YM2149_EnvBuild         (void);
                    254: static void    Ym2149_Init             (void);
                    255: static void    Ym2149_Reset            (void);
                    256: 
                    257: static ymu32   YM2149_RndCompute       (void);
                    258: static ymu32   Ym2149_ToneStepCompute  (ymu8 rHigh , ymu8 rLow);
                    259: static ymu32   Ym2149_NoiseStepCompute (ymu8 rNoise);
                    260: static ymu32   Ym2149_EnvStepCompute   (ymu8 rHigh , ymu8 rLow);
                    261: static ymsample        YM2149_NextSample       (void);
                    262: 
                    263: static void    Sound_SetSamplesPassed  (void);
                    264: static void    Sound_GenerateSamples   (void);
                    265: 
                    266: 
                    267: 
                    268: /*--------------------------------------------------------------*/
                    269: /* DC Adjuster / Low Pass Filter routines.                     */
                    270: /*--------------------------------------------------------------*/
                    271: 
                    272: static void    DcAdjuster_Reset(void)
                    273: {
                    274:        int     i;
1.1.1.14! root      275: 
1.1.1.12  root      276:        for (i=0 ; i<DC_ADJUST_BUFFERLEN ; i++)
                    277:                dc_buffer[i] = 0;
                    278: 
                    279:        dc_pos = 0;
                    280:        dc_sum = 0;
                    281: }
                    282: 
                    283: 
                    284: static void    DcAdjuster_AddSample(ymsample sample)
1.1       root      285: {
1.1.1.12  root      286:        dc_sum -= dc_buffer[dc_pos];
                    287:        dc_sum += sample;
1.1       root      288: 
1.1.1.12  root      289:        dc_buffer[dc_pos] = sample;
                    290:        dc_pos = (dc_pos+1)&(DC_ADJUST_BUFFERLEN-1);
                    291: }
                    292: 
                    293: 
                    294: static ymsample        DcAdjuster_GetDcLevel(void)
                    295: {
                    296:        return dc_sum / DC_ADJUST_BUFFERLEN;
                    297: }
                    298: 
                    299: 
                    300: static void    LowPassFilter_Reset(void)
                    301: {
                    302:        m_lowPassFilter[0] = 0;
                    303:        m_lowPassFilter[1] = 0;
                    304: }
                    305: 
                    306: 
                    307: static ymsample        LowPassFilter(ymsample in)
                    308: {
                    309:        ymsample        out;
                    310:  
                    311:        out = (m_lowPassFilter[0]>>2) + (m_lowPassFilter[1]>>1) + (in>>2);
                    312:        m_lowPassFilter[0] = m_lowPassFilter[1];
                    313:        m_lowPassFilter[1] = in;
                    314:        return out;
                    315: }
                    316: 
                    317: 
                    318: 
                    319: /*--------------------------------------------------------------*/
                    320: /* Build the volume conversion table used to simulate the      */
                    321: /* behaviour of DAC used with the YM2149 in the atari ST.      */
                    322: /* The final 32*32*32 table is built using a 16*16*16 table    */
                    323: /* of all possible fixed volume combinations on a ST.          */
                    324: /*--------------------------------------------------------------*/
                    325: 
                    326: static int     volumetable_get(int i, int j, int k)
                    327: {
                    328:        /* access at boundary finds the last value instead of the first */
                    329:        if (i == 16)
                    330:                i = 15;
                    331:        if (j == 16)
                    332:                j = 15;
                    333:        if (k == 16)
                    334:                k = 15;
1.1.1.14! root      335: 
1.1.1.12  root      336:        return volumetable_original[i + 16 * j + 16 * 16 * k];
                    337: }
                    338: 
                    339: static void    volumetable_set(ymu16 *volumetable, int i, int j, int k, int val)
                    340: {
                    341:        volumetable[i + 32 * j + 32 * 32 * k] = val;
                    342: }
                    343: 
                    344: /* the table is exponential in nature. These weighing factors approximate
                    345:  * that the value in-between needs to be closer to the lower value in y2 */
                    346: static int     volumetable_interpolate(int y1, int y2)
                    347: {
                    348:        int erpolate;
                    349:        erpolate = (y1 * 4 + y2 * 6) / 10u;
                    350:        if (erpolate > 65535)
1.1.1.11  root      351:        {
1.1.1.12  root      352: //             fprintf ( stderr , "sature>:%d %d %d\n",erpolate,y1,y2 );
                    353:                erpolate = 65535;
1.1.1.11  root      354:        }
1.1.1.12  root      355:        if (erpolate < 0)
                    356:        {
                    357: //             fprintf ( stderr , "sature<:%d %d %d\n",erpolate,y1,y2 );
                    358:                erpolate = 0;
                    359:        }
                    360:        return erpolate;
                    361: }
1.1.1.11  root      362: 
1.1.1.12  root      363: static void    interpolate_volumetable(ymu16 *out)
                    364: {
                    365:        int i, j, k;
                    366:        int i1, i2;
                    367: 
                    368:        /* we are doing 4-dimensional interpolation here. For each
                    369:        * known measurement point, we must find 8 new values. These values occur
                    370:        * as follows:
                    371:        *
                    372:        * - one at the exact same position
                    373:        * - one half-way in i direction
                    374:        * - one half-way in j direction
                    375:        * - one half-way in k direction
                    376:        * - one half-way in i+j direction
                    377:        * - one half-way in i+k direction
                    378:        * - one half-way in j+k direction
                    379:        * - one half-way in i+j+k direction
                    380:        *
                    381:        * The algorithm currently is very simplistic. Probably more points should be
                    382:        * weighted in the multicomponented directions, for instance i+j+k should be
                    383:        * an average of all surrounding data points. This probably doesn't matter much,
                    384:        * though. This is because the only way to reach those locations is to modulate
                    385:        * more than one voice with the envelope, and this is rare.
                    386:        */
                    387: 
                    388:        for (i = 0; i < 16; i++)
1.1.1.11  root      389:        {
1.1.1.12  root      390:                for (j = 0; j < 16; j++)
                    391:                {
                    392:                        for (k = 0; k < 16; k++)
                    393:                        {
                    394:                                i1 = volumetable_get(i, j, k);
                    395:                                /* copy value unchanged to new position */
                    396:                                volumetable_set(out,i*2, j*2, k*2, i1);
1.1.1.14! root      397:  
1.1.1.12  root      398:                                /* interpolate in i direction */
                    399:                                i2 = volumetable_get(i + 1, j, k);
                    400:                                volumetable_set(out,i*2 + 1, j*2, k*2, volumetable_interpolate(i1, i2));
1.1.1.14! root      401: 
1.1.1.12  root      402:                                /* interpolate in j direction */
                    403:                                i2 = volumetable_get(i, j+1, k);
                    404:                                volumetable_set(out,i*2, j*2 + 1, k*2, volumetable_interpolate(i1, i2));
1.1.1.14! root      405: 
1.1.1.12  root      406:                                /* interpolate in k direction */
                    407:                                i2 = volumetable_get(i, j, k+1);
                    408:                                volumetable_set(out,i*2, j*2, k*2+1, volumetable_interpolate(i1, i2));
                    409: 
                    410:                                /* interpolate in i + j direction */
                    411:                                i2 = volumetable_get(i + 1, j + 1, k);
                    412:                                volumetable_set(out,i*2 + 1, j*2 + 1, k*2, volumetable_interpolate(i1, i2));
1.1.1.14! root      413: 
1.1.1.12  root      414:                                /* interpolate in i + k direction */
                    415:                                i2 = volumetable_get(i + 1, j, k + 1);
                    416:                                volumetable_set(out,i*2 + 1, j*2, k*2 + 1, volumetable_interpolate(i1, i2));
1.1.1.14! root      417: 
1.1.1.12  root      418:                                /* interpolate in j + k direction */
                    419:                                i2 = volumetable_get(i, j + 1, k + 1);
                    420:                                volumetable_set(out,i*2, j*2 + 1, k*2 + 1, volumetable_interpolate(i1, i2));
                    421: 
                    422:                                /* interpolate in i + j + k direction */
                    423:                                i2 = volumetable_get(i + 1, j + 1, k + 1);
                    424:                                volumetable_set(out,i*2 + 1, j*2 + 1, k*2 + 1, volumetable_interpolate(i1, i2));
                    425:                        }
                    426:                }
1.1.1.11  root      427:        }
1.1       root      428: }
                    429: 
1.1.1.5   root      430: 
1.1.1.12  root      431: 
                    432: 
1.1.1.2   root      433: /*-----------------------------------------------------------------------*/
1.1.1.11  root      434: /**
1.1.1.12  root      435:  * Build a linear version of the conversion table.
                    436:  * We use the mean of the 3 volumes converted to 16 bit values
                    437:  * (each value of ymout1c5bit is in [0,65535])
1.1.1.11  root      438:  */
1.1.1.12  root      439: 
                    440: static void    YM2149_BuildLinearVolumeTable(ymu16 *out)
1.1       root      441: {
1.1.1.12  root      442:        int     i, j, k;
                    443:        int     res;
                    444: 
                    445:        for (i = 0; i < 32; i++)
                    446:                for (j = 0; j < 32; j++)
                    447:                        for (k = 0; k < 32; k++)
                    448:                        {
                    449:                                res = ( ymout1c5bit[ i ] + ymout1c5bit[ j ] + ymout1c5bit[ k ] ) / 3;
                    450:                                volumetable_set ( out, i, j, k, res );
                    451:                        }
                    452: }
                    453: 
                    454: 
                    455: 
1.1       root      456: 
1.1.1.12  root      457: /*-----------------------------------------------------------------------*/
                    458: /**
                    459:  * Normalise and optionally center the volume table used to
                    460:  * convert the 3 volumes to a final signed 16 bit sample.
                    461:  * This allows to adapt the amplitude/volume of the samples and
                    462:  * to convert unsigned values to signed values.
                    463:  * - in_5bit contains 32*32*32 unsigned values in the range
                    464:  *     [0,65535].
                    465:  * - out_5bit will contain signed values
                    466:  * Possible values are :
                    467:  *     Level=65535 and DoCenter=TRUE -> [-32768,32767]
1.1.1.14! root      468:  *     Level=32767 and DoCenter=false -> [0,32767]
1.1.1.12  root      469:  */
                    470: 
                    471: static void    YM2149_Normalise_5bit_Table(ymu16 *in_5bit , yms16 *out_5bit, unsigned int Level, bool DoCenter)
                    472: {
                    473:        if ( Level )
1.1.1.11  root      474:        {
1.1.1.14! root      475:                int h;
1.1.1.12  root      476:                int Max = in_5bit[0x7fff];
                    477:                int Center = Level>>1;
1.1.1.14! root      478:                //fprintf ( stderr , "level %d max %d center %d\n" , Level, Max, Center );
        !           479: 
1.1.1.12  root      480:                /* Change the amplitude of the signal to 'level' : [0,max] -> [0,level] */
                    481:                /* Then optionally center the signal around Level/2 */
                    482:                /* This means we go from sthg like [0,65535] to [-32768, 32767] if Level=65535 and DoCenter=TRUE */
                    483:                for (h=0; h<32*32*32; h++)
                    484:                {
                    485:                        int tmp = in_5bit[h], res;
                    486:                        res = tmp * Level / Max;
1.1.1.14! root      487: 
1.1.1.12  root      488:                        if ( DoCenter )
                    489:                                res -= Center;
                    490: 
                    491:                        out_5bit[h] = res;
1.1.1.14! root      492:                        //fprintf ( stderr , "h %d in %d out %d\n" , h , tmp , res );
1.1.1.12  root      493:                }
1.1.1.11  root      494:        }
1.1       root      495: }
                    496: 
1.1.1.5   root      497: 
1.1.1.12  root      498: 
                    499: 
1.1.1.2   root      500: /*-----------------------------------------------------------------------*/
1.1.1.11  root      501: /**
1.1.1.12  root      502:  * Precompute all 16 possible envelopes.
                    503:  * Each envelope is made of 3 blocks of 32 volumes.
1.1.1.11  root      504:  */
1.1.1.12  root      505: 
                    506: static void    YM2149_EnvBuild ( void )
1.1       root      507: {
1.1.1.12  root      508:        int     env;
                    509:        int     block;
                    510:        int     vol=0 , inc=0;
                    511:        int     i;
1.1       root      512: 
1.1.1.12  root      513: 
                    514:        for ( env=0 ; env<16 ; env++ )                          /* 16 possible envelopes */
                    515:                for ( block=0 ; block<3 ; block++ )             /* 3 blocks to define an envelope */
                    516:                {
1.1.1.14! root      517:                        switch ( YmEnvDef[ env ][ block ] )
        !           518:                        {
1.1.1.12  root      519:                                case ENV_GODOWN :       vol=31 ; inc=-1 ; break;
                    520:                                case ENV_GOUP :         vol=0  ; inc=1 ; break;
                    521:                                case ENV_DOWN :         vol=0  ; inc=0 ; break;
                    522:                                case ENV_UP :           vol=31 ; inc=0 ; break;
1.1.1.14! root      523:                        }
        !           524: 
1.1.1.12  root      525:                        for ( i=0 ; i<32 ; i++ )                /* 32 volumes per block */
                    526:                        {
                    527:                                YmEnvWaves[ env ][ block*32 + i ] = YM_MERGE_VOICE ( vol , vol , vol );
                    528:                                vol += inc;
                    529:                        }
                    530:                }
                    531: }
                    532: 
                    533: 
                    534: 
                    535: /*-----------------------------------------------------------------------*/
                    536: /**
                    537:  * Init some internal tables for faster results (env, volume)
                    538:  * and reset the internal states.
                    539:  */
                    540: 
                    541: static void    Ym2149_Init(void)
                    542: {
                    543:        /* Build the 16 envelope shapes */
                    544:        YM2149_EnvBuild();
                    545: 
                    546:        /* Depending on the volume mixing method, we use a table based on real measures */
                    547:        /* or a table based on a linear volume mixing. */
                    548:        if ( YmVolumeMixing == YM_TABLE_MIXING )
                    549:                interpolate_volumetable(ymout5_u16);    /* expand the 16*16*16 values in volumetable_original to 32*32*32 */
                    550:        else
                    551:                YM2149_BuildLinearVolumeTable(ymout5_u16);      /* combine the 32 possible volumes */
                    552: 
                    553:        /* Normalise/center the values (convert from u16 to s16) */
                    554:        YM2149_Normalise_5bit_Table ( ymout5_u16 , ymout5 , YM_OUTPUT_LEVEL , YM_OUTPUT_CENTERED );
                    555: 
                    556:        /* Reset YM2149 internal states */
                    557:        Ym2149_Reset();
                    558: }
                    559: 
                    560: 
                    561: 
                    562: /*-----------------------------------------------------------------------*/
                    563: /**
                    564:  * Reset all ym registers as well as the internal varaibles
                    565:  */
                    566: 
                    567: static void    Ym2149_Reset(void)
                    568: {
                    569:        int     i;
1.1.1.14! root      570: 
1.1.1.12  root      571:        for ( i=0 ; i<14 ; i++ )
                    572:                Sound_WriteReg ( i , 0 );
                    573: 
                    574:        Sound_WriteReg ( 7 , 0xff );
                    575: 
                    576:        currentNoise = 0xffff;
1.1.1.14! root      577: 
1.1.1.12  root      578:        RndRack = 1;
1.1.1.14! root      579: 
1.1.1.12  root      580:        envShape = 0;
                    581:        envPos = 0;
                    582: 
                    583:        DcAdjuster_Reset ();
                    584:        LowPassFilter_Reset ();
                    585: }
                    586: 
                    587: 
                    588: 
                    589: /*-----------------------------------------------------------------------*/
                    590: /**
                    591:  * Returns a pseudo random value, used to generate white noise.
                    592:  */
                    593: 
                    594: static ymu32   YM2149_RndCompute(void)
                    595: {
                    596:        ymu32   bit;
1.1.1.14! root      597: 
1.1.1.12  root      598:        bit = (RndRack&1) ^ ((RndRack>>2)&1);
                    599:        RndRack = (RndRack>>1) | (bit<<16);
                    600:        return (bit ? 0 : 0xffff);
                    601: }
                    602: 
                    603: 
                    604: 
                    605: /*-----------------------------------------------------------------------*/
                    606: /**
                    607:  * Compute steps for tone, noise and env, based on the input
                    608:  * period.
                    609:  */
                    610: 
                    611: static ymu32   Ym2149_ToneStepCompute(ymu8 rHigh , ymu8 rLow)
                    612: {
                    613:        int     per;
1.1.1.14! root      614:        yms64   step;
1.1.1.12  root      615: 
                    616:        per = rHigh&15;
                    617:        per = (per<<8)+rLow;
1.1.1.14! root      618:        if (per <= 5)
1.1.1.12  root      619:                return 0;
                    620: 
1.1.1.14! root      621:        step = YM_ATARI_CLOCK;
1.1.1.12  root      622:        step <<= (15+16-3);
                    623:        step /= (per * YM_REPLAY_FREQ);
                    624: 
                    625:        return step;
                    626: }
                    627: 
                    628: 
                    629: static ymu32   Ym2149_NoiseStepCompute(ymu8 rNoise)
                    630: {
                    631:        int     per;
1.1.1.14! root      632:        yms64   step;
1.1.1.12  root      633: 
                    634:        per = (rNoise&0x1f);
                    635:        if (per<3)
                    636:                return 0;
                    637: 
1.1.1.14! root      638:        step = YM_ATARI_CLOCK;
1.1.1.12  root      639:        step <<= (16-1-3);
                    640:        step /= (per * YM_REPLAY_FREQ);
                    641: 
                    642:        return step;
1.1       root      643: }
                    644: 
1.1.1.5   root      645: 
1.1.1.2   root      646: /*-----------------------------------------------------------------------*/
1.1.1.11  root      647: /**
1.1.1.12  root      648:  * Compute envelope's step. The envelope is made of different patterns
                    649:  * of 32 volumes. In each pattern, the volume is changed at frequency
                    650:  * Fe = MasterClock / ( 8 * EnvPer ).
                    651:  * In our case, we use a lower replay freq ; between 2 consecutive calls
                    652:  * to envelope's generation, the internal counter will advance 'step'
                    653:  * units, where step = MasterClock / ( 8 * EnvPer * YM_REPLAY_FREQ )
                    654:  * As 'step' requires floating point to be stored, we use left shifting
                    655:  * to multiply 'step' by a fixed amount. All operations are made with
                    656:  * shifted values ; to get the final value, we must right shift the
                    657:  * result. We use '<<24', which gives 8 bits for the integer part, and
                    658:  * the equivalent of 24 bits for the fractional part.
                    659:  * Since we're using large numbers, we temporarily use 64 bits integer
                    660:  * to avoid overflow and keep largest precision possible.
1.1.1.11  root      661:  */
1.1.1.12  root      662: 
                    663: static ymu32   Ym2149_EnvStepCompute(ymu8 rHigh , ymu8 rLow)
1.1       root      664: {
1.1.1.12  root      665:        yms64   per;
1.1.1.14! root      666:        yms64   step;
1.1       root      667: 
1.1.1.12  root      668:        per = rHigh;
                    669:        per = (per<<8)+rLow;
                    670: 
1.1.1.14! root      671:        step = YM_ATARI_CLOCK;
1.1.1.12  root      672:        step <<= 24;
                    673:        if ( per > 0 )
                    674:                step /= (8 * per * YM_REPLAY_FREQ);     /* 0x5ab < step < 0x5ab3f46 at 44.1 kHz */
                    675:        else
                    676:                step /= (8 * 1/2 * YM_REPLAY_FREQ);     /* result for Per=0 is half the result for Per=1 */
                    677: 
                    678:        return step;
                    679: }
                    680: 
                    681: 
                    682: 
                    683: /*-----------------------------------------------------------------------*/
                    684: /**
                    685:  * Main function : compute the value of the next sample.
                    686:  * Mixes all 3 voices with tone+noise+env and apply low pass
                    687:  * filter if needed.
                    688:  */
                    689: 
                    690: static ymsample        YM2149_NextSample(void)
                    691: {
                    692:        ymsample        sample;
                    693:        int             bt;
                    694:        ymu32           bn;
                    695:        ymu16           Env3Voices;
                    696:        ymu16           Tone3Voices;
                    697: 
                    698: 
                    699:        /* Noise value : 0 or 0xffff */
                    700:        if ( noisePos&0xffff0000 )
                    701:        {
                    702:                currentNoise ^= YM2149_RndCompute();
                    703:                noisePos &= 0xffff;
                    704:        }
                    705:        bn = currentNoise;                              /* 0 or 0xffff */
                    706: 
                    707:        /* Get the 5 bits volume corresponding to the current envelope's position */
                    708:        Env3Voices = YmEnvWaves[ envShape ][ envPos>>24 ];      /* integer part of envPos is in bits 24-31 */
                    709:        Env3Voices &= EnvMask3Voices;                   /* only keep volumes for voices using envelope */
                    710: 
                    711: //fprintf ( stderr , "env %x %x %x\n" , Env3Voices , envStep , envPos );
                    712: 
                    713:        /* Tone3Voices will contain the output state of each voice : 0 or 0x1f */
                    714:        bt = ((((yms32)posA)>>31) | mixerTA) & (bn | mixerNA);  /* 0 or 0xffff */
                    715:        Tone3Voices = bt & YM_MASK_1VOICE;                      /* 0 or 0x1f */
                    716:        bt = ((((yms32)posB)>>31) | mixerTB) & (bn | mixerNB);
                    717:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 5;
                    718:        bt = ((((yms32)posC)>>31) | mixerTC) & (bn | mixerNC);
                    719:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 10;
                    720: 
                    721:        /* Combine fixed volumes and envelope volumes and keep the resulting */
                    722:        /* volumes depending on the output state of each voice (0 or 0x1f) */
                    723:        Tone3Voices &= ( Env3Voices | Vol3Voices );
                    724: 
                    725:        /* D/A conversion of the 3 volumes into a sample using a precomputed conversion table */
                    726:        sample = ymout5[ Tone3Voices ];                 /* 16 bits signed value */
                    727: 
                    728: 
                    729:        /* Increment positions */
                    730:        posA += stepA;
                    731:        posB += stepB;
                    732:        posC += stepC;
                    733:        noisePos += noiseStep;
1.1.1.14! root      734: 
1.1.1.12  root      735:        envPos += envStep;
                    736:        if ( envPos >= (3*32) << 24 )                   /* blocks 0, 1 and 2 were used (envPos 0 to 95) */
                    737:                envPos -= (2*32) << 24;                 /* replay/loop blocks 1 and 2 (envPos 32 to 95) */
                    738: 
1.1.1.14! root      739:        DcAdjuster_AddSample(sample);                   /* Calculate DC level */
        !           740:        sample = sample - DcAdjuster_GetDcLevel();      /* normalize sound level */
1.1.1.12  root      741: 
                    742:        /* Apply low pass filter ? */
                    743:        if ( UseLowPassFilter )
1.1.1.11  root      744:        {
1.1.1.14! root      745:                sample = LowPassFilter(sample);
1.1.1.11  root      746:        }
1.1.1.12  root      747: 
                    748:        return sample;
1.1       root      749: }
                    750: 
                    751: 
1.1.1.12  root      752: 
1.1.1.2   root      753: /*-----------------------------------------------------------------------*/
1.1.1.11  root      754: /**
1.1.1.12  root      755:  * Update internal variables (steps, volume masks, ...) each
                    756:  * time an YM register is changed.
1.1.1.11  root      757:  */
                    758: 
1.1.1.12  root      759: void   Sound_WriteReg( int reg , Uint8 data )
1.1.1.7   root      760: {
1.1.1.12  root      761:        switch (reg)
                    762:        {
                    763:                case 0:
                    764:                        SoundRegs[0] = data;
                    765:                        stepA = Ym2149_ToneStepCompute ( SoundRegs[1] , SoundRegs[0] );
                    766:                        if (!stepA) posA = 1u<<31;              // Assume output always 1 if 0 period (for Digi-sample)
                    767:                        break;
                    768: 
                    769:                case 1:
                    770:                        SoundRegs[1] = data & 0x0f;
                    771:                        stepA = Ym2149_ToneStepCompute ( SoundRegs[1] , SoundRegs[0] );
                    772:                        if (!stepA) posA = 1u<<31;              // Assume output always 1 if 0 period (for Digi-sample)
                    773:                        break;
                    774: 
                    775:                case 2:
                    776:                        SoundRegs[2] = data;
                    777:                        stepB = Ym2149_ToneStepCompute ( SoundRegs[3] , SoundRegs[2] );
                    778:                        if (!stepB) posB = 1u<<31;              // Assume output always 1 if 0 period (for Digi-sample)
                    779:                        break;
1.1.1.7   root      780: 
1.1.1.12  root      781:                case 3:
                    782:                        SoundRegs[3] = data & 0x0f;
                    783:                        stepB = Ym2149_ToneStepCompute ( SoundRegs[3] , SoundRegs[2] );
                    784:                        if (!stepB) posB = 1u<<31;              // Assume output always 1 if 0 period (for Digi-sample)
                    785:                        break;
                    786: 
                    787:                case 4:
                    788:                        SoundRegs[4] = data;
                    789:                        stepC = Ym2149_ToneStepCompute ( SoundRegs[5] , SoundRegs[4] );
                    790:                        if (!stepC) posC = 1u<<31;              // Assume output always 1 if 0 period (for Digi-sample)
                    791:                        break;
                    792: 
                    793:                case 5:
                    794:                        SoundRegs[5] = data & 0x0f;
                    795:                        stepC = Ym2149_ToneStepCompute ( SoundRegs[5] , SoundRegs[4] );
                    796:                        if (!stepC) posC = 1u<<31;              // Assume output always 1 if 0 period (for Digi-sample)
                    797:                        break;
                    798: 
                    799:                case 6:
                    800:                        SoundRegs[6] = data & 0x1f;
                    801:                        noiseStep = Ym2149_NoiseStepCompute ( SoundRegs[6] );
                    802:                        if (!noiseStep)
                    803:                        {
                    804:                                noisePos = 0;
                    805:                                currentNoise = 0xffff;
                    806:                        }
                    807:                        break;
                    808: 
                    809:                case 7:
                    810:                        SoundRegs[7] = data & 0x3f;                     /* ignore bits 6 and 7 */
                    811:                        mixerTA = (data&(1<<0)) ? 0xffff : 0;
                    812:                        mixerTB = (data&(1<<1)) ? 0xffff : 0;
                    813:                        mixerTC = (data&(1<<2)) ? 0xffff : 0;
                    814:                        mixerNA = (data&(1<<3)) ? 0xffff : 0;
                    815:                        mixerNB = (data&(1<<4)) ? 0xffff : 0;
                    816:                        mixerNC = (data&(1<<5)) ? 0xffff : 0;
                    817:                        break;
                    818: 
                    819:                case 8:
                    820:                        SoundRegs[8] = data & 0x1f;
                    821:                        if ( data & 0x10 )
                    822:                        {
                    823:                                EnvMask3Voices |= YM_MASK_A;            /* env ON */
                    824:                                Vol3Voices &= ~YM_MASK_A;               /* fixed vol OFF */
                    825:                        }
                    826:                        else
                    827:                        {
                    828:                                EnvMask3Voices &= ~YM_MASK_A;           /* env OFF */
                    829:                                Vol3Voices &= ~YM_MASK_A;               /* clear previous vol */
                    830:                                Vol3Voices |= YmVolume4to5[ SoundRegs[8] ];     /* fixed vol ON */
                    831:                        }
                    832:                        break;
1.1.1.14! root      833: 
1.1.1.12  root      834:                case 9:
                    835:                        SoundRegs[9] = data & 0x1f;
                    836:                        if ( data & 0x10 )
                    837:                        {
                    838:                                EnvMask3Voices |= YM_MASK_B;            /* env ON */
                    839:                                Vol3Voices &= ~YM_MASK_B;               /* fixed vol OFF */
                    840:                        }
                    841:                        else
                    842:                        {
                    843:                                EnvMask3Voices &= ~YM_MASK_B;           /* env OFF */
                    844:                                Vol3Voices &= ~YM_MASK_B;               /* clear previous vol */
                    845:                                Vol3Voices |= ( YmVolume4to5[ SoundRegs[9] ] ) << 5;    /* fixed vol ON */
                    846:                        }
                    847:                        break;
1.1.1.14! root      848: 
1.1.1.12  root      849:                case 10:
                    850:                        SoundRegs[10] = data & 0x1f;
                    851:                        if ( data & 0x10 )
                    852:                        {
                    853:                                EnvMask3Voices |= YM_MASK_C;            /* env ON */
                    854:                                Vol3Voices &= ~YM_MASK_C;               /* fixed vol OFF */
                    855:                        }
                    856:                        else
                    857:                        {
                    858:                                EnvMask3Voices &= ~YM_MASK_C;           /* env OFF */
                    859:                                Vol3Voices &= ~YM_MASK_C;               /* clear previous vol */
                    860:                                Vol3Voices |= ( YmVolume4to5[ SoundRegs[10] ] ) << 10;  /* fixed vol ON */
                    861:                        }
                    862:                        break;
                    863: 
                    864:                case 11:
                    865:                        SoundRegs[11] = data;
                    866:                        envStep = Ym2149_EnvStepCompute ( SoundRegs[12] , SoundRegs[11] );
                    867:                        break;
                    868: 
                    869:                case 12:
                    870:                        SoundRegs[12] = data;
                    871:                        envStep = Ym2149_EnvStepCompute ( SoundRegs[12] , SoundRegs[11] );
                    872:                        break;
                    873: 
                    874:                case 13:
                    875:                        SoundRegs[13] = data & 0xf;
                    876:                        envPos = 0;                                     /* when writing to EnvShape, we must reset the EnvPos */
                    877:                        envShape = SoundRegs[13];
1.1.1.14! root      878:                        bEnvelopeFreqFlag = true;                       /* used for YmFormat saving */
1.1.1.12  root      879:                        break;
                    880: 
                    881:        }
                    882: }
                    883: 
                    884: 
                    885: 
                    886: /*-----------------------------------------------------------------------*/
                    887: /**
                    888:  * Init random generator, sound tables and envelopes
                    889:  * (called only once when Hatari starts)
                    890:  */
                    891: void Sound_Init(void)
                    892: {
                    893:        /* Build volume/env tables, ... */
                    894:        Ym2149_Init();
1.1.1.14! root      895: 
1.1.1.11  root      896:        Sound_Reset();
1.1.1.7   root      897: }
                    898: 
                    899: 
                    900: /*-----------------------------------------------------------------------*/
1.1.1.11  root      901: /**
1.1.1.12  root      902:  * Reset the sound emulation (called from Reset_ST() in reset.c)
1.1.1.11  root      903:  */
1.1.1.7   root      904: void Sound_Reset(void)
                    905: {
1.1.1.11  root      906:        /* Lock audio system before accessing variables which are used by the
                    907:         * callback function, too! */
                    908:        Audio_Lock();
1.1.1.9   root      909: 
1.1.1.11  root      910:        /* Clear sound mixing buffer: */
1.1.1.12  root      911:        memset(MixBuffer, 0, sizeof(MixBuffer));
1.1.1.7   root      912: 
1.1.1.11  root      913:        /* Clear cycle counts, buffer index and register '13' flags */
                    914:        Cycles_SetCounter(CYCLES_COUNTER_SOUND, 0);
1.1.1.14! root      915:        bEnvelopeFreqFlag = false;
        !           916: 
1.1.1.11  root      917:        CompleteSndBufIdx = 0;
                    918:        /* We do not start with 0 here to fake some initial samples: */
                    919:        nGeneratedSamples = SoundBufferSize + SAMPLES_PER_FRAME;
                    920:        ActiveSndBufIdx = nGeneratedSamples % MIXBUFFER_SIZE;
1.1.1.7   root      921: 
1.1.1.12  root      922:        Ym2149_Reset();
1.1.1.9   root      923: 
1.1.1.11  root      924:        Audio_Unlock();
1.1.1.7   root      925: }
                    926: 
                    927: 
                    928: /*-----------------------------------------------------------------------*/
1.1.1.11  root      929: /**
                    930:  * Reset the sound buffer index variables.
                    931:  */
1.1.1.9   root      932: void Sound_ResetBufferIndex(void)
1.1.1.7   root      933: {
1.1.1.11  root      934:        Audio_Lock();
                    935:        nGeneratedSamples = SoundBufferSize + SAMPLES_PER_FRAME;
                    936:        ActiveSndBufIdx =  (CompleteSndBufIdx + nGeneratedSamples) % MIXBUFFER_SIZE;
                    937:        Audio_Unlock();
1.1.1.7   root      938: }
                    939: 
                    940: 
                    941: /*-----------------------------------------------------------------------*/
1.1.1.11  root      942: /**
                    943:  * Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                    944:  */
1.1.1.12  root      945: void Sound_MemorySnapShot_Capture(bool bSave)
1.1.1.7   root      946: {
1.1.1.11  root      947:        /* Save/Restore details */
1.1.1.12  root      948:        MemorySnapShot_Store(&stepA, sizeof(stepA));
                    949:        MemorySnapShot_Store(&stepB, sizeof(stepB));
                    950:        MemorySnapShot_Store(&stepC, sizeof(stepC));
                    951:        MemorySnapShot_Store(&posA, sizeof(posA));
                    952:        MemorySnapShot_Store(&posB, sizeof(posB));
                    953:        MemorySnapShot_Store(&posC, sizeof(posC));
                    954: 
                    955:        MemorySnapShot_Store(&mixerTA, sizeof(mixerTA));
                    956:        MemorySnapShot_Store(&mixerTB, sizeof(mixerTB));
                    957:        MemorySnapShot_Store(&mixerTC, sizeof(mixerTC));
                    958:        MemorySnapShot_Store(&mixerNA, sizeof(mixerNA));
                    959:        MemorySnapShot_Store(&mixerNB, sizeof(mixerNB));
                    960:        MemorySnapShot_Store(&mixerNC, sizeof(mixerNC));
                    961: 
                    962:        MemorySnapShot_Store(&noiseStep, sizeof(noiseStep));
                    963:        MemorySnapShot_Store(&noisePos, sizeof(noisePos));
                    964:        MemorySnapShot_Store(&currentNoise, sizeof(currentNoise));
                    965:        MemorySnapShot_Store(&RndRack, sizeof(RndRack));
                    966: 
                    967:        MemorySnapShot_Store(&envStep, sizeof(envStep));
                    968:        MemorySnapShot_Store(&envPos, sizeof(envPos));
                    969:        MemorySnapShot_Store(&envShape, sizeof(envShape));
1.1.1.14! root      970: 
1.1.1.12  root      971:        MemorySnapShot_Store(&EnvMask3Voices, sizeof(EnvMask3Voices));
                    972:        MemorySnapShot_Store(&Vol3Voices, sizeof(Vol3Voices));
1.1.1.14! root      973: 
1.1.1.12  root      974:        MemorySnapShot_Store(SoundRegs, sizeof(SoundRegs));
                    975: 
1.1.1.14! root      976:        // MemorySnapShot_Store(&YmVolumeMixing, sizeof(YmVolumeMixing));
        !           977:        // MemorySnapShot_Store(&UseLowPassFilter, sizeof(UseLowPassFilter));
1.1.1.7   root      978: }
                    979: 
                    980: 
                    981: /*-----------------------------------------------------------------------*/
1.1.1.11  root      982: /**
                    983:  * Find how many samples to generate and store in 'nSamplesToGenerate'
                    984:  * Also update sound cycles counter to store how many we actually did
                    985:  * so generates set amount each frame.
                    986:  */
1.1.1.7   root      987: static void Sound_SetSamplesPassed(void)
1.1       root      988: {
1.1.1.11  root      989:        int nSampleCycles;
                    990:        int nSamplesPerFrame;
                    991:        int nSoundCycles;
                    992: 
                    993:        nSoundCycles = Cycles_GetCounter(CYCLES_COUNTER_SOUND);
                    994: 
                    995:        /* 160256 cycles per VBL, 44Khz = 882 samples per VBL */
                    996:        /* 882/160256 samples per clock cycle */
                    997:        nSamplesPerFrame = SAMPLES_PER_FRAME;
                    998: 
                    999:        nSamplesToGenerate = nSoundCycles * nSamplesPerFrame / CYCLES_PER_FRAME;
                   1000:        if (nSamplesToGenerate > nSamplesPerFrame)
                   1001:                nSamplesToGenerate = nSamplesPerFrame;
                   1002: 
                   1003:        nSampleCycles = nSamplesToGenerate * CYCLES_PER_FRAME / nSamplesPerFrame;
                   1004:        nSoundCycles -= nSampleCycles;
                   1005:        Cycles_SetCounter(CYCLES_COUNTER_SOUND, nSoundCycles);
                   1006: 
                   1007:        if (nSamplesToGenerate > MIXBUFFER_SIZE - nGeneratedSamples)
                   1008:        {
                   1009:                nSamplesToGenerate = MIXBUFFER_SIZE - nGeneratedSamples;
                   1010:                if (nSamplesToGenerate < 0)
                   1011:                        nSamplesToGenerate = 0;
                   1012:        }
1.1       root     1013: }
                   1014: 
1.1.1.5   root     1015: 
1.1.1.2   root     1016: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1017: /**
                   1018:  * Generate samples for all channels during this time-frame
                   1019:  */
1.1.1.5   root     1020: static void Sound_GenerateSamples(void)
1.1       root     1021: {
1.1.1.12  root     1022:        int     i;
                   1023:        int     idx;
1.1.1.14! root     1024: 
1.1.1.12  root     1025:        if (nSamplesToGenerate <= 0)
                   1026:                return;
1.1.1.14! root     1027: 
1.1.1.12  root     1028:        for (i = 0; i < nSamplesToGenerate; i++)
1.1.1.11  root     1029:        {
1.1.1.12  root     1030:                idx = (ActiveSndBufIdx + i) % MIXBUFFER_SIZE;
                   1031:                MixBuffer[idx][0] = MixBuffer[idx][1] = YM2149_NextSample();
1.1.1.11  root     1032:        }
1.1.1.14! root     1033: 
1.1.1.12  root     1034:        DmaSnd_GenerateSamples(ActiveSndBufIdx, nSamplesToGenerate);
                   1035: 
                   1036:        ActiveSndBufIdx = (ActiveSndBufIdx + nSamplesToGenerate) % MIXBUFFER_SIZE;
                   1037:        nGeneratedSamples += nSamplesToGenerate;
1.1       root     1038: }
                   1039: 
1.1.1.5   root     1040: 
1.1.1.2   root     1041: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1042: /**
                   1043:  * This is called to built samples up until this clock cycle
                   1044:  */
1.1.1.5   root     1045: void Sound_Update(void)
1.1       root     1046: {
1.1.1.11  root     1047:        int OldSndBufIdx = ActiveSndBufIdx;
1.1.1.5   root     1048: 
1.1.1.11  root     1049:        /* Make sure that we don't interfere with the audio callback function */
                   1050:        Audio_Lock();
1.1.1.6   root     1051: 
1.1.1.11  root     1052:        /* Find how many to generate */
                   1053:        Sound_SetSamplesPassed();
                   1054:        /* And generate */
                   1055:        Sound_GenerateSamples();
1.1       root     1056: 
1.1.1.11  root     1057:        /* Allow audio callback function to occur again */
                   1058:        Audio_Unlock();
1.1.1.6   root     1059: 
1.1.1.11  root     1060:        /* Save to WAV file, if open */
                   1061:        if (bRecordingWav)
                   1062:                WAVFormat_Update(MixBuffer, OldSndBufIdx, nSamplesToGenerate);
1.1       root     1063: }
                   1064: 
1.1.1.5   root     1065: 
1.1.1.2   root     1066: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1067: /**
                   1068:  * On each VBL (50fps) complete samples.
                   1069:  */
1.1.1.5   root     1070: void Sound_Update_VBL(void)
1.1       root     1071: {
1.1.1.11  root     1072:        Sound_Update();
1.1.1.5   root     1073: 
1.1.1.11  root     1074:        /* Clear write to register '13', used for YM file saving */
1.1.1.14! root     1075:        bEnvelopeFreqFlag = false;
1.1       root     1076: }
                   1077: 
                   1078: 
1.1.1.2   root     1079: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1080: /**
                   1081:  * Start recording sound, as .YM or .WAV output
                   1082:  */
1.1.1.12  root     1083: bool Sound_BeginRecording(char *pszCaptureFileName)
1.1       root     1084: {
1.1.1.12  root     1085:        bool bRet;
1.1.1.7   root     1086: 
1.1.1.11  root     1087:        if (!pszCaptureFileName || strlen(pszCaptureFileName) <= 3)
                   1088:        {
                   1089:                Log_Printf(LOG_ERROR, "Illegal sound recording file name!\n");
1.1.1.14! root     1090:                return false;
1.1.1.11  root     1091:        }
                   1092: 
                   1093:        /* Did specify .YM or .WAV? If neither report error */
                   1094:        if (File_DoesFileExtensionMatch(pszCaptureFileName,".ym"))
                   1095:                bRet = YMFormat_BeginRecording(pszCaptureFileName);
                   1096:        else if (File_DoesFileExtensionMatch(pszCaptureFileName,".wav"))
                   1097:                bRet = WAVFormat_OpenFile(pszCaptureFileName);
                   1098:        else
                   1099:        {
                   1100:                Log_AlertDlg(LOG_ERROR, "Unknown Sound Recording format.\n"
                   1101:                             "Please specify a .YM or .WAV output file.");
1.1.1.14! root     1102:                bRet = false;
1.1.1.11  root     1103:        }
                   1104: 
                   1105:        return bRet;
1.1       root     1106: }
                   1107: 
1.1.1.5   root     1108: 
1.1.1.2   root     1109: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1110: /**
                   1111:  * End sound recording
                   1112:  */
1.1.1.7   root     1113: void Sound_EndRecording(void)
1.1       root     1114: {
1.1.1.11  root     1115:        /* Stop sound recording and close files */
                   1116:        if (bRecordingYM)
                   1117:                YMFormat_EndRecording();
                   1118:        if (bRecordingWav)
                   1119:                WAVFormat_CloseFile();
1.1       root     1120: }
                   1121: 
1.1.1.6   root     1122: 
1.1.1.2   root     1123: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1124: /**
                   1125:  * Are we recording sound data?
                   1126:  */
1.1.1.12  root     1127: bool Sound_AreWeRecording(void)
1.1       root     1128: {
1.1.1.11  root     1129:        return (bRecordingYM || bRecordingWav);
1.1       root     1130: }
1.1.1.12  root     1131: 

unix.superglobalmegacorp.com

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