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

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

unix.superglobalmegacorp.com

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