|
|
1.1 root 1: /*
2: Hatari
3:
4: This is where we emulate the YM2149. To obtain cycle-accurate timing we store the current cycle
5: time and this is incremented during each instruction. When a write occurs in the PSG registers
6: we take the difference in time and generate this many samples using the previous register data.
7: Now we begin again from this point. To make sure we always have 1/50th of samples we update
8: the buffer generation every 1/50th second, just in case no write took place on the PSG.
9: As with most 'sample' emulation it appears very quiet. We detect for any sample playback on a channel
10: by a decay timer on the channel amplitude - this will remain high if the PSG register is constantly
11: written to. We use this decay timer to boost the output of a sampled channel so the final sound is more
12: even through-out.
13: NOTE: If the emulator runs slower than 50fps it cannot update the buffers, but the DirectSound thread still
14: needs some data to play to prevent a 'pop'. The ONLY feasible solution is to play the same buffer again.
15: I have tried all kinds of methods to play the sound 'slower', but this produces un-even timing in the
16: sound and it simply doesn't work. If the emulator cannot keep the speed, users will have to turn off
17: the sound - that's it.
18: */
19:
20: #include "main.h"
21: #include "decode.h"
22: #include "audio.h"
23: #include "debug.h"
24: #include "dialog.h"
25: #include "file.h"
26: #include "int.h"
27: #include "memAlloc.h"
28: #include "memorySnapShot.h"
29: #include "misc.h"
30: #include "psg.h"
31: #include "sound.h"
32: #include "video.h"
33: #include "wavFormat.h"
34: #include "ymFormat.h"
35:
36: #define LONGLONG long long /* ??? */
37:
38: #define ENVELOPE_PERIOD(Fine,Coarse) (((unsigned long)Coarse)<<8) + (unsigned long)Fine
39: #define NOISE_PERIOD(Freq) ((((unsigned long)Freq)&0x1f)<<11)
40: #define TONE_PERIOD(Fine,Coarse) ((((unsigned long)Coarse)&0x0f)<<8) + (unsigned long)Fine
41: #define MIXTABLE_SIZE (256*8) /* Large table, so don't overflow */
42: #define TONEFREQ_SHIFT 28 /* 4.28 fixed point */
43: #define NOISEFREQ_SHIFT 28 /* 4.28 fixed point */
44: #define ENVFREQ_SHIFT 16 /* 16.16 fixed */
45:
46: /* Original wave samples */
47: int EnvelopeShapeValues[16*1024]; /* Shape x Length(repeat 3rd/4th entries) */
48: /* Frequency and time period samples */
49: unsigned long ChannelFreq[3], EnvelopeFreq, NoiseFreq; /* Current frequency of each channel A,B,C,Envelope and Noise */
50: int ChannelAmpDecayTime[3]; /* Store counter to show if amplitude is changed to generate 'samples' */
51: int Envelope[SAMPLES_BUFFER_SIZE],Noise[SAMPLES_BUFFER_SIZE]; /* Current sample for this time period */
52: /* Output channel data */
53: int Channel_A_Buffer[SAMPLES_BUFFER_SIZE],Channel_B_Buffer[SAMPLES_BUFFER_SIZE],Channel_C_Buffer[SAMPLES_BUFFER_SIZE];
54: /* Use table to convert from (A+B+C) to clipped 'unsigned char' for DirectSound buffer */
55: char MixTable[MIXTABLE_SIZE]; /* -ve and +ve range */
56: char *pMixTable = &MixTable[MIXTABLE_SIZE/2]; /* Signed index into above */
57: BOOL bWriteEnvelopeFreq; /* Did write to register '13' - causes frequency reset */
58: BOOL bWriteChannelAAmp,bWriteChannelBAmp,bWriteChannelCAmp; /* Did write to amplitude registers? */
59: BOOL bEnvelopeFreqFlag; /* As above, but cleared each frame for YM saving */
60: int OddEvenSoundFrame = 0; /* 11Khz does no divide nicely(remainder 0.5), so use this */
61: int nSamplesToGenerate; /* How many samples are needed for this time-frame */
62: // Buffer to store circular samples
63: char MixBuffer[MIXBUFFER_SIZE];
64: int CompleteSoundBuffer,ActiveSoundBuffer; /* Index of complete and current into above mix buffer */
65:
66: //-----------------------------------------------------------------------
67: // Envelope shapes
68: ENVSHAPE EnvShapes[16] = {
69: { 127,-128,-128,-128, -1, 0, 0, 0 }, /* \_____ 00xx */
70: { 127,-128,-128,-128, -1, 0, 0, 0 }, /* \_____ 00xx */
71: { 127,-128,-128,-128, -1, 0, 0, 0 }, /* \_____ 00xx */
72: { 127,-128,-128,-128, -1, 0, 0, 0 }, /* \_____ 00xx */
73: { -128,-128,-128,-128, 1, 0, 0, 0 }, /* /_____ 01xx */
74: { -128,-128,-128,-128, 1, 0, 0, 0 }, /* /_____ 01xx */
75: { -128,-128,-128,-128, 1, 0, 0, 0 }, /* /_____ 01xx */
76: { -128,-128,-128,-128, 1, 0, 0, 0 }, /* /_____ 01xx */
77: { 127,127,127,127, -1,-1,-1,-1 }, /* \\\\\\ 1000 */
78: { 127,-128,-128,-128, -1, 0, 0, 0 }, /* \_____ 1001 */
79: { 127,-128,127,-128, -1, 1,-1, 1 }, /* \/\/\/ 1010 */
80: { 127,127,127,127, -1, 0, 0, 0 }, /* \~~~~~ 1011 */
81: { -128,-128,-128,-128, 1, 1, 1, 1 }, /* ////// 1100 */
82: { -128,127,127,127, 1, 0, 0, 0 }, /* /~~~~~ 1101 */
83: { -128,127,-128,127, 1,-1, 1,-1 }, /* /\/\/\ 1110 */
84: { -128,-128,-128,-128, 1, 0, 0, 0 } /* /_____ 1111 */
85: };
86:
87: /* Square wave look up table */
88: int SquareWave[16] = { 127,127,127,127,127,127,127,127, -128,-128,-128,-128,-128,-128,-128,-128 };
89: /* LogTable */
90: int LogTable[256];
91: int LogTable16[16];
92: int *pEnvelopeLogTable = &LogTable[128];
93:
94: //-----------------------------------------------------------------------
95: /*
96: Init sound tables and envelopes
97: */
98: void Sound_Init(void)
99: {
100: Sound_CreateLogTables();
101: Sound_CreateEnvelopeShapes();
102: Sound_CreateSoundMixClipTable();
103:
104: Sound_Reset();
105: }
106:
107: //-----------------------------------------------------------------------
108: /*
109: Reset the sound emulation
110: */
111: void Sound_Reset(void)
112: {
113: int i;
114:
115: // Clear buffer, passed to DirectSound
116: Sound_ClearMixBuffer();
117:
118: /* Clear cycle counts, buffer index and register '13' flags */
119: SoundCycles = 0;
120: CompleteSoundBuffer = ActiveSoundBuffer = 0;
121: bEnvelopeFreqFlag = FALSE;
122: bWriteEnvelopeFreq = FALSE;
123: bWriteChannelAAmp = bWriteChannelBAmp = bWriteChannelCAmp = FALSE;
124:
125: // Clear frequency counter
126: for(i=0; i<3; i++) {
127: ChannelFreq[i] =
128: ChannelAmpDecayTime[i] = 0;
129: }
130: EnvelopeFreq = NoiseFreq = 0;
131: }
132:
133: //-----------------------------------------------------------------------
134: /*
135: Clear mixer buffer, where samples are stored ready to pass to sound player
136: */
137: void Sound_ClearMixBuffer(void)
138: {
139: // Clear buffer, passed to DirectSound
140: Memory_Clear(MixBuffer,MIXBUFFER_SIZE);
141: }
142:
143: //-----------------------------------------------------------------------
144: /*
145: Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
146: */
147: void Sound_MemorySnapShot_Capture(BOOL bSave)
148: {
149: // Save/Restore details
150: MemorySnapShot_Store(ChannelFreq,sizeof(ChannelFreq));
151: MemorySnapShot_Store(&EnvelopeFreq,sizeof(EnvelopeFreq));
152: MemorySnapShot_Store(&NoiseFreq,sizeof(NoiseFreq));
153: }
154:
155: //-----------------------------------------------------------------------
156: /*
157: Create Log tables
158: */
159: void Sound_CreateLogTables(void)
160: {
161: float a;
162: int i;
163:
164: /* Generate 'log' table for envelope output. It isn't quite a 'log' but it mimicks the ST */
165: // output very well
166: a = 1.0f;
167: for(i=0; i<256; i++) {
168: LogTable[255-i] = (int)(255*a);
169: a /= 1.02f;
170: }
171: LogTable[0] = 0;
172:
173: /* And a 16 entry version(thanks to Nick for the '/= 1.5' bit) */
174: /* This is VERY important for clear sample playback */
175: a = 1.0f;
176: for(i=0; i<15; i++) {
177: LogTable16[15-i] = (int)(255*a);
178: a /= 1.5f;
179: }
180: LogTable16[0] = 0;
181: }
182:
183: //-----------------------------------------------------------------------
184: /*
185: Create envelope shape, store to table
186: ( Wave is stored as 4 cycles, where cycles 1,2 are start and 3,4 are looped )
187: */
188: void Sound_CreateEnvelopeShape(ENVSHAPE *pEnvShape,int *pEnvelopeValues)
189: {
190: int i,j,Value;
191:
192: // Create shape
193: for(i=0; i<4; i++) {
194: Value = pEnvShape->WaveStart[i]; // Set starting value for gradient
195: for(j=0; j<256; j++,Value+=pEnvShape->WaveDelta[i])
196: *pEnvelopeValues++ = Misc_LimitInt(Value,-128,127);
197: }
198: }
199:
200: //-----------------------------------------------------------------------
201: /*
202: Create YM2149 envelope shapes(x16)
203: */
204: void Sound_CreateEnvelopeShapes(void)
205: {
206: int i;
207:
208: // Create 'envelopes' for YM table
209: for(i=0; i<16; i++)
210: Sound_CreateEnvelopeShape(&EnvShapes[i],&EnvelopeShapeValues[i*1024]);
211: }
212:
213: //-----------------------------------------------------------------------
214: /*
215: Create table to clip samples top 8-bit range
216: This keeps then 'signed', although DirectSound wants 'unsigned' values but
217: we keep them signed so we can vary the volume easily
218: */
219: void Sound_CreateSoundMixClipTable(void)
220: {
221: int i,v;
222:
223: // Create table to 'clip' values to -128...127
224: for(i=0; i<MIXTABLE_SIZE; i++) {
225: v = (float)(i-(MIXTABLE_SIZE/2)) * 0.3f; // Scale, to prevent clipping
226: if (v<-128) v = -128; // Limit -128..128
227: if (v>127) v = 127;
228: MixTable[i] = v;
229: }
230: }
231:
232: //-----------------------------------------------------------------------
233: /*
234: Copy emulation sound buffer to DirectSound
235: This routine is called from Windows thread every 1/50th of a second
236: */
237: void Sound_PassYMSamplesToDirectSound(void)
238: {
239: // Copy data to DirectSound
240: if (bDirectSoundWorking) {
241: // Is emulator running?
242: if (bEmulationActive!=EMULATION_ACTIVE) {
243: // Now pass completed buffer to DirectSound, toggle odd/even frame(for 11Khz timing)
244: DAudio_WriteSamplesIntoBuffer(MixBuffer,CompleteSoundBuffer,SoundPlayBackFreqFrameLengths[OutputAudioFreqIndex][OddEvenSoundFrame],RAMP_DOWN);
245: OddEvenSoundFrame ^= TRUE;
246: }
247: else {
248: // Now pass completed buffer to DirectSound, toggle odd/even frame(for 11Khz timing)
249: DAudio_WriteSamplesIntoBuffer(MixBuffer,CompleteSoundBuffer,SoundPlayBackFreqFrameLengths[OutputAudioFreqIndex][OddEvenSoundFrame],RAMP_UP);
250: OddEvenSoundFrame ^= TRUE;
251: }
252: }
253: }
254:
255: //-----------------------------------------------------------------------
256: /*
257: Find how many samples to generate and store in 'nSamplesToGenerate'
258: Also update 'SoundCycles' to store how many we actually did so generates set amount each frame
259: */
260: void Sound_SetSamplesPassed(void)
261: {
262: int nSampleCycles;
263: int Dec=1;
264:
265: // Check how many cycles have passed, as we use this to help find out if we are playing sample data
266:
267: // First, add decay to channel amplitude variables
268: if (SoundCycles>(CYCLES_PER_FRAME/4))
269: Dec = 16; // Been long time between sound writes, must be normal tone sound
270:
271: if (!bWriteChannelAAmp) { // Not written to amplitude, decay value
272: ChannelAmpDecayTime[0]-=Dec;
273: if (ChannelAmpDecayTime[0]<0) ChannelAmpDecayTime[0] = 0;
274: }
275: if (!bWriteChannelBAmp) {
276: ChannelAmpDecayTime[1]-=Dec;
277: if (ChannelAmpDecayTime[1]<0) ChannelAmpDecayTime[1] = 0;
278: }
279: if (!bWriteChannelCAmp) {
280: ChannelAmpDecayTime[2]-=Dec;
281: if (ChannelAmpDecayTime[2]<0) ChannelAmpDecayTime[2] = 0;
282: }
283:
284: // 160256 cycles per VBL, 44Khz = 882 samples per VBL
285: // 882/160256 samples per clock cycle
286: nSamplesToGenerate = (int)( (float)SoundCycles * ((float)SAMPLES_PER_FRAME/(float)CYCLES_PER_FRAME) );
287: if (nSamplesToGenerate>SAMPLES_PER_FRAME)
288: nSamplesToGenerate = SAMPLES_PER_FRAME;
289:
290: nSampleCycles = (int)( (float)nSamplesToGenerate / ((float)SAMPLES_PER_FRAME/(float)CYCLES_PER_FRAME) );
291: SoundCycles -= nSampleCycles;
292: }
293:
294: //-----------------------------------------------------------------------
295: /*
296: Generate envelope wave for this time-frame
297: */
298: void Sound_GenerateEnvelope(unsigned char EnvShape, unsigned char Fine, unsigned char Coarse)
299: {
300: int *pEnvelopeValues;
301: unsigned long EnvelopePeriod,EnvelopeFreqDelta;
302: int i;
303:
304: // Find envelope details
305: if (bWriteEnvelopeFreq)
306: EnvelopeFreq = 0;
307: pEnvelopeValues = &EnvelopeShapeValues[ (EnvShape&0x0f)*1024 ]; // Envelope shape values
308: EnvelopePeriod = ENVELOPE_PERIOD((unsigned long)Fine,(unsigned long)Coarse);
309:
310: if (EnvelopePeriod==0) // Handle div by zero
311: EnvelopeFreqDelta = 0;
312: else
313: EnvelopeFreqDelta = ((LONGLONG)YM_FREQ<<ENVFREQ_SHIFT) / (EnvelopePeriod); // 16.16 fixed point
314:
315: // Create envelope from current shape and frequency
316: for(i=0; i<nSamplesToGenerate; i++) {
317: Envelope[i] = pEnvelopeValues[EnvelopeFreq>>ENVFREQ_SHIFT]; // Store envelope wave, already applied 'log' function
318: EnvelopeFreq += EnvelopeFreqDelta;
319: if (EnvelopeFreq&0xfe000000)
320: EnvelopeFreq = 0x02000000 | (EnvelopeFreq&0x01ffffff); // Keep in range 512-1024 once past 511!
321: }
322: }
323:
324: //-----------------------------------------------------------------------
325: /*
326: Generate nosie for this time-frame
327: */
328: void Sound_GenerateNoise(unsigned char MixerControl, unsigned char NoiseGen)
329: {
330: int NoiseValue;
331: unsigned long NoisePeriod,NoiseFreqDelta;
332: int i;
333:
334: NoisePeriod = NOISE_PERIOD((unsigned long)NoiseGen);
335:
336: if (NoisePeriod==0) // Handle div by zero
337: NoiseFreqDelta = 0;
338: else
339: NoiseFreqDelta = (((LONGLONG)YM_FREQ)<<NOISEFREQ_SHIFT) / NoisePeriod; // 4.28 fixed point
340:
341: // Generate noise samples
342: for(i=0; i<nSamplesToGenerate; i++) {
343: NoiseValue = (unsigned int)Misc_GetRandom()%96; // Get random value
344: if (SquareWave[NoiseFreq>>NOISEFREQ_SHIFT]<=0) // Add to square wave at given frequency
345: NoiseValue = -NoiseValue;
346:
347: Noise[i] = NoiseValue;
348: NoiseFreq += NoiseFreqDelta;
349: }
350: }
351:
352: //-----------------------------------------------------------------------
353: /*
354: Generate channel of samples for this time-frame
355: */
356: void Sound_GenerateChannel(int *pBuffer, unsigned char ToneFine, unsigned char ToneCoarse,unsigned char Amplitude,unsigned char MixerControl,unsigned long *pChannelFreq,int MixMask)
357: {
358: int *pNoise = Noise, *pEnvelope = Envelope;
359: unsigned long ToneFreq=*pChannelFreq;
360: unsigned long TonePeriod;
361: unsigned long ToneFreqDelta;
362: int i,Amp,Mix;
363: int ToneOutput,NoiseOutput,MixerOutput,EnvelopeOutput,AmplitudeOutput;
364:
365: TonePeriod = TONE_PERIOD((unsigned long)ToneFine,(unsigned long)ToneCoarse);
366: // Find frequency of channel
367: if (TonePeriod==0)
368: ToneFreqDelta = 0; // Handle div by zero
369: else
370: ToneFreqDelta = (((LONGLONG)YM_FREQ)<<TONEFREQ_SHIFT) / TonePeriod; // 4.28 fixed point
371: Amp = LogTable16[(Amplitude&0x0f)];
372: Mix = (MixerControl>>MixMask)&9; // Read I/O Mixer
373:
374: // Check if we are trying to play a 'sample' - we need to up the volume on these as they tend to be rather quiet
375: if ((Amplitude&0x10)==0) { // Fixed level amplitude?
376: ChannelAmpDecayTime[MixMask]++; // Increment counter to find out if we are playing samples...
377: if (ChannelAmpDecayTime[MixMask]>16)
378: ChannelAmpDecayTime[MixMask] = 16; // And limit
379: }
380:
381: for(i=0; i<nSamplesToGenerate; i++) {
382: // Output from Tone Generator(0-255)
383: ToneOutput = SquareWave[ToneFreq>>TONEFREQ_SHIFT];
384:
385: // Output from Noise Generator(0-255)
386: NoiseOutput = *pNoise++;
387: // Output from Mixer(combines Tone+Noise)
388: switch (Mix) {
389: case 0: // Has Noise and Tone
390: MixerOutput = NoiseOutput+ToneOutput;
391: break;
392: case 1: // Has Noise
393: MixerOutput = NoiseOutput;
394: break;
395: case 8: // Has Tone
396: MixerOutput = ToneOutput;
397: break;
398:
399: default: // This is used to emulate samples - should give no output, but ST gives set tone!!??
400: // MixerControl gets set to give a continuous tone and then then Amplitude
401: // of channels A,B and C get changed with all other registers in the PSG
402: // staying as zero's. This produces the sounds from Quartet, Speech, NoiseTracker etc...!
403: MixerOutput = 127;
404: }
405:
406: EnvelopeOutput = pEnvelopeLogTable[*pEnvelope++];
407:
408: if ((Amplitude&0x10)==0) {
409: AmplitudeOutput = Amp; // Fixed level amplitude
410:
411: // As with most emulators, sample playback is always 'quiet'. We check to see if
412: // the amplitude of a channel is repeatedly changing and when this is detected we
413: // scale the volume accordingly
414: if (ChannelAmpDecayTime[MixMask]>8)
415: AmplitudeOutput <<= 1; // Scale up by a factor of 2
416: }
417: else
418: AmplitudeOutput = EnvelopeOutput;
419:
420: *pBuffer++ = (MixerOutput*AmplitudeOutput)>>8;
421:
422: ToneFreq+=ToneFreqDelta;
423: }
424:
425: // Store back incremented frequency, for next call
426: *pChannelFreq = ToneFreq;
427: }
428:
429: //-----------------------------------------------------------------------
430: /*
431: Generate samples for all channels during this time-frame
432: */
433: void Sound_GenerateSamples(void)
434: {
435: int *pChannelA=Channel_A_Buffer, *pChannelB=Channel_B_Buffer, *pChannelC=Channel_C_Buffer;
436: int i;
437:
438: // Anything to do?
439: if (nSamplesToGenerate>0) {
440: // Generate envelope/noise samples for this time
441: Sound_GenerateEnvelope(PSGRegisters[PSG_REG_ENV_SHAPE],PSGRegisters[PSG_REG_ENV_FINE],PSGRegisters[PSG_REG_ENV_COARSE]);
442: Sound_GenerateNoise(PSGRegisters[PSG_REG_MIXER_CONTROL],PSGRegisters[PSG_REG_NOISE_GENERATOR]);
443:
444: // Generate 3 channels, store to separate buffer so can mix/clip
445: Sound_GenerateChannel(pChannelA,PSGRegisters[PSG_REG_CHANNEL_A_FINE],PSGRegisters[PSG_REG_CHANNEL_A_COARSE],PSGRegisters[PSG_REG_CHANNEL_A_AMP],PSGRegisters[PSG_REG_MIXER_CONTROL],&ChannelFreq[0],0);
446: Sound_GenerateChannel(pChannelB,PSGRegisters[PSG_REG_CHANNEL_B_FINE],PSGRegisters[PSG_REG_CHANNEL_B_COARSE],PSGRegisters[PSG_REG_CHANNEL_B_AMP],PSGRegisters[PSG_REG_MIXER_CONTROL],&ChannelFreq[1],1);
447: Sound_GenerateChannel(pChannelC,PSGRegisters[PSG_REG_CHANNEL_C_FINE],PSGRegisters[PSG_REG_CHANNEL_C_COARSE],PSGRegisters[PSG_REG_CHANNEL_C_AMP],PSGRegisters[PSG_REG_MIXER_CONTROL],&ChannelFreq[2],2);
448:
449: // Mix channels together, using table to clip and also convert to 'unsigned char'
450: for(i=0; i<nSamplesToGenerate; i++)
451: MixBuffer[(i+ActiveSoundBuffer)&MIXBUFFER_LENGTH] = pMixTable[(*pChannelA++) + (*pChannelB++) + (*pChannelC++)];
452: ActiveSoundBuffer = (ActiveSoundBuffer+nSamplesToGenerate)&MIXBUFFER_LENGTH;
453:
454: // Reset the write to register '13' flag
455: bWriteEnvelopeFreq = FALSE;
456: // And amplitude write flags
457: bWriteChannelAAmp = bWriteChannelBAmp = bWriteChannelCAmp = FALSE;
458: }
459: }
460:
461: //-----------------------------------------------------------------------
462: /*
463: On each VBL(50fps) complete samples so DirectSound has something to copy
464: */
465: void Sound_Update_VBL(void)
466: {
467: // Find how many to generate(enough to fill VBL)
468: Sound_SetSamplesPassed();
469: // And generate
470: Sound_GenerateSamples();
471:
472: // We should now have generated a frame of samples, give or take a few
473: // So, reset pointers(to keep exact time) and ready for next completed buffer
474: ActiveSoundBuffer = CompleteSoundBuffer;
475: CompleteSoundBuffer = (CompleteSoundBuffer+SAMPLES_PER_FRAME)&MIXBUFFER_LENGTH;
476: // Save to WAV file, if open
477: WAVFormat_Update(MixBuffer,CompleteSoundBuffer);
478:
479: // Clear write to register '13', used for YM file saving
480: bEnvelopeFreqFlag = FALSE;
481: }
482:
483: //-----------------------------------------------------------------------
484: /*
485: This is called to built samples up until this clock cycle
486: */
487: void Sound_Update(void)
488: {
489: // Find how many to generate
490: Sound_SetSamplesPassed();
491: // And generate
492: Sound_GenerateSamples();
493: }
494:
495:
496: //-----------------------------------------------------------------------
497: /*
498: Start recording sound, as .YM or .WAV output
499: */
500: BOOL Sound_BeginRecording(char *pszCaptureFileName)
501: {
502: BOOL bRet;
503:
504: // Did specify .YM or .WAV? If neither report error
505: if (File_DoesFileExtensionMatch(pszCaptureFileName,".ym") || (strlen(pszCaptureFileName)<=0) )
506: bRet = YMFormat_BeginRecording(/*hWnd,*/pszCaptureFileName);
507: else if (File_DoesFileExtensionMatch(pszCaptureFileName,".wav"))
508: bRet = WAVFormat_OpenFile(/*hWnd,*/pszCaptureFileName);
509: else {
510: Main_Message("Unknown Sound Recording format\n\n.Please specify a .YM or .WAV output file.",PROG_NAME /*,MB_OK|MB_ICONSTOP*/);
511: bRet = FALSE;
512: }
513:
514: return(bRet);
515: }
516:
517: //-----------------------------------------------------------------------
518: /*
519: End sound recording
520: */
521: void Sound_EndRecording(/*HWND hWnd*/)
522: {
523: // Stop sound recording and close files
524: if (bRecordingYM)
525: YMFormat_EndRecording(/*hWnd*/);
526: if (bRecordingWav)
527: WAVFormat_CloseFile(/*hWnd*/);
528: }
529:
530: //-----------------------------------------------------------------------
531: /*
532: Are we recording sound data?
533: */
534: BOOL Sound_AreWeRecording(void)
535: {
536: return(bRecordingYM || bRecordingWav);
537: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.