spu: get rid of pCurr -1, pass right chans to silent handler
[pcsx_rearmed.git] / plugins / dfsound / sdl.c
1 /* SDL Driver for P.E.Op.S Sound Plugin
2  * Copyright (c) 2010, Wei Mingzhi <whistler_wmz@users.sf.net>.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA
17  */
18
19 #include "stdafx.h"
20
21 #include "externals.h"
22 #include <SDL.h>
23
24 #define BUFFER_SIZE             22050
25
26 short                   *pSndBuffer = NULL;
27 int                             iBufSize = 0;
28 volatile int    iReadPos = 0, iWritePos = 0;
29
30 static void SOUND_FillAudio(void *unused, Uint8 *stream, int len) {
31         short *p = (short *)stream;
32
33         len /= sizeof(short);
34
35         while (iReadPos != iWritePos && len > 0) {
36                 *p++ = pSndBuffer[iReadPos++];
37                 if (iReadPos >= iBufSize) iReadPos = 0;
38                 --len;
39         }
40
41         // Fill remaining space with zero
42         while (len > 0) {
43                 *p++ = 0;
44                 --len;
45         }
46 }
47
48 static void InitSDL() {
49         if (SDL_WasInit(SDL_INIT_EVERYTHING)) {
50                 SDL_InitSubSystem(SDL_INIT_AUDIO);
51         } else {
52                 SDL_Init(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE);
53         }
54 }
55
56 static void DestroySDL() {
57         if (SDL_WasInit(SDL_INIT_EVERYTHING & ~SDL_INIT_AUDIO)) {
58                 SDL_QuitSubSystem(SDL_INIT_AUDIO);
59         } else {
60                 SDL_Quit();
61         }
62 }
63
64 void SetupSound(void) {
65         SDL_AudioSpec                           spec;
66
67         if (pSndBuffer != NULL) return;
68
69         InitSDL();
70
71         spec.freq = 44100;
72         spec.format = AUDIO_S16SYS;
73         spec.channels = 2;
74         spec.samples = 512;
75         spec.callback = SOUND_FillAudio;
76
77         if (SDL_OpenAudio(&spec, NULL) < 0) {
78                 DestroySDL();
79                 return;
80         }
81
82         iBufSize = BUFFER_SIZE;
83
84         pSndBuffer = (short *)malloc(iBufSize * sizeof(short));
85         if (pSndBuffer == NULL) {
86                 SDL_CloseAudio();
87                 return;
88         }
89
90         iReadPos = 0;
91         iWritePos = 0;
92
93         SDL_PauseAudio(0);
94 }
95
96 void RemoveSound(void) {
97         if (pSndBuffer == NULL) return;
98
99         SDL_CloseAudio();
100         DestroySDL();
101
102         free(pSndBuffer);
103         pSndBuffer = NULL;
104 }
105
106 unsigned long SoundGetBytesBuffered(void) {
107         int size;
108
109         if (pSndBuffer == NULL) return SOUNDSIZE;
110
111         size = iReadPos - iWritePos;
112         if (size <= 0) size += iBufSize;
113
114         if (size < iBufSize / 2) return SOUNDSIZE;
115
116         return 0;
117 }
118
119 void SoundFeedStreamData(unsigned char *pSound, long lBytes) {
120         short *p = (short *)pSound;
121
122         if (pSndBuffer == NULL) return;
123
124         while (lBytes > 0) {
125                 if (((iWritePos + 1) % iBufSize) == iReadPos) break;
126
127                 pSndBuffer[iWritePos] = *p++;
128
129                 ++iWritePos;
130                 if (iWritePos >= iBufSize) iWritePos = 0;
131
132                 lBytes -= sizeof(short);
133         }
134 }