1 /* FCE Ultra - NES/Famicom Emulator
\r
3 * Copyright notice for this file:
\r
4 * Copyright (C) 2002 Ben Parnell
\r
6 * This program is free software; you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation; either version 2 of the License, or
\r
9 * (at your option) any later version.
\r
11 * This program is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with this program; if not, write to the Free Software
\r
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
22 void WriteWaveData(int32 *Buffer, int Count);
\r
23 DWORD WINAPI DSThread(LPVOID lpParam);
\r
24 LPDIRECTSOUND ppDS=0;
\r
25 LPDIRECTSOUNDBUFFER ppbuf=0;
\r
26 LPDIRECTSOUNDBUFFER ppbufsec=0;
\r
27 LPDIRECTSOUNDBUFFER ppbufw;
\r
29 DSBUFFERDESC DSBufferDesc;
\r
33 static int DSBufferSize=0;
\r
36 void TrashSound(void)
\r
41 IDirectSoundBuffer_Stop(ppbufsec);
\r
42 IDirectSoundBuffer_Release(ppbufsec);
\r
47 IDirectSoundBuffer_Stop(ppbuf);
\r
48 IDirectSoundBuffer_Release(ppbuf);
\r
53 IDirectSound_Release(ppDS);
\r
59 static VOID *feegle[2];
\r
60 static DWORD dook[2];
\r
61 static DWORD writepos=0,playpos=0,lplaypos=0;
\r
62 void CheckDStatus(void)
\r
66 IDirectSoundBuffer_GetStatus(ppbufw, &status);
\r
68 if(status&DSBSTATUS_BUFFERLOST)
\r
70 IDirectSoundBuffer_Restore(ppbufw);
\r
73 if(!(status&DSBSTATUS_PLAYING))
\r
76 writepos=((soundbufsize)<<bittage);
\r
77 IDirectSoundBuffer_SetFormat(ppbufw,&wf);
\r
78 IDirectSoundBuffer_Play(ppbufw,0,0,DSBPLAY_LOOPING);
\r
82 static int16 MBuffer[2048];
\r
83 void FCEUD_WriteSoundData(int32 *Buffer, int Count)
\r
89 WriteWaveData(Buffer, Count);
\r
93 for(P=0;P<Count;P++)
\r
94 *(((uint8*)MBuffer)+P)=((int8)(Buffer[P]>>8))^128;
\r
98 for(P=0;P<Count;P++)
\r
99 MBuffer[P]=Buffer[P];
\r
103 IDirectSoundBuffer_GetCurrentPosition(ppbufw,&playpos,0);
\r
105 if(writepos>=DSBufferSize)
\r
106 if(playpos<lplaypos)
\r
107 writepos-=DSBufferSize;
\r
110 /* If the write position is beyond the fill buffer, block. */
\r
111 if(writepos>=(playpos+(soundbufsize<<bittage)))
\r
112 //if(!(writepos<playpos+((soundbufsize)<<bittage)))
\r
122 stime=writepos-(playpos+(soundbufsize<<bittage));
\r
131 else if(soundsleep==2)
\r
134 stime=writepos-(playpos+(soundbufsize<<bittage));
\r
143 if(!soundo || NoWaiting) return;
\r
147 if(netplaytype && netplayon)
\r
149 if(writepos<=playpos+128)
\r
150 writepos=playpos+(soundbufsize<<bittage);
\r
154 feegle[0]=feegle[1]=0;
\r
158 ddrval=IDirectSoundBuffer_Lock(ppbufw,(writepos%DSBufferSize),Count<<bittage,&feegle[0],&dook[0],&feegle[1],&dook[1],0);
\r
162 if(feegle[1]!=0 && feegle[1]!=feegle[0])
\r
166 memset(feegle[0],0x80,dook[0]);
\r
167 memset(feegle[1],0x80,dook[1]);
\r
171 memcpy(feegle[0],(uint8 *)MBuffer,dook[0]);
\r
172 memcpy(feegle[1],((uint8 *)MBuffer)+dook[0],dook[1]);
\r
178 memset(feegle[0],0x80,dook[0]);
\r
180 memcpy(feegle[0],(uint8 *)MBuffer,dook[0]);
\r
183 IDirectSoundBuffer_Unlock(ppbufw,feegle[0],dook[0],feegle[1],dook[1]);
\r
184 writepos+=Count<<bittage;
\r
195 memset(&wf,0x00,sizeof(wf));
\r
196 wf.wFormatTag = WAVE_FORMAT_PCM;
\r
198 wf.nSamplesPerSec = soundrate;
\r
200 ddrval=DirectSoundCreate(0,&ppDS,0);
\r
201 if (ddrval != DS_OK)
\r
203 FCEUD_PrintError("DirectSound: Error creating DirectSound object.");
\r
207 if(soundoptions&SO_SECONDARY)
\r
210 ddrval=IDirectSound_SetCooperativeLevel(ppDS,hAppWnd,DSSCL_PRIORITY);
\r
211 if (ddrval != DS_OK)
\r
213 FCEUD_PrintError("DirectSound: Error setting cooperative level to DDSCL_PRIORITY.");
\r
220 ddrval=IDirectSound_SetCooperativeLevel(ppDS,hAppWnd,DSSCL_WRITEPRIMARY);
\r
221 if (ddrval != DS_OK)
\r
223 FCEUD_PrintError("DirectSound: Error setting cooperative level to DDSCL_WRITEPRIMARY. Forcing use of secondary sound buffer and trying again...");
\r
224 soundoptions|=SO_SECONDARY;
\r
228 memset(&dscaps,0x00,sizeof(dscaps));
\r
229 dscaps.dwSize=sizeof(dscaps);
\r
230 ddrval=IDirectSound_GetCaps(ppDS,&dscaps);
\r
233 FCEUD_PrintError("DirectSound: Error getting capabilities.");
\r
237 if(dscaps.dwFlags&DSCAPS_EMULDRIVER)
\r
238 FCEUD_PrintError("DirectSound: Sound device is being emulated through waveform-audio functions. Sound quality will most likely be awful. Try to update your sound device's sound drivers.");
\r
240 IDirectSound_Compact(ppDS);
\r
242 memset(&DSBufferDesc,0x00,sizeof(DSBUFFERDESC));
\r
243 DSBufferDesc.dwSize=sizeof(DSBufferDesc);
\r
244 if(soundoptions&SO_SECONDARY)
\r
245 DSBufferDesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
\r
247 DSBufferDesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_GETCURRENTPOSITION2;
\r
249 ddrval=IDirectSound_CreateSoundBuffer(ppDS,&DSBufferDesc,&ppbuf,0);
\r
250 if (ddrval != DS_OK)
\r
252 FCEUD_PrintError("DirectSound: Error creating primary buffer.");
\r
257 memset(&wfa,0x00,sizeof(wfa));
\r
259 if(soundoptions&SO_FORCE8BIT)
\r
264 if( (!(dscaps.dwFlags&DSCAPS_PRIMARY16BIT)) ||
\r
265 (!(dscaps.dwFlags&DSCAPS_SECONDARY16BIT) && (soundoptions&SO_SECONDARY)))
\r
267 FCEUD_PrintError("DirectSound: 16-bit sound is not supported. Forcing 8-bit sound.");
\r
269 soundoptions|=SO_FORCE8BIT;
\r
273 wf.wBitsPerSample=8<<bittage;
\r
274 wf.nBlockAlign = bittage+1;
\r
275 wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
\r
277 ddrval=IDirectSoundBuffer_SetFormat(ppbuf,&wf);
\r
278 if (ddrval != DS_OK)
\r
280 FCEUD_PrintError("DirectSound: Error setting primary buffer format.");
\r
285 IDirectSoundBuffer_GetFormat(ppbuf,&wfa,sizeof(wfa),0);
\r
287 if(soundoptions&SO_SECONDARY)
\r
289 memset(&DSBufferDesc,0x00,sizeof(DSBUFFERDESC));
\r
290 DSBufferDesc.dwSize=sizeof(DSBufferDesc);
\r
291 DSBufferDesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
\r
292 if(soundoptions&SO_GFOCUS)
\r
293 DSBufferDesc.dwFlags|=DSBCAPS_GLOBALFOCUS;
\r
294 DSBufferDesc.dwBufferBytes=32768;
\r
295 DSBufferDesc.lpwfxFormat=&wfa;
\r
296 ddrval=IDirectSound_CreateSoundBuffer(ppDS, &DSBufferDesc, &ppbufsec, 0);
\r
297 if (ddrval != DS_OK)
\r
299 FCEUD_PrintError("DirectSound: Error creating secondary buffer.");
\r
305 //sprintf(TempArray,"%d\n",wfa.nSamplesPerSec);
\r
306 //FCEUD_PrintError(TempArray);
\r
308 if(soundoptions&SO_SECONDARY)
\r
310 DSBufferSize=32768;
\r
311 IDirectSoundBuffer_SetCurrentPosition(ppbufsec,0);
\r
316 memset(&dsbcaps,0,sizeof(dsbcaps));
\r
317 dsbcaps.dwSize=sizeof(dsbcaps);
\r
318 ddrval=IDirectSoundBuffer_GetCaps(ppbuf,&dsbcaps);
\r
319 if (ddrval != DS_OK)
\r
321 FCEUD_PrintError("DirectSound: Error getting buffer capabilities.");
\r
326 DSBufferSize=dsbcaps.dwBufferBytes;
\r
328 if(DSBufferSize<8192)
\r
330 FCEUD_PrintError("DirectSound: Primary buffer size is too small!");
\r
337 soundbufsize=(soundbuftime*soundrate/1000);
\r
338 FCEUI_Sound(soundrate);
\r
342 BOOL CALLBACK SoundConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
347 case WM_INITDIALOG:
\r
349 CheckDlgButton(hwndDlg,126,BST_CHECKED);
\r
350 if(soundoptions&SO_FORCE8BIT)
\r
351 CheckDlgButton(hwndDlg,122,BST_CHECKED);
\r
352 if(soundoptions&SO_SECONDARY)
\r
353 CheckDlgButton(hwndDlg,123,BST_CHECKED);
\r
354 if(soundoptions&SO_GFOCUS)
\r
355 CheckDlgButton(hwndDlg,124,BST_CHECKED);
\r
356 SetDlgItemInt(hwndDlg,200,soundrate,0);
\r
358 /* Volume Trackbar */
\r
359 SendDlgItemMessage(hwndDlg,500,TBM_SETRANGE,1,MAKELONG(0,200));
\r
360 SendDlgItemMessage(hwndDlg,500,TBM_SETTICFREQ,25,0);
\r
361 SendDlgItemMessage(hwndDlg,500,TBM_SETPOS,1,200-soundvolume);
\r
363 /* buffer size time trackbar */
\r
364 SendDlgItemMessage(hwndDlg,128,TBM_SETRANGE,1,MAKELONG(15,200));
\r
365 SendDlgItemMessage(hwndDlg,128,TBM_SETTICFREQ,1,0);
\r
366 SendDlgItemMessage(hwndDlg,128,TBM_SETPOS,1,soundbuftime);
\r
370 sprintf(tbuf,"%d",soundbuftime);
\r
371 SetDlgItemText(hwndDlg,666,(LPTSTR)tbuf);
\r
374 SendDlgItemMessage(hwndDlg,129,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Mean");
\r
375 SendDlgItemMessage(hwndDlg,129,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Nice");
\r
376 SendDlgItemMessage(hwndDlg,129,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Nicest");
\r
377 SendDlgItemMessage(hwndDlg,129,CB_SETCURSEL,soundsleep,(LPARAM)(LPSTR)0);
\r
380 // This doesn't seem to work. Hmm...
\r
381 //if((HWND)lParam==(HWND)128)
\r
384 soundbuftime=SendDlgItemMessage(hwndDlg,128,TBM_GETPOS,0,0);
\r
385 sprintf(tbuf,"%d",soundbuftime);
\r
386 SetDlgItemText(hwndDlg,666,(LPTSTR)tbuf);
\r
390 case WM_QUIT: goto gornk;
\r
393 switch(wParam&0xFFFF)
\r
398 if(IsDlgButtonChecked(hwndDlg,122)==BST_CHECKED)
\r
399 soundoptions|=SO_FORCE8BIT;
\r
400 if(IsDlgButtonChecked(hwndDlg,123)==BST_CHECKED)
\r
401 soundoptions|=SO_SECONDARY;
\r
402 if(IsDlgButtonChecked(hwndDlg,124)==BST_CHECKED)
\r
403 soundoptions|=SO_GFOCUS;
\r
404 if(IsDlgButtonChecked(hwndDlg,126)==BST_CHECKED)
\r
408 x=GetDlgItemInt(hwndDlg,200,0,0);
\r
409 if(x<8192 || x>65535)
\r
411 FCEUD_PrintError("Sample rate is out of range(8192-65535).");
\r
417 soundvolume=200-SendDlgItemMessage(hwndDlg,500,TBM_GETPOS,0,0);
\r
418 FCEUI_SetSoundVolume(soundvolume);
\r
419 soundsleep=SendDlgItemMessage(hwndDlg,129,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
\r
420 EndDialog(hwndDlg,0);
\r
428 void ConfigSound(void)
\r
430 int backo=soundo,sr=soundrate;
\r
431 int so=soundoptions;
\r
433 DialogBox(fceu_hInstance,"SOUNDCONFIG",hAppWnd,SoundConCallB);
\r
435 if(((backo?1:0)!=(soundo?1:0)))
\r
440 soundo=InitSound();
\r
442 else if(( soundoptions!=so || (sr!=soundrate)) && soundo)
\r
445 soundo=InitSound();
\r
447 soundbufsize=(soundbuftime*soundrate/1000);
\r
451 void StopSound(void)
\r
454 IDirectSoundBuffer_Stop(ppbufw);
\r