|
|
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(¤tNoise, 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.