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