#if 0 //To compile, type: nmake heartest.cpp heartest.exe : heartest.obj link heartest dinput.lib dsound.lib dxguid.lib user32.lib winmm.lib gdi32.lib /opt:nowin98 heartest.obj : heartest.cpp cl /c heartest.cpp /Ox /G6 /MD !if 0 #endif #include #include #include #include #include #include #include #include #include //Note: NTSC horizontal retrace squeal is: 15,734hz #define TITLE "Ken's Hearing Test Program" //Global window variables HWND ghwnd; HINSTANCE ghinst, ghpinst; LPSTR gcmdline; int gncmdshow; long xdim, ydim; char keystatus[256]; #define BLOCKSIZ (640*4) //DSOUND variables & code-------------------------------------------------------------------- //intrate of 70 has slow attack because of my stupid attack interpolation long samplerate = 44100, numspeakers = 2, bytespersample = 2, intrate = 16; long sndlag, sndfill, sndbufsiz, sndwritepos; LPDIRECTSOUND lpds = 0; LPDIRECTSOUNDBUFFER dsbuf = 0; void mixbytes(void *dasnd, long danumbytes); long initsnd () { DSBUFFERDESC dsbdesc; DSBCAPS dsbcaps; WAVEFORMATEX wft; void *write1 = 0, *write2 = 0; unsigned long length1 = 0, length2 = 0; HRESULT hr; if (DirectSoundCreate(0,&lpds,0) < 0) { MessageBox(ghwnd,"DirectSoundCreate failed",TITLE,MB_OK); return(0); } //DDSCL_NORMAL: locked at 22050,8,m? //DDSCL_EXCLUSIVE: for primary access //DDSCL_WRITEPRIMARY: most priviledged access if (lpds->SetCooperativeLevel(ghwnd,DSSCL_WRITEPRIMARY) < 0) { lpds->Release(); MessageBox(ghwnd,"DirectSound SetCooperativeLevel failed",TITLE,MB_OK); return(0); } wft.wFormatTag = WAVE_FORMAT_PCM; wft.nSamplesPerSec = samplerate; wft.wBitsPerSample = (bytespersample<<3); wft.nChannels = numspeakers; wft.nBlockAlign = (wft.wBitsPerSample>>3) * wft.nChannels; wft.nAvgBytesPerSec = wft.nSamplesPerSec * wft.nBlockAlign; wft.cbSize = 0; memset(&dsbdesc,0,sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); //DSBCAPS_STATIC (sound is repeated) //DSBCAPS_GLOBALFOCUS (sound is played in other applications) //DSBCAPS_STICKYFOCUS (sound is played only when other app doesn't use dsound) //DSBCAPS_CTRLFREQUENCY ? //DSBCAPS_GETCURRENTPOSITION2 dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER|DSBCAPS_STICKYFOCUS |DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRL3D; dsbdesc.dwBufferBytes = 0; //0 for primary dsbdesc.lpwfxFormat = 0; //0 for primary if (lpds->CreateSoundBuffer(&dsbdesc,&dsbuf,0) < 0) { lpds->Release(); MessageBox(ghwnd,"CreateSoundBuffer failed",TITLE,MB_OK); return(0); } if ((hr = dsbuf->SetFormat(&wft)) != DS_OK) { char snotbuf[128]; if (hr != DSERR_INVALIDPARAM) return(0); dsbuf->GetFormat(&wft,sizeof(wft),0); wsprintf(snotbuf,"Defaulting to these values:\nsamplerate=%d\nnumspeakers=%d\nbitspersamp=%d",wft.nSamplesPerSec,wft.nChannels,wft.wBitsPerSample); MessageBox(0,snotbuf,"DirectSound doesn't support those parameters :(",MB_OK); samplerate = wft.nSamplesPerSec; numspeakers = wft.nChannels; bytespersample = (wft.wBitsPerSample>>3); } memset(&dsbcaps,0,sizeof(DSBCAPS)); dsbcaps.dwSize = sizeof(DSBCAPS); dsbuf->GetCaps(&dsbcaps); sndbufsiz = dsbcaps.dwBufferBytes; sndlag = sndfill = ((wft.nAvgBytesPerSec/intrate)&~(wft.nBlockAlign-1)); sndwritepos = 0; if (dsbuf->Play(0,0,DSBPLAY_LOOPING) == DSERR_BUFFERLOST) //Try (0,0,DSBPLAY_LOOPING) { dsbuf->Restore(); dsbuf->Play(0,0,DSBPLAY_LOOPING); } return(1); } void uninitsnd () { if (dsbuf) { dsbuf->Stop(); dsbuf->Release(); dsbuf = 0; } if (lpds) { lpds->Release(); lpds = 0; } } void sndbreathe () { void *write1 = 0, *write2 = 0; unsigned long length1 = 0, length2 = 0, playpos = 0; long i; dsbuf->GetCurrentPosition(&playpos,(unsigned long *)&i); i = sndwritepos-playpos; if (i < 0) i += sndbufsiz; if (i >= sndlag) return; if ((i = dsbuf->Lock(sndwritepos,sndfill,&write1,&length1,&write2,&length2,0)) == DSERR_BUFFERLOST) { //FIX THIS CODE!!! //dsbuf->Restore(); ////dsbuf->Play(0,0,DSBPLAY_LOOPING); //i = dsbuf->Lock(sndwritepos,sndfill,&write1,&length1,&write2,&length2,0); } if (i != DS_OK) return; if (write1) mixbytes(write1,length1); if (write2) mixbytes(write2,length2); dsbuf->Unlock(write1,length1,write2,length2); sndwritepos += length1+length2; if (sndwritepos >= sndbufsiz) sndwritepos -= sndbufsiz; } //END DSOUND variables & code----------------------------------------------------------------- //Input: -128 to 127, Output: 0 to 255 static _inline long clipit8 (long a) { _asm { mov eax, a shr eax, 8 add eax, 128 cmp eax, 256 jb short skipit1 cmp eax, 0x80000000 sbb eax, eax skipit1: mov a, eax } return(a); } //Input: -32768 to 32767, Output: -32768 to 32767 static _inline long clipit16 (long a) { _asm { mov eax, a add eax, 32768 cmp eax, 65536 jb short skipit2 cmp eax, 0x80000000 sbb eax, eax skipit2: sub eax, 32768 mov a, eax } return(a); } static _inline long mulscale28 (long a, long d) { _asm { mov eax, a mov edx, d imul edx shrd eax, edx, 28 mov a, eax } return(a); } #define PI 3.141592653589793 static long stemp[16384]; //Max size: 48000hz/70intspersec static long olbuf[1600], orbuf[1600], pixcnt = 0; static long vol[2] = {0,0}, volinc[2], inoteplc = 0; static double mulfrq = 0, mulfrqi = 0.0; static double noteplc = 0.0, curfrq = 440.0; void mixbytes (void *dasnd, long danumbytes) { double d; long i, j, k, numsamples; numsamples = danumbytes/(numspeakers*bytespersample); for(i=0;i vol[k]) volinc[k] = ((j-vol[k])>>10); else volinc[k] = -((vol[k]-j)>>10); } //Update frequency: d = (double)curfrq*PI*2.0/(double)samplerate; if (!(vol[0]&vol[1])) mulfrq = d; mulfrqi = (d-mulfrq)/1024.0; } d = sin(noteplc); stemp[i*2 ] = (long)(d*(double)vol[0]/16384.0); stemp[i*2+1] = (long)(d*(double)vol[1]/16384.0); noteplc += mulfrq; if (noteplc >= PI) noteplc -= PI*2.0; mulfrq += mulfrqi; vol[0] += volinc[0]; vol[1] += volinc[1]; inoteplc++; } HDC hDC = GetDC(ghwnd); for(i=0;i>17); orbuf[pixcnt] = (((stemp[i*2+1]+32768+65536)*ydim)>>17); SetPixel(hDC,pixcnt,olbuf[pixcnt],0x4040ff); SetPixel(hDC,pixcnt,orbuf[pixcnt],0xff4040); pixcnt++; if (pixcnt >= xdim) pixcnt = 0; } ReleaseDC(ghwnd,hDC); switch(numspeakers) //Clip samples { case 1: j = numsamples; if (bytespersample == 1) for(i=0;i>16); break; case WM_KEYDOWN: keystatus[((lParam>>16)&127)+((lParam>>17)&128)] = 1; break; case WM_KEYUP: keystatus[((lParam>>16)&127)+((lParam>>17)&128)] = 0; break; case WM_DESTROY: PostQuitMessage(0); break; } return(DefWindowProc(hwnd,msg,wParam,lParam)); } static long quitprogram = 0, quitparam; void winbreathe () { MSG msg; while (PeekMessage(&msg,0,0,0,PM_REMOVE)) { if (msg.message == WM_QUIT) { quitprogram = 1; quitparam = msg.wParam; } TranslateMessage(&msg); DispatchMessage(&msg); } } int PASCAL WinMain (HINSTANCE hinst, HINSTANCE hpinst, LPSTR cmdline, int ncmdshow) { WNDCLASS wc; HDC hDC; double ofrq; long totalxdim, totalydim; char tempbuf[256]; ghinst = hinst; ghpinst = hpinst; gcmdline = cmdline; gncmdshow = ncmdshow; if (!ghpinst) { wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; wc.cbClsExtra = wc.cbWndExtra = 0; wc.hInstance = ghinst; wc.hIcon = LoadIcon(0,IDI_APPLICATION); wc.hCursor = LoadCursor(0,IDC_ARROW); wc.hbrBackground = (HBRUSH__ *)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = wc.lpszClassName = TITLE; if (!RegisterClass(&wc)) return(0); } hDC = GetDC(0); totalxdim = GetDeviceCaps(hDC,HORZRES); totalydim = GetDeviceCaps(hDC,VERTRES); ReleaseDC(ghwnd,hDC); if (!(ghwnd = CreateWindow(TITLE,TITLE,WS_OVERLAPPEDWINDOW,(totalxdim-640)>>1,(totalydim-480)>>1,640,480,0,0,ghinst,0))) return(0); memset((void *)keystatus,0,sizeof(keystatus)); ShowWindow(ghwnd,gncmdshow); UpdateWindow(ghwnd); if (!initsnd()) { uninitsnd(); return(0); } do { sndbreathe(); winbreathe(); if (keystatus[1]) PostMessage(ghwnd,WM_CLOSE,0,0); ofrq = curfrq; if (keystatus[0x37]) { keystatus[0x37] = 0; curfrq *= 2.0; } if (keystatus[0xb5]) { keystatus[0xb5] = 0; curfrq *= 0.5; } if (keystatus[0xd2]) { keystatus[0xd2] = 0; curfrq += 1000.0; } if (keystatus[0xd3]) { keystatus[0xd3] = 0; curfrq -= 1000.0; } if (keystatus[0xc7]) { keystatus[0xc7] = 0; curfrq += 100.0; } if (keystatus[0xcf]) { keystatus[0xcf] = 0; curfrq -= 100.0; } if (keystatus[0xc9]) { keystatus[0xc9] = 0; curfrq += 10.0; } if (keystatus[0xd1]) { keystatus[0xd1] = 0; curfrq -= 10.0; } if (keystatus[0x4a]) { keystatus[0x4a] = 0; curfrq += 1.0; } if (keystatus[0x4e]) { keystatus[0x4e] = 0; curfrq -= 1.0; } if (curfrq < 0.0) curfrq = 0.0; if (curfrq > samplerate*0.5) curfrq = samplerate*0.5; if (curfrq != ofrq) InvalidateRect(ghwnd,0,1); } while (!quitprogram); uninitsnd(); return(quitparam); } #if 0 !endif #endif