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

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.                            */
                     69: 
                     70: 
                     71: 
1.1.1.14  root       72: const char Sound_fileid[] = "Hatari sound.c : " __DATE__ " " __TIME__;
1.1.1.5   root       73: 
                     74: #include <SDL_types.h>
1.1       root       75: 
                     76: #include "main.h"
                     77: #include "audio.h"
1.1.1.10  root       78: #include "cycles.h"
1.1.1.15  root       79: #include "configuration.h"
1.1.1.9   root       80: #include "dmaSnd.h"
1.1.1.15  root       81: #include "crossbar.h"
1.1       root       82: #include "file.h"
1.1.1.15  root       83: #include "cycInt.h"
1.1.1.8   root       84: #include "log.h"
1.1       root       85: #include "memorySnapShot.h"
                     86: #include "psg.h"
                     87: #include "sound.h"
1.1.1.16! root       88: #include "screen.h"
1.1       root       89: #include "video.h"
                     90: #include "wavFormat.h"
                     91: #include "ymFormat.h"
1.1.1.15  root       92: #include "avi_record.h"
1.1.1.16! root       93: #include "clocks_timings.h"
1.1       root       94: 
                     95: 
                     96: 
1.1.1.12  root       97: /*--------------------------------------------------------------*/
                     98: /* Definition of the possible envelopes shapes (using 5 bits)  */
                     99: /*--------------------------------------------------------------*/
                    100: 
                    101: #define        ENV_GODOWN      0               /* 31 ->  0 */
                    102: #define        ENV_GOUP        1               /*  0 -> 31 */
                    103: #define        ENV_DOWN        2               /*  0 ->  0 */
                    104: #define        ENV_UP          3               /* 31 -> 31 */
                    105: 
                    106: /* To generate an envelope, we first use block 0, then we repeat blocks 1 and 2 */
                    107: static const int YmEnvDef[ 16 ][ 3 ] = {
                    108:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 0 \___ */
                    109:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 1 \___ */
                    110:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 2 \___ */
                    111:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 3 \___ */
                    112:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 4 /___ */
                    113:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 5 /___ */
                    114:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 6 /___ */
                    115:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 7 /___ */
                    116:        { ENV_GODOWN,   ENV_GODOWN, ENV_GODOWN } ,      /* 8 \\\\ */
                    117:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 9 \___ */
                    118:        { ENV_GODOWN,   ENV_GOUP, ENV_GODOWN } ,        /* A \/\/ */
                    119:        { ENV_GODOWN,   ENV_UP, ENV_UP } ,              /* B \--- */
                    120:        { ENV_GOUP,     ENV_GOUP, ENV_GOUP } ,          /* C //// */
                    121:        { ENV_GOUP,     ENV_UP, ENV_UP } ,              /* D /--- */
                    122:        { ENV_GOUP,     ENV_GODOWN, ENV_GOUP } ,        /* E /\/\ */
                    123:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* F /___ */
                    124:        };
                    125: 
                    126: 
                    127: /* Buffer to store the 16 envelopes built from YmEnvDef */
                    128: static ymu16   YmEnvWaves[ 16 ][ 32 * 3 ];             /* 16 envelopes with 3 blocks of 32 volumes */
1.1.1.3   root      129: 
1.1       root      130: 
1.1.1.12  root      131: 
                    132: /*--------------------------------------------------------------*/
                    133: /* Definition of the volumes tables (using 5 bits) and of the  */
                    134: /* mixing parameters for the 3 voices.                         */
                    135: /*--------------------------------------------------------------*/
                    136: 
                    137: /* 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) */
                    138: /* Vol 0 should be 310 when measuread as a voltage, but we set it to 0 in order to have a volume=0 matching */
                    139: /* the 0 level of a 16 bits unsigned sample (no sound output) */
                    140: static const ymu16 ymout1c5bit[ 32 ] =
                    141: {
                    142:   0 /*310*/,  369,  438,  521,  619,  735,  874, 1039,
                    143:  1234, 1467, 1744, 2072, 2463, 2927, 3479, 4135,
                    144:  4914, 5841, 6942, 8250, 9806,11654,13851,16462,
                    145: 19565,23253,27636,32845,39037,46395,55141,65535
1.1       root      146: };
                    147: 
1.1.1.12  root      148: /* Convert a constant 4 bits volume to the internal 5 bits value : */
                    149: /* volume5=volume4*2+1, except for volumes 0 and 1 which become 0 and 2, */
                    150: /* in order to map [0,15] into [0,31] (O must remain 0, and 15 must give 31) */
                    151: static const ymu16 YmVolume4to5[ 16 ] = { 0,2,5,7,9,11,13,15,17,19,21,23,25,27,29,31 };
1.1       root      152: 
1.1.1.12  root      153: /* Table of unsigned 4 bit D/A output level for 3 channels as measured on a real ST */
                    154: static ymu16 volumetable_original[ 16 * 16 * 16 ] =
                    155: #include "ym2149_fixed_vol.h"
1.1.1.5   root      156: 
1.1.1.12  root      157: /* Corresponding table interpolated to 5 bit D/A output level (16 bits unsigned) */
                    158: static ymu16 ymout5_u16[ 32 * 32 * 32 ];
                    159: 
                    160: /* Same table, after conversion to signed results (same pointer, with different type) */
                    161: static yms16 *ymout5 = (yms16 *)ymout5_u16;
                    162: 
                    163: 
                    164: 
                    165: /*--------------------------------------------------------------*/
                    166: /* Other constants / macros                                    */
                    167: /*--------------------------------------------------------------*/
                    168: 
                    169: /* Number of generated samples per frame (eg. 44Khz=882) */
1.1.1.16! root      170: #define SAMPLES_PER_FRAME  (nAudioFrequency/nScreenRefreshRate)
1.1.1.12  root      171: 
                    172: /* Current sound replay freq (usually 44100 Hz) */
1.1.1.14  root      173: #define YM_REPLAY_FREQ   nAudioFrequency
1.1.1.12  root      174: 
1.1.1.16! root      175: /* YM-2149 clock on all Atari models is 2 MHz */
        !           176: #define YM_ATARI_CLOCK         (MachineClocks.YM_Freq)
1.1.1.12  root      177: 
                    178: 
                    179: /* Merge/read the 3 volumes in a single integer (5 bits per volume) */
                    180: #define        YM_MERGE_VOICE(C,B,A)   ( (C)<<10 | (B)<<5 | A )
                    181: #define        YM_MASK_1VOICE          0x1f
                    182: #define YM_MASK_A              0x1f
                    183: #define YM_MASK_B              (0x1f<<5)
                    184: #define YM_MASK_C              (0x1f<<10)
                    185: 
                    186: 
                    187: /* Constants for YM2149_Normalise_5bit_Table */
                    188: #define        YM_OUTPUT_LEVEL                 0x7fff          /* amplitude of the final signal (0..65535 if centered, 0..32767 if not) */
1.1.1.14  root      189: #define YM_OUTPUT_CENTERED             false
1.1.1.12  root      190: 
                    191: 
                    192: 
                    193: /*--------------------------------------------------------------*/
                    194: /* Variables for the DC adjuster / Low Pass Filter             */
                    195: /*--------------------------------------------------------------*/
                    196: #define DC_ADJUST_BUFFERLEN            512             /* must be a power of 2 */
                    197: 
                    198: static ymsample        dc_buffer[DC_ADJUST_BUFFERLEN];
                    199: static int     dc_pos;
                    200: static int     dc_sum;
                    201: static ymsample        m_lowPassFilter[2];
                    202: 
                    203: 
                    204: 
                    205: /*--------------------------------------------------------------*/
                    206: /* Variables for the YM2149 emulator (need to be saved and     */
                    207: /* restored in memory snapshots)                               */
                    208: /*--------------------------------------------------------------*/
                    209: 
                    210: static ymu32   stepA , stepB , stepC;
                    211: static ymu32   posA , posB , posC;
                    212: static ymu32   mixerTA , mixerTB , mixerTC;
                    213: static ymu32   mixerNA , mixerNB , mixerNC;
                    214: 
                    215: static ymu32   noiseStep;
                    216: static ymu32   noisePos;
                    217: static ymu32   currentNoise;
                    218: static ymu32   RndRack;                                /* current random seed */
                    219: 
                    220: static ymu32   envStep;
                    221: static ymu32   envPos;
                    222: static int     envShape;
                    223: 
                    224: static ymu16   EnvMask3Voices = 0;                     /* mask is 0x1f for voices having an active envelope */
                    225: static ymu16   Vol3Voices = 0;                         /* volume 0-0x1f for voices having a constant volume */
                    226:                                                        /* volume is set to 0 if voice has an envelope in EnvMask3Voices */
                    227: 
                    228: 
                    229: /* Global variables that can be changed/read from other parts of Hatari */
                    230: Uint8          SoundRegs[ 14 ];
                    231: 
1.1.1.16! root      232: int            YmVolumeMixing = YM_TABLE_MIXING;
1.1.1.14  root      233: bool           UseLowPassFilter = false;
1.1.1.12  root      234: 
                    235: bool           bEnvelopeFreqFlag;                      /* Cleared each frame for YM saving */
                    236: 
                    237: Sint16         MixBuffer[MIXBUFFER_SIZE][2];
                    238: int            nGeneratedSamples;                      /* Generated samples since audio buffer update */
                    239: static int     ActiveSndBufIdx;                        /* Current working index into above mix buffer */
1.1.1.16! root      240: static int     ActiveSndBufIdxAvi;                     /* Current working index to save an AVI audio frame */
        !           241: 
        !           242: static yms64   SamplesPerFrame_unrounded = 0;          /* Number of samples for the current VBL, with simulated fractional part */
        !           243: static int     SamplesPerFrame;                        /* Number of samples to generate for the current VBL */
        !           244: static int     CurrentSamplesNb = 0;                   /* Number of samples already generated for the current VBL */
1.1.1.12  root      245: 
1.1.1.16! root      246: bool           Sound_BufferIndexNeedReset = false;
1.1.1.12  root      247: 
                    248: 
                    249: /*--------------------------------------------------------------*/
                    250: /* Local functions prototypes                                  */
                    251: /*--------------------------------------------------------------*/
                    252: 
                    253: static void    DcAdjuster_Reset        (void);
                    254: static void    DcAdjuster_AddSample    (ymsample sample);
                    255: static ymsample        DcAdjuster_GetDcLevel   (void);
                    256: static void    LowPassFilter_Reset     (void);
                    257: static ymsample        LowPassFilter           (ymsample in);
                    258: 
                    259: static int     volumetable_get         (int i, int j, int k);
                    260: static void    volumetable_set         (ymu16 *volumetable, int i, int j, int k, int val);
                    261: static int     volumetable_interpolate (int y1, int y2);
                    262: static void    interpolate_volumetable (ymu16 *out);
                    263: 
                    264: static void    YM2149_BuildLinearVolumeTable(ymu16 *out);
                    265: static void    YM2149_Normalise_5bit_Table(ymu16 *in_5bit , yms16 *out_5bit, unsigned int Level, bool DoCenter);
                    266: 
                    267: static void    YM2149_EnvBuild         (void);
1.1.1.16! root      268: static void    Ym2149_BuildVolumeTable (void);
1.1.1.12  root      269: static void    Ym2149_Init             (void);
                    270: static void    Ym2149_Reset            (void);
                    271: 
                    272: static ymu32   YM2149_RndCompute       (void);
                    273: static ymu32   Ym2149_ToneStepCompute  (ymu8 rHigh , ymu8 rLow);
                    274: static ymu32   Ym2149_NoiseStepCompute (ymu8 rNoise);
                    275: static ymu32   Ym2149_EnvStepCompute   (ymu8 rHigh , ymu8 rLow);
                    276: static ymsample        YM2149_NextSample       (void);
                    277: 
1.1.1.16! root      278: static int     Sound_SetSamplesPassed(bool FillFrame);
        !           279: static void    Sound_GenerateSamples(int SamplesToGenerate);
1.1.1.12  root      280: 
                    281: 
                    282: 
                    283: /*--------------------------------------------------------------*/
                    284: /* DC Adjuster / Low Pass Filter routines.                     */
                    285: /*--------------------------------------------------------------*/
                    286: 
                    287: static void    DcAdjuster_Reset(void)
                    288: {
                    289:        int     i;
1.1.1.14  root      290: 
1.1.1.12  root      291:        for (i=0 ; i<DC_ADJUST_BUFFERLEN ; i++)
                    292:                dc_buffer[i] = 0;
                    293: 
                    294:        dc_pos = 0;
                    295:        dc_sum = 0;
                    296: }
                    297: 
                    298: 
                    299: static void    DcAdjuster_AddSample(ymsample sample)
1.1       root      300: {
1.1.1.12  root      301:        dc_sum -= dc_buffer[dc_pos];
                    302:        dc_sum += sample;
1.1       root      303: 
1.1.1.12  root      304:        dc_buffer[dc_pos] = sample;
                    305:        dc_pos = (dc_pos+1)&(DC_ADJUST_BUFFERLEN-1);
                    306: }
                    307: 
                    308: 
                    309: static ymsample        DcAdjuster_GetDcLevel(void)
                    310: {
                    311:        return dc_sum / DC_ADJUST_BUFFERLEN;
                    312: }
                    313: 
                    314: 
                    315: static void    LowPassFilter_Reset(void)
                    316: {
                    317:        m_lowPassFilter[0] = 0;
                    318:        m_lowPassFilter[1] = 0;
                    319: }
                    320: 
                    321: 
                    322: static ymsample        LowPassFilter(ymsample in)
                    323: {
                    324:        ymsample        out;
                    325:  
                    326:        out = (m_lowPassFilter[0]>>2) + (m_lowPassFilter[1]>>1) + (in>>2);
                    327:        m_lowPassFilter[0] = m_lowPassFilter[1];
                    328:        m_lowPassFilter[1] = in;
                    329:        return out;
                    330: }
                    331: 
                    332: 
                    333: 
                    334: /*--------------------------------------------------------------*/
                    335: /* Build the volume conversion table used to simulate the      */
                    336: /* behaviour of DAC used with the YM2149 in the atari ST.      */
                    337: /* The final 32*32*32 table is built using a 16*16*16 table    */
                    338: /* of all possible fixed volume combinations on a ST.          */
                    339: /*--------------------------------------------------------------*/
                    340: 
                    341: static int     volumetable_get(int i, int j, int k)
                    342: {
                    343:        /* access at boundary finds the last value instead of the first */
                    344:        if (i == 16)
                    345:                i = 15;
                    346:        if (j == 16)
                    347:                j = 15;
                    348:        if (k == 16)
                    349:                k = 15;
1.1.1.14  root      350: 
1.1.1.12  root      351:        return volumetable_original[i + 16 * j + 16 * 16 * k];
                    352: }
                    353: 
                    354: static void    volumetable_set(ymu16 *volumetable, int i, int j, int k, int val)
                    355: {
                    356:        volumetable[i + 32 * j + 32 * 32 * k] = val;
                    357: }
                    358: 
                    359: /* the table is exponential in nature. These weighing factors approximate
                    360:  * that the value in-between needs to be closer to the lower value in y2 */
                    361: static int     volumetable_interpolate(int y1, int y2)
                    362: {
                    363:        int erpolate;
                    364:        erpolate = (y1 * 4 + y2 * 6) / 10u;
                    365:        if (erpolate > 65535)
1.1.1.11  root      366:        {
1.1.1.12  root      367: //             fprintf ( stderr , "sature>:%d %d %d\n",erpolate,y1,y2 );
                    368:                erpolate = 65535;
1.1.1.11  root      369:        }
1.1.1.12  root      370:        if (erpolate < 0)
                    371:        {
                    372: //             fprintf ( stderr , "sature<:%d %d %d\n",erpolate,y1,y2 );
                    373:                erpolate = 0;
                    374:        }
                    375:        return erpolate;
                    376: }
1.1.1.11  root      377: 
1.1.1.12  root      378: static void    interpolate_volumetable(ymu16 *out)
                    379: {
                    380:        int i, j, k;
                    381:        int i1, i2;
                    382: 
                    383:        /* we are doing 4-dimensional interpolation here. For each
                    384:        * known measurement point, we must find 8 new values. These values occur
                    385:        * as follows:
                    386:        *
                    387:        * - one at the exact same position
                    388:        * - one half-way in i direction
                    389:        * - one half-way in j direction
                    390:        * - one half-way in k direction
                    391:        * - one half-way in i+j direction
                    392:        * - one half-way in i+k direction
                    393:        * - one half-way in j+k direction
                    394:        * - one half-way in i+j+k direction
                    395:        *
                    396:        * The algorithm currently is very simplistic. Probably more points should be
                    397:        * weighted in the multicomponented directions, for instance i+j+k should be
                    398:        * an average of all surrounding data points. This probably doesn't matter much,
                    399:        * though. This is because the only way to reach those locations is to modulate
                    400:        * more than one voice with the envelope, and this is rare.
                    401:        */
                    402: 
                    403:        for (i = 0; i < 16; i++)
1.1.1.11  root      404:        {
1.1.1.12  root      405:                for (j = 0; j < 16; j++)
                    406:                {
                    407:                        for (k = 0; k < 16; k++)
                    408:                        {
                    409:                                i1 = volumetable_get(i, j, k);
                    410:                                /* copy value unchanged to new position */
                    411:                                volumetable_set(out,i*2, j*2, k*2, i1);
1.1.1.14  root      412:  
1.1.1.12  root      413:                                /* interpolate in i direction */
                    414:                                i2 = volumetable_get(i + 1, j, k);
                    415:                                volumetable_set(out,i*2 + 1, j*2, k*2, volumetable_interpolate(i1, i2));
1.1.1.14  root      416: 
1.1.1.12  root      417:                                /* interpolate in j direction */
                    418:                                i2 = volumetable_get(i, j+1, k);
                    419:                                volumetable_set(out,i*2, j*2 + 1, k*2, volumetable_interpolate(i1, i2));
1.1.1.14  root      420: 
1.1.1.12  root      421:                                /* interpolate in k direction */
                    422:                                i2 = volumetable_get(i, j, k+1);
                    423:                                volumetable_set(out,i*2, j*2, k*2+1, volumetable_interpolate(i1, i2));
                    424: 
                    425:                                /* interpolate in i + j direction */
                    426:                                i2 = volumetable_get(i + 1, j + 1, k);
                    427:                                volumetable_set(out,i*2 + 1, j*2 + 1, k*2, volumetable_interpolate(i1, i2));
1.1.1.14  root      428: 
1.1.1.12  root      429:                                /* interpolate in i + k direction */
                    430:                                i2 = volumetable_get(i + 1, j, k + 1);
                    431:                                volumetable_set(out,i*2 + 1, j*2, k*2 + 1, volumetable_interpolate(i1, i2));
1.1.1.14  root      432: 
1.1.1.12  root      433:                                /* interpolate in j + k direction */
                    434:                                i2 = volumetable_get(i, j + 1, k + 1);
                    435:                                volumetable_set(out,i*2, j*2 + 1, k*2 + 1, volumetable_interpolate(i1, i2));
                    436: 
                    437:                                /* interpolate in i + j + k direction */
                    438:                                i2 = volumetable_get(i + 1, j + 1, k + 1);
                    439:                                volumetable_set(out,i*2 + 1, j*2 + 1, k*2 + 1, volumetable_interpolate(i1, i2));
                    440:                        }
                    441:                }
1.1.1.11  root      442:        }
1.1       root      443: }
                    444: 
1.1.1.5   root      445: 
1.1.1.12  root      446: 
                    447: 
1.1.1.2   root      448: /*-----------------------------------------------------------------------*/
1.1.1.11  root      449: /**
1.1.1.12  root      450:  * Build a linear version of the conversion table.
                    451:  * We use the mean of the 3 volumes converted to 16 bit values
                    452:  * (each value of ymout1c5bit is in [0,65535])
1.1.1.11  root      453:  */
1.1.1.12  root      454: 
                    455: static void    YM2149_BuildLinearVolumeTable(ymu16 *out)
1.1       root      456: {
1.1.1.12  root      457:        int     i, j, k;
                    458:        int     res;
                    459: 
                    460:        for (i = 0; i < 32; i++)
                    461:                for (j = 0; j < 32; j++)
                    462:                        for (k = 0; k < 32; k++)
                    463:                        {
                    464:                                res = ( ymout1c5bit[ i ] + ymout1c5bit[ j ] + ymout1c5bit[ k ] ) / 3;
                    465:                                volumetable_set ( out, i, j, k, res );
                    466:                        }
                    467: }
                    468: 
                    469: 
                    470: 
1.1       root      471: 
1.1.1.12  root      472: /*-----------------------------------------------------------------------*/
                    473: /**
                    474:  * Normalise and optionally center the volume table used to
                    475:  * convert the 3 volumes to a final signed 16 bit sample.
                    476:  * This allows to adapt the amplitude/volume of the samples and
                    477:  * to convert unsigned values to signed values.
                    478:  * - in_5bit contains 32*32*32 unsigned values in the range
                    479:  *     [0,65535].
                    480:  * - out_5bit will contain signed values
                    481:  * Possible values are :
                    482:  *     Level=65535 and DoCenter=TRUE -> [-32768,32767]
1.1.1.14  root      483:  *     Level=32767 and DoCenter=false -> [0,32767]
1.1.1.12  root      484:  */
                    485: 
                    486: static void    YM2149_Normalise_5bit_Table(ymu16 *in_5bit , yms16 *out_5bit, unsigned int Level, bool DoCenter)
                    487: {
                    488:        if ( Level )
1.1.1.11  root      489:        {
1.1.1.14  root      490:                int h;
1.1.1.12  root      491:                int Max = in_5bit[0x7fff];
                    492:                int Center = Level>>1;
1.1.1.14  root      493:                //fprintf ( stderr , "level %d max %d center %d\n" , Level, Max, Center );
                    494: 
1.1.1.12  root      495:                /* Change the amplitude of the signal to 'level' : [0,max] -> [0,level] */
                    496:                /* Then optionally center the signal around Level/2 */
                    497:                /* This means we go from sthg like [0,65535] to [-32768, 32767] if Level=65535 and DoCenter=TRUE */
                    498:                for (h=0; h<32*32*32; h++)
                    499:                {
                    500:                        int tmp = in_5bit[h], res;
                    501:                        res = tmp * Level / Max;
1.1.1.14  root      502: 
1.1.1.12  root      503:                        if ( DoCenter )
                    504:                                res -= Center;
                    505: 
                    506:                        out_5bit[h] = res;
1.1.1.14  root      507:                        //fprintf ( stderr , "h %d in %d out %d\n" , h , tmp , res );
1.1.1.12  root      508:                }
1.1.1.11  root      509:        }
1.1       root      510: }
                    511: 
1.1.1.5   root      512: 
1.1.1.12  root      513: 
                    514: 
1.1.1.2   root      515: /*-----------------------------------------------------------------------*/
1.1.1.11  root      516: /**
1.1.1.12  root      517:  * Precompute all 16 possible envelopes.
                    518:  * Each envelope is made of 3 blocks of 32 volumes.
1.1.1.11  root      519:  */
1.1.1.12  root      520: 
                    521: static void    YM2149_EnvBuild ( void )
1.1       root      522: {
1.1.1.12  root      523:        int     env;
                    524:        int     block;
                    525:        int     vol=0 , inc=0;
                    526:        int     i;
1.1       root      527: 
1.1.1.12  root      528: 
                    529:        for ( env=0 ; env<16 ; env++ )                          /* 16 possible envelopes */
                    530:                for ( block=0 ; block<3 ; block++ )             /* 3 blocks to define an envelope */
                    531:                {
1.1.1.14  root      532:                        switch ( YmEnvDef[ env ][ block ] )
                    533:                        {
1.1.1.12  root      534:                                case ENV_GODOWN :       vol=31 ; inc=-1 ; break;
                    535:                                case ENV_GOUP :         vol=0  ; inc=1 ; break;
                    536:                                case ENV_DOWN :         vol=0  ; inc=0 ; break;
                    537:                                case ENV_UP :           vol=31 ; inc=0 ; break;
1.1.1.14  root      538:                        }
                    539: 
1.1.1.12  root      540:                        for ( i=0 ; i<32 ; i++ )                /* 32 volumes per block */
                    541:                        {
                    542:                                YmEnvWaves[ env ][ block*32 + i ] = YM_MERGE_VOICE ( vol , vol , vol );
                    543:                                vol += inc;
                    544:                        }
                    545:                }
                    546: }
                    547: 
                    548: 
                    549: 
                    550: /*-----------------------------------------------------------------------*/
                    551: /**
1.1.1.16! root      552:  * Depending on the YM mixing method, build the table used to convert
        !           553:  * the 3 YM volumes into a single sample.
1.1.1.12  root      554:  */
                    555: 
1.1.1.16! root      556: static void    Ym2149_BuildVolumeTable(void)
1.1.1.12  root      557: {
                    558:        /* Depending on the volume mixing method, we use a table based on real measures */
                    559:        /* or a table based on a linear volume mixing. */
                    560:        if ( YmVolumeMixing == YM_TABLE_MIXING )
1.1.1.16! root      561:                interpolate_volumetable(ymout5_u16);            /* expand the 16*16*16 values in volumetable_original to 32*32*32 */
1.1.1.12  root      562:        else
                    563:                YM2149_BuildLinearVolumeTable(ymout5_u16);      /* combine the 32 possible volumes */
                    564: 
                    565:        /* Normalise/center the values (convert from u16 to s16) */
                    566:        YM2149_Normalise_5bit_Table ( ymout5_u16 , ymout5 , YM_OUTPUT_LEVEL , YM_OUTPUT_CENTERED );
1.1.1.16! root      567: }
        !           568: 
        !           569: 
        !           570: 
        !           571: /*-----------------------------------------------------------------------*/
        !           572: /**
        !           573:  * Init some internal tables for faster results (env, volume)
        !           574:  * and reset the internal states.
        !           575:  */
        !           576: 
        !           577: static void    Ym2149_Init(void)
        !           578: {
        !           579:        /* Build the 16 envelope shapes */
        !           580:        YM2149_EnvBuild();
        !           581: 
        !           582:        /* Build the volume conversion table */
        !           583:        Ym2149_BuildVolumeTable();
1.1.1.12  root      584: 
                    585:        /* Reset YM2149 internal states */
                    586:        Ym2149_Reset();
                    587: }
                    588: 
                    589: 
                    590: 
                    591: /*-----------------------------------------------------------------------*/
                    592: /**
1.1.1.16! root      593:  * Reset all ym registers as well as the internal variables
1.1.1.12  root      594:  */
                    595: 
                    596: static void    Ym2149_Reset(void)
                    597: {
                    598:        int     i;
1.1.1.14  root      599: 
1.1.1.12  root      600:        for ( i=0 ; i<14 ; i++ )
                    601:                Sound_WriteReg ( i , 0 );
                    602: 
                    603:        Sound_WriteReg ( 7 , 0xff );
                    604: 
1.1.1.16! root      605:        posA = 0;
        !           606:        posB = 0;
        !           607:        posC = 0;
        !           608: 
1.1.1.12  root      609:        currentNoise = 0xffff;
1.1.1.14  root      610: 
1.1.1.12  root      611:        RndRack = 1;
1.1.1.14  root      612: 
1.1.1.12  root      613:        envShape = 0;
                    614:        envPos = 0;
                    615: 
                    616:        DcAdjuster_Reset ();
                    617:        LowPassFilter_Reset ();
                    618: }
                    619: 
                    620: 
                    621: 
                    622: /*-----------------------------------------------------------------------*/
                    623: /**
                    624:  * Returns a pseudo random value, used to generate white noise.
                    625:  */
                    626: 
                    627: static ymu32   YM2149_RndCompute(void)
                    628: {
                    629:        ymu32   bit;
1.1.1.14  root      630: 
1.1.1.12  root      631:        bit = (RndRack&1) ^ ((RndRack>>2)&1);
                    632:        RndRack = (RndRack>>1) | (bit<<16);
                    633:        return (bit ? 0 : 0xffff);
                    634: }
                    635: 
                    636: 
                    637: 
                    638: /*-----------------------------------------------------------------------*/
                    639: /**
1.1.1.16! root      640:  * Compute tone's step based on the input period.
        !           641:  * Although for tone we should have the same result when per==0 and per==1,
        !           642:  * this gives some very sharp and unpleasant sounds in the emulation.
        !           643:  * To get a better sound, we consider all per<=5 to give step=0, which will
        !           644:  * produce a constant output at value '1'. This should be handled with some
        !           645:  * proper filters to remove high frequencies as on a real ST (where per<=9
        !           646:  * gives nearly no audible sound).
        !           647:  * A common replay freq of 44.1 kHz will also not be high enough to correctly
        !           648:  * render possible tone's freq of 125 or 62.5 kHz (when per==1 or per==2)
1.1.1.12  root      649:  */
                    650: 
1.1.1.16! root      651: #define NEWSTEP
        !           652: #ifndef NEWSTEP
1.1.1.12  root      653: static ymu32   Ym2149_ToneStepCompute(ymu8 rHigh , ymu8 rLow)
                    654: {
                    655:        int     per;
1.1.1.14  root      656:        yms64   step;
1.1.1.12  root      657: 
                    658:        per = rHigh&15;
                    659:        per = (per<<8)+rLow;
1.1.1.14  root      660:        if (per <= 5)
1.1.1.12  root      661:                return 0;
                    662: 
1.1.1.14  root      663:        step = YM_ATARI_CLOCK;
1.1.1.12  root      664:        step <<= (15+16-3);
                    665:        step /= (per * YM_REPLAY_FREQ);
                    666: 
                    667:        return step;
                    668: }
1.1.1.16! root      669: #else
        !           670: static ymu32   Ym2149_ToneStepCompute(ymu8 rHigh , ymu8 rLow)
        !           671: {
        !           672:        int     per;
        !           673:        yms64   step;
        !           674: 
        !           675:        per = rHigh&15;
        !           676:        per = (per<<8)+rLow;
        !           677: 
        !           678: #if 0                                                  /* need some high freq filters for this to work correctly */
        !           679:        if ( per == 0 )
        !           680:                per = 1;                                /* result for Per=0 is the same as for Per=1 */ 
        !           681: #else
        !           682:        if ( per <= 5 )
        !           683:                return 0;                               /* discard too high frequencies, they give a very bad sound */  
        !           684: #endif
        !           685: 
        !           686:        step = YM_ATARI_CLOCK;
        !           687:        step <<= 24;
        !           688: 
        !           689:        step /= (per * 8 * YM_REPLAY_FREQ);             /* 0x5ab9 < step < 0x5ab3f46 at 44.1 kHz */
        !           690: 
        !           691:        return step;
        !           692: }
        !           693: #endif
1.1.1.12  root      694: 
1.1.1.16! root      695: /*-----------------------------------------------------------------------*/
        !           696: /**
        !           697:  * Compute noise's step based on the input period.
        !           698:  * On a real STF, we get the same result when per==0 and per==1.
        !           699:  * A common replay freq of 44.1 kHz will not be high enough to correctly
        !           700:  * render possible noise's freq of 125 or 62.5 kHz (when per==1 or per==2).
        !           701:  * With a random wave such as noise, this means that with a replay freq
        !           702:  * of 44.1 kHz, per==1 and per==2 (as well as per==3) will sound the same :
        !           703:  *     per==1   step=0x2d59fa3   freq=125 kHz
        !           704:  *     per==2   step=0x16acfd1   freq=62.5 kHz
        !           705:  *     per==3   step=0x0f1dfe1   freq=41.7 kHz
        !           706:  */
1.1.1.12  root      707: 
1.1.1.16! root      708: #ifndef NEWSTEP
1.1.1.12  root      709: static ymu32   Ym2149_NoiseStepCompute(ymu8 rNoise)
                    710: {
                    711:        int     per;
1.1.1.14  root      712:        yms64   step;
1.1.1.12  root      713: 
                    714:        per = (rNoise&0x1f);
                    715:        if (per<3)
                    716:                return 0;
                    717: 
1.1.1.14  root      718:        step = YM_ATARI_CLOCK;
1.1.1.12  root      719:        step <<= (16-1-3);
                    720:        step /= (per * YM_REPLAY_FREQ);
                    721: 
                    722:        return step;
1.1       root      723: }
1.1.1.16! root      724: #else
        !           725: static ymu32   Ym2149_NoiseStepCompute(ymu8 rNoise)
        !           726: {
        !           727:        int     per;
        !           728:        yms64   step;
        !           729: 
        !           730:        per = (rNoise&0x1f);
1.1       root      731: 
1.1.1.16! root      732:        if ( per == 0 )
        !           733:                per = 1;                                /* result for Per=0 is the same as for Per=1 */ 
        !           734: 
        !           735:        step = YM_ATARI_CLOCK;
        !           736:        step <<= 24;
        !           737: 
        !           738:        step /= (per * 16 * YM_REPLAY_FREQ);            /* 0x17683f < step < 0x2d59fa3 at 44.1 kHz */
        !           739: 
        !           740:        return step;
        !           741: }
        !           742: #endif
1.1.1.5   root      743: 
1.1.1.2   root      744: /*-----------------------------------------------------------------------*/
1.1.1.11  root      745: /**
1.1.1.12  root      746:  * Compute envelope's step. The envelope is made of different patterns
                    747:  * of 32 volumes. In each pattern, the volume is changed at frequency
                    748:  * Fe = MasterClock / ( 8 * EnvPer ).
                    749:  * In our case, we use a lower replay freq ; between 2 consecutive calls
                    750:  * to envelope's generation, the internal counter will advance 'step'
                    751:  * units, where step = MasterClock / ( 8 * EnvPer * YM_REPLAY_FREQ )
                    752:  * As 'step' requires floating point to be stored, we use left shifting
                    753:  * to multiply 'step' by a fixed amount. All operations are made with
                    754:  * shifted values ; to get the final value, we must right shift the
                    755:  * result. We use '<<24', which gives 8 bits for the integer part, and
                    756:  * the equivalent of 24 bits for the fractional part.
                    757:  * Since we're using large numbers, we temporarily use 64 bits integer
                    758:  * to avoid overflow and keep largest precision possible.
1.1.1.16! root      759:  * On a real STF, we get the same result when per==0 and per==1.
1.1.1.11  root      760:  */
1.1.1.12  root      761: 
                    762: static ymu32   Ym2149_EnvStepCompute(ymu8 rHigh , ymu8 rLow)
1.1       root      763: {
1.1.1.12  root      764:        yms64   per;
1.1.1.14  root      765:        yms64   step;
1.1       root      766: 
1.1.1.12  root      767:        per = rHigh;
                    768:        per = (per<<8)+rLow;
                    769: 
1.1.1.14  root      770:        step = YM_ATARI_CLOCK;
1.1.1.12  root      771:        step <<= 24;
1.1.1.16! root      772: 
        !           773:        if ( per == 0 )
        !           774:                per = 1;                                /* result for Per=0 is the same as for Per=1 */ 
        !           775: 
        !           776:        step /= (8 * per * YM_REPLAY_FREQ);             /* 0x5ab < step < 0x5ab3f46 at 44.1 kHz */
1.1.1.12  root      777: 
                    778:        return step;
                    779: }
                    780: 
                    781: 
                    782: 
                    783: /*-----------------------------------------------------------------------*/
                    784: /**
                    785:  * Main function : compute the value of the next sample.
                    786:  * Mixes all 3 voices with tone+noise+env and apply low pass
                    787:  * filter if needed.
1.1.1.16! root      788:  * All operations are done with integer math, using <<24 to simulate
        !           789:  * floating point precision : upper 8 bits are the integer part, lower 24
        !           790:  * are the fractional part.
        !           791:  * Tone is a square wave with 2 states 0 or 1. If integer part of posX is
        !           792:  * even (bit24=0) we consider output is 0, else (bit24=1) we consider
        !           793:  * output is 1. This gives the value of bt for one voice after extending it
        !           794:  * to all 0 bits or all 1 bits using a '-'
1.1.1.12  root      795:  */
                    796: 
1.1.1.16! root      797: #ifndef NEWSTEP
1.1.1.12  root      798: static ymsample        YM2149_NextSample(void)
                    799: {
                    800:        ymsample        sample;
                    801:        int             bt;
                    802:        ymu32           bn;
                    803:        ymu16           Env3Voices;
                    804:        ymu16           Tone3Voices;
                    805: 
                    806: 
                    807:        /* Noise value : 0 or 0xffff */
                    808:        if ( noisePos&0xffff0000 )
                    809:        {
                    810:                currentNoise ^= YM2149_RndCompute();
                    811:                noisePos &= 0xffff;
                    812:        }
                    813:        bn = currentNoise;                              /* 0 or 0xffff */
                    814: 
                    815:        /* Get the 5 bits volume corresponding to the current envelope's position */
                    816:        Env3Voices = YmEnvWaves[ envShape ][ envPos>>24 ];      /* integer part of envPos is in bits 24-31 */
                    817:        Env3Voices &= EnvMask3Voices;                   /* only keep volumes for voices using envelope */
                    818: 
                    819: //fprintf ( stderr , "env %x %x %x\n" , Env3Voices , envStep , envPos );
                    820: 
                    821:        /* Tone3Voices will contain the output state of each voice : 0 or 0x1f */
                    822:        bt = ((((yms32)posA)>>31) | mixerTA) & (bn | mixerNA);  /* 0 or 0xffff */
                    823:        Tone3Voices = bt & YM_MASK_1VOICE;                      /* 0 or 0x1f */
                    824:        bt = ((((yms32)posB)>>31) | mixerTB) & (bn | mixerNB);
                    825:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 5;
                    826:        bt = ((((yms32)posC)>>31) | mixerTC) & (bn | mixerNC);
                    827:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 10;
                    828: 
                    829:        /* Combine fixed volumes and envelope volumes and keep the resulting */
                    830:        /* volumes depending on the output state of each voice (0 or 0x1f) */
                    831:        Tone3Voices &= ( Env3Voices | Vol3Voices );
                    832: 
                    833:        /* D/A conversion of the 3 volumes into a sample using a precomputed conversion table */
                    834:        sample = ymout5[ Tone3Voices ];                 /* 16 bits signed value */
                    835: 
                    836: 
                    837:        /* Increment positions */
                    838:        posA += stepA;
                    839:        posB += stepB;
                    840:        posC += stepC;
                    841:        noisePos += noiseStep;
1.1.1.14  root      842: 
1.1.1.12  root      843:        envPos += envStep;
                    844:        if ( envPos >= (3*32) << 24 )                   /* blocks 0, 1 and 2 were used (envPos 0 to 95) */
                    845:                envPos -= (2*32) << 24;                 /* replay/loop blocks 1 and 2 (envPos 32 to 95) */
                    846: 
1.1.1.14  root      847:        DcAdjuster_AddSample(sample);                   /* Calculate DC level */
                    848:        sample = sample - DcAdjuster_GetDcLevel();      /* normalize sound level */
1.1.1.12  root      849: 
                    850:        /* Apply low pass filter ? */
                    851:        if ( UseLowPassFilter )
1.1.1.11  root      852:        {
1.1.1.14  root      853:                sample = LowPassFilter(sample);
1.1.1.11  root      854:        }
1.1.1.12  root      855: 
                    856:        return sample;
1.1       root      857: }
1.1.1.16! root      858: #else
        !           859: static ymsample        YM2149_NextSample(void)
        !           860: {
        !           861:        ymsample        sample;
        !           862:        ymu32           bt;
        !           863:        ymu32           bn;
        !           864:        ymu16           Env3Voices;                     /* 0x00CCBBAA */
        !           865:        ymu16           Tone3Voices;                    /* 0x00CCBBAA */
1.1       root      866: 
                    867: 
1.1.1.16! root      868:        /* Noise value : 0 or 0xffff */
        !           869:        if ( noisePos&0xff000000 )                      /* integer part > 0 */
        !           870:        {
        !           871:                currentNoise ^= YM2149_RndCompute();
        !           872:                noisePos &= 0xffffff;                   /* keep fractional part of noisePos */
        !           873:        }
        !           874:        bn = currentNoise;                              /* 0 or 0xffff */
        !           875: 
        !           876:        /* Get the 5 bits volume corresponding to the current envelope's position */
        !           877:        Env3Voices = YmEnvWaves[ envShape ][ envPos>>24 ];      /* integer part of envPos is in bits 24-31 */
        !           878:        Env3Voices &= EnvMask3Voices;                   /* only keep volumes for voices using envelope */
        !           879: 
        !           880: //fprintf ( stderr , "env %x %x %x\n" , Env3Voices , envStep , envPos );
        !           881: 
        !           882:        /* Tone3Voices will contain the output state of each voice : 0 or 0x1f */
        !           883:        bt = -( (posA>>24) & 1);                        /* 0 if bit24=0 or 0xffffffff if bit24=1 */
        !           884:        bt = (bt | mixerTA) & (bn | mixerNA);           /* 0 or 0xffff */
        !           885:        Tone3Voices = bt & YM_MASK_1VOICE;              /* 0 or 0x1f */
        !           886:        bt = -( (posB>>24) & 1);
        !           887:        bt = (bt | mixerTB) & (bn | mixerNB);
        !           888:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 5;
        !           889:        bt = -( (posC>>24) & 1);
        !           890:        bt = (bt | mixerTC) & (bn | mixerNC);
        !           891:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 10;
        !           892: 
        !           893:        /* Combine fixed volumes and envelope volumes and keep the resulting */
        !           894:        /* volumes depending on the output state of each voice (0 or 0x1f) */
        !           895:        Tone3Voices &= ( Env3Voices | Vol3Voices );
        !           896: 
        !           897:        /* D/A conversion of the 3 volumes into a sample using a precomputed conversion table */
        !           898:        sample = ymout5[ Tone3Voices ];                 /* 16 bits signed value */
        !           899: 
        !           900: 
        !           901:        /* Increment positions */
        !           902:        posA += stepA;
        !           903:        posB += stepB;
        !           904:        posC += stepC;
        !           905:        noisePos += noiseStep;
        !           906: 
        !           907:        envPos += envStep;
        !           908:        if ( envPos >= (3*32) << 24 )                   /* blocks 0, 1 and 2 were used (envPos 0 to 95) */
        !           909:                envPos -= (2*32) << 24;                 /* replay/loop blocks 1 and 2 (envPos 32 to 95) */
        !           910: 
        !           911:        DcAdjuster_AddSample(sample);                   /* Calculate DC level */
        !           912:        sample = sample - DcAdjuster_GetDcLevel();      /* normalize sound level */
        !           913: 
        !           914:        /* Apply low pass filter ? */
        !           915:        if ( UseLowPassFilter )
        !           916:        {
        !           917:                sample = LowPassFilter(sample);
        !           918:        }
        !           919: 
        !           920:        return sample;
        !           921: }
        !           922: #endif
        !           923: 
1.1.1.12  root      924: 
1.1.1.2   root      925: /*-----------------------------------------------------------------------*/
1.1.1.11  root      926: /**
1.1.1.12  root      927:  * Update internal variables (steps, volume masks, ...) each
                    928:  * time an YM register is changed.
1.1.1.11  root      929:  */
1.1.1.16! root      930: #ifndef NEWSTEP
        !           931: #define BIT_SHIFT 31
        !           932: #else
        !           933: #define BIT_SHIFT 24
        !           934: #endif
1.1.1.12  root      935: void   Sound_WriteReg( int reg , Uint8 data )
1.1.1.7   root      936: {
1.1.1.12  root      937:        switch (reg)
                    938:        {
                    939:                case 0:
                    940:                        SoundRegs[0] = data;
                    941:                        stepA = Ym2149_ToneStepCompute ( SoundRegs[1] , SoundRegs[0] );
1.1.1.16! root      942:                        if (!stepA) posA = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root      943:                        break;
                    944: 
                    945:                case 1:
                    946:                        SoundRegs[1] = data & 0x0f;
                    947:                        stepA = Ym2149_ToneStepCompute ( SoundRegs[1] , SoundRegs[0] );
1.1.1.16! root      948:                        if (!stepA) posA = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root      949:                        break;
                    950: 
                    951:                case 2:
                    952:                        SoundRegs[2] = data;
                    953:                        stepB = Ym2149_ToneStepCompute ( SoundRegs[3] , SoundRegs[2] );
1.1.1.16! root      954:                        if (!stepB) posB = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root      955:                        break;
1.1.1.7   root      956: 
1.1.1.12  root      957:                case 3:
                    958:                        SoundRegs[3] = data & 0x0f;
                    959:                        stepB = Ym2149_ToneStepCompute ( SoundRegs[3] , SoundRegs[2] );
1.1.1.16! root      960:                        if (!stepB) posB = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root      961:                        break;
                    962: 
                    963:                case 4:
                    964:                        SoundRegs[4] = data;
                    965:                        stepC = Ym2149_ToneStepCompute ( SoundRegs[5] , SoundRegs[4] );
1.1.1.16! root      966:                        if (!stepC) posC = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root      967:                        break;
                    968: 
                    969:                case 5:
                    970:                        SoundRegs[5] = data & 0x0f;
                    971:                        stepC = Ym2149_ToneStepCompute ( SoundRegs[5] , SoundRegs[4] );
1.1.1.16! root      972:                        if (!stepC) posC = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.12  root      973:                        break;
                    974: 
                    975:                case 6:
                    976:                        SoundRegs[6] = data & 0x1f;
                    977:                        noiseStep = Ym2149_NoiseStepCompute ( SoundRegs[6] );
                    978:                        if (!noiseStep)
                    979:                        {
                    980:                                noisePos = 0;
                    981:                                currentNoise = 0xffff;
                    982:                        }
                    983:                        break;
                    984: 
                    985:                case 7:
                    986:                        SoundRegs[7] = data & 0x3f;                     /* ignore bits 6 and 7 */
                    987:                        mixerTA = (data&(1<<0)) ? 0xffff : 0;
                    988:                        mixerTB = (data&(1<<1)) ? 0xffff : 0;
                    989:                        mixerTC = (data&(1<<2)) ? 0xffff : 0;
                    990:                        mixerNA = (data&(1<<3)) ? 0xffff : 0;
                    991:                        mixerNB = (data&(1<<4)) ? 0xffff : 0;
                    992:                        mixerNC = (data&(1<<5)) ? 0xffff : 0;
                    993:                        break;
                    994: 
                    995:                case 8:
                    996:                        SoundRegs[8] = data & 0x1f;
                    997:                        if ( data & 0x10 )
                    998:                        {
                    999:                                EnvMask3Voices |= YM_MASK_A;            /* env ON */
                   1000:                                Vol3Voices &= ~YM_MASK_A;               /* fixed vol OFF */
                   1001:                        }
                   1002:                        else
                   1003:                        {
                   1004:                                EnvMask3Voices &= ~YM_MASK_A;           /* env OFF */
                   1005:                                Vol3Voices &= ~YM_MASK_A;               /* clear previous vol */
                   1006:                                Vol3Voices |= YmVolume4to5[ SoundRegs[8] ];     /* fixed vol ON */
                   1007:                        }
                   1008:                        break;
1.1.1.14  root     1009: 
1.1.1.12  root     1010:                case 9:
                   1011:                        SoundRegs[9] = data & 0x1f;
                   1012:                        if ( data & 0x10 )
                   1013:                        {
                   1014:                                EnvMask3Voices |= YM_MASK_B;            /* env ON */
                   1015:                                Vol3Voices &= ~YM_MASK_B;               /* fixed vol OFF */
                   1016:                        }
                   1017:                        else
                   1018:                        {
                   1019:                                EnvMask3Voices &= ~YM_MASK_B;           /* env OFF */
                   1020:                                Vol3Voices &= ~YM_MASK_B;               /* clear previous vol */
                   1021:                                Vol3Voices |= ( YmVolume4to5[ SoundRegs[9] ] ) << 5;    /* fixed vol ON */
                   1022:                        }
                   1023:                        break;
1.1.1.14  root     1024: 
1.1.1.12  root     1025:                case 10:
                   1026:                        SoundRegs[10] = data & 0x1f;
                   1027:                        if ( data & 0x10 )
                   1028:                        {
                   1029:                                EnvMask3Voices |= YM_MASK_C;            /* env ON */
                   1030:                                Vol3Voices &= ~YM_MASK_C;               /* fixed vol OFF */
                   1031:                        }
                   1032:                        else
                   1033:                        {
                   1034:                                EnvMask3Voices &= ~YM_MASK_C;           /* env OFF */
                   1035:                                Vol3Voices &= ~YM_MASK_C;               /* clear previous vol */
                   1036:                                Vol3Voices |= ( YmVolume4to5[ SoundRegs[10] ] ) << 10;  /* fixed vol ON */
                   1037:                        }
                   1038:                        break;
                   1039: 
                   1040:                case 11:
                   1041:                        SoundRegs[11] = data;
                   1042:                        envStep = Ym2149_EnvStepCompute ( SoundRegs[12] , SoundRegs[11] );
                   1043:                        break;
                   1044: 
                   1045:                case 12:
                   1046:                        SoundRegs[12] = data;
                   1047:                        envStep = Ym2149_EnvStepCompute ( SoundRegs[12] , SoundRegs[11] );
                   1048:                        break;
                   1049: 
                   1050:                case 13:
                   1051:                        SoundRegs[13] = data & 0xf;
                   1052:                        envPos = 0;                                     /* when writing to EnvShape, we must reset the EnvPos */
                   1053:                        envShape = SoundRegs[13];
1.1.1.14  root     1054:                        bEnvelopeFreqFlag = true;                       /* used for YmFormat saving */
1.1.1.12  root     1055:                        break;
                   1056: 
                   1057:        }
                   1058: }
                   1059: 
                   1060: 
                   1061: 
                   1062: /*-----------------------------------------------------------------------*/
                   1063: /**
                   1064:  * Init random generator, sound tables and envelopes
                   1065:  * (called only once when Hatari starts)
                   1066:  */
                   1067: void Sound_Init(void)
                   1068: {
                   1069:        /* Build volume/env tables, ... */
                   1070:        Ym2149_Init();
1.1.1.14  root     1071: 
1.1.1.11  root     1072:        Sound_Reset();
1.1.1.7   root     1073: }
                   1074: 
                   1075: 
                   1076: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1077: /**
1.1.1.12  root     1078:  * Reset the sound emulation (called from Reset_ST() in reset.c)
1.1.1.11  root     1079:  */
1.1.1.7   root     1080: void Sound_Reset(void)
                   1081: {
1.1.1.11  root     1082:        /* Lock audio system before accessing variables which are used by the
                   1083:         * callback function, too! */
                   1084:        Audio_Lock();
1.1.1.9   root     1085: 
1.1.1.11  root     1086:        /* Clear sound mixing buffer: */
1.1.1.12  root     1087:        memset(MixBuffer, 0, sizeof(MixBuffer));
1.1.1.7   root     1088: 
1.1.1.11  root     1089:        /* Clear cycle counts, buffer index and register '13' flags */
                   1090:        Cycles_SetCounter(CYCLES_COUNTER_SOUND, 0);
1.1.1.14  root     1091:        bEnvelopeFreqFlag = false;
                   1092: 
1.1.1.11  root     1093:        CompleteSndBufIdx = 0;
                   1094:        /* We do not start with 0 here to fake some initial samples: */
                   1095:        nGeneratedSamples = SoundBufferSize + SAMPLES_PER_FRAME;
                   1096:        ActiveSndBufIdx = nGeneratedSamples % MIXBUFFER_SIZE;
1.1.1.16! root     1097:        SamplesPerFrame = SAMPLES_PER_FRAME;
        !          1098:        CurrentSamplesNb = 0;
        !          1099:        ActiveSndBufIdxAvi = ActiveSndBufIdx;
1.1.1.15  root     1100: //fprintf ( stderr , "Sound_Reset SoundBufferSize %d SAMPLES_PER_FRAME %d nGeneratedSamples %d , ActiveSndBufIdx %d\n" ,
                   1101: //     SoundBufferSize , SAMPLES_PER_FRAME, nGeneratedSamples , ActiveSndBufIdx );
1.1.1.7   root     1102: 
1.1.1.12  root     1103:        Ym2149_Reset();
1.1.1.9   root     1104: 
1.1.1.11  root     1105:        Audio_Unlock();
1.1.1.7   root     1106: }
                   1107: 
                   1108: 
                   1109: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1110: /**
                   1111:  * Reset the sound buffer index variables.
1.1.1.16! root     1112:  * Very important : this function should only be called by setting
        !          1113:  * Sound_BufferIndexNeedReset=true ; sound buffer index should be reset
        !          1114:  * only after the sound for the whole VBL was updated (CurrentSamplesNb returns to 0)
        !          1115:  * else it will alter the value of DMA Frame Count ($ff8909/0b/0d) and
        !          1116:  * could cause crashes in some programs.
1.1.1.11  root     1117:  */
1.1.1.9   root     1118: void Sound_ResetBufferIndex(void)
1.1.1.7   root     1119: {
1.1.1.11  root     1120:        Audio_Lock();
                   1121:        nGeneratedSamples = SoundBufferSize + SAMPLES_PER_FRAME;
                   1122:        ActiveSndBufIdx =  (CompleteSndBufIdx + nGeneratedSamples) % MIXBUFFER_SIZE;
1.1.1.16! root     1123:        SamplesPerFrame = SAMPLES_PER_FRAME;
        !          1124:        CurrentSamplesNb = 0;
        !          1125:        ActiveSndBufIdxAvi = ActiveSndBufIdx;
1.1.1.15  root     1126: //fprintf ( stderr , "Sound_ResetBufferIndex SoundBufferSize %d SAMPLES_PER_FRAME %d nGeneratedSamples %d , ActiveSndBufIdx %d\n" ,
                   1127: //     SoundBufferSize , SAMPLES_PER_FRAME, nGeneratedSamples , ActiveSndBufIdx );
1.1.1.11  root     1128:        Audio_Unlock();
1.1.1.7   root     1129: }
                   1130: 
                   1131: 
                   1132: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1133: /**
                   1134:  * Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                   1135:  */
1.1.1.12  root     1136: void Sound_MemorySnapShot_Capture(bool bSave)
1.1.1.7   root     1137: {
1.1.1.11  root     1138:        /* Save/Restore details */
1.1.1.12  root     1139:        MemorySnapShot_Store(&stepA, sizeof(stepA));
                   1140:        MemorySnapShot_Store(&stepB, sizeof(stepB));
                   1141:        MemorySnapShot_Store(&stepC, sizeof(stepC));
                   1142:        MemorySnapShot_Store(&posA, sizeof(posA));
                   1143:        MemorySnapShot_Store(&posB, sizeof(posB));
                   1144:        MemorySnapShot_Store(&posC, sizeof(posC));
                   1145: 
                   1146:        MemorySnapShot_Store(&mixerTA, sizeof(mixerTA));
                   1147:        MemorySnapShot_Store(&mixerTB, sizeof(mixerTB));
                   1148:        MemorySnapShot_Store(&mixerTC, sizeof(mixerTC));
                   1149:        MemorySnapShot_Store(&mixerNA, sizeof(mixerNA));
                   1150:        MemorySnapShot_Store(&mixerNB, sizeof(mixerNB));
                   1151:        MemorySnapShot_Store(&mixerNC, sizeof(mixerNC));
                   1152: 
                   1153:        MemorySnapShot_Store(&noiseStep, sizeof(noiseStep));
                   1154:        MemorySnapShot_Store(&noisePos, sizeof(noisePos));
                   1155:        MemorySnapShot_Store(&currentNoise, sizeof(currentNoise));
                   1156:        MemorySnapShot_Store(&RndRack, sizeof(RndRack));
                   1157: 
                   1158:        MemorySnapShot_Store(&envStep, sizeof(envStep));
                   1159:        MemorySnapShot_Store(&envPos, sizeof(envPos));
                   1160:        MemorySnapShot_Store(&envShape, sizeof(envShape));
1.1.1.14  root     1161: 
1.1.1.12  root     1162:        MemorySnapShot_Store(&EnvMask3Voices, sizeof(EnvMask3Voices));
                   1163:        MemorySnapShot_Store(&Vol3Voices, sizeof(Vol3Voices));
1.1.1.14  root     1164: 
1.1.1.12  root     1165:        MemorySnapShot_Store(SoundRegs, sizeof(SoundRegs));
                   1166: 
1.1.1.14  root     1167:        // MemorySnapShot_Store(&YmVolumeMixing, sizeof(YmVolumeMixing));
                   1168:        // MemorySnapShot_Store(&UseLowPassFilter, sizeof(UseLowPassFilter));
1.1.1.7   root     1169: }
                   1170: 
                   1171: 
                   1172: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1173: /**
                   1174:  * Find how many samples to generate and store in 'nSamplesToGenerate'
                   1175:  * Also update sound cycles counter to store how many we actually did
                   1176:  * so generates set amount each frame.
1.1.1.16! root     1177:  * If FillFrame is true, this means we reach the end of the VBL and me must
        !          1178:  * add as many samples as necessary to get a total of SamplesPerFrame
        !          1179:  * for this VBL.
1.1.1.11  root     1180:  */
1.1.1.16! root     1181: static int Sound_SetSamplesPassed(bool FillFrame)
1.1       root     1182: {
1.1.1.11  root     1183:        int nSoundCycles;
1.1.1.16! root     1184:        int SamplesToGenerate;                          /* How many samples are needed for this time-frame */
        !          1185: 
        !          1186:        nSoundCycles = Cycles_GetCounter(CYCLES_COUNTER_VIDEO);
1.1.1.11  root     1187: 
1.1.1.16! root     1188:        /* example : 160256 cycles per VBL, 44Khz = 882 samples per VBL at 50 Hz */
        !          1189:        /* 882/160256 samples per cpu clock cycle */
1.1.1.11  root     1190: 
1.1.1.16! root     1191:        /* Total number of samples that we should have at this point of the VBL */
        !          1192:        SamplesToGenerate = nSoundCycles * SamplesPerFrame
        !          1193:                / ClocksTimings_GetCyclesPerVBL ( ConfigureParams.System.nMachineType , nScreenRefreshRate );
1.1.1.11  root     1194: 
1.1.1.16! root     1195: //if (SamplesToGenerate > SamplesPerFrame )
        !          1196: //fprintf ( stderr , "over run %d %d\n" , SamplesPerFrame , SamplesToGenerate );
1.1.1.11  root     1197: 
1.1.1.16! root     1198:        if (SamplesToGenerate > SamplesPerFrame)
        !          1199:                SamplesToGenerate = SamplesPerFrame;
        !          1200: 
        !          1201:        SamplesToGenerate -= CurrentSamplesNb;          /* don't count samples that were already generated up to now */
        !          1202:        if ( SamplesToGenerate < 0 )
        !          1203:                SamplesToGenerate = 0;
        !          1204: 
        !          1205: 
        !          1206:        /* If we're called from the VBL interrupt (FillFrame==true), we must ensure we have */
        !          1207:        /* an exact total of SamplesPerFrame samples during a full VBL (we take into account */
        !          1208:        /* the samples that were already generated during this VBL) */
        !          1209:        if ( FillFrame )
        !          1210:        {
        !          1211:                SamplesToGenerate = SamplesPerFrame - CurrentSamplesNb; /* how many samples are missing to reach SamplesPerFrame */
        !          1212:                if ( SamplesToGenerate < 0 )
        !          1213:                        SamplesToGenerate = 0;
        !          1214:        }
1.1.1.11  root     1215: 
1.1.1.16! root     1216:        /* Check we don't fill the sound's ring buffer before it's played by Audio_Callback()   */
        !          1217:        /* This should never happen, except if the system suffers major slowdown due to other   */
        !          1218:        /* processes or if we run in fast forward mode.                                         */
        !          1219:        /* In the case of slowdown, we set Sound_BufferIndexNeedReset to "resync" the working   */
        !          1220:        /* buffer's index ActiveSndBufIdx with the system buffer's index CompleteSndBufIdx.     */
        !          1221:        /* In the case of fast forward, we do nothing here, Sound_BufferIndexNeedReset will be  */
        !          1222:        /* set when the user exits fast forward mode.                                           */
        !          1223:        if ( ( SamplesToGenerate > MIXBUFFER_SIZE - nGeneratedSamples ) && ( ConfigureParams.System.bFastForward == false )
        !          1224:            && ( ConfigureParams.Sound.bEnableSound == true ) )
1.1.1.11  root     1225:        {
1.1.1.16! root     1226:                Log_Printf ( LOG_WARN , "Your system is too slow, some sound samples were not correctly emulated\n" );
        !          1227:                Sound_BufferIndexNeedReset = true;
1.1.1.11  root     1228:        }
1.1.1.16! root     1229: 
        !          1230: //fprintf ( stderr , "vbl %d hbl %d samp_gen %d / %d frac %lx\n" , nVBLs , nHBL , SamplesToGenerate , SamplesPerFrame , (long int)SamplesPerFrame_unrounded );
        !          1231: 
        !          1232:        return SamplesToGenerate;
1.1       root     1233: }
                   1234: 
1.1.1.5   root     1235: 
1.1.1.2   root     1236: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1237: /**
                   1238:  * Generate samples for all channels during this time-frame
                   1239:  */
1.1.1.16! root     1240: static void Sound_GenerateSamples(int SamplesToGenerate)
1.1       root     1241: {
1.1.1.12  root     1242:        int     i;
                   1243:        int     idx;
1.1.1.14  root     1244: 
1.1.1.16! root     1245:        if (SamplesToGenerate <= 0)
1.1.1.12  root     1246:                return;
1.1.1.14  root     1247: 
1.1.1.15  root     1248:        if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
1.1.1.11  root     1249:        {
1.1.1.16! root     1250:                for (i = 0; i < SamplesToGenerate; i++)
1.1.1.15  root     1251:                {
                   1252:                        idx = (ActiveSndBufIdx + i) % MIXBUFFER_SIZE;
                   1253:                        MixBuffer[idx][0] = MixBuffer[idx][1] = YM2149_NextSample();
                   1254:                }
                   1255:                /* If Falcon emulation, crossbar does the job */
1.1.1.16! root     1256:                Crossbar_GenerateSamples(ActiveSndBufIdx, SamplesToGenerate);
1.1.1.11  root     1257:        }
1.1.1.15  root     1258:        else if (ConfigureParams.System.nMachineType != MACHINE_ST)
                   1259:        {
1.1.1.16! root     1260:                for (i = 0; i < SamplesToGenerate; i++)
1.1.1.15  root     1261:                {
                   1262:                        idx = (ActiveSndBufIdx + i) % MIXBUFFER_SIZE;
                   1263:                        MixBuffer[idx][0] = MixBuffer[idx][1] = (YM2149_NextSample() >> 1);
                   1264:                }
                   1265:                /* If Ste or TT emulation, DmaSnd does the job */
1.1.1.16! root     1266:                DmaSnd_GenerateSamples(ActiveSndBufIdx, SamplesToGenerate);
1.1.1.15  root     1267:        }
                   1268:        else if (ConfigureParams.System.nMachineType == MACHINE_ST)
                   1269:        {
1.1.1.16! root     1270:                for (i = 0; i < SamplesToGenerate; i++)
1.1.1.15  root     1271:                {
                   1272:                        idx = (ActiveSndBufIdx + i) % MIXBUFFER_SIZE;
                   1273:                        MixBuffer[idx][0] = MixBuffer[idx][1] = YM2149_NextSample();
                   1274:                }
                   1275:                /* If ST emulation, DmaSnd doesn't do the job
                   1276:                DmaSnd_GenerateSamples(ActiveSndBufIdx, nSamplesToGenerate); */
                   1277:        }
1.1.1.12  root     1278: 
1.1.1.16! root     1279:        ActiveSndBufIdx = (ActiveSndBufIdx + SamplesToGenerate) % MIXBUFFER_SIZE;
        !          1280:        nGeneratedSamples += SamplesToGenerate;
        !          1281:        CurrentSamplesNb += SamplesToGenerate;                          /* number of samples generated for current VBL */
1.1       root     1282: }
                   1283: 
1.1.1.5   root     1284: 
1.1.1.2   root     1285: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1286: /**
                   1287:  * This is called to built samples up until this clock cycle
1.1.1.16! root     1288:  * Sound_Update can be called several times during a VBL ; we must ensure
        !          1289:  * that we generate exactly SamplesPerFrame samples between 2 calls
        !          1290:  * to Sound_Update_VBL.
1.1.1.11  root     1291:  */
1.1.1.16! root     1292: void Sound_Update(bool FillFrame)
1.1       root     1293: {
1.1.1.11  root     1294:        int OldSndBufIdx = ActiveSndBufIdx;
1.1.1.16! root     1295:        int SamplesToGenerate;
1.1.1.5   root     1296: 
1.1.1.11  root     1297:        /* Make sure that we don't interfere with the audio callback function */
                   1298:        Audio_Lock();
1.1.1.6   root     1299: 
1.1.1.16! root     1300:        /* Find how many samples to generate */
        !          1301:        SamplesToGenerate = Sound_SetSamplesPassed( FillFrame );
        !          1302: 
1.1.1.11  root     1303:        /* And generate */
1.1.1.16! root     1304:        Sound_GenerateSamples( SamplesToGenerate );
1.1       root     1305: 
1.1.1.11  root     1306:        /* Allow audio callback function to occur again */
                   1307:        Audio_Unlock();
1.1.1.6   root     1308: 
1.1.1.11  root     1309:        /* Save to WAV file, if open */
                   1310:        if (bRecordingWav)
1.1.1.16! root     1311:                WAVFormat_Update(MixBuffer, OldSndBufIdx, SamplesToGenerate);
1.1       root     1312: }
                   1313: 
1.1.1.5   root     1314: 
1.1.1.2   root     1315: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1316: /**
1.1.1.16! root     1317:  * On the end of each VBL, complete audio buffer to reach SamplesPerFrame samples.
        !          1318:  * As Sound_Update(false) could be called several times during the VBL, the audio
        !          1319:  * buffer might be already partially filled.
        !          1320:  * We must first complete the buffer using the same value of SamplesPerFrame
        !          1321:  * by calling Sound_Update(true) ; then we can compute a new value for
        !          1322:  * SamplesPerFrame that will be used for the next VBL to come.
1.1.1.11  root     1323:  */
1.1.1.5   root     1324: void Sound_Update_VBL(void)
1.1       root     1325: {
1.1.1.16! root     1326:        Sound_Update(true);                                     /* generate as many samples as needed to fill this VBL */
        !          1327: //fprintf ( stderr , "vbl done %d %d\n" , SamplesPerFrame , CurrentSamplesNb );
1.1.1.5   root     1328: 
1.1.1.16! root     1329:        CurrentSamplesNb = 0;                                   /* VBL is complete, reset counter for next VBL */
        !          1330: 
        !          1331:        /*Compute a fractional equivalent of SamplesPerFrame for the next VBL, to avoid rounding propagation */
        !          1332:        SamplesPerFrame_unrounded += (yms64) ClocksTimings_GetSamplesPerVBL ( ConfigureParams.System.nMachineType ,
        !          1333:                        nScreenRefreshRate , nAudioFrequency );
        !          1334:        SamplesPerFrame = SamplesPerFrame_unrounded >> 28;              /* use integer part */
        !          1335:        SamplesPerFrame_unrounded &= 0x0fffffff;                        /* keep fractional part in the lower 28 bits */
        !          1336: 
        !          1337:        /* Reset sound buffer if needed (after pause, fast forward, slow system, ...) */
        !          1338:        if ( Sound_BufferIndexNeedReset )
        !          1339:        {
        !          1340:                Sound_ResetBufferIndex ();
        !          1341:                Sound_BufferIndexNeedReset = false;
        !          1342:        }
        !          1343:        
        !          1344:        /* Record AVI audio frame is necessary */
1.1.1.15  root     1345:        if ( bRecordingAvi )
                   1346:        {
1.1.1.16! root     1347:                int Len;
1.1.1.15  root     1348: 
1.1.1.16! root     1349:                Len = ActiveSndBufIdx - ActiveSndBufIdxAvi;     /* number of generated samples for this frame */
        !          1350:                if ( Len < 0 )
        !          1351:                        Len += MIXBUFFER_SIZE;                  /* end of ring buffer was reached */
1.1.1.15  root     1352: 
1.1.1.16! root     1353:                Avi_RecordAudioStream ( MixBuffer , ActiveSndBufIdxAvi , Len );
1.1.1.15  root     1354:        }
                   1355: 
1.1.1.16! root     1356:        ActiveSndBufIdxAvi = ActiveSndBufIdx;                   /* save new position for next AVI audio frame */
        !          1357: 
1.1.1.11  root     1358:        /* Clear write to register '13', used for YM file saving */
1.1.1.14  root     1359:        bEnvelopeFreqFlag = false;
1.1       root     1360: }
                   1361: 
                   1362: 
1.1.1.2   root     1363: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1364: /**
                   1365:  * Start recording sound, as .YM or .WAV output
                   1366:  */
1.1.1.12  root     1367: bool Sound_BeginRecording(char *pszCaptureFileName)
1.1       root     1368: {
1.1.1.12  root     1369:        bool bRet;
1.1.1.7   root     1370: 
1.1.1.11  root     1371:        if (!pszCaptureFileName || strlen(pszCaptureFileName) <= 3)
                   1372:        {
                   1373:                Log_Printf(LOG_ERROR, "Illegal sound recording file name!\n");
1.1.1.14  root     1374:                return false;
1.1.1.11  root     1375:        }
                   1376: 
                   1377:        /* Did specify .YM or .WAV? If neither report error */
                   1378:        if (File_DoesFileExtensionMatch(pszCaptureFileName,".ym"))
                   1379:                bRet = YMFormat_BeginRecording(pszCaptureFileName);
                   1380:        else if (File_DoesFileExtensionMatch(pszCaptureFileName,".wav"))
                   1381:                bRet = WAVFormat_OpenFile(pszCaptureFileName);
                   1382:        else
                   1383:        {
                   1384:                Log_AlertDlg(LOG_ERROR, "Unknown Sound Recording format.\n"
                   1385:                             "Please specify a .YM or .WAV output file.");
1.1.1.14  root     1386:                bRet = false;
1.1.1.11  root     1387:        }
                   1388: 
                   1389:        return bRet;
1.1       root     1390: }
                   1391: 
1.1.1.5   root     1392: 
1.1.1.2   root     1393: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1394: /**
                   1395:  * End sound recording
                   1396:  */
1.1.1.7   root     1397: void Sound_EndRecording(void)
1.1       root     1398: {
1.1.1.11  root     1399:        /* Stop sound recording and close files */
                   1400:        if (bRecordingYM)
                   1401:                YMFormat_EndRecording();
                   1402:        if (bRecordingWav)
                   1403:                WAVFormat_CloseFile();
1.1       root     1404: }
                   1405: 
1.1.1.6   root     1406: 
1.1.1.2   root     1407: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1408: /**
                   1409:  * Are we recording sound data?
                   1410:  */
1.1.1.12  root     1411: bool Sound_AreWeRecording(void)
1.1       root     1412: {
1.1.1.11  root     1413:        return (bRecordingYM || bRecordingWav);
1.1       root     1414: }
1.1.1.12  root     1415: 
1.1.1.16! root     1416: 
        !          1417: /*-----------------------------------------------------------------------*/
        !          1418: /**
        !          1419:  * Rebuild volume conversion table
        !          1420:  */
        !          1421: void Sound_SetYmVolumeMixing(void)
        !          1422: {
        !          1423:        /* Build the volume conversion table */
        !          1424:        Ym2149_BuildVolumeTable();
        !          1425: }
        !          1426: 

unix.superglobalmegacorp.com

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