1 /*
2 playAudio.c
3 PortAudio v19 code for all actually outputting the audio
4 Depends on:
5 playAudio.h
6 BinauralBeat.h
7
8 Copyright (C) 2008 Bret Logan
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25 //IMPORTANT: PortAudio was used for multi-platform compatibility. PortAudio v18
26 //still uses OSS, which is a problem because most linux systems now are ALSA,
27 //and therefore only emulate OSS. And the drawback: ALSA doesn't mix OSS apps
28 //well or at all. This means that a cheap soundcard with no onboard mixers
29 //(most, actually), can only run one OSS a time (unlike real OSS, which did
30 //software mixing).
31 //PortAudio v19 has ALSA in it; this file represents the last stable v18
32 //before Gnaural switches to v19, which is sometimes called "PortAudio2"
33
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37
38 #include "BinauralBeat.h"
39 #include "playAudio.h"
40
41 //START Globals for Port Audio handling:
42 PaStream *playAudio_SoundStream = NULL; //this will equal NULL if the sound system wasn't detected, so use to check
43 PaDeviceIndex playAudio_SoundDevice = GNAURAL_USEDEFAULTSOUNDDEVICE;
44 PaStreamParameters outputStreamParams;
45
46 //################################################
47 //START PortAudio v19 code:
48
49 // ======================================
50 // PortAudio will call this local function:
playAudio_MyCallback(const void * inputBuffer,void * outputBuffer,unsigned long framesPerBuffer,const PaStreamCallbackTimeInfo * timeInfo,PaStreamCallbackFlags statusFlags,void * userData)51 static int playAudio_MyCallback (const void *inputBuffer,
52 void *outputBuffer,
53 unsigned long framesPerBuffer,
54 const PaStreamCallbackTimeInfo * timeInfo,
55 PaStreamCallbackFlags statusFlags,
56 void *userData)
57 {
58 if (playAudio_SoundStream != NULL)
59 {
60 BB_MainLoop (outputBuffer, (framesPerBuffer << 2));
61 }
62 // BB_UserSoundProc(outputBuffer, (framesPerBuffer<<2));//IMPORTANT: no matter what units the sndbuffer uses, CBinauralBeat wants sndbufsize in bytes
63 return 0; //return 1 to stop sound server
64 }
65
66 //======================================
playAudio_SoundStart()67 void playAudio_SoundStart ()
68 {
69 Pa_StartStream (playAudio_SoundStream);
70 }
71
72 // ======================================
playAudio_GetAPI(int i)73 void playAudio_GetAPI (int i)
74 {
75 char tmpstr[64];
76 const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo (i);
77
78 if (NULL == deviceInfo)
79 {
80 BB_ERROUT ("Pa_GetDeviceInfo returned NULL"); //20100628: fixed a segfault when "Cannot connect to server socket err = No such file or directory"
81 return;
82 }
83
84 const PaHostApiInfo *apiInfo = Pa_GetHostApiInfo (deviceInfo->hostApi);
85
86 if (NULL == apiInfo)
87 {
88 BB_ERROUT ("CPa_GetHostApiInfo returned NULL");
89 return;
90 }
91
92 strcpy (tmpstr, "Sound API: ");
93 switch (apiInfo->type)
94 {
95 case paALSA:
96 strcat (tmpstr, "ALSA");
97 break;
98
99 case paOSS:
100 strcat (tmpstr, "OSS");
101 break;
102
103 case paJACK:
104 strcat (tmpstr, "JACK");
105 break;
106
107 case paASIO:
108 strcat (tmpstr, "ASIO");
109 break;
110
111 case paMME:
112 strcat (tmpstr, "MME");
113 break;
114
115 case paDirectSound:
116 strcat (tmpstr, "DirectSound");
117 break;
118
119 case paBeOS:
120 strcat (tmpstr, "BeOS");
121 break;
122
123 case paAL:
124 strcat (tmpstr, "AL");
125 break;
126
127 case paCoreAudio:
128 strcat (tmpstr, "CoreAudio");
129 break;
130
131 case paSoundManager:
132 strcat (tmpstr, "SoundManager");
133 break;
134
135 case paAudioScienceHPI:
136 strcat (tmpstr, "AudioScienceHPI");
137 break;
138
139 case paWASAPI:
140 strcat (tmpstr, "WASAPI");
141 break;
142
143 case paWDMKS:
144 strcat (tmpstr, "WDMKS");
145 break;
146
147 case paInDevelopment:
148 strcat (tmpstr, "In Development");
149 break;
150
151 default:
152 strcat (tmpstr, "Unknown");
153 break;
154 }
155
156 BB_DBGOUT (tmpstr);
157 }
158
159 //======================================
playAudio_SoundInit(char * local_tmpstr)160 int playAudio_SoundInit (char *local_tmpstr)
161 {
162 PaError err;
163 int data; //Not using this currently
164
165 BB_DBGOUT_STR ("Starting sound:", Pa_GetVersionText ());
166
167 err = Pa_Initialize ();
168 if (err != paNoError)
169 {
170 //let user know status of audio system:
171 sprintf (local_tmpstr, "Audio System Init: %s", Pa_GetErrorText (err));
172 return EXIT_FAILURE;
173 }
174
175 if (playAudio_SoundDevice == GNAURAL_USEDEFAULTSOUNDDEVICE)
176 {
177 playAudio_SoundDevice = Pa_GetDefaultOutputDevice ();
178 }
179
180 if (TRUE == BB_DebugFlag)
181 playAudio_GetAPI (playAudio_SoundDevice);
182
183 outputStreamParams.device = playAudio_SoundDevice;
184 outputStreamParams.channelCount = 2;
185 outputStreamParams.sampleFormat = paInt16; // short -- use for inteleaved 32-bit stereo
186
187 err = Pa_OpenStream (&playAudio_SoundStream, NULL, &outputStreamParams, GNAURAL_SAMPLE_RATE, GNAURAL_FRAMES_PER_BUFFER, paClipOff, // we won't output out of range samples so don't bother clipping them
188 playAudio_MyCallback, &data);
189
190 //let user know status of audio system:
191 sprintf (local_tmpstr, "Init Audio System: %s [device %d]",
192 Pa_GetErrorText (err), playAudio_SoundDevice);
193
194 if (err != paNoError)
195 {
196 BB_ERROUT (local_tmpstr);
197 return EXIT_FAILURE;
198 }
199
200 return EXIT_SUCCESS;
201 } //end playAudio_SoundInit
202
203 // ======================================
playAudio_SoundCleanup()204 void playAudio_SoundCleanup ()
205 {
206 BB_DBGOUT ("Stopping PortAudio sound");
207 if (playAudio_SoundStream != NULL)
208 {
209 Pa_StopStream (playAudio_SoundStream);
210 Pa_CloseStream (playAudio_SoundStream);
211 }
212 Pa_Terminate ();
213 playAudio_SoundStream = NULL;
214 playAudio_SoundDevice = GNAURAL_USEDEFAULTSOUNDDEVICE;
215 //all done with PortAudio
216 }
217
218 //END PortAudio v19 code
219 //################################################
220