dfb9fc10aafb439b84fbd80156ca5fc495262e96
[cyclone68000.git] / PicoDrive / Wave.cpp
1 \r
2 // This file is part of the PicoDrive Megadrive Emulator\r
3 \r
4 // This code is licensed under the GNU General Public License version 2.0 and the MAME License.\r
5 // You can choose the license that has the most advantages for you.\r
6 \r
7 // SVN repository can be found at http://code.google.com/p/cyclone68000/\r
8 \r
9 #include "stdafx.h"\r
10 \r
11 int WaveRate=0;\r
12 int WaveLen=0; // Length of each buffer in samples\r
13 short *WaveDest=NULL; // Destination to render sound\r
14 \r
15 static HWAVEOUT WaveOut=NULL;\r
16 static short *WaveBuf=NULL; // Wave double-buffer\r
17 static WAVEHDR WaveHeader[2]; // WAVEHDR for each buffer\r
18 static int WavePlay=0; // Next buffer side to play\r
19 \r
20 int WaveInit()\r
21 {\r
22   WAVEFORMATEX wfx;\r
23   WAVEHDR *pwh=NULL;\r
24 \r
25   if (WaveOut) return 0; // Already initted\r
26 \r
27   memset(&wfx,0,sizeof(wfx));\r
28   memset(&WaveHeader,0,sizeof(WaveHeader));\r
29 \r
30   wfx.wFormatTag=WAVE_FORMAT_PCM;\r
31   wfx.nChannels=2; // stereo\r
32   wfx.nSamplesPerSec=WaveRate; // sample rate\r
33   wfx.wBitsPerSample=16;\r
34   // Calculate bytes per sample and per second\r
35   wfx.nBlockAlign=(unsigned short)( (wfx.wBitsPerSample>>3)*wfx.nChannels );\r
36   wfx.nAvgBytesPerSec=wfx.nSamplesPerSec*wfx.nBlockAlign;\r
37 \r
38   waveOutOpen(&WaveOut,WAVE_MAPPER,&wfx,0,NULL,CALLBACK_NULL);\r
39 \r
40   // Allocate both buffers\r
41   WaveBuf=(short *)malloc(WaveLen<<3);\r
42   if (WaveBuf==NULL) return 1;\r
43   memset(WaveBuf,0,WaveLen<<3);\r
44 \r
45   // Make WAVEHDRs for both buffers\r
46   pwh=WaveHeader+0;\r
47   pwh->lpData=(char *)WaveBuf;\r
48   pwh->dwBufferLength=WaveLen<<2;\r
49   pwh->dwLoops=1;\r
50 \r
51   pwh=WaveHeader+1;\r
52   *pwh=WaveHeader[0]; pwh->lpData+=WaveLen<<2;\r
53 \r
54   // Prepare the buffers\r
55   waveOutPrepareHeader(WaveOut,WaveHeader,  sizeof(WAVEHDR));\r
56   waveOutPrepareHeader(WaveOut,WaveHeader+1,sizeof(WAVEHDR));\r
57 \r
58   // Queue both buffers:\r
59   WavePlay=0;\r
60   WaveHeader[0].dwFlags|=WHDR_DONE;\r
61   WaveHeader[1].dwFlags|=WHDR_DONE;\r
62   WaveUpdate();\r
63   return 0;\r
64 }\r
65 \r
66 int WaveExit()\r
67 {\r
68   WAVEHDR *pwh=NULL;\r
69   int i=0;\r
70 \r
71   if (WaveOut) waveOutReset(WaveOut);\r
72 \r
73   for (i=0;i<2;i++)\r
74   {\r
75     pwh=WaveHeader+i;\r
76     if (pwh->lpData) waveOutUnprepareHeader(WaveOut,pwh,sizeof(*pwh));\r
77   }\r
78   memset(WaveHeader,0,sizeof(WaveHeader));\r
79 \r
80   free(WaveBuf); WaveBuf=NULL; WaveLen=0;\r
81 \r
82   if (WaveOut) waveOutClose(WaveOut);  WaveOut=NULL;\r
83   return 0;\r
84 }\r
85 \r
86 int WaveUpdate()\r
87 {\r
88   WAVEHDR *pwh=NULL; int i=0;\r
89   int Last=-1;\r
90 \r
91   for (i=0;i<2;i++)\r
92   {\r
93     pwh=WaveHeader+WavePlay;\r
94     if (pwh->lpData==NULL) return 1; // Not initted\r
95 \r
96     if (pwh->dwFlags&WHDR_DONE)\r
97     {\r
98       // This buffer has finished - start it playing again\r
99       WaveDest=(short *)pwh->lpData;\r
100       SndRender();\r
101       WaveDest=NULL;\r
102       \r
103       waveOutWrite(WaveOut,pwh,sizeof(*pwh));\r
104       Last=WavePlay; // Remember the last buffer we played\r
105     }\r
106 \r
107     WavePlay++; WavePlay&=1;\r
108   }\r
109 \r
110   if (Last>=0) WavePlay=Last^1; // Next buffer to play is the other one\r
111   return 0;\r
112 }\r