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

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.1.22! root       31:   NOTE [NP] : As of June 2017, Hatari uses a completely new/rewritten cycle exact YM2149 emulation.
        !            32: 
        !            33:   Instead of updating YM2149's state on every host call (for example at 44.1 kHz), YM2149's state is now updated
        !            34:   at 250 kHz (which is the base frequency used by real YM2149 to handle its various counters) and
        !            35:   then downsampled to the host frequency.
        !            36:   This is required to perfectly emulate transitions when the periods for tone/noise/envelope
        !            37:   are changed and whether a new phase should be started or the current phase should be extended.
        !            38: 
        !            39:   Using a custom program on a real STF, it's possible to change YM2149 registers at very precise
        !            40:   cycles during various sound phases and to record the STF sound output as a wav file on a modern PC.
        !            41:   The wav file can then be studied (using Audacity for example) to precisely see how and when
        !            42:   a change in a register affects the sound output.
        !            43: 
        !            44:   Based on these measures I made, the following behaviours of the YM2149 were confirmed :
        !            45: 
        !            46:     - unlike what it written in Yamaha documentation, each period counter doesn't count
        !            47:       from 'period' down to 0, but count up from 0 until the counter reaches 'period'.
        !            48:       The counter is incremented at 250 kHz, with the following pseudo code :
        !            49: 
        !            50:          tone_counter = tone_counter+1
        !            51:          if ( tone_counter >= tone_period )
        !            52:            tone_counter = 0
        !            53:            invert tone output
        !            54: 
        !            55:       This means that when a new value is written in tone period A for example, the current phase
        !            56:       will be either extended (if new_period_A > tone_counter_A) or a new phase will be
        !            57:       started immediately (if new_period_A < tone_counter_A).
        !            58: 
        !            59:     - noise counter is incremented twice slower than tone counter ; for example with period=31
        !            60:       a tone phase will remain up or down for ~0.0001 sec, but a noise phase will remain up or down
        !            61:       for ~0.0002 sec. This is equivalent to incrementing noise counter at 125 kHz instead
        !            62:       of 250 kHz like tone counter.
        !            63: 
        !            64:     - it is known that when writing to the env wave register (reg 13) the current envelope
        !            65:       is restarted from the start (this is often used in so called sync-buzzer effects).
        !            66:       But the measures on the resulting wav file of the YM2149 also show that the current
        !            67:       envelope phase is restarted at the same time that envelope wave register is written to.
        !            68: 
        !            69:     - The various counters for tone/noise/env all give the same result when period=1 and when period=0.
        !            70:       For noise and envelope, this can be seen when sampling the sound output as above
        !            71:       For tone, this was also measured using a logic analyser (to sample at much higher rate than 250 kHz)
        !            72: 
        !            73:     - 2 voices playing tones at the same frequency and at the same volume can cancel each other partially
        !            74:       or completely, giving no sound output at all.
        !            75:       This happens when the phase for one voice is "up" while the phase for the other voice
        !            76:       is "down", then on the next phase inversion, 1st voice will be "down" and 2nd voice will be "up".
        !            77:       In such cases, the sum of these 2 tone waveforms will give a constant output signal, producing no sound at all.
        !            78:       If both voices are not fully in opposite phase, the resulting sound will vary depending
        !            79:       on how much phases are in common and how much they "cancel" each other
        !            80: 
1.1       root       81: */
1.1.1.12  root       82: 
                     83: /* 2008/05/05  [NP]    Fix case where period is 0 for noise, sound or envelope.        */
                     84: /*                     In that case, a real ST sounds as if period was in fact 1.      */
                     85: /*                     (fix buggy sound replay in ESwat that set volume<0 and trigger  */
                     86: /*                     a badly initialised envelope with envper=0).                    */
                     87: /* 2008/07/27  [NP]    Better separation between accesses to the YM hardware registers */
                     88: /*                     and the sound rendering routines. Use Sound_WriteReg() to pass  */
                     89: /*                     all writes to the sound rendering functions. This allows to     */
1.1.1.19  root       90: /*                     have sound.c independent of psg.c (to ease replacement of       */
1.1.1.12  root       91: /*                     sound.c by another rendering method).                           */
                     92: /* 2008/08/02  [NP]    Initial convert of Ym2149Ex.cpp from C++ to C.                  */
                     93: /*                     Remove unused part of the code (StSound specific).              */
                     94: /* 2008/08/09  [NP]    Complete integration of StSound routines into sound.c           */
                     95: /*                     Set EnvPer=3 if EnvPer<3 (ESwat buggy replay).                  */
                     96: /* 2008/08/13  [NP]    StSound was generating samples in the range 0-32767, instead    */
                     97: /*                     of really signed samples between -32768 and 32767, which could  */
                     98: /*                     give incorrect results in many case.                            */
                     99: /* 2008/09/06  [NP]    Use sc68 volumes table for a more accurate mixing of the voices */
                    100: /*                     All volumes are converted to 5 bits and the table contains      */
                    101: /*                     32*32*32 values. Samples are signed and centered to get the     */
                    102: /*                     biggest amplitude possible.                                     */
                    103: /*                     Faster mixing routines for tone+volume+envelope (don't use      */
                    104: /*                     StSound's version anymore, it gave problem with some GCC).      */
                    105: /* 2008/09/17  [NP]    Add ym_normalise_5bit_table to normalise the 32*32*32 table and */
                    106: /*                     to optionally center 16 bit signed sample.                      */
                    107: /*                     Possibility to mix volumes using a table measured on ST or a    */
                    108: /*                     linear mean of the 3 channels' volume.                          */
                    109: /*                     Default mixing set to YM_LINEAR_MIXING.                         */
                    110: /* 2008/10/14  [NP]    Full support for 5 bits volumes : envelopes are generated with  */
                    111: /*                     32 volumes per pattern as on a real YM-2149. Fixed volumes      */
                    112: /*                     on 4 bits are converted to their 5 bits equivalent. This should */
                    113: /*                     give the maximum accuracy possible when computing volumes.      */
                    114: /*                     New version of Ym2149_EnvStepCompute to handle 5 bits volumes.  */
                    115: /*                     Function YM2149_EnvBuild to compute the 96 volumes that define  */
                    116: /*                     a single envelope (32 initial volumes, then 64 repeated values).*/
                    117: /* 2008/10/26  [NP]    Correctly save/restore all necessary variables in               */
                    118: /*                     Sound_MemorySnapShot_Capture.                                   */
                    119: /* 2008/11/23  [NP]    Clean source, remove old sound core.                            */
1.1.1.17  root      120: /* 2011/11/03  [DS]    Stereo DC filtering which accounts for DMA sound.               */
1.1.1.22! root      121: /* 2017/06/xx  [NP]    New cycle exact emulation method, all counters are incremented  */
        !           122: /*                     using a simulated freq of 250 kHz. Some undocumented cases      */
        !           123: /*                     where also measured on real STF to improve accuracy.            */
1.1.1.12  root      124: 
                    125: 
                    126: 
1.1.1.14  root      127: const char Sound_fileid[] = "Hatari sound.c : " __DATE__ " " __TIME__;
1.1.1.5   root      128: 
                    129: #include <SDL_types.h>
1.1       root      130: 
                    131: #include "main.h"
                    132: #include "audio.h"
1.1.1.10  root      133: #include "cycles.h"
1.1.1.21  root      134: #include "m68000.h"
1.1.1.15  root      135: #include "configuration.h"
1.1.1.9   root      136: #include "dmaSnd.h"
1.1.1.15  root      137: #include "crossbar.h"
1.1       root      138: #include "file.h"
1.1.1.15  root      139: #include "cycInt.h"
1.1.1.8   root      140: #include "log.h"
1.1       root      141: #include "memorySnapShot.h"
                    142: #include "psg.h"
                    143: #include "sound.h"
1.1.1.16  root      144: #include "screen.h"
1.1       root      145: #include "video.h"
                    146: #include "wavFormat.h"
                    147: #include "ymFormat.h"
1.1.1.15  root      148: #include "avi_record.h"
1.1.1.16  root      149: #include "clocks_timings.h"
1.1       root      150: 
                    151: 
                    152: 
1.1.1.12  root      153: /*--------------------------------------------------------------*/
                    154: /* Definition of the possible envelopes shapes (using 5 bits)  */
                    155: /*--------------------------------------------------------------*/
                    156: 
                    157: #define        ENV_GODOWN      0               /* 31 ->  0 */
                    158: #define        ENV_GOUP        1               /*  0 -> 31 */
                    159: #define        ENV_DOWN        2               /*  0 ->  0 */
                    160: #define        ENV_UP          3               /* 31 -> 31 */
                    161: 
                    162: /* To generate an envelope, we first use block 0, then we repeat blocks 1 and 2 */
                    163: static const int YmEnvDef[ 16 ][ 3 ] = {
                    164:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 0 \___ */
                    165:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 1 \___ */
                    166:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 2 \___ */
                    167:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 3 \___ */
                    168:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 4 /___ */
                    169:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 5 /___ */
                    170:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 6 /___ */
                    171:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* 7 /___ */
                    172:        { ENV_GODOWN,   ENV_GODOWN, ENV_GODOWN } ,      /* 8 \\\\ */
                    173:        { ENV_GODOWN,   ENV_DOWN, ENV_DOWN } ,          /* 9 \___ */
                    174:        { ENV_GODOWN,   ENV_GOUP, ENV_GODOWN } ,        /* A \/\/ */
                    175:        { ENV_GODOWN,   ENV_UP, ENV_UP } ,              /* B \--- */
                    176:        { ENV_GOUP,     ENV_GOUP, ENV_GOUP } ,          /* C //// */
                    177:        { ENV_GOUP,     ENV_UP, ENV_UP } ,              /* D /--- */
                    178:        { ENV_GOUP,     ENV_GODOWN, ENV_GOUP } ,        /* E /\/\ */
                    179:        { ENV_GOUP,     ENV_DOWN, ENV_DOWN } ,          /* F /___ */
                    180:        };
                    181: 
                    182: 
                    183: /* Buffer to store the 16 envelopes built from YmEnvDef */
                    184: static ymu16   YmEnvWaves[ 16 ][ 32 * 3 ];             /* 16 envelopes with 3 blocks of 32 volumes */
1.1.1.3   root      185: 
1.1       root      186: 
1.1.1.12  root      187: 
                    188: /*--------------------------------------------------------------*/
                    189: /* Definition of the volumes tables (using 5 bits) and of the  */
                    190: /* mixing parameters for the 3 voices.                         */
                    191: /*--------------------------------------------------------------*/
                    192: 
                    193: /* 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) */
                    194: /* Vol 0 should be 310 when measuread as a voltage, but we set it to 0 in order to have a volume=0 matching */
                    195: /* the 0 level of a 16 bits unsigned sample (no sound output) */
                    196: static const ymu16 ymout1c5bit[ 32 ] =
                    197: {
                    198:   0 /*310*/,  369,  438,  521,  619,  735,  874, 1039,
                    199:  1234, 1467, 1744, 2072, 2463, 2927, 3479, 4135,
                    200:  4914, 5841, 6942, 8250, 9806,11654,13851,16462,
                    201: 19565,23253,27636,32845,39037,46395,55141,65535
1.1       root      202: };
                    203: 
1.1.1.12  root      204: /* Convert a constant 4 bits volume to the internal 5 bits value : */
1.1.1.18  root      205: /* volume5=volume4*2+1, except for volumes 0 and 1 which remain 0 and 1, */
1.1.1.12  root      206: /* in order to map [0,15] into [0,31] (O must remain 0, and 15 must give 31) */
1.1.1.18  root      207: static const ymu16 YmVolume4to5[ 16 ] = { 0,1,5,7,9,11,13,15,17,19,21,23,25,27,29,31 };
1.1       root      208: 
1.1.1.12  root      209: /* Table of unsigned 4 bit D/A output level for 3 channels as measured on a real ST */
1.1.1.18  root      210: static ymu16 volumetable_original[16][16][16] =
1.1.1.12  root      211: #include "ym2149_fixed_vol.h"
1.1.1.5   root      212: 
1.1.1.12  root      213: /* Corresponding table interpolated to 5 bit D/A output level (16 bits unsigned) */
1.1.1.18  root      214: static ymu16 ymout5_u16[32][32][32];
1.1.1.12  root      215: 
                    216: /* Same table, after conversion to signed results (same pointer, with different type) */
                    217: static yms16 *ymout5 = (yms16 *)ymout5_u16;
                    218: 
                    219: 
                    220: 
                    221: /*--------------------------------------------------------------*/
                    222: /* Other constants / macros                                    */
                    223: /*--------------------------------------------------------------*/
                    224: 
                    225: /* Number of generated samples per frame (eg. 44Khz=882) */
1.1.1.22! root      226: #define SAMPLES_PER_FRAME      (nAudioFrequency/nScreenRefreshRate)
1.1.1.12  root      227: 
                    228: /* Current sound replay freq (usually 44100 Hz) */
1.1.1.22! root      229: #define YM_REPLAY_FREQ         nAudioFrequency
1.1.1.12  root      230: 
1.1.1.22! root      231: /* YM-2149 clock on all Atari models is 2 MHz (CPU freq / 4) */
        !           232: /* Period counters for tone/noise/env are based on YM clock / 8 = 250 kHz */
1.1.1.16  root      233: #define YM_ATARI_CLOCK         (MachineClocks.YM_Freq)
1.1.1.22! root      234: #define YM_ATARI_CLOCK_COUNTER (YM_ATARI_CLOCK / 8)
1.1.1.12  root      235: 
                    236: /* Merge/read the 3 volumes in a single integer (5 bits per volume) */
                    237: #define        YM_MERGE_VOICE(C,B,A)   ( (C)<<10 | (B)<<5 | A )
                    238: #define        YM_MASK_1VOICE          0x1f
                    239: #define YM_MASK_A              0x1f
                    240: #define YM_MASK_B              (0x1f<<5)
                    241: #define YM_MASK_C              (0x1f<<10)
                    242: 
                    243: 
                    244: /* Constants for YM2149_Normalise_5bit_Table */
                    245: #define        YM_OUTPUT_LEVEL                 0x7fff          /* amplitude of the final signal (0..65535 if centered, 0..32767 if not) */
1.1.1.14  root      246: #define YM_OUTPUT_CENTERED             false
1.1.1.12  root      247: 
                    248: 
                    249: 
                    250: /*--------------------------------------------------------------*/
                    251: /* Variables for the YM2149 emulator (need to be saved and     */
                    252: /* restored in memory snapshots)                               */
                    253: /*--------------------------------------------------------------*/
                    254: 
1.1.1.22! root      255: #define YM_250                                         /* runs at 250 kHz with low quality downsample at YM_REPLAY_FREQ */
        !           256: #define YM_250_MORE                                    /* runs at 250 kHz with more accurate downsample at YM_REPLAY_FREQ using YM2149_Resample_Method */
        !           257: //#define YM_250_DEBUG                                 /* write raw 250 kHz samples to a file 'hatari_250.wav' */
        !           258: 
        !           259: 
        !           260: /* For our internal computations to convert down/up square wave signals into 0-31 volume, */
        !           261: /* we consider that 'up' is 31 and 'down' is 0 */
        !           262: #define        YM_SQUARE_UP            0x1f
        !           263: #define        YM_SQUARE_DOWN          0x00
        !           264: 
        !           265: static ymu16   ToneA_per , ToneA_count , ToneA_val , ToneA_force;
        !           266: static ymu16   ToneB_per , ToneB_count , ToneB_val , ToneB_force;
        !           267: static ymu16   ToneC_per , ToneC_count , ToneC_val , ToneC_force;
        !           268: static ymu16   Noise_per , Noise_count , Noise_val;
        !           269: static ymu16   Env_per , Env_count;
        !           270: 
        !           271: static ymu32   YM_Clock_Step;
        !           272: 
1.1.1.12  root      273: static ymu32   stepA , stepB , stepC;
                    274: static ymu32   posA , posB , posC;
                    275: static ymu32   mixerTA , mixerTB , mixerTC;
                    276: static ymu32   mixerNA , mixerNB , mixerNC;
                    277: 
                    278: static ymu32   noiseStep;
                    279: static ymu32   noisePos;
                    280: static ymu32   currentNoise;
                    281: static ymu32   RndRack;                                /* current random seed */
                    282: 
                    283: static ymu32   envStep;
1.1.1.22! root      284: static ymu32   Env_pos;
        !           285: static int     Env_shape;
1.1.1.12  root      286: 
                    287: static ymu16   EnvMask3Voices = 0;                     /* mask is 0x1f for voices having an active envelope */
                    288: static ymu16   Vol3Voices = 0;                         /* volume 0-0x1f for voices having a constant volume */
                    289:                                                        /* volume is set to 0 if voice has an envelope in EnvMask3Voices */
                    290: 
                    291: 
                    292: /* Global variables that can be changed/read from other parts of Hatari */
                    293: Uint8          SoundRegs[ 14 ];
                    294: 
1.1.1.16  root      295: int            YmVolumeMixing = YM_TABLE_MIXING;
1.1.1.22! root      296: 
        !           297: int            YM2149_LPF_Filter = YM2149_LPF_FILTER_PWM;
        !           298: // int         YM2149_LPF_Filter = YM2149_LPF_FILTER_NONE;     /* For debug */
        !           299: int            YM2149_HPF_Filter = YM2149_HPF_FILTER_IIR;
        !           300: // int         YM2149_HPF_Filter = YM2149_HPF_FILTER_NONE;     /* For debug */
        !           301: 
        !           302: //int          YM2149_Resample_Method = YM2149_RESAMPLE_METHOD_NEAREST;
        !           303: int            YM2149_Resample_Method = YM2149_RESAMPLE_METHOD_WEIGHTED_AVERAGE_2;
        !           304: 
1.1.1.12  root      305: 
                    306: bool           bEnvelopeFreqFlag;                      /* Cleared each frame for YM saving */
                    307: 
                    308: Sint16         MixBuffer[MIXBUFFER_SIZE][2];
                    309: int            nGeneratedSamples;                      /* Generated samples since audio buffer update */
                    310: static int     ActiveSndBufIdx;                        /* Current working index into above mix buffer */
1.1.1.16  root      311: static int     ActiveSndBufIdxAvi;                     /* Current working index to save an AVI audio frame */
                    312: 
                    313: static yms64   SamplesPerFrame_unrounded = 0;          /* Number of samples for the current VBL, with simulated fractional part */
                    314: static int     SamplesPerFrame;                        /* Number of samples to generate for the current VBL */
                    315: static int     CurrentSamplesNb = 0;                   /* Number of samples already generated for the current VBL */
1.1.1.12  root      316: 
1.1.1.16  root      317: bool           Sound_BufferIndexNeedReset = false;
1.1.1.12  root      318: 
                    319: 
1.1.1.22! root      320: #ifdef YM_250_MORE
        !           321: #define                YM_BUFFER_250_SIZE      ( MIXBUFFER_SIZE * 8 )  /* Size to store samples generated at 250 kHz (must be a power of 2) */
        !           322:                                                        /* As we usually output at 44.1 or 48 kHz using MIXBUFFER_SIZE, having */
        !           323:                                                        /* a buffer x8 is nearly equivalent when generating at 250 kHz */
        !           324: ymsample       YM_Buffer_250[ YM_BUFFER_250_SIZE ];
        !           325: static int     YM_Buffer_250_pos_write = 0;            /* Current writing position into above buffer */
        !           326: static int     YM_Buffer_250_pos_read = 0;             /* Current reading position into above buffer */
        !           327: 
        !           328: static int     SamplesToGenerate_250;
        !           329: 
        !           330: #endif
        !           331: 
        !           332: 
1.1.1.12  root      333: /*--------------------------------------------------------------*/
                    334: /* Local functions prototypes                                  */
                    335: /*--------------------------------------------------------------*/
                    336: 
1.1.1.17  root      337: static ymsample        LowPassFilter           (ymsample x0);
1.1.1.18  root      338: static ymsample        PWMaliasFilter          (ymsample x0);
1.1.1.12  root      339: 
1.1.1.18  root      340: static void    interpolate_volumetable (ymu16 volumetable[32][32][32]);
1.1.1.12  root      341: 
1.1.1.18  root      342: static void    YM2149_BuildModelVolumeTable(ymu16 volumetable[32][32][32]);
                    343: static void    YM2149_BuildLinearVolumeTable(ymu16 volumetable[32][32][32]);
1.1.1.12  root      344: static void    YM2149_Normalise_5bit_Table(ymu16 *in_5bit , yms16 *out_5bit, unsigned int Level, bool DoCenter);
                    345: 
                    346: static void    YM2149_EnvBuild         (void);
1.1.1.16  root      347: static void    Ym2149_BuildVolumeTable (void);
1.1.1.12  root      348: static void    Ym2149_Init             (void);
                    349: static void    Ym2149_Reset            (void);
                    350: 
                    351: static ymu32   YM2149_RndCompute       (void);
                    352: static ymu32   Ym2149_ToneStepCompute  (ymu8 rHigh , ymu8 rLow);
                    353: static ymu32   Ym2149_NoiseStepCompute (ymu8 rNoise);
                    354: static ymu32   Ym2149_EnvStepCompute   (ymu8 rHigh , ymu8 rLow);
1.1.1.22! root      355: static ymu16   YM2149_TonePer          (ymu8 rHigh , ymu8 rLow , ymu16 *pTone_force);
        !           356: static ymu16   YM2149_NoisePer         (ymu8 rNoise);
        !           357: static ymu16   YM2149_EnvPer           (ymu8 rHigh , ymu8 rLow);
        !           358: static void    YM2149_TonePerFilter    (ymu16 per , ymu16 *pTone_force);
1.1.1.12  root      359: 
1.1.1.16  root      360: static int     Sound_SetSamplesPassed(bool FillFrame);
                    361: static void    Sound_GenerateSamples(int SamplesToGenerate);
1.1.1.12  root      362: 
                    363: 
                    364: 
                    365: /*--------------------------------------------------------------*/
1.1.1.17  root      366: /* DC Adjuster                                                 */
1.1.1.12  root      367: /*--------------------------------------------------------------*/
                    368: 
1.1.1.17  root      369: /**
                    370:  * 6dB/octave first order HPF fc = (1.0-0.998)*44100/(2.0*pi)
                    371:  * Z pole = 0.99804 --> FS = 44100 Hz : fc=13.7 Hz (11 Hz meas)
                    372:  * a = (int32_t)(32768.0*(1.0 - pole)) :       a = 64 !!!
                    373:  * Input range: -32768 to 32767  Maximum step: +65536 or -65472
                    374:  */
                    375: ymsample       Subsonic_IIR_HPF_Left(ymsample x0)
1.1.1.12  root      376: {
1.1.1.17  root      377:        static  yms32   x1 = 0, y1 = 0, y0 = 0;
1.1.1.14  root      378: 
1.1.1.22! root      379:        if ( YM2149_HPF_Filter == YM2149_HPF_FILTER_NONE )
        !           380:                return x0;
        !           381: 
1.1.1.17  root      382:        y1 += ((x0 - x1)<<15) - (y0<<6);  /*  64*y0  */
                    383:        y0 = y1>>15;
                    384:        x1 = x0;
1.1.1.12  root      385: 
1.1.1.17  root      386:        return y0;
1.1.1.12  root      387: }
                    388: 
                    389: 
1.1.1.17  root      390: ymsample       Subsonic_IIR_HPF_Right(ymsample x0)
1.1       root      391: {
1.1.1.17  root      392:        static  yms32   x1 = 0, y1 = 0, y0 = 0;
1.1.1.12  root      393: 
1.1.1.22! root      394:        if ( YM2149_HPF_Filter == YM2149_HPF_FILTER_NONE )
        !           395:                return x0;
        !           396: 
1.1.1.17  root      397:        y1 += ((x0 - x1)<<15) - (y0<<6);  /*  64*y0  */
                    398:        y0 = y1>>15;
                    399:        x1 = x0;
1.1.1.12  root      400: 
1.1.1.17  root      401:        return y0;
1.1.1.12  root      402: }
                    403: 
                    404: 
1.1.1.17  root      405: /*--------------------------------------------------------------*/
                    406: /* Low Pass Filter routines.                                   */
                    407: /*--------------------------------------------------------------*/
1.1.1.12  root      408: 
1.1.1.17  root      409: /**
                    410:  * Get coefficients for different Fs (C10 is in ST only):
                    411:  * Wc = 2*M_PI*4895.1;
                    412:  * Fs = 44100;
                    413:  * warp = Wc/tanf((Wc/2)/Fs);
                    414:  * b = Wc/(warp+Wc);
                    415:  * a = (Wc-warp)/(warp+Wc);
                    416:  *
                    417:  * #define B_z (yms32)( 0.2667*(1<<15))
                    418:  * #define A_z (yms32)(-0.4667*(1<<15))
                    419:  *
                    420:  * y0 = (B_z*(x0 + x1) - A_z*y0) >> 15;
                    421:  * x1 = x0;
                    422:  *
                    423:  * The Lowpass Filter formed by C10 = 0.1 uF
                    424:  * and
1.1.1.18  root      425:  * R8=1k // 1k*(65119-46602)/65119 // R9=10k // R10=5.1k //
1.1.1.17  root      426:  * (R12=470)*(100=Q1_HFE) = 206.865 ohms when YM2149 is High
                    427:  * and
                    428:  * R8=1k // R9=10k // R10=5.1k // (R12=470)*(100=Q1_HFE)
                    429:  *                        = 759.1   ohms when YM2149 is Low
                    430:  * High corner is 1/(2*pi*(0.1*10e-6)*206.865) fc = 7693.7 Hz
                    431:  * Low  corner is 1/(2*pi*(0.1*10e-6)*795.1)   fc = 2096.6 Hz
                    432:  * Notes:
                    433:  * - using STF reference designators R8 R9 R10 C10 (from dec 1986 schematics)
                    434:  * - using corresponding numbers from psgstrep and psgquart
                    435:  * - 65119 is the largest value in Paulo's psgstrep table
                    436:  * - 46602 is the largest value in Paulo's psgquart table
                    437:  * - this low pass filter uses the highest cutoff frequency
                    438:  *   on the STf (a slightly lower frequency is reasonable).
                    439:  *
                    440:  * A first order lowpass filter with a high cutoff frequency
                    441:  * is used when the YM2149 pulls high, and a lowpass filter
                    442:  * with a low cutoff frequency is used when R8 pulls low.
                    443:  */
                    444: static ymsample        LowPassFilter(ymsample x0)
                    445: {
                    446:        static  yms32 y0 = 0, x1 = 0;
                    447: 
                    448:        if (x0 >= y0)
                    449:        /* YM Pull up:   fc = 7586.1 Hz (44.1 KHz), fc = 8257.0 Hz (48 KHz) */
                    450:                y0 = (3*(x0 + x1) + (y0<<1)) >> 3;
                    451:        else
                    452:        /* R8 Pull down: fc = 1992.0 Hz (44.1 KHz), fc = 2168.0 Hz (48 KHz) */
                    453:                y0 = ((x0 + x1) + (6*y0)) >> 3;
1.1.1.12  root      454: 
1.1.1.17  root      455:        x1 = x0;
                    456:        return y0;
1.1.1.12  root      457: }
                    458: 
1.1.1.18  root      459: /**
                    460:  * This piecewise selective filter works by filtering the falling
                    461:  * edge of a sampled pulse-wave differently from the rising edge.
                    462:  *
                    463:  * Piecewise selective filtering is effective because harmonics on
                    464:  * one part of a wave partially define harmonics on other portions.
                    465:  *
                    466:  * Piecewise selective filtering can efficiently reduce aliasing
                    467:  * with minimal harmonic removal.
                    468:  *
                    469:  * I disclose this information into the public domain so that it
                    470:  * cannot be patented. May 23 2012 David Savinkoff.
                    471:  */
                    472: static ymsample        PWMaliasFilter(ymsample x0)
                    473: {
                    474:        static  yms32 y0 = 0, x1 = 0;
                    475: 
                    476:        if (x0 >= y0)
                    477:        /* YM Pull up   */
                    478:                y0 = x0;
                    479:        else
                    480:        /* R8 Pull down */
                    481:                y0 = (3*(x0 + x1) + (y0<<1)) >> 3;
                    482: 
                    483:        x1 = x0;
                    484:        return y0;
                    485: }
                    486: 
1.1.1.12  root      487: 
                    488: 
                    489: /*--------------------------------------------------------------*/
                    490: /* Build the volume conversion table used to simulate the      */
                    491: /* behaviour of DAC used with the YM2149 in the atari ST.      */
                    492: /* The final 32*32*32 table is built using a 16*16*16 table    */
                    493: /* of all possible fixed volume combinations on a ST.          */
                    494: /*--------------------------------------------------------------*/
                    495: 
1.1.1.18  root      496: static void    interpolate_volumetable(ymu16 volumetable[32][32][32])
1.1.1.12  root      497: {
1.1.1.18  root      498:        int     i, j, k;
1.1.1.12  root      499: 
1.1.1.18  root      500:        for (i = 1; i < 32; i += 2) { /* Copy 16 Panels to make a Block */
                    501:                for (j = 1; j < 32; j += 2) { /* Copy 16 Rows to make a Panel */
                    502:                        for (k = 1; k < 32; k += 2) { /* Copy 16 Elements to make a Row */
                    503:                                volumetable[i][j][k] = volumetable_original[(i-1)/2][(j-1)/2][(k-1)/2];
1.1.1.12  root      504:                        }
1.1.1.18  root      505:                        volumetable[i][j][0] = volumetable[i][j][1]; /* Move 0th Element */
                    506:                        volumetable[i][j][1] = volumetable[i][j][3]; /* Move 1st Element */
                    507:                        /* Interpolate 3rd Element */
                    508:                        volumetable[i][j][3] = (ymu16)(0.5 + sqrt((double)volumetable[i][j][1] * volumetable[i][j][5]));
                    509:                        for (k = 2; k < 32; k += 2) /* Interpolate Even Elements */
                    510:                                volumetable[i][j][k] = (ymu16)(0.5 + sqrt((double)volumetable[i][j][k-1] * volumetable[i][j][k+1]));
1.1.1.12  root      511:                }
1.1.1.18  root      512:                for (k = 0; k < 32; k++) {
                    513:                        volumetable[i][0][k] = volumetable[i][1][k]; /* Move 0th Row */
                    514:                        volumetable[i][1][k] = volumetable[i][3][k]; /* Move 1st Row */
                    515:                        /* Interpolate 3rd Row */
                    516:                        volumetable[i][3][k] = (ymu16)(0.5 + sqrt((double)volumetable[i][1][k] * volumetable[i][5][k]));
                    517:                }
                    518:                for (j = 2; j < 32; j += 2) /* Interpolate Even Rows */
                    519:                        for (k = 0; k < 32; k++)
                    520:                                volumetable[i][j][k] = (ymu16)(0.5 + sqrt((double)volumetable[i][j-1][k] * volumetable[i][j+1][k]));
1.1.1.11  root      521:        }
1.1.1.18  root      522:        for (j = 0; j < 32; j++)
                    523:                for (k = 0; k < 32; k++) {
                    524:                        volumetable[0][j][k] = volumetable[1][j][k]; /* Move 0th Panel */
                    525:                        volumetable[1][j][k] = volumetable[3][j][k]; /* Move 1st Panel */
                    526:                        /* Interpolate 3rd Panel */
                    527:                        volumetable[3][j][k] = (ymu16)(0.5 + sqrt((double)volumetable[1][j][k] * volumetable[5][j][k]));
                    528:                }
                    529:        for (i = 2; i < 32; i += 2) /* Interpolate Even Panels */
                    530:                for (j = 0; j < 32; j++) /* Interpolate Even Panels */
                    531:                        for (k = 0; k < 32; k++)
                    532:                                volumetable[i][j][k] = (ymu16)(0.5 + sqrt((double)volumetable[i-1][j][k] * volumetable[i+1][j][k]));
1.1       root      533: }
                    534: 
1.1.1.5   root      535: 
1.1.1.12  root      536: 
                    537: 
1.1.1.2   root      538: /*-----------------------------------------------------------------------*/
1.1.1.11  root      539: /**
1.1.1.12  root      540:  * Build a linear version of the conversion table.
                    541:  * We use the mean of the 3 volumes converted to 16 bit values
                    542:  * (each value of ymout1c5bit is in [0,65535])
1.1.1.11  root      543:  */
1.1.1.12  root      544: 
1.1.1.18  root      545: static void    YM2149_BuildLinearVolumeTable(ymu16 volumetable[32][32][32])
1.1       root      546: {
1.1.1.12  root      547:        int     i, j, k;
                    548: 
                    549:        for (i = 0; i < 32; i++)
                    550:                for (j = 0; j < 32; j++)
                    551:                        for (k = 0; k < 32; k++)
1.1.1.18  root      552:                                volumetable[i][j][k] = (ymu16)( ((ymu32)ymout1c5bit[i] + ymout1c5bit[j] + ymout1c5bit[k]) / 3);
1.1.1.12  root      553: }
                    554: 
                    555: 
                    556: 
1.1       root      557: 
1.1.1.12  root      558: /*-----------------------------------------------------------------------*/
                    559: /**
1.1.1.17  root      560:  * Build a circuit analysed version of the conversion table.
                    561:  * David Savinkoff designed this algorithm by analysing data
                    562:  * measured by Paulo Simoes and Benjamin Gerard.
                    563:  * The numbers are arrived at by assuming a current steering
                    564:  * resistor ladder network and using the voltage divider rule.
1.1.1.18  root      565:  *
                    566:  * If one looks at the ST schematic of the YM2149, one sees
                    567:  * three sound pins tied together and attached to a 1000 ohm
                    568:  * resistor (1k) that has the other end grounded.
                    569:  * The 1k resistor is also in parallel with a 0.1 microfarad
                    570:  * capacitor (on the Atari ST, not STE or others). The voltage
                    571:  * developed across the 1K resistor is the output voltage which
                    572:  * I call Vout.
                    573:  *
1.1.1.19  root      574:  * The output of the YM2149 is modelled well as pullup resistors.
1.1.1.18  root      575:  * Thus, the three sound pins are seen as three parallel
                    576:  * computer-controlled, adjustable pull-up resistors.
                    577:  * To emulate the output of the YM2149, one must determine the
                    578:  * resistance values of the YM2149 relative to the 1k resistor,
                    579:  * which is done by the 'math model'.
                    580:  *
                    581:  * The AC + DC math model is:
                    582:  *
                    583:  * (MaxVol*WARP) / (1.0 + 1.0/(conductance_[i]+conductance_[j]+conductance_[k]))
                    584:  * or
                    585:  * (MaxVol*WARP) / (1.0 + 1.0/( 1/Ra +1/Rb  +1/Rc )) , Ra = channel A resistance
                    586:  *
                    587:  * Note that the first 1.0 in the formula represents the
                    588:  * normalized 1k resistor (1.0 * 1000 ohms = 1k).
                    589:  *
                    590:  * The YM2149 DC component model represents the output voltage
                    591:  * filtered of high frequency AC component, but DC component
                    592:  * remains.
                    593:  * The YM2149 DC component mode treats the voltage exactly as if
                    594:  * it were low pass filtered. This is more than what is required
                    595:  * to make 'quartet mode sound'. Simplicity leads to Generality!
                    596:  *
                    597:  * The DC component model model is:
                    598:  *
                    599:  * (MaxVol*WARP) / (2.0 + 1.0/( 1/Ra + 1/Rb  + 1/Rc))
                    600:  * or
                    601:  * (MaxVol*WARP*0.5) / (1.0 + 0.5/( 1/Ra + 1/Rb  + 1/Rc))
                    602:  *
                    603:  * Note that the 1.0 represents the normalized 1k resistor.
                    604:  * 0.5 represents 50% duty cycle for the parallel resistors
                    605:  * being summed (this effectively doubles the pull-up resistance).
1.1.1.17  root      606:  */
                    607: 
1.1.1.18  root      608: static void    YM2149_BuildModelVolumeTable(ymu16 volumetable[32][32][32])
1.1.1.17  root      609: {
1.1.1.18  root      610: #define MaxVol  65535.0               /* Normal Mode Maximum value in table */
                    611: #define FOURTH2 1.19                  /* Fourth root of two from YM2149 */
                    612: #define WARP    1.666666666666666667  /* measured as 1.65932 from 46602 */
1.1.1.17  root      613: 
                    614:        double conductance;
                    615:        double conductance_[32];
                    616:        int     i, j, k;
                    617: 
                    618: /**
                    619:  * YM2149 and R8=1k follows (2^-1/4)^(n-31) better when 2 voices are
                    620:  * summed (A+B or B+C or C+A) rather than individually (A or B or C):
1.1.1.18  root      621:  *   conductance = 2.0/3.0/(1.0-1.0/WARP)-2.0/3.0;
1.1.1.17  root      622:  * When taken into consideration with three voices.
                    623:  *
                    624:  * Note that the YM2149 does not use laser trimmed resistances, thus
                    625:  * has offsets that are added and/or multiplied with (2^-1/4)^(n-31).
                    626:  */
1.1.1.18  root      627:        conductance = 2.0/3.0/(1.0-1.0/WARP)-2.0/3.0; /* conductance = 1.0 */
1.1.1.17  root      628: 
                    629: /**
                    630:  * Because the YM current output (voltage source with series resistances)
                    631:  * is connected to a grounded resistor to develop the output voltage
                    632:  * (instead of a current to voltage converter), the output transfer
                    633:  * function is not linear. Thus:
                    634:  * 2.0*conductance_[n] = 1.0/(1.0-1.0/FOURTH2/(1.0/conductance + 1.0))-1.0;
                    635:  */
                    636:        for (i = 31; i >= 1; i--)
                    637:        {
                    638:                conductance_[i] = conductance/2.0;
                    639:                conductance = 1.0/(1.0-1.0/FOURTH2/(1.0/conductance + 1.0))-1.0;
                    640:        }
1.1.1.18  root      641:        conductance_[0] = 1.0e-8; /* Avoid divide by zero */
1.1.1.17  root      642: 
1.1.1.18  root      643: /**
                    644:  * YM2149 AC + DC components model:
                    645:  * (Note that Maxvol is 65119 in Simoes' table, 65535 in Gerard's)
                    646:  *
                    647:  * Sum the conductances as a function of a voltage divider:
                    648:  * Vout=Vin*Rout/(Rout+Rin)
                    649:  */
1.1.1.17  root      650:        for (i = 0; i < 32; i++)
                    651:                for (j = 0; j < 32; j++)
                    652:                        for (k = 0; k < 32; k++)
                    653:                        {
1.1.1.18  root      654:                                volumetable[i][j][k] = (ymu16)(0.5+(MaxVol*WARP)/(1.0 +
1.1.1.17  root      655:                                        1.0/(conductance_[i]+conductance_[j]+conductance_[k])));
                    656:                        }
1.1.1.18  root      657: 
                    658: /**
                    659:  * YM2149 DC component model:
                    660:  * R8=1k (pulldown) + YM//1K (pullup) with YM 50% duty PWM
                    661:  * (Note that MaxVol is 46602 in Paulo Simoes Quartet mode table)
                    662:  *
                    663:  *     for (i = 0; i < 32; i++)
                    664:  *             for (j = 0; j < 32; j++)
                    665:  *                     for (k = 0; k < 32; k++)
                    666:  *                     {
                    667:  *                             volumetable[i][j][k] = (ymu16)(0.5+(MaxVol*WARP)/(1.0 +
                    668:  *                                     2.0/(conductance_[i]+conductance_[j]+conductance_[k])));
                    669:  *                     }
                    670:  */
1.1.1.17  root      671: }
                    672: 
                    673: 
                    674: 
                    675: 
                    676: /*-----------------------------------------------------------------------*/
                    677: /**
1.1.1.12  root      678:  * Normalise and optionally center the volume table used to
                    679:  * convert the 3 volumes to a final signed 16 bit sample.
                    680:  * This allows to adapt the amplitude/volume of the samples and
                    681:  * to convert unsigned values to signed values.
                    682:  * - in_5bit contains 32*32*32 unsigned values in the range
                    683:  *     [0,65535].
                    684:  * - out_5bit will contain signed values
                    685:  * Possible values are :
                    686:  *     Level=65535 and DoCenter=TRUE -> [-32768,32767]
1.1.1.14  root      687:  *     Level=32767 and DoCenter=false -> [0,32767]
1.1.1.19  root      688:  *     Level=16383 and DoCenter=false -> [0,16383] (to avoid overflow with DMA sound on STe)
1.1.1.12  root      689:  */
                    690: 
                    691: static void    YM2149_Normalise_5bit_Table(ymu16 *in_5bit , yms16 *out_5bit, unsigned int Level, bool DoCenter)
                    692: {
                    693:        if ( Level )
1.1.1.11  root      694:        {
1.1.1.14  root      695:                int h;
1.1.1.12  root      696:                int Max = in_5bit[0x7fff];
1.1.1.19  root      697:                int Center = (Level+1)>>1;
1.1.1.14  root      698:                //fprintf ( stderr , "level %d max %d center %d\n" , Level, Max, Center );
                    699: 
1.1.1.12  root      700:                /* Change the amplitude of the signal to 'level' : [0,max] -> [0,level] */
                    701:                /* Then optionally center the signal around Level/2 */
                    702:                /* This means we go from sthg like [0,65535] to [-32768, 32767] if Level=65535 and DoCenter=TRUE */
                    703:                for (h=0; h<32*32*32; h++)
                    704:                {
                    705:                        int tmp = in_5bit[h], res;
                    706:                        res = tmp * Level / Max;
1.1.1.14  root      707: 
1.1.1.12  root      708:                        if ( DoCenter )
                    709:                                res -= Center;
                    710: 
                    711:                        out_5bit[h] = res;
1.1.1.14  root      712:                        //fprintf ( stderr , "h %d in %d out %d\n" , h , tmp , res );
1.1.1.12  root      713:                }
1.1.1.11  root      714:        }
1.1       root      715: }
                    716: 
1.1.1.5   root      717: 
1.1.1.12  root      718: 
                    719: 
1.1.1.2   root      720: /*-----------------------------------------------------------------------*/
1.1.1.11  root      721: /**
1.1.1.12  root      722:  * Precompute all 16 possible envelopes.
                    723:  * Each envelope is made of 3 blocks of 32 volumes.
1.1.1.11  root      724:  */
1.1.1.12  root      725: 
                    726: static void    YM2149_EnvBuild ( void )
1.1       root      727: {
1.1.1.12  root      728:        int     env;
                    729:        int     block;
                    730:        int     vol=0 , inc=0;
                    731:        int     i;
1.1       root      732: 
1.1.1.12  root      733: 
                    734:        for ( env=0 ; env<16 ; env++ )                          /* 16 possible envelopes */
                    735:                for ( block=0 ; block<3 ; block++ )             /* 3 blocks to define an envelope */
                    736:                {
1.1.1.14  root      737:                        switch ( YmEnvDef[ env ][ block ] )
                    738:                        {
1.1.1.12  root      739:                                case ENV_GODOWN :       vol=31 ; inc=-1 ; break;
                    740:                                case ENV_GOUP :         vol=0  ; inc=1 ; break;
                    741:                                case ENV_DOWN :         vol=0  ; inc=0 ; break;
                    742:                                case ENV_UP :           vol=31 ; inc=0 ; break;
1.1.1.14  root      743:                        }
                    744: 
1.1.1.12  root      745:                        for ( i=0 ; i<32 ; i++ )                /* 32 volumes per block */
                    746:                        {
                    747:                                YmEnvWaves[ env ][ block*32 + i ] = YM_MERGE_VOICE ( vol , vol , vol );
                    748:                                vol += inc;
                    749:                        }
                    750:                }
                    751: }
                    752: 
                    753: 
                    754: 
                    755: /*-----------------------------------------------------------------------*/
                    756: /**
1.1.1.16  root      757:  * Depending on the YM mixing method, build the table used to convert
                    758:  * the 3 YM volumes into a single sample.
1.1.1.12  root      759:  */
                    760: 
1.1.1.16  root      761: static void    Ym2149_BuildVolumeTable(void)
1.1.1.12  root      762: {
                    763:        /* Depending on the volume mixing method, we use a table based on real measures */
                    764:        /* or a table based on a linear volume mixing. */
1.1.1.17  root      765:        if ( YmVolumeMixing == YM_MODEL_MIXING )
                    766:                YM2149_BuildModelVolumeTable(ymout5_u16);       /* create 32*32*32 circuit analysed model of the volume table */
                    767:        else if ( YmVolumeMixing == YM_TABLE_MIXING )
1.1.1.16  root      768:                interpolate_volumetable(ymout5_u16);            /* expand the 16*16*16 values in volumetable_original to 32*32*32 */
1.1.1.12  root      769:        else
                    770:                YM2149_BuildLinearVolumeTable(ymout5_u16);      /* combine the 32 possible volumes */
                    771: 
                    772:        /* Normalise/center the values (convert from u16 to s16) */
1.1.1.19  root      773:        /* On STE/TT, we use YM_OUTPUT_LEVEL>>1 to avoid overflow with DMA sound */
1.1.1.21  root      774:        if (Config_IsMachineSTE() || Config_IsMachineTT())
1.1.1.19  root      775:                YM2149_Normalise_5bit_Table ( ymout5_u16[0][0] , ymout5 , (YM_OUTPUT_LEVEL>>1) , YM_OUTPUT_CENTERED );
                    776:        else
                    777:                YM2149_Normalise_5bit_Table ( ymout5_u16[0][0] , ymout5 , YM_OUTPUT_LEVEL , YM_OUTPUT_CENTERED );
1.1.1.16  root      778: }
                    779: 
                    780: 
                    781: 
                    782: /*-----------------------------------------------------------------------*/
                    783: /**
                    784:  * Init some internal tables for faster results (env, volume)
                    785:  * and reset the internal states.
                    786:  */
                    787: 
                    788: static void    Ym2149_Init(void)
                    789: {
                    790:        /* Build the 16 envelope shapes */
                    791:        YM2149_EnvBuild();
                    792: 
                    793:        /* Build the volume conversion table */
                    794:        Ym2149_BuildVolumeTable();
1.1.1.12  root      795: 
                    796:        /* Reset YM2149 internal states */
                    797:        Ym2149_Reset();
                    798: }
                    799: 
                    800: 
                    801: 
                    802: /*-----------------------------------------------------------------------*/
                    803: /**
1.1.1.16  root      804:  * Reset all ym registers as well as the internal variables
1.1.1.12  root      805:  */
                    806: 
                    807: static void    Ym2149_Reset(void)
                    808: {
                    809:        int     i;
1.1.1.14  root      810: 
1.1.1.12  root      811:        for ( i=0 ; i<14 ; i++ )
                    812:                Sound_WriteReg ( i , 0 );
                    813: 
                    814:        Sound_WriteReg ( 7 , 0xff );
                    815: 
1.1.1.22! root      816:        /* Reset internal variables and counters */
        !           817:        ToneA_per = ToneA_count = 0;
        !           818:        ToneB_per = ToneB_count = 0;
        !           819:        ToneC_per = ToneC_count = 0;
        !           820:        Noise_per = Noise_count = 0;
        !           821:        Env_per = Env_count = 0;
        !           822: 
        !           823:        ToneA_val = ToneB_val = ToneC_val = Noise_val = YM_SQUARE_DOWN;
        !           824:        ToneA_force = ToneB_force = ToneC_force = 0;
        !           825: 
        !           826:        YM2149_TonePerFilter ( ToneA_per , &ToneA_force );
        !           827:        YM2149_TonePerFilter ( ToneB_per , &ToneB_force );
        !           828:        YM2149_TonePerFilter ( ToneC_per , &ToneC_force );
        !           829: 
        !           830:        YM_Clock_Step = 0;
        !           831: 
        !           832:        RndRack = 1;
        !           833: 
        !           834:        /* old code */
        !           835: 
1.1.1.16  root      836:        posA = 0;
                    837:        posB = 0;
                    838:        posC = 0;
                    839: 
1.1.1.12  root      840:        currentNoise = 0xffff;
1.1.1.14  root      841: 
1.1.1.22! root      842:        Env_shape = 0;
        !           843:        Env_pos = 0;
1.1.1.12  root      844: }
                    845: 
                    846: 
                    847: 
                    848: /*-----------------------------------------------------------------------*/
                    849: /**
                    850:  * Returns a pseudo random value, used to generate white noise.
1.1.1.19  root      851:  * As measured by David Savinkoff, the YM2149 uses a 17 stage LSFR with
                    852:  * 2 taps (17,14)
1.1.1.12  root      853:  */
                    854: 
                    855: static ymu32   YM2149_RndCompute(void)
                    856: {
1.1.1.19  root      857:        /*  17 stage, 2 taps (17, 14) LFSR */
                    858:        if (RndRack & 1)
                    859:        {
                    860:                RndRack = RndRack>>1 ^ 0x12000;         /* bits 17 and 14 are ones */
                    861:                return 0xffff;
                    862:        }
                    863:        else
                    864:        {       RndRack >>= 1;
                    865:                return 0;
                    866:        }
1.1.1.12  root      867: }
                    868: 
                    869: 
                    870: 
                    871: /*-----------------------------------------------------------------------*/
                    872: /**
1.1.1.16  root      873:  * Compute tone's step based on the input period.
                    874:  * Although for tone we should have the same result when per==0 and per==1,
                    875:  * this gives some very sharp and unpleasant sounds in the emulation.
                    876:  * To get a better sound, we consider all per<=5 to give step=0, which will
                    877:  * produce a constant output at value '1'. This should be handled with some
                    878:  * proper filters to remove high frequencies as on a real ST (where per<=9
                    879:  * gives nearly no audible sound).
                    880:  * A common replay freq of 44.1 kHz will also not be high enough to correctly
                    881:  * render possible tone's freq of 125 or 62.5 kHz (when per==1 or per==2)
1.1.1.12  root      882:  */
                    883: 
1.1.1.16  root      884: static ymu32   Ym2149_ToneStepCompute(ymu8 rHigh , ymu8 rLow)
                    885: {
                    886:        int     per;
                    887:        yms64   step;
                    888: 
                    889:        per = rHigh&15;
                    890:        per = (per<<8)+rLow;
                    891: 
1.1.1.22! root      892: #if 1                                                  /* need some high freq filters for this to work correctly */
1.1.1.16  root      893:        if ( per == 0 )
                    894:                per = 1;                                /* result for Per=0 is the same as for Per=1 */ 
                    895: #else
1.1.1.18  root      896:        if  (per <= (int)(YM_ATARI_CLOCK/(YM_REPLAY_FREQ*7)) )
                    897:                return 0;                               /* discard frequencies higher than 80% of nyquist rate. */
1.1.1.16  root      898: #endif
                    899: 
                    900:        step = YM_ATARI_CLOCK;
                    901:        step <<= 24;
                    902: 
                    903:        step /= (per * 8 * YM_REPLAY_FREQ);             /* 0x5ab9 < step < 0x5ab3f46 at 44.1 kHz */
                    904: 
                    905:        return step;
                    906: }
1.1.1.21  root      907: 
                    908: 
1.1.1.22! root      909: static ymu16   YM2149_TonePer(ymu8 rHigh , ymu8 rLow , ymu16 *pTone_force)
        !           910: {
        !           911:        ymu16   per;
        !           912: 
        !           913:        per = ( ( rHigh & 0x0f ) << 8 ) + rLow;
        !           914:        YM2149_TonePerFilter ( per , pTone_force );
        !           915:        return per;
        !           916: }
        !           917: 
        !           918: 
        !           919: static ymu16   YM2149_NoisePer(ymu8 rNoise)
        !           920: {
        !           921:        ymu16   per;
        !           922: 
        !           923:        per = rNoise & 0x1f;
        !           924:        return per;
        !           925: }
        !           926: 
        !           927: 
        !           928: static ymu16   YM2149_EnvPer(ymu8 rHigh , ymu8 rLow)
        !           929: {
        !           930:        ymu16   per;
        !           931: 
        !           932:        per = ( rHigh << 8 ) + rLow;
        !           933:        return per;
        !           934: }
        !           935: 
        !           936: 
        !           937: 
1.1.1.12  root      938: 
1.1.1.16  root      939: /*-----------------------------------------------------------------------*/
                    940: /**
                    941:  * Compute noise's step based on the input period.
                    942:  * On a real STF, we get the same result when per==0 and per==1.
                    943:  * A common replay freq of 44.1 kHz will not be high enough to correctly
                    944:  * render possible noise's freq of 125 or 62.5 kHz (when per==1 or per==2).
                    945:  * With a random wave such as noise, this means that with a replay freq
                    946:  * of 44.1 kHz, per==1 and per==2 (as well as per==3) will sound the same :
                    947:  *     per==1   step=0x2d59fa3   freq=125 kHz
                    948:  *     per==2   step=0x16acfd1   freq=62.5 kHz
                    949:  *     per==3   step=0x0f1dfe1   freq=41.7 kHz
                    950:  */
1.1.1.12  root      951: 
1.1.1.16  root      952: static ymu32   Ym2149_NoiseStepCompute(ymu8 rNoise)
                    953: {
                    954:        int     per;
                    955:        yms64   step;
                    956: 
                    957:        per = (rNoise&0x1f);
1.1       root      958: 
1.1.1.16  root      959:        if ( per == 0 )
1.1.1.22! root      960:                per = 1;
1.1.1.16  root      961: 
                    962:        step = YM_ATARI_CLOCK;
                    963:        step <<= 24;
                    964: 
                    965:        step /= (per * 16 * YM_REPLAY_FREQ);            /* 0x17683f < step < 0x2d59fa3 at 44.1 kHz */
                    966: 
                    967:        return step;
                    968: }
1.1.1.21  root      969: 
                    970: 
1.1.1.5   root      971: 
1.1.1.2   root      972: /*-----------------------------------------------------------------------*/
1.1.1.11  root      973: /**
1.1.1.12  root      974:  * Compute envelope's step. The envelope is made of different patterns
                    975:  * of 32 volumes. In each pattern, the volume is changed at frequency
                    976:  * Fe = MasterClock / ( 8 * EnvPer ).
                    977:  * In our case, we use a lower replay freq ; between 2 consecutive calls
                    978:  * to envelope's generation, the internal counter will advance 'step'
                    979:  * units, where step = MasterClock / ( 8 * EnvPer * YM_REPLAY_FREQ )
                    980:  * As 'step' requires floating point to be stored, we use left shifting
                    981:  * to multiply 'step' by a fixed amount. All operations are made with
                    982:  * shifted values ; to get the final value, we must right shift the
                    983:  * result. We use '<<24', which gives 8 bits for the integer part, and
                    984:  * the equivalent of 24 bits for the fractional part.
                    985:  * Since we're using large numbers, we temporarily use 64 bits integer
                    986:  * to avoid overflow and keep largest precision possible.
1.1.1.16  root      987:  * On a real STF, we get the same result when per==0 and per==1.
1.1.1.11  root      988:  */
1.1.1.12  root      989: 
                    990: static ymu32   Ym2149_EnvStepCompute(ymu8 rHigh , ymu8 rLow)
1.1       root      991: {
1.1.1.12  root      992:        yms64   per;
1.1.1.14  root      993:        yms64   step;
1.1       root      994: 
1.1.1.12  root      995:        per = rHigh;
                    996:        per = (per<<8)+rLow;
                    997: 
1.1.1.14  root      998:        step = YM_ATARI_CLOCK;
1.1.1.12  root      999:        step <<= 24;
1.1.1.16  root     1000: 
                   1001:        if ( per == 0 )
                   1002:                per = 1;                                /* result for Per=0 is the same as for Per=1 */ 
                   1003: 
                   1004:        step /= (8 * per * YM_REPLAY_FREQ);             /* 0x5ab < step < 0x5ab3f46 at 44.1 kHz */
1.1.1.12  root     1005: 
                   1006:        return step;
                   1007: }
                   1008: 
                   1009: 
                   1010: 
                   1011: /*-----------------------------------------------------------------------*/
                   1012: /**
1.1.1.22! root     1013:  * Filter tone period to get audible results
        !          1014:  *  - in the YM2149, per=0 is the same as per=1
        !          1015:  *  - if per is too low compared to the current replay freq, we output
        !          1016:  *    a constant signal (on a real ST, period <= 9 is not audible in mose cases)
        !          1017:  * TODO : remove this function as we emulate YM2149 at 250 kHz
        !          1018:  */
        !          1019: 
        !          1020: static void    YM2149_TonePerFilter (ymu16 per , ymu16 *pTone_force)
        !          1021: {
        !          1022:        *pTone_force = 0;
        !          1023: 
        !          1024: #ifndef        YM_250_MORE
        !          1025:        /* Discard frequencies higher than 80% of nyquist rate (depending on the current replay freq in Hatari) */
        !          1026:        /* Output a constant signal in that case */
        !          1027:        if  ( per <= (int)(YM_ATARI_CLOCK/(YM_REPLAY_FREQ*7)) )
        !          1028:                *pTone_force = YM_SQUARE_UP;
        !          1029: #endif
        !          1030: }
        !          1031: 
        !          1032: 
        !          1033: 
        !          1034: /*-----------------------------------------------------------------------*/
        !          1035: /**
1.1.1.12  root     1036:  * Main function : compute the value of the next sample.
                   1037:  * Mixes all 3 voices with tone+noise+env and apply low pass
                   1038:  * filter if needed.
1.1.1.16  root     1039:  * All operations are done with integer math, using <<24 to simulate
                   1040:  * floating point precision : upper 8 bits are the integer part, lower 24
                   1041:  * are the fractional part.
                   1042:  * Tone is a square wave with 2 states 0 or 1. If integer part of posX is
                   1043:  * even (bit24=0) we consider output is 0, else (bit24=1) we consider
                   1044:  * output is 1. This gives the value of bt for one voice after extending it
                   1045:  * to all 0 bits or all 1 bits using a '-'
1.1.1.12  root     1046:  */
                   1047: 
1.1.1.22! root     1048: #ifndef YM_250
        !          1049: 
1.1.1.16  root     1050: static ymsample        YM2149_NextSample(void)
                   1051: {
                   1052:        ymsample        sample;
                   1053:        ymu32           bt;
                   1054:        ymu32           bn;
                   1055:        ymu16           Env3Voices;                     /* 0x00CCBBAA */
                   1056:        ymu16           Tone3Voices;                    /* 0x00CCBBAA */
1.1       root     1057: 
                   1058: 
1.1.1.16  root     1059:        /* Noise value : 0 or 0xffff */
                   1060:        if ( noisePos&0xff000000 )                      /* integer part > 0 */
                   1061:        {
1.1.1.19  root     1062:                currentNoise = YM2149_RndCompute();
1.1.1.16  root     1063:                noisePos &= 0xffffff;                   /* keep fractional part of noisePos */
                   1064:        }
                   1065:        bn = currentNoise;                              /* 0 or 0xffff */
                   1066: 
                   1067:        /* Get the 5 bits volume corresponding to the current envelope's position */
1.1.1.22! root     1068:        Env3Voices = YmEnvWaves[ Env_shape ][ Env_pos>>24 ];    /* integer part of Env_pos is in bits 24-31 */
1.1.1.16  root     1069:        Env3Voices &= EnvMask3Voices;                   /* only keep volumes for voices using envelope */
                   1070: 
1.1.1.22! root     1071: //fprintf ( stderr , "env %x %x %x\n" , Env3Voices , envStep , Env_pos );
1.1.1.16  root     1072: 
                   1073:        /* Tone3Voices will contain the output state of each voice : 0 or 0x1f */
                   1074:        bt = -( (posA>>24) & 1);                        /* 0 if bit24=0 or 0xffffffff if bit24=1 */
                   1075:        bt = (bt | mixerTA) & (bn | mixerNA);           /* 0 or 0xffff */
                   1076:        Tone3Voices = bt & YM_MASK_1VOICE;              /* 0 or 0x1f */
                   1077:        bt = -( (posB>>24) & 1);
                   1078:        bt = (bt | mixerTB) & (bn | mixerNB);
                   1079:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 5;
                   1080:        bt = -( (posC>>24) & 1);
                   1081:        bt = (bt | mixerTC) & (bn | mixerNC);
                   1082:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 10;
                   1083: 
                   1084:        /* Combine fixed volumes and envelope volumes and keep the resulting */
                   1085:        /* volumes depending on the output state of each voice (0 or 0x1f) */
                   1086:        Tone3Voices &= ( Env3Voices | Vol3Voices );
                   1087: 
                   1088:        /* D/A conversion of the 3 volumes into a sample using a precomputed conversion table */
1.1.1.18  root     1089: 
                   1090:        if (stepA == 0  &&  (Tone3Voices & YM_MASK_A) > 1)
                   1091:                Tone3Voices -= 1;     /* Voice A AC component removed; Transient DC component remains */
                   1092: 
                   1093:        if (stepB == 0  &&  (Tone3Voices & YM_MASK_B) > 1<<5)
                   1094:                Tone3Voices -= 1<<5;  /* Voice B AC component removed; Transient DC component remains */
                   1095: 
                   1096:        if (stepC == 0  &&  (Tone3Voices & YM_MASK_C) > 1<<10)
                   1097:                Tone3Voices -= 1<<10; /* Voice C AC component removed; Transient DC component remains */
                   1098: 
1.1.1.16  root     1099:        sample = ymout5[ Tone3Voices ];                 /* 16 bits signed value */
                   1100: 
                   1101: 
                   1102:        /* Increment positions */
                   1103:        posA += stepA;
                   1104:        posB += stepB;
                   1105:        posC += stepC;
                   1106:        noisePos += noiseStep;
                   1107: 
1.1.1.22! root     1108:        Env_pos += envStep;
        !          1109:        if ( Env_pos >= (3*32) << 24 )                  /* blocks 0, 1 and 2 were used (Env_pos 0 to 95) */
        !          1110:                Env_pos -= (2*32) << 24;                /* replay/loop blocks 1 and 2 (Env_pos 32 to 95) */
1.1.1.16  root     1111: 
                   1112:        /* Apply low pass filter ? */
1.1.1.22! root     1113:        if ( YM2149_LPF_Filter == YM2149_LPF_FILTER_PWM )
        !          1114:                return PWMaliasFilter(sample);
        !          1115:        else if ( YM2149_LPF_Filter == YM2149_LPF_FILTER_LPF_STF )
1.1.1.18  root     1116:                return LowPassFilter(sample);
                   1117:        else
1.1.1.22! root     1118:                return sample;
        !          1119: }
        !          1120: 
        !          1121: #else
        !          1122: 
        !          1123: #ifndef YM_250_MORE
        !          1124: static ymsample        YM2149_NextSample_250(void)
        !          1125: {
        !          1126:        ymsample        sample;
        !          1127:        ymu32           bt;
        !          1128:        ymu16           Env3Voices;                     /* 0x00CCBBAA */
        !          1129:        ymu16           Tone3Voices;                    /* 0x00CCBBAA */
        !          1130:        static ymu16    Freq_div_2 = 0;
        !          1131: 
        !          1132: 
        !          1133:        /* Emulate as many internal YM cycles as needed until we reach */
        !          1134:        /* the expected replay freq YM_REPLAY_FREQ */
        !          1135:        while ( YM_Clock_Step < YM_ATARI_CLOCK_COUNTER )
        !          1136:        {
        !          1137:                /* Emulate 1 internal YM2149 cycle : increase all counters */
        !          1138:                /* As measured on a real YM2149, result for per==0 is the same as for per==1 */
        !          1139:                /* To obtain this in our code, counters are incremented first, then compared to per, */
        !          1140:                /* which gives the same result when per=1 and when per=0 */
        !          1141: 
        !          1142:                /* Special case for noise counter, it's increased at 125 KHz, not 250 KHz */
        !          1143:                Freq_div_2 ^= 1;
        !          1144:                if ( Freq_div_2 == 0 )
        !          1145:                        Noise_count++;
        !          1146:                if ( Noise_count >= Noise_per )
        !          1147:                {
        !          1148:                        Noise_count = 0;
        !          1149:                        Noise_val = YM2149_RndCompute();/* 0 or 0xffff */
        !          1150:                }
        !          1151: 
        !          1152:                /* Other counters are increased on every call, at 250 KHz */
        !          1153:                ToneA_count++;
        !          1154:                if ( ToneA_count >= ToneA_per )
        !          1155:                {
        !          1156:                        ToneA_count = 0;
        !          1157:                        ToneA_val ^= YM_SQUARE_UP;      /* 0 or 0x1f */
        !          1158:                }
        !          1159: 
        !          1160:                ToneB_count++;
        !          1161:                if ( ToneB_count >= ToneB_per )
        !          1162:                {
        !          1163:                        ToneB_count = 0;
        !          1164:                        ToneB_val ^= YM_SQUARE_UP;      /* 0 or 0x1f */
        !          1165:                }
        !          1166: 
        !          1167:                ToneC_count++;
        !          1168:                if ( ToneC_count >= ToneC_per )
        !          1169:                {
        !          1170:                        ToneC_count = 0;
        !          1171:                        ToneC_val ^= YM_SQUARE_UP;      /* 0 or 0x1f */
        !          1172:                }
        !          1173: 
        !          1174:                Env_count += 1;
        !          1175:                if ( Env_count >= Env_per )
        !          1176:                {
        !          1177:                        Env_count = 0;
        !          1178:                        Env_pos += 1;
        !          1179:                        if ( Env_pos >= 3*32 )          /* blocks 0, 1 and 2 were used (Env_pos 0 to 95) */
        !          1180:                                Env_pos -= 2*32;        /* replay/loop blocks 1 and 2 (Env_pos 32 to 95) */
        !          1181:                }
        !          1182: 
        !          1183:                /* Increase ratio counter between YM_Clock and AudioFreq */
        !          1184:                YM_Clock_Step += YM_REPLAY_FREQ;
        !          1185:        }
        !          1186:        YM_Clock_Step -= YM_ATARI_CLOCK_COUNTER;
        !          1187: 
        !          1188:        /* Build 'sample' value with the latest values of tone/noise/volume/env */
        !          1189: 
        !          1190:        /* Get the 5 bits volume corresponding to the current envelope's position */
        !          1191:        Env3Voices = YmEnvWaves[ Env_shape ][ Env_pos ];
        !          1192:        Env3Voices &= EnvMask3Voices;                   /* only keep volumes for voices using envelope */
        !          1193: 
        !          1194:        /* Tone3Voices will contain the output state of each voice : 0 or 0x1f */
        !          1195:        bt = ToneA_val | ToneA_force;                   /* Force tone to constant 0x1f if needed (filter for very low per values) */
        !          1196:        bt = (bt | mixerTA) & (Noise_val | mixerNA);    /* 0 or 0xffff */
        !          1197:        Tone3Voices = bt & YM_MASK_1VOICE;              /* 0 or 0x1f */
        !          1198: 
        !          1199:        bt = ToneB_val | ToneB_force;
        !          1200:        bt = (bt | mixerTB) & (Noise_val | mixerNB);
        !          1201:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 5;
        !          1202: 
        !          1203:        bt = ToneC_val | ToneC_force;
        !          1204:        bt = (bt | mixerTC) & (Noise_val | mixerNC);
        !          1205:        Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 10;
        !          1206: 
        !          1207:        /* Combine fixed volumes and envelope volumes and keep the resulting */
        !          1208:        /* volumes depending on the output state of each voice (0 or 0x1f) */
        !          1209:        Tone3Voices &= ( Env3Voices | Vol3Voices );
        !          1210: 
        !          1211:        /* D/A conversion of the 3 volumes into a sample using a precomputed conversion table */
        !          1212:        if (ToneA_force && (Tone3Voices & YM_MASK_A) > 1)
        !          1213:                Tone3Voices -= 1;                       /* Voice A AC component removed; Transient DC component remains */
        !          1214: 
        !          1215:        if (ToneB_force && (Tone3Voices & YM_MASK_B) > 1<<5)
        !          1216:                Tone3Voices -= 1<<5;                    /* Voice B AC component removed; Transient DC component remains */
        !          1217: 
        !          1218:        if (ToneC_force && (Tone3Voices & YM_MASK_C) > 1<<10)
        !          1219:                Tone3Voices -= 1<<10;                   /* Voice C AC component removed; Transient DC component remains */
        !          1220: 
        !          1221:        sample = ymout5[ Tone3Voices ];                 /* 16 bits signed value */
        !          1222: 
        !          1223:        /* Apply low pass filter ? */
        !          1224:        if ( YM2149_LPF_Filter == YM2149_LPF_FILTER_LPF_STF )
        !          1225:                return LowPassFilter(sample);
        !          1226:        else if ( YM2149_LPF_Filter == YM2149_LPF_FILTER_PWM )
1.1.1.18  root     1227:                return PWMaliasFilter(sample);
1.1.1.22! root     1228:        else
        !          1229:                return sample;
1.1.1.16  root     1230: }
1.1.1.21  root     1231: 
1.1.1.22! root     1232: #else
        !          1233: 
        !          1234: 
1.1.1.16  root     1235: 
1.1.1.12  root     1236: 
1.1.1.22! root     1237: #ifdef YM_250_DEBUG
        !          1238: /*-----------------------------------------------------------------------*/
        !          1239: /**
        !          1240:  * Write raw 250 kHz samples into a wav sound file as "mono + signed 16 bit PCM + little endian"
        !          1241:  * This is used to compare sound before downsampling at native output freq (eg 44.1 kHz)
        !          1242:  * and to measure the quality of the downsampling method
        !          1243:  */
        !          1244: static void    YM2149_DoSamples_250_Debug ( int SamplesToGenerate , int pos )
        !          1245: {
        !          1246:        static Uint8 WavHeader[] =
        !          1247:        {
        !          1248:                /* RIFF chunk */
        !          1249:                'R', 'I', 'F', 'F',      /* "RIFF" (ASCII Characters) */
        !          1250:                0, 0, 0, 0,              /* Total Length Of Package To Follow (patched when file is closed) */
        !          1251:                'W', 'A', 'V', 'E',      /* "WAVE" (ASCII Characters) */
        !          1252:                /* Format chunk */
        !          1253:                'f', 'm', 't', ' ',      /* "fmt_" (ASCII Characters) */
        !          1254:                0x10, 0, 0, 0,           /* Length Of FORMAT Chunk (always 0x10) */
        !          1255:                0x01, 0,                 /* Always 0x01 */
        !          1256:                0x02, 0,                 /* Number of channels (2 for stereo) */
        !          1257:                0, 0, 0, 0,              /* Sample rate (patched when file header is written) */
        !          1258:                0, 0, 0, 0,              /* Bytes per second (patched when file header is written) */
        !          1259:                0x04, 0,                 /* Bytes per sample (4 = 16 bit stereo) */
        !          1260:                0x10, 0,                 /* Bits per sample (16 bit) */
        !          1261:                /* Data chunk */
        !          1262:                'd', 'a', 't', 'a',
        !          1263:                0, 0, 0, 0,              /* Length of data to follow (will be patched when file is closed) */
        !          1264:        };
        !          1265:        FILE            *file_ptr;
        !          1266:        int             val;
        !          1267:        ymsample        sample;
        !          1268:        int             n;
        !          1269:        static int      wav_size;
        !          1270: 
        !          1271: 
        !          1272:        if ( File_Exists ( "hatari_250.wav" ) )
        !          1273:        {
        !          1274:                file_ptr = fopen( "hatari_250.wav", "rb+");
        !          1275:                fseek ( file_ptr , 0 , SEEK_END );
        !          1276:        }
        !          1277:        else
        !          1278:        {
        !          1279:                file_ptr = fopen( "hatari_250.wav", "wb");
        !          1280:                /* Patch mono, 2 bytes per sample */
        !          1281:                WavHeader[22] = (Uint8)0x01;
        !          1282:                WavHeader[32] = (Uint8)0x02;
        !          1283: 
        !          1284:                /* Patch sample frequency in header structure */
        !          1285:                val = 250000;
        !          1286:                WavHeader[24] = (Uint8)val;
        !          1287:                WavHeader[25] = (Uint8)(val >> 8);
        !          1288:                WavHeader[26] = (Uint8)(val >> 16);
        !          1289:                WavHeader[27] = (Uint8)(val >> 24);
        !          1290:                /* Patch bytes per second in header structure */
        !          1291:                val = 250000 * 2;
        !          1292:                WavHeader[28] = (Uint8)val;
        !          1293:                WavHeader[29] = (Uint8)(val >> 8);
        !          1294:                WavHeader[30] = (Uint8)(val >> 16);
        !          1295:                WavHeader[31] = (Uint8)(val >> 24);
        !          1296: 
        !          1297:                fwrite ( &WavHeader, sizeof(WavHeader), 1, file_ptr );
        !          1298:        }
        !          1299: 
        !          1300:        for ( n=0 ; n<SamplesToGenerate_250 ; n++ )
        !          1301:        {
        !          1302:                sample = SDL_SwapLE16 ( YM_Buffer_250[ pos ] );
        !          1303:                fwrite ( &sample , sizeof(sample) , 1 , file_ptr );
        !          1304:                pos = ( pos + 1 ) % YM_BUFFER_250_SIZE;
        !          1305:                wav_size += 2;
        !          1306:        }
        !          1307: 
        !          1308:        /* Update sizes in header */
        !          1309:        val = 12+24+8+wav_size-8;                       /* RIFF size */
        !          1310:        WavHeader[4] = (Uint8)val;
        !          1311:        WavHeader[5] = (Uint8)(val >> 8);
        !          1312:        WavHeader[6] = (Uint8)(val >> 16);
        !          1313:        WavHeader[7] = (Uint8)(val >> 24);
        !          1314:        val = wav_size;                                 /* data size */
        !          1315:        WavHeader[40] = (Uint8)val;
        !          1316:        WavHeader[41] = (Uint8)(val >> 8);
        !          1317:        WavHeader[42] = (Uint8)(val >> 16);
        !          1318:        WavHeader[43] = (Uint8)(val >> 24);
        !          1319: 
        !          1320:        rewind ( file_ptr );
        !          1321:        fwrite ( &WavHeader, sizeof(WavHeader), 1, file_ptr );
        !          1322: 
        !          1323:        fclose ( file_ptr );
        !          1324: }
        !          1325: #endif
        !          1326: 
        !          1327: 
        !          1328: static void    YM2149_DoSamples_250 ( int SamplesToGenerate )
        !          1329: {
        !          1330:        ymsample        sample;
        !          1331:        ymu32           bt;
        !          1332:        ymu16           Env3Voices;                     /* 0x00CCBBAA */
        !          1333:        ymu16           Tone3Voices;                    /* 0x00CCBBAA */
        !          1334:        static ymu16    Freq_div_2 = 0;
        !          1335:        int             pos;
        !          1336:        int             n;
        !          1337: 
        !          1338: 
        !          1339:        /* Generate enough 250 kHz samples to obtain SamplesToGenerate + 1 samples after downsampling to YM_REPLAY_FREQ */
        !          1340:        SamplesToGenerate_250 = floor ( (double)( SamplesToGenerate + 1 ) * YM_ATARI_CLOCK_COUNTER / YM_REPLAY_FREQ );
        !          1341: 
        !          1342:        /* We need to generate less samples if some of the previous ones were not read yet */
        !          1343:        /* (handle the case where pos_write can wrap at the end of the ring buffer) */
        !          1344:        if ( YM_Buffer_250_pos_write >= YM_Buffer_250_pos_read )
        !          1345:                SamplesToGenerate_250 -= ( YM_Buffer_250_pos_write - YM_Buffer_250_pos_read );
        !          1346:        else
        !          1347:                SamplesToGenerate_250 -= ( YM_Buffer_250_pos_write + YM_BUFFER_250_SIZE - YM_Buffer_250_pos_read );
        !          1348: 
        !          1349:        /* Don't do anything if there's already enough samples between pos_read and pos_write */
        !          1350:        if ( SamplesToGenerate_250 <= 0 )
        !          1351:                return;
        !          1352: 
        !          1353:        pos = YM_Buffer_250_pos_write;
        !          1354: 
        !          1355:        /* Emulate as many internal YM cycles as needed to generate samples */
        !          1356:        for ( n=0 ; n<SamplesToGenerate_250 ; n++ )
        !          1357:        {
        !          1358:                /* Emulate 1 internal YM2149 cycle : increase all counters */
        !          1359:                /* As measured on a real YM2149, result for per==0 is the same as for per==1 */
        !          1360:                /* To obtain this in our code, counters are incremented first, then compared to per, */
        !          1361:                /* which gives the same result when per=1 and when per=0 */
        !          1362: 
        !          1363:                /* Special case for noise counter, it's increased at 125 KHz, not 250 KHz */
        !          1364:                Freq_div_2 ^= 1;
        !          1365:                if ( Freq_div_2 == 0 )
        !          1366:                        Noise_count++;
        !          1367:                if ( Noise_count >= Noise_per )
        !          1368:                {
        !          1369:                        Noise_count = 0;
        !          1370:                        Noise_val = YM2149_RndCompute();/* 0 or 0xffff */
        !          1371:                }
        !          1372: 
        !          1373:                /* Other counters are increased on every call, at 250 KHz */
        !          1374:                ToneA_count++;
        !          1375:                if ( ToneA_count >= ToneA_per )
        !          1376:                {
        !          1377:                        ToneA_count = 0;
        !          1378:                        ToneA_val ^= YM_SQUARE_UP;      /* 0 or 0x1f */
        !          1379:                }
        !          1380: 
        !          1381:                ToneB_count++;
        !          1382:                if ( ToneB_count >= ToneB_per )
        !          1383:                {
        !          1384:                        ToneB_count = 0;
        !          1385:                        ToneB_val ^= YM_SQUARE_UP;      /* 0 or 0x1f */
        !          1386:                }
        !          1387: 
        !          1388:                ToneC_count++;
        !          1389:                if ( ToneC_count >= ToneC_per )
        !          1390:                {
        !          1391:                        ToneC_count = 0;
        !          1392:                        ToneC_val ^= YM_SQUARE_UP;      /* 0 or 0x1f */
        !          1393:                }
        !          1394: 
        !          1395:                Env_count += 1;
        !          1396:                if ( Env_count >= Env_per )
        !          1397:                {
        !          1398:                        Env_count = 0;
        !          1399:                        Env_pos += 1;
        !          1400:                        if ( Env_pos >= 3*32 )          /* blocks 0, 1 and 2 were used (Env_pos 0 to 95) */
        !          1401:                                Env_pos -= 2*32;        /* replay/loop blocks 1 and 2 (Env_pos 32 to 95) */
        !          1402:                }
        !          1403: 
        !          1404:                /* Build 'sample' value with the values of tone/noise/volume/env */
        !          1405: 
        !          1406:                /* Get the 5 bits volume corresponding to the current envelope's position */
        !          1407:                Env3Voices = YmEnvWaves[ Env_shape ][ Env_pos ];
        !          1408:                Env3Voices &= EnvMask3Voices;                   /* only keep volumes for voices using envelope */
        !          1409: 
        !          1410:                /* Tone3Voices will contain the output state of each voice : 0 or 0x1f */
        !          1411:                /* TODO : remove ToneX_force, not needed at 250 kHz */
        !          1412:                bt = ToneA_val | ToneA_force;                   /* Force tone to constant 0x1f if needed (filter for very low per values) */
        !          1413:                bt = (bt | mixerTA) & (Noise_val | mixerNA);    /* 0 or 0xffff */
        !          1414:                Tone3Voices = bt & YM_MASK_1VOICE;              /* 0 or 0x1f */
        !          1415: 
        !          1416:                bt = ToneB_val | ToneB_force;
        !          1417:                bt = (bt | mixerTB) & (Noise_val | mixerNB);
        !          1418:                Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 5;
        !          1419: 
        !          1420:                bt = ToneC_val | ToneC_force;
        !          1421:                bt = (bt | mixerTC) & (Noise_val | mixerNC);
        !          1422:                Tone3Voices |= ( bt & YM_MASK_1VOICE ) << 10;
        !          1423: 
        !          1424:                /* Combine fixed volumes and envelope volumes and keep the resulting */
        !          1425:                /* volumes depending on the output state of each voice (0 or 0x1f) */
        !          1426:                Tone3Voices &= ( Env3Voices | Vol3Voices );
        !          1427: 
        !          1428:                /* D/A conversion of the 3 volumes into a sample using a precomputed conversion table */
        !          1429:                if (ToneA_force && (Tone3Voices & YM_MASK_A) > 1)
        !          1430:                        Tone3Voices -= 1;                       /* Voice A AC component removed; Transient DC component remains */
        !          1431: 
        !          1432:                if (ToneB_force && (Tone3Voices & YM_MASK_B) > 1<<5)
        !          1433:                        Tone3Voices -= 1<<5;                    /* Voice B AC component removed; Transient DC component remains */
        !          1434: 
        !          1435:                if (ToneC_force && (Tone3Voices & YM_MASK_C) > 1<<10)
        !          1436:                        Tone3Voices -= 1<<10;                   /* Voice C AC component removed; Transient DC component remains */
        !          1437: 
        !          1438:                sample = ymout5[ Tone3Voices ];                 /* 16 bits signed value */
        !          1439: 
        !          1440:                /* Apply low pass filter ? */
        !          1441:                if ( YM2149_LPF_Filter == YM2149_LPF_FILTER_LPF_STF )
        !          1442:                        sample = LowPassFilter ( sample );
        !          1443:                else if ( YM2149_LPF_Filter == YM2149_LPF_FILTER_PWM )
        !          1444:                        sample = PWMaliasFilter ( sample );
        !          1445: 
        !          1446:                /* Store sample */
        !          1447:                YM_Buffer_250[ pos ] = sample;
        !          1448:                pos = ( pos + 1 ) % YM_BUFFER_250_SIZE;
        !          1449:        }
        !          1450: 
        !          1451: 
        !          1452: #ifdef YM_250_DEBUG
        !          1453:        /* write raw 250 kHz samples into a wav file */
        !          1454:        YM2149_DoSamples_250_Debug ( SamplesToGenerate_250 , YM_Buffer_250_pos_write );
        !          1455: #endif
        !          1456: 
        !          1457:        YM_Buffer_250_pos_write = pos;
        !          1458: 
        !          1459: }
        !          1460: 
        !          1461: 
        !          1462: 
        !          1463: 
        !          1464: /*-----------------------------------------------------------------------*/
        !          1465: /**
        !          1466:  * Downsample the YM2149 samples data from 250 KHz to YM_REPLAY_FREQ and
        !          1467:  * return the next sample to output.
        !          1468:  *
        !          1469:  * This method will choose the nearest sample from the input buffer
        !          1470:  * which can be not precise enough when frequencies from the input
        !          1471:  * buffer are much higher than YM_REPLAY_FREQ (see Nyquist rate)
        !          1472:  *
        !          1473:  * advantage : fast method
        !          1474:  * disadvantage : more aliasing when high frequency notes are played
        !          1475:  */
        !          1476: static ymsample        YM2149_Next_Resample_Nearest ( void )
        !          1477: {
        !          1478:        static double   pos_fract = 0;
        !          1479:        ymsample        sample;
        !          1480: 
        !          1481: 
        !          1482:        /* Get the nearest sample at pos_read or pos_read+1 */
        !          1483:        if ( pos_fract < 0.5 )
        !          1484:                sample = YM_Buffer_250[ YM_Buffer_250_pos_read ];
        !          1485:        else
        !          1486:                sample = YM_Buffer_250[ ( YM_Buffer_250_pos_read + 1 ) % YM_BUFFER_250_SIZE ];
        !          1487: 
        !          1488:        /* Increase fractional pos and integer pos */
        !          1489:        pos_fract += ( (double)YM_ATARI_CLOCK_COUNTER ) / YM_REPLAY_FREQ;
        !          1490: 
        !          1491:        YM_Buffer_250_pos_read = ( YM_Buffer_250_pos_read + (int)pos_fract ) % YM_BUFFER_250_SIZE;
        !          1492:        pos_fract -= (int)pos_fract;                    /* 0 <= pos_fract < 1 */
        !          1493: 
        !          1494:        return sample;
        !          1495: }
        !          1496: 
        !          1497: 
        !          1498: 
        !          1499: /*-----------------------------------------------------------------------*/
        !          1500: /**
        !          1501:  * Downsample the YM2149 samples data from 250 KHz to YM_REPLAY_FREQ and
        !          1502:  * return the next sample to output.
        !          1503:  *
        !          1504:  * This method will do a weighted average between the 2 input samples
        !          1505:  * surrounding the theoretical position of the sample we want to generate
        !          1506:  *
        !          1507:  * It's a little slower than 'Resample_Nearest' but more accurate 
        !          1508:  */
        !          1509: static ymsample        YM2149_Next_Resample_Weighted_Average_2 ( void )
        !          1510: {
        !          1511:        static double   pos_fract = 0;
        !          1512:        ymsample        sample_before , sample_after;
        !          1513:        ymsample        sample;
        !          1514: 
        !          1515: 
        !          1516:        /* Get the 2 samples that surround pos_read and do a weighted average */
        !          1517:        sample_before = YM_Buffer_250[ YM_Buffer_250_pos_read ];
        !          1518:        sample_after = YM_Buffer_250[ ( YM_Buffer_250_pos_read + 1 ) % YM_BUFFER_250_SIZE ];
        !          1519:        sample = round ( ( 1.0 - pos_fract ) * sample_before + pos_fract * sample_after );
        !          1520: //fprintf ( stderr , "b=%04x a=%04x frac=%f -> res=%04x\n" , sample_before , sample_after , pos_fract , sample );
        !          1521: 
        !          1522:        /* Increase fractional pos and integer pos */
        !          1523:        pos_fract += ( (double)YM_ATARI_CLOCK_COUNTER ) / YM_REPLAY_FREQ;
        !          1524: 
        !          1525:        YM_Buffer_250_pos_read = ( YM_Buffer_250_pos_read + (int)pos_fract ) % YM_BUFFER_250_SIZE;
        !          1526:        pos_fract -= (int)pos_fract;                    /* 0 <= pos_fract < 1 */
        !          1527: 
        !          1528:        return sample;
        !          1529: }
        !          1530: 
        !          1531: 
        !          1532: 
        !          1533: /*-----------------------------------------------------------------------*/
        !          1534: /**
        !          1535:  * Downsample the YM2149 samples data from 250 KHz to YM_REPLAY_FREQ and
        !          1536:  * return the next sample to output.
        !          1537:  *
        !          1538:  * TODO : this method will do a weighted average of all the sample from the input
        !          1539:  * buffer that surround an output sample (for example 250 KHz / 44.1 KHz would
        !          1540:  * do a weighted average on ~5.66 input samples)
        !          1541:  *
        !          1542:  * Would be slower than 'Weighted_Average_2' and take more time. Need to be tested
        !          1543:  * as musics don't use very high freq so often, so it's not sure the quality would
        !          1544:  * be worth the extra time.
        !          1545:  */
        !          1546:  static ymsample       YM2149_Next_Resample_Weighted_Average_N ( void )
        !          1547: {
        !          1548:        return 0;
        !          1549: }
        !          1550: 
        !          1551: 
        !          1552: 
        !          1553: static ymsample        YM2149_NextSample_250_2 ( void )
        !          1554: {
        !          1555:        if ( YM2149_Resample_Method == YM2149_RESAMPLE_METHOD_WEIGHTED_AVERAGE_2 )
        !          1556:                return YM2149_Next_Resample_Weighted_Average_2 ();
        !          1557: 
        !          1558:        else if ( YM2149_Resample_Method == YM2149_RESAMPLE_METHOD_NEAREST )
        !          1559:                return YM2149_Next_Resample_Nearest ();
        !          1560: 
        !          1561:        else if ( YM2149_Resample_Method == YM2149_RESAMPLE_METHOD_WEIGHTED_AVERAGE_N )
        !          1562:                return YM2149_Next_Resample_Weighted_Average_N ();
        !          1563: 
        !          1564:        else
        !          1565:                return 0;
        !          1566: }
        !          1567: #endif
        !          1568: 
        !          1569: #endif
        !          1570: 
1.1.1.2   root     1571: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1572: /**
1.1.1.12  root     1573:  * Update internal variables (steps, volume masks, ...) each
                   1574:  * time an YM register is changed.
1.1.1.11  root     1575:  */
1.1.1.16  root     1576: #define BIT_SHIFT 24
1.1.1.12  root     1577: void   Sound_WriteReg( int reg , Uint8 data )
1.1.1.7   root     1578: {
1.1.1.12  root     1579:        switch (reg)
                   1580:        {
                   1581:                case 0:
                   1582:                        SoundRegs[0] = data;
                   1583:                        stepA = Ym2149_ToneStepCompute ( SoundRegs[1] , SoundRegs[0] );
1.1.1.16  root     1584:                        if (!stepA) posA = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.22! root     1585:                        ToneA_per = YM2149_TonePer ( SoundRegs[1] , SoundRegs[0] , &ToneA_force );
1.1.1.12  root     1586:                        break;
                   1587: 
                   1588:                case 1:
                   1589:                        SoundRegs[1] = data & 0x0f;
                   1590:                        stepA = Ym2149_ToneStepCompute ( SoundRegs[1] , SoundRegs[0] );
1.1.1.16  root     1591:                        if (!stepA) posA = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.22! root     1592:                        ToneA_per = YM2149_TonePer ( SoundRegs[1] , SoundRegs[0] , &ToneA_force );
1.1.1.12  root     1593:                        break;
                   1594: 
                   1595:                case 2:
                   1596:                        SoundRegs[2] = data;
                   1597:                        stepB = Ym2149_ToneStepCompute ( SoundRegs[3] , SoundRegs[2] );
1.1.1.16  root     1598:                        if (!stepB) posB = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.22! root     1599:                        ToneB_per = YM2149_TonePer ( SoundRegs[3] , SoundRegs[2] , &ToneB_force );
1.1.1.12  root     1600:                        break;
1.1.1.7   root     1601: 
1.1.1.12  root     1602:                case 3:
                   1603:                        SoundRegs[3] = data & 0x0f;
                   1604:                        stepB = Ym2149_ToneStepCompute ( SoundRegs[3] , SoundRegs[2] );
1.1.1.16  root     1605:                        if (!stepB) posB = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.22! root     1606:                        ToneB_per = YM2149_TonePer ( SoundRegs[3] , SoundRegs[2] , &ToneB_force );
1.1.1.12  root     1607:                        break;
                   1608: 
                   1609:                case 4:
                   1610:                        SoundRegs[4] = data;
                   1611:                        stepC = Ym2149_ToneStepCompute ( SoundRegs[5] , SoundRegs[4] );
1.1.1.16  root     1612:                        if (!stepC) posC = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.22! root     1613:                        ToneC_per = YM2149_TonePer ( SoundRegs[5] , SoundRegs[4] , &ToneC_force );
1.1.1.12  root     1614:                        break;
                   1615: 
                   1616:                case 5:
                   1617:                        SoundRegs[5] = data & 0x0f;
                   1618:                        stepC = Ym2149_ToneStepCompute ( SoundRegs[5] , SoundRegs[4] );
1.1.1.16  root     1619:                        if (!stepC) posC = 1u<<BIT_SHIFT;               // Assume output always 1 if 0 period (for Digi-sample)
1.1.1.22! root     1620:                        ToneC_per = YM2149_TonePer ( SoundRegs[5] , SoundRegs[4] , &ToneC_force );
1.1.1.12  root     1621:                        break;
                   1622: 
                   1623:                case 6:
                   1624:                        SoundRegs[6] = data & 0x1f;
                   1625:                        noiseStep = Ym2149_NoiseStepCompute ( SoundRegs[6] );
                   1626:                        if (!noiseStep)
                   1627:                        {
                   1628:                                noisePos = 0;
                   1629:                                currentNoise = 0xffff;
                   1630:                        }
1.1.1.22! root     1631:                        Noise_per = YM2149_NoisePer ( SoundRegs[6] );
1.1.1.12  root     1632:                        break;
                   1633: 
                   1634:                case 7:
                   1635:                        SoundRegs[7] = data & 0x3f;                     /* ignore bits 6 and 7 */
                   1636:                        mixerTA = (data&(1<<0)) ? 0xffff : 0;
                   1637:                        mixerTB = (data&(1<<1)) ? 0xffff : 0;
                   1638:                        mixerTC = (data&(1<<2)) ? 0xffff : 0;
                   1639:                        mixerNA = (data&(1<<3)) ? 0xffff : 0;
                   1640:                        mixerNB = (data&(1<<4)) ? 0xffff : 0;
                   1641:                        mixerNC = (data&(1<<5)) ? 0xffff : 0;
                   1642:                        break;
                   1643: 
                   1644:                case 8:
                   1645:                        SoundRegs[8] = data & 0x1f;
                   1646:                        if ( data & 0x10 )
                   1647:                        {
                   1648:                                EnvMask3Voices |= YM_MASK_A;            /* env ON */
                   1649:                                Vol3Voices &= ~YM_MASK_A;               /* fixed vol OFF */
                   1650:                        }
                   1651:                        else
                   1652:                        {
                   1653:                                EnvMask3Voices &= ~YM_MASK_A;           /* env OFF */
                   1654:                                Vol3Voices &= ~YM_MASK_A;               /* clear previous vol */
                   1655:                                Vol3Voices |= YmVolume4to5[ SoundRegs[8] ];     /* fixed vol ON */
                   1656:                        }
                   1657:                        break;
1.1.1.14  root     1658: 
1.1.1.12  root     1659:                case 9:
                   1660:                        SoundRegs[9] = data & 0x1f;
                   1661:                        if ( data & 0x10 )
                   1662:                        {
                   1663:                                EnvMask3Voices |= YM_MASK_B;            /* env ON */
                   1664:                                Vol3Voices &= ~YM_MASK_B;               /* fixed vol OFF */
                   1665:                        }
                   1666:                        else
                   1667:                        {
                   1668:                                EnvMask3Voices &= ~YM_MASK_B;           /* env OFF */
                   1669:                                Vol3Voices &= ~YM_MASK_B;               /* clear previous vol */
                   1670:                                Vol3Voices |= ( YmVolume4to5[ SoundRegs[9] ] ) << 5;    /* fixed vol ON */
                   1671:                        }
                   1672:                        break;
1.1.1.14  root     1673: 
1.1.1.12  root     1674:                case 10:
                   1675:                        SoundRegs[10] = data & 0x1f;
                   1676:                        if ( data & 0x10 )
                   1677:                        {
                   1678:                                EnvMask3Voices |= YM_MASK_C;            /* env ON */
                   1679:                                Vol3Voices &= ~YM_MASK_C;               /* fixed vol OFF */
                   1680:                        }
                   1681:                        else
                   1682:                        {
                   1683:                                EnvMask3Voices &= ~YM_MASK_C;           /* env OFF */
                   1684:                                Vol3Voices &= ~YM_MASK_C;               /* clear previous vol */
                   1685:                                Vol3Voices |= ( YmVolume4to5[ SoundRegs[10] ] ) << 10;  /* fixed vol ON */
                   1686:                        }
                   1687:                        break;
                   1688: 
                   1689:                case 11:
                   1690:                        SoundRegs[11] = data;
                   1691:                        envStep = Ym2149_EnvStepCompute ( SoundRegs[12] , SoundRegs[11] );
1.1.1.22! root     1692:                        Env_per = YM2149_EnvPer ( SoundRegs[12] , SoundRegs[11] );
1.1.1.12  root     1693:                        break;
                   1694: 
                   1695:                case 12:
                   1696:                        SoundRegs[12] = data;
                   1697:                        envStep = Ym2149_EnvStepCompute ( SoundRegs[12] , SoundRegs[11] );
1.1.1.22! root     1698:                        Env_per = YM2149_EnvPer ( SoundRegs[12] , SoundRegs[11] );
1.1.1.12  root     1699:                        break;
                   1700: 
                   1701:                case 13:
                   1702:                        SoundRegs[13] = data & 0xf;
1.1.1.22! root     1703:                        Env_pos = 0;                                    /* when writing to Env_shape, we must reset the Env_pos */
        !          1704:                        Env_count = 0;                                  /* this also starts a new phase */
        !          1705:                        Env_shape = SoundRegs[13];
1.1.1.14  root     1706:                        bEnvelopeFreqFlag = true;                       /* used for YmFormat saving */
1.1.1.12  root     1707:                        break;
                   1708: 
                   1709:        }
                   1710: }
                   1711: 
                   1712: 
                   1713: 
                   1714: /*-----------------------------------------------------------------------*/
                   1715: /**
                   1716:  * Init random generator, sound tables and envelopes
                   1717:  * (called only once when Hatari starts)
                   1718:  */
                   1719: void Sound_Init(void)
                   1720: {
                   1721:        /* Build volume/env tables, ... */
                   1722:        Ym2149_Init();
1.1.1.14  root     1723: 
1.1.1.11  root     1724:        Sound_Reset();
1.1.1.7   root     1725: }
                   1726: 
                   1727: 
                   1728: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1729: /**
1.1.1.12  root     1730:  * Reset the sound emulation (called from Reset_ST() in reset.c)
1.1.1.11  root     1731:  */
1.1.1.7   root     1732: void Sound_Reset(void)
                   1733: {
1.1.1.11  root     1734:        /* Lock audio system before accessing variables which are used by the
                   1735:         * callback function, too! */
                   1736:        Audio_Lock();
1.1.1.9   root     1737: 
1.1.1.11  root     1738:        /* Clear sound mixing buffer: */
1.1.1.12  root     1739:        memset(MixBuffer, 0, sizeof(MixBuffer));
1.1.1.7   root     1740: 
1.1.1.11  root     1741:        /* Clear cycle counts, buffer index and register '13' flags */
                   1742:        Cycles_SetCounter(CYCLES_COUNTER_SOUND, 0);
1.1.1.14  root     1743:        bEnvelopeFreqFlag = false;
                   1744: 
1.1.1.11  root     1745:        CompleteSndBufIdx = 0;
                   1746:        /* We do not start with 0 here to fake some initial samples: */
                   1747:        nGeneratedSamples = SoundBufferSize + SAMPLES_PER_FRAME;
                   1748:        ActiveSndBufIdx = nGeneratedSamples % MIXBUFFER_SIZE;
1.1.1.16  root     1749:        SamplesPerFrame = SAMPLES_PER_FRAME;
                   1750:        CurrentSamplesNb = 0;
                   1751:        ActiveSndBufIdxAvi = ActiveSndBufIdx;
1.1.1.15  root     1752: //fprintf ( stderr , "Sound_Reset SoundBufferSize %d SAMPLES_PER_FRAME %d nGeneratedSamples %d , ActiveSndBufIdx %d\n" ,
                   1753: //     SoundBufferSize , SAMPLES_PER_FRAME, nGeneratedSamples , ActiveSndBufIdx );
1.1.1.7   root     1754: 
1.1.1.12  root     1755:        Ym2149_Reset();
1.1.1.9   root     1756: 
1.1.1.11  root     1757:        Audio_Unlock();
1.1.1.7   root     1758: }
                   1759: 
                   1760: 
                   1761: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1762: /**
                   1763:  * Reset the sound buffer index variables.
1.1.1.16  root     1764:  * Very important : this function should only be called by setting
                   1765:  * Sound_BufferIndexNeedReset=true ; sound buffer index should be reset
                   1766:  * only after the sound for the whole VBL was updated (CurrentSamplesNb returns to 0)
                   1767:  * else it will alter the value of DMA Frame Count ($ff8909/0b/0d) and
                   1768:  * could cause crashes in some programs.
1.1.1.11  root     1769:  */
1.1.1.9   root     1770: void Sound_ResetBufferIndex(void)
1.1.1.7   root     1771: {
1.1.1.11  root     1772:        Audio_Lock();
                   1773:        nGeneratedSamples = SoundBufferSize + SAMPLES_PER_FRAME;
                   1774:        ActiveSndBufIdx =  (CompleteSndBufIdx + nGeneratedSamples) % MIXBUFFER_SIZE;
1.1.1.16  root     1775:        SamplesPerFrame = SAMPLES_PER_FRAME;
                   1776:        CurrentSamplesNb = 0;
                   1777:        ActiveSndBufIdxAvi = ActiveSndBufIdx;
1.1.1.15  root     1778: //fprintf ( stderr , "Sound_ResetBufferIndex SoundBufferSize %d SAMPLES_PER_FRAME %d nGeneratedSamples %d , ActiveSndBufIdx %d\n" ,
                   1779: //     SoundBufferSize , SAMPLES_PER_FRAME, nGeneratedSamples , ActiveSndBufIdx );
1.1.1.11  root     1780:        Audio_Unlock();
1.1.1.7   root     1781: }
                   1782: 
                   1783: 
                   1784: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1785: /**
                   1786:  * Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                   1787:  */
1.1.1.12  root     1788: void Sound_MemorySnapShot_Capture(bool bSave)
1.1.1.7   root     1789: {
1.1.1.11  root     1790:        /* Save/Restore details */
1.1.1.12  root     1791:        MemorySnapShot_Store(&stepA, sizeof(stepA));
                   1792:        MemorySnapShot_Store(&stepB, sizeof(stepB));
                   1793:        MemorySnapShot_Store(&stepC, sizeof(stepC));
                   1794:        MemorySnapShot_Store(&posA, sizeof(posA));
                   1795:        MemorySnapShot_Store(&posB, sizeof(posB));
                   1796:        MemorySnapShot_Store(&posC, sizeof(posC));
                   1797: 
                   1798:        MemorySnapShot_Store(&mixerTA, sizeof(mixerTA));
                   1799:        MemorySnapShot_Store(&mixerTB, sizeof(mixerTB));
                   1800:        MemorySnapShot_Store(&mixerTC, sizeof(mixerTC));
                   1801:        MemorySnapShot_Store(&mixerNA, sizeof(mixerNA));
                   1802:        MemorySnapShot_Store(&mixerNB, sizeof(mixerNB));
                   1803:        MemorySnapShot_Store(&mixerNC, sizeof(mixerNC));
                   1804: 
                   1805:        MemorySnapShot_Store(&noiseStep, sizeof(noiseStep));
                   1806:        MemorySnapShot_Store(&noisePos, sizeof(noisePos));
                   1807:        MemorySnapShot_Store(&currentNoise, sizeof(currentNoise));
                   1808:        MemorySnapShot_Store(&RndRack, sizeof(RndRack));
                   1809: 
                   1810:        MemorySnapShot_Store(&envStep, sizeof(envStep));
1.1.1.22! root     1811:        MemorySnapShot_Store(&Env_pos, sizeof(Env_pos));
        !          1812:        MemorySnapShot_Store(&Env_shape, sizeof(Env_shape));
1.1.1.14  root     1813: 
1.1.1.12  root     1814:        MemorySnapShot_Store(&EnvMask3Voices, sizeof(EnvMask3Voices));
                   1815:        MemorySnapShot_Store(&Vol3Voices, sizeof(Vol3Voices));
1.1.1.14  root     1816: 
1.1.1.12  root     1817:        MemorySnapShot_Store(SoundRegs, sizeof(SoundRegs));
                   1818: 
1.1.1.14  root     1819:        // MemorySnapShot_Store(&YmVolumeMixing, sizeof(YmVolumeMixing));
1.1.1.22! root     1820: 
        !          1821: #ifdef YM_250
        !          1822: Env_pos = 0;
        !          1823: #endif
        !          1824: 
1.1.1.7   root     1825: }
                   1826: 
                   1827: 
                   1828: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1829: /**
                   1830:  * Find how many samples to generate and store in 'nSamplesToGenerate'
                   1831:  * Also update sound cycles counter to store how many we actually did
                   1832:  * so generates set amount each frame.
1.1.1.16  root     1833:  * If FillFrame is true, this means we reach the end of the VBL and me must
                   1834:  * add as many samples as necessary to get a total of SamplesPerFrame
                   1835:  * for this VBL.
1.1.1.11  root     1836:  */
1.1.1.16  root     1837: static int Sound_SetSamplesPassed(bool FillFrame)
1.1       root     1838: {
1.1.1.11  root     1839:        int nSoundCycles;
1.1.1.16  root     1840:        int SamplesToGenerate;                          /* How many samples are needed for this time-frame */
                   1841: 
1.1.1.21  root     1842: 
1.1.1.22! root     1843:        /* If we're called from the VBL interrupt (FillFrame==true), we must ensure we have */
        !          1844:        /* an exact total of SamplesPerFrame samples during a full VBL (we take into account */
        !          1845:        /* the samples that were already generated during this VBL) */
        !          1846:        if ( FillFrame )
        !          1847:        {
        !          1848:                SamplesToGenerate = SamplesPerFrame - CurrentSamplesNb; /* how many samples are missing to reach SamplesPerFrame */
        !          1849:        }
1.1.1.11  root     1850: 
1.1.1.22! root     1851:        else
        !          1852:        {
        !          1853:                // TODO use the difference with previous value of CyclesGlobalClockCounter (when FillFrame==true) instead of CYCLES_COUNTER_VIDEO
        !          1854:                nSoundCycles = Cycles_GetCounter(CYCLES_COUNTER_VIDEO);
        !          1855: //fprintf ( stderr , "nSoundCycles %d SamplesPerFrame %d\n" , nSoundCycles , SamplesPerFrame );
        !          1856: 
        !          1857:                /* example : 160256 cycles per VBL, 44Khz = 882 samples per VBL at 50 Hz */
        !          1858:                /* 882/160256 samples per cpu clock cycle */
        !          1859: 
        !          1860:                /* Total number of samples that we should have at this point of the VBL */
        !          1861:                SamplesToGenerate = nSoundCycles * SamplesPerFrame
        !          1862:                        / ClocksTimings_GetCyclesPerVBL ( ConfigureParams.System.nMachineType , nScreenRefreshRate );
1.1.1.11  root     1863: 
1.1.1.16  root     1864: //if (SamplesToGenerate > SamplesPerFrame )
                   1865: //fprintf ( stderr , "over run %d %d\n" , SamplesPerFrame , SamplesToGenerate );
1.1.1.11  root     1866: 
1.1.1.22! root     1867:                if (SamplesToGenerate > SamplesPerFrame)
        !          1868:                        SamplesToGenerate = SamplesPerFrame;
        !          1869: 
        !          1870:                SamplesToGenerate -= CurrentSamplesNb;          /* don't count samples that were already generated up to now */
        !          1871:        }
1.1.1.16  root     1872: 
                   1873:        if ( SamplesToGenerate < 0 )
                   1874:                SamplesToGenerate = 0;
                   1875: 
                   1876:        /* Check we don't fill the sound's ring buffer before it's played by Audio_Callback()   */
                   1877:        /* This should never happen, except if the system suffers major slowdown due to other   */
                   1878:        /* processes or if we run in fast forward mode.                                         */
                   1879:        /* In the case of slowdown, we set Sound_BufferIndexNeedReset to "resync" the working   */
                   1880:        /* buffer's index ActiveSndBufIdx with the system buffer's index CompleteSndBufIdx.     */
                   1881:        /* In the case of fast forward, we do nothing here, Sound_BufferIndexNeedReset will be  */
                   1882:        /* set when the user exits fast forward mode.                                           */
                   1883:        if ( ( SamplesToGenerate > MIXBUFFER_SIZE - nGeneratedSamples ) && ( ConfigureParams.System.bFastForward == false )
                   1884:            && ( ConfigureParams.Sound.bEnableSound == true ) )
1.1.1.11  root     1885:        {
1.1.1.21  root     1886:                static int logcnt = 0;
                   1887:                if (logcnt++ < 50)
                   1888:                {
                   1889:                        Log_Printf(LOG_WARN, "Your system is too slow, "
                   1890:                                   "some sound samples were not correctly emulated\n");
                   1891:                }
1.1.1.16  root     1892:                Sound_BufferIndexNeedReset = true;
1.1.1.11  root     1893:        }
1.1.1.16  root     1894: 
                   1895: //fprintf ( stderr , "vbl %d hbl %d samp_gen %d / %d frac %lx\n" , nVBLs , nHBL , SamplesToGenerate , SamplesPerFrame , (long int)SamplesPerFrame_unrounded );
                   1896: 
                   1897:        return SamplesToGenerate;
1.1       root     1898: }
                   1899: 
1.1.1.5   root     1900: 
1.1.1.2   root     1901: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1902: /**
                   1903:  * Generate samples for all channels during this time-frame
                   1904:  */
1.1.1.16  root     1905: static void Sound_GenerateSamples(int SamplesToGenerate)
1.1       root     1906: {
1.1.1.12  root     1907:        int     i;
                   1908:        int     idx;
1.1.1.14  root     1909: 
1.1.1.16  root     1910:        if (SamplesToGenerate <= 0)
1.1.1.12  root     1911:                return;
1.1.1.14  root     1912: 
1.1.1.21  root     1913:        if (Config_IsMachineFalcon())
1.1.1.11  root     1914:        {
1.1.1.22! root     1915: #ifdef YM_250_MORE
        !          1916:                YM2149_DoSamples_250 ( SamplesToGenerate );
        !          1917: #endif
1.1.1.16  root     1918:                for (i = 0; i < SamplesToGenerate; i++)
1.1.1.15  root     1919:                {
                   1920:                        idx = (ActiveSndBufIdx + i) % MIXBUFFER_SIZE;
1.1.1.22! root     1921: #ifndef YM_250
1.1.1.17  root     1922:                        MixBuffer[idx][0] = MixBuffer[idx][1] = Subsonic_IIR_HPF_Left( YM2149_NextSample() );
1.1.1.22! root     1923: #else
        !          1924: #ifndef YM_250_MORE
        !          1925:                        MixBuffer[idx][0] = MixBuffer[idx][1] = Subsonic_IIR_HPF_Left( YM2149_NextSample_250() );
        !          1926: #else
        !          1927:                        MixBuffer[idx][0] = MixBuffer[idx][1] = Subsonic_IIR_HPF_Left( YM2149_NextSample_250_2() );
        !          1928: #endif
        !          1929: #endif
1.1.1.15  root     1930:                }
                   1931:                /* If Falcon emulation, crossbar does the job */
1.1.1.16  root     1932:                Crossbar_GenerateSamples(ActiveSndBufIdx, SamplesToGenerate);
1.1.1.11  root     1933:        }
1.1.1.21  root     1934:        else if (!Config_IsMachineST())
1.1.1.15  root     1935:        {
1.1.1.22! root     1936: #ifdef YM_250_MORE
        !          1937:                YM2149_DoSamples_250 ( SamplesToGenerate );
        !          1938: #endif
1.1.1.16  root     1939:                for (i = 0; i < SamplesToGenerate; i++)
1.1.1.15  root     1940:                {
                   1941:                        idx = (ActiveSndBufIdx + i) % MIXBUFFER_SIZE;
1.1.1.22! root     1942: #ifndef YM_250
1.1.1.18  root     1943:                        MixBuffer[idx][0] = MixBuffer[idx][1] = YM2149_NextSample();
1.1.1.22! root     1944: #else
        !          1945: #ifndef YM_250_MORE
        !          1946:                        MixBuffer[idx][0] = MixBuffer[idx][1] = YM2149_NextSample_250();
        !          1947: #else
        !          1948:                        MixBuffer[idx][0] = MixBuffer[idx][1] = YM2149_NextSample_250_2();
        !          1949: #endif
        !          1950: #endif
1.1.1.15  root     1951:                }
1.1.1.17  root     1952:                /* If Ste or TT emulation, DmaSnd does mixing and filtering */
1.1.1.16  root     1953:                DmaSnd_GenerateSamples(ActiveSndBufIdx, SamplesToGenerate);
1.1.1.15  root     1954:        }
1.1.1.21  root     1955:        else
1.1.1.15  root     1956:        {
1.1.1.22! root     1957: #ifdef YM_250_MORE
        !          1958:                YM2149_DoSamples_250 ( SamplesToGenerate );
        !          1959: #endif
1.1.1.16  root     1960:                for (i = 0; i < SamplesToGenerate; i++)
1.1.1.15  root     1961:                {
                   1962:                        idx = (ActiveSndBufIdx + i) % MIXBUFFER_SIZE;
1.1.1.22! root     1963: #ifndef YM_250
1.1.1.17  root     1964:                        MixBuffer[idx][0] = MixBuffer[idx][1] = Subsonic_IIR_HPF_Left( YM2149_NextSample() );
1.1.1.22! root     1965: #else
        !          1966: #ifndef YM_250_MORE
        !          1967:                        MixBuffer[idx][0] = MixBuffer[idx][1] = Subsonic_IIR_HPF_Left( YM2149_NextSample_250() );
        !          1968: #else
        !          1969:                        MixBuffer[idx][0] = MixBuffer[idx][1] = Subsonic_IIR_HPF_Left( YM2149_NextSample_250_2() );
        !          1970: #endif
        !          1971: #endif
1.1.1.15  root     1972:                }
                   1973:        }
1.1.1.12  root     1974: 
1.1.1.16  root     1975:        ActiveSndBufIdx = (ActiveSndBufIdx + SamplesToGenerate) % MIXBUFFER_SIZE;
                   1976:        nGeneratedSamples += SamplesToGenerate;
                   1977:        CurrentSamplesNb += SamplesToGenerate;                          /* number of samples generated for current VBL */
1.1       root     1978: }
                   1979: 
1.1.1.5   root     1980: 
1.1.1.2   root     1981: /*-----------------------------------------------------------------------*/
1.1.1.11  root     1982: /**
                   1983:  * This is called to built samples up until this clock cycle
1.1.1.16  root     1984:  * Sound_Update can be called several times during a VBL ; we must ensure
                   1985:  * that we generate exactly SamplesPerFrame samples between 2 calls
                   1986:  * to Sound_Update_VBL.
1.1.1.11  root     1987:  */
1.1.1.16  root     1988: void Sound_Update(bool FillFrame)
1.1       root     1989: {
1.1.1.11  root     1990:        int OldSndBufIdx = ActiveSndBufIdx;
1.1.1.16  root     1991:        int SamplesToGenerate;
1.1.1.5   root     1992: 
1.1.1.11  root     1993:        /* Make sure that we don't interfere with the audio callback function */
                   1994:        Audio_Lock();
1.1.1.6   root     1995: 
1.1.1.16  root     1996:        /* Find how many samples to generate */
                   1997:        SamplesToGenerate = Sound_SetSamplesPassed( FillFrame );
1.1.1.22! root     1998: //fprintf ( stderr , "sound update %d %d\n" , FillFrame , SamplesToGenerate );
1.1.1.16  root     1999: 
1.1.1.11  root     2000:        /* And generate */
1.1.1.16  root     2001:        Sound_GenerateSamples( SamplesToGenerate );
1.1       root     2002: 
1.1.1.11  root     2003:        /* Allow audio callback function to occur again */
                   2004:        Audio_Unlock();
1.1.1.6   root     2005: 
1.1.1.11  root     2006:        /* Save to WAV file, if open */
                   2007:        if (bRecordingWav)
1.1.1.16  root     2008:                WAVFormat_Update(MixBuffer, OldSndBufIdx, SamplesToGenerate);
1.1       root     2009: }
                   2010: 
1.1.1.5   root     2011: 
1.1.1.2   root     2012: /*-----------------------------------------------------------------------*/
1.1.1.11  root     2013: /**
1.1.1.16  root     2014:  * On the end of each VBL, complete audio buffer to reach SamplesPerFrame samples.
                   2015:  * As Sound_Update(false) could be called several times during the VBL, the audio
                   2016:  * buffer might be already partially filled.
                   2017:  * We must first complete the buffer using the same value of SamplesPerFrame
                   2018:  * by calling Sound_Update(true) ; then we can compute a new value for
                   2019:  * SamplesPerFrame that will be used for the next VBL to come.
1.1.1.11  root     2020:  */
1.1.1.5   root     2021: void Sound_Update_VBL(void)
1.1       root     2022: {
1.1.1.16  root     2023:        Sound_Update(true);                                     /* generate as many samples as needed to fill this VBL */
                   2024: //fprintf ( stderr , "vbl done %d %d\n" , SamplesPerFrame , CurrentSamplesNb );
1.1.1.5   root     2025: 
1.1.1.16  root     2026:        CurrentSamplesNb = 0;                                   /* VBL is complete, reset counter for next VBL */
                   2027: 
                   2028:        /*Compute a fractional equivalent of SamplesPerFrame for the next VBL, to avoid rounding propagation */
                   2029:        SamplesPerFrame_unrounded += (yms64) ClocksTimings_GetSamplesPerVBL ( ConfigureParams.System.nMachineType ,
                   2030:                        nScreenRefreshRate , nAudioFrequency );
                   2031:        SamplesPerFrame = SamplesPerFrame_unrounded >> 28;              /* use integer part */
                   2032:        SamplesPerFrame_unrounded &= 0x0fffffff;                        /* keep fractional part in the lower 28 bits */
                   2033: 
                   2034:        /* Reset sound buffer if needed (after pause, fast forward, slow system, ...) */
                   2035:        if ( Sound_BufferIndexNeedReset )
                   2036:        {
                   2037:                Sound_ResetBufferIndex ();
                   2038:                Sound_BufferIndexNeedReset = false;
                   2039:        }
                   2040:        
                   2041:        /* Record AVI audio frame is necessary */
1.1.1.15  root     2042:        if ( bRecordingAvi )
                   2043:        {
1.1.1.16  root     2044:                int Len;
1.1.1.15  root     2045: 
1.1.1.16  root     2046:                Len = ActiveSndBufIdx - ActiveSndBufIdxAvi;     /* number of generated samples for this frame */
                   2047:                if ( Len < 0 )
                   2048:                        Len += MIXBUFFER_SIZE;                  /* end of ring buffer was reached */
1.1.1.15  root     2049: 
1.1.1.16  root     2050:                Avi_RecordAudioStream ( MixBuffer , ActiveSndBufIdxAvi , Len );
1.1.1.15  root     2051:        }
                   2052: 
1.1.1.16  root     2053:        ActiveSndBufIdxAvi = ActiveSndBufIdx;                   /* save new position for next AVI audio frame */
                   2054: 
1.1.1.11  root     2055:        /* Clear write to register '13', used for YM file saving */
1.1.1.14  root     2056:        bEnvelopeFreqFlag = false;
1.1       root     2057: }
                   2058: 
                   2059: 
1.1.1.2   root     2060: /*-----------------------------------------------------------------------*/
1.1.1.11  root     2061: /**
                   2062:  * Start recording sound, as .YM or .WAV output
                   2063:  */
1.1.1.12  root     2064: bool Sound_BeginRecording(char *pszCaptureFileName)
1.1       root     2065: {
1.1.1.12  root     2066:        bool bRet;
1.1.1.7   root     2067: 
1.1.1.11  root     2068:        if (!pszCaptureFileName || strlen(pszCaptureFileName) <= 3)
                   2069:        {
                   2070:                Log_Printf(LOG_ERROR, "Illegal sound recording file name!\n");
1.1.1.14  root     2071:                return false;
1.1.1.11  root     2072:        }
                   2073: 
                   2074:        /* Did specify .YM or .WAV? If neither report error */
                   2075:        if (File_DoesFileExtensionMatch(pszCaptureFileName,".ym"))
                   2076:                bRet = YMFormat_BeginRecording(pszCaptureFileName);
                   2077:        else if (File_DoesFileExtensionMatch(pszCaptureFileName,".wav"))
                   2078:                bRet = WAVFormat_OpenFile(pszCaptureFileName);
                   2079:        else
                   2080:        {
                   2081:                Log_AlertDlg(LOG_ERROR, "Unknown Sound Recording format.\n"
                   2082:                             "Please specify a .YM or .WAV output file.");
1.1.1.14  root     2083:                bRet = false;
1.1.1.11  root     2084:        }
                   2085: 
                   2086:        return bRet;
1.1       root     2087: }
                   2088: 
1.1.1.5   root     2089: 
1.1.1.2   root     2090: /*-----------------------------------------------------------------------*/
1.1.1.11  root     2091: /**
                   2092:  * End sound recording
                   2093:  */
1.1.1.7   root     2094: void Sound_EndRecording(void)
1.1       root     2095: {
1.1.1.11  root     2096:        /* Stop sound recording and close files */
                   2097:        if (bRecordingYM)
                   2098:                YMFormat_EndRecording();
                   2099:        if (bRecordingWav)
                   2100:                WAVFormat_CloseFile();
1.1       root     2101: }
                   2102: 
1.1.1.6   root     2103: 
1.1.1.2   root     2104: /*-----------------------------------------------------------------------*/
1.1.1.11  root     2105: /**
                   2106:  * Are we recording sound data?
                   2107:  */
1.1.1.12  root     2108: bool Sound_AreWeRecording(void)
1.1       root     2109: {
1.1.1.11  root     2110:        return (bRecordingYM || bRecordingWav);
1.1       root     2111: }
1.1.1.12  root     2112: 
1.1.1.16  root     2113: 
                   2114: /*-----------------------------------------------------------------------*/
                   2115: /**
                   2116:  * Rebuild volume conversion table
                   2117:  */
                   2118: void Sound_SetYmVolumeMixing(void)
                   2119: {
                   2120:        /* Build the volume conversion table */
                   2121:        Ym2149_BuildVolumeTable();
                   2122: }
                   2123: 

unix.superglobalmegacorp.com

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