spu: fix xa masking, was causing noise
[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 = iDisStereo ? 1 : 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         if (iDisStereo) iBufSize /= 2;
84
85         pSndBuffer = (short *)malloc(iBufSize * sizeof(short));
86         if (pSndBuffer == NULL) {
87                 SDL_CloseAudio();
88                 return;
89         }
90
91         iReadPos = 0;
92         iWritePos = 0;
93
94         SDL_PauseAudio(0);
95 }
96
97 void RemoveSound(void) {
98         if (pSndBuffer == NULL) return;
99
100         SDL_CloseAudio();
101         DestroySDL();
102
103         free(pSndBuffer);
104         pSndBuffer = NULL;
105 }
106
107 unsigned long SoundGetBytesBuffered(void) {
108         int size;
109
110         if (pSndBuffer == NULL) return SOUNDSIZE;
111
112         size = iReadPos - iWritePos;
113         if (size <= 0) size += iBufSize;
114
115         if (size < iBufSize / 2) return SOUNDSIZE;
116
117         return 0;
118 }
119
120 void SoundFeedStreamData(unsigned char *pSound, long lBytes) {
121         short *p = (short *)pSound;
122
123         if (pSndBuffer == NULL) return;
124
125         while (lBytes > 0) {
126                 if (((iWritePos + 1) % iBufSize) == iReadPos) break;
127
128                 pSndBuffer[iWritePos] = *p++;
129
130                 ++iWritePos;
131                 if (iWritePos >= iBufSize) iWritePos = 0;
132
133                 lBytes -= sizeof(short);
134         }
135 }