PEBL 2.2
Psychology Experiment Building Language - Cross-platform psychological experiment development system
portaudio/PlatformAudioOut.cpp
Go to the documentation of this file.
1//* -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- */
3// Name: src/platforms/portaudio/PlatformAudio.cpp
4// Purpose: Contains platform-specific audio playing/recording routines
5// Author: Shane T. Mueller, Ph.D.
6// Copyright: (c) 2003-2026 Shane T. Mueller <smueller@obereed.net>
7// License: GPL 2
8//
9//
10//
11// This file is part of the PEBL project.
12//
13// PEBL is free software; you can redistribute it and/or modify
14// it under the terms of the GNU General Public License as published by
15// the Free Software Foundation; either version 2 of the License, or
16// (at your option) any later version.
17//
18// PEBL is distributed in the hope that it will be useful,
19// but WITHOUT ANY WARRANTY; without even the implied warranty of
20// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21// GNU General Public License for more details.
22//
23// You should have received a copy of the GNU General Public License
24// along with PEBL; if not, write to the Free Software
25// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
28#include "PlatformAudioOut.h"
29#include "../../devices/PAudioOut.h"
30
31#include "../../utility/PEBLPath.h"
32#include "../../utility/PError.h"
33#include "../../base/Evaluator.h"
34
35#include "portaudio.h"
36
37int PEBLAudioCallback(const void *inputBuffer, void *outputBuffer,
38 unsigned long framesPerBuffer,
39 const PaStreamCallbackTimeInfo *timeInfo,
40 const PaStreamCallbackFlags statusFlags, void *userData );
41
42
43using std::string;
44using std::cout;
45
49
50
51
52PlatformAudioOut::PlatformAudioOut(const char * soundfilename)
53{
54
55 //Check to see if we can find the sound file; if not, call everything off.
56 string filename = Evaluator::gPath.FindFile(soundfilename);
57
58 if(filename == "")
59 PError::SignalFatalError(string("Unable to find sound file [") + soundfilename + string("]."));
60
61
62 LoadSoundFile(filename.c_str());
63 Initialize();
64}
65
66
68{
69 SDL_FreeWAV(mWave.audio);
70
71}
72
73
74bool PlatformAudioOut::LoadSoundFile(const char* soundfilename)
75{
76 //Check to see if we can find the sound file; if not, call everything off.
77 string filename = Evaluator::gPath.FindFile(soundfilename);
78
79 if(filename == "")
80 PError::SignalFatalError(string("Unable to find sound file [") + soundfilename + string("]."));
81
82
83 /* Load the wave file into memory */
84 if ( SDL_LoadWAV(filename.c_str(), &mWave.spec, &mWave.audio, &mWave.audiolen) == NULL )
85 {
86 fprintf(stderr, "Couldn't load %s: %s\n", mFileName, SDL_GetError());
87 return false;
88 }
89
90 cout << "------------------------------------\n";
91 cout << "Loading Sound File. Specs:\n";
92 cout << "Frequency: [" << mWave.spec.freq << "]\n";
93 cout << "Format: [" << mWave.spec.format << "]\n";
94 cout << "Channels: [" << mWave.spec.channels << "]\n";
95 cout << "Silence: [" << mWave.spec.silence << "]\n";
96 cout << "Samples: [" << mWave.spec.samples << "]\n";
97 cout << "Size: [" << mWave.spec.size << "]\n";
98 cout << "------------------------------------\n";
99 mLoaded = true;
100 mWave.spec.callback = PlayCallBack;
101 mWave.spec.userdata = &mWave;
102 return true;
103}
104
105
106//This must be called after the audio is initialized but before it can
107//be played. It actually opens the audio device for playing.
109{
110
111 if (mLoaded && SDL_OpenAudio(&mWave.spec, NULL) < 0 ) {
112 fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
113 return false;
114 }
115
116 //Reset the position to the beginning.
117 mWave.audiopos = 0;
118
119 return true;
120}
121
122
124{
125 SDL_CloseAudio(); //Close the current audio stream just in case something is playing.
126 Initialize();
127 SDL_PauseAudio(0);
128
129 return true;
130}
131
132
133//This will play the file, not returning until it is complete.
134//Do not count on immediate return, as the function goes to sleep
136{
137
138 SDL_CloseAudio();
139 Initialize();
140 SDL_PauseAudio(0);
141 while(SDL_GetAudioStatus() == SDL_AUDIO_PLAYING)
142 {
143 //Wait at least 10 ms before checking again.
144 SDL_Delay(10);
145 }
146 SDL_CloseAudio();
147
148 return true;
149}
150
152{
153 SDL_PauseAudio(1);
154 //Set the audio stream back to the beginning.
155 SDL_CloseAudio();
156 mWave.audiopos=0;
157 return true;
158}
159
160void PlayCallBack(void * udata, Uint8 * stream, int len)
161{
162
163 // cout << "Callback Called\n" <<endl;
164 Uint8 * waveptr;
165 int waveleft;
166
167 //Cast udata to a proper form--this is dangerous and nasty.
168 AudioInfo * wave = (AudioInfo*)(udata);
169
170 //Put pointer at the proper place in the buffer.
171 waveptr = wave->audio + wave->audiopos;
172 waveleft = wave->audiolen - wave->audiopos;
173
174 // cout << "waveleft: " << waveleft << " len:" << len << endl;
175 if(waveleft >= len)
176 {
177 SDL_MixAudio(stream, waveptr, len, SDL_MIX_MAXVOLUME);
178 wave->audiopos += len;
179
180 }
181 else
182 {
183 //This plays the rest of the file and stops playing.
184 SDL_MixAudio(stream, waveptr, waveleft, SDL_MIX_MAXVOLUME);
185 wave->audiopos += waveleft;
186 SDL_PauseAudio(1);
187 wave->audiopos=0; //Reset it back to the beginning.
188
189 }
190
191}
#define NULL
Definition BinReloc.cpp:317
static PEBLPath gPath
std::string FindFile(const string &filename)
Definition PEBLPath.cpp:368
bool LoadSoundFile(const char *filename)
friend void PlayCallBack(void *dummy, Uint8 *stream, int len)
void SignalFatalError(const std::string &message)
void PlayCallBack(void *udata, Uint8 *stream, int len)
int PEBLAudioCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, const PaStreamCallbackFlags statusFlags, void *userData)
Uint8 * audio
SDL_AudioSpec spec
Uint32 audiolen