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

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

unix.superglobalmegacorp.com

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