PEBL 2.2
Psychology Experiment Building Language - Cross-platform psychological experiment development system
PlatformAudioOut Class Reference

#include <PlatformAudio.h>

Inheritance diagram for PlatformAudioOut:
PAudioOut PAudioOut PAudioOut PEBLObjectBase PAudioOut PEBLObjectBase PDevice PDevice PDevice PDevice

Public Member Functions

 PlatformAudioOut ()
 
 PlatformAudioOut (const char *filename)
 
 ~PlatformAudioOut ()
 
bool LoadSoundFile (const char *filename)
 
bool CreateSineWave (float freq, double length, int amplitude)
 
bool CreateSquareWave (float freq, double length, int amplitude)
 
bool CreateSawtoothWave (float freq, double length, int amplitude)
 
bool CreateChirp ()
 
bool Play ()
 
bool PlayForeground ()
 
bool Stop ()
 
bool Initialize ()
 
void AddTrack (char *handle, AudioInfo track)
 
void RemoveTrack (char *handle)
 
Uint8 * MixTracks ()
 
 PlatformAudioOut ()
 
 PlatformAudioOut (const char *filename)
 
 ~PlatformAudioOut ()
 
bool LoadSoundFile (const char *filename)
 
bool CreateSineWave (float freq, double length, int amplitude)
 
bool CreateSquareWave (float freq, double length, int amplitude)
 
bool CreateSawtoothWave (float freq, double length, int amplitude)
 
bool CreateChirp ()
 
bool Play ()
 
bool PlayForeground ()
 
bool Stop ()
 
bool Initialize ()
 
void AddTrack (char *handle, AudioInfo track)
 
void RemoveTrack (char *handle)
 
Uint8 * MixTracks ()
 
 PlatformAudioOut ()
 
 PlatformAudioOut (const std::string &filename)
 
virtual ~PlatformAudioOut ()
 
virtual bool LoadSoundFile (const std::string &filename)
 
bool LoadSoundFromData (Uint8 *buffer, long unsigned int size, SDL_AudioSpec *spec, Uint32 recordpos=0)
 
virtual bool CreateSineWave (float freq, long unsigned int length, long double volume)
 
virtual bool Play ()
 
virtual bool PlayForeground ()
 
virtual bool Stop ()
 
void SaveBufferToWave (Variant filename)
 
bool ConvertAudio (AudioInfo &info)
 
counted_ptr< AudioInfoGetAudioInfo ()
 
void PrintAudioInfo ()
 
virtual bool Initialize ()
 
 PlatformAudioOut ()
 
 PlatformAudioOut (const std::string &filename)
 
virtual ~PlatformAudioOut ()
 
virtual bool LoadSoundFile (const std::string &filename)
 
virtual bool Play ()
 
virtual bool Stop ()
 
virtual int SaveBufferToWave (const std::string &filename)
 
- Public Member Functions inherited from PAudioOut
 PAudioOut ()
 
 PAudioOut (const std::string &filename)
 
virtual ~PAudioOut ()
 
virtual bool SetPanning (const double left, const double right)
 
virtual PEBL_DEVICE_TYPE GetDeviceType ()
 
- Public Member Functions inherited from PDevice
 PDevice ()
 The Standard constructor.
 
virtual ~PDevice ()
 The Standard destructor.
 
virtual int GetState (int iface) const
 
- Public Member Functions inherited from PEBLObjectBase
 PEBLObjectBase ()
 Standard Constructor.
 
 PEBLObjectBase (ComplexDataType cdt)
 Standard Constructor.
 
 PEBLObjectBase (const PEBLObjectBase &pob)
 
virtual ~PEBLObjectBase ()
 Standard Destructor.
 
virtual bool InitializeProperty (std::string name, Variant v)
 
virtual bool SetProperty (std::string name, Variant v)
 
Variant GetProperty (std::string) const
 
virtual ObjectValidationError ValidateProperty (std::string, Variant v) const
 
virtual ObjectValidationError ValidateProperty (std::string) const
 
ComplexDataType GetType ()
 
virtual std::string ObjectName () const
 
virtual std::ostream & PrintProperties (std::ostream &out)
 
virtual Variant GetPropertyList ()
 

Protected Member Functions

virtual std::ostream & SendToStream (std::ostream &out) const
 

Friends

void PlayCallBack (void *dummy, Uint8 *stream, int len)
 
void PlayCallBack (void *dummy, Uint8 *stream, int len)
 

Additional Inherited Members

- Protected Attributes inherited from PAudioOut
unsigned int mSampleRate
 
int mChannel
 
long double mAmplitudeLeft
 
long double mAmplitudeRight
 
- Protected Attributes inherited from PEBLObjectBase
ComplexDataType mCDT
 
std::map< std::string, VariantmProperties
 

Detailed Description

Definition at line 41 of file PlatformAudio.h.

Constructor & Destructor Documentation

◆ PlatformAudioOut() [1/8]

PlatformAudioOut::PlatformAudioOut ( )

Definition at line 46 of file portaudio/PlatformAudioOut.cpp.

47{
48}

◆ PlatformAudioOut() [2/8]

PlatformAudioOut::PlatformAudioOut ( const char *  filename)

Definition at line 52 of file portaudio/PlatformAudioOut.cpp.

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}
static PEBLPath gPath
std::string FindFile(const string &filename)
Definition PEBLPath.cpp:368
bool LoadSoundFile(const char *filename)
void SignalFatalError(const std::string &message)

References PEBLPath::FindFile(), Evaluator::gPath, Initialize(), LoadSoundFile(), and PError::SignalFatalError().

◆ ~PlatformAudioOut() [1/4]

PlatformAudioOut::~PlatformAudioOut ( )

Definition at line 67 of file portaudio/PlatformAudioOut.cpp.

68{
69 SDL_FreeWAV(mWave.audio);
70
71}
Uint8 * audio

References AudioInfo::audio.

◆ PlatformAudioOut() [3/8]

PlatformAudioOut::PlatformAudioOut ( )

◆ PlatformAudioOut() [4/8]

PlatformAudioOut::PlatformAudioOut ( const char *  filename)

◆ ~PlatformAudioOut() [2/4]

PlatformAudioOut::~PlatformAudioOut ( )

◆ PlatformAudioOut() [5/8]

PlatformAudioOut::PlatformAudioOut ( )

◆ PlatformAudioOut() [6/8]

PlatformAudioOut::PlatformAudioOut ( const std::string &  filename)

Definition at line 5 of file validator/PlatformAudioOut.cpp.

@ CDT_AUDIOOUT
Definition PEBLObject.h:47
PEBLObjectBase()
Standard Constructor.

◆ ~PlatformAudioOut() [3/4]

virtual PlatformAudioOut::~PlatformAudioOut ( )
virtual

◆ PlatformAudioOut() [7/8]

PlatformAudioOut::PlatformAudioOut ( )

◆ PlatformAudioOut() [8/8]

PlatformAudioOut::PlatformAudioOut ( const std::string &  filename)

◆ ~PlatformAudioOut() [4/4]

virtual PlatformAudioOut::~PlatformAudioOut ( )
virtual

Member Function Documentation

◆ AddTrack() [1/2]

void PlatformAudioOut::AddTrack ( char *  handle,
AudioInfo  track 
)

◆ AddTrack() [2/2]

void PlatformAudioOut::AddTrack ( char *  handle,
AudioInfo  track 
)

◆ ConvertAudio()

bool PlatformAudioOut::ConvertAudio ( AudioInfo info)

Definition at line 231 of file sdl/PlatformAudioOut.cpp.

232{
233
234
235
236
237 // Code heavily borrowed from some SDL tutorial
238
239 SDL_AudioCVT cvt; /* audio format conversion structure */
240 SDL_AudioSpec loaded = mWave.spec; /* format of the loaded data */
241 SDL_AudioSpec target = info.spec;
242 Uint8 *new_buf;
243
244
245 /* Build a conversion structure for converting the samples.
246 This structure contains the data SDL needs to quickly
247 convert between sample formats. */
248
249 std::cerr << "Converting from " << loaded.format<<"|"<<(int)loaded.channels<<"|"<< loaded.freq<<"to "<<
250 target.format<<"|"<< (int)target.channels<<"|"<<target.freq<<std::endl;
251
252 SDL_AudioSpec * desired=(SDL_AudioSpec *)malloc(sizeof(SDL_AudioSpec));
253 desired->freq=target.freq;
254 desired->format=target.format;
255 desired->channels = target.channels;
256 desired->samples=target.samples;
257 desired->callback=NULL;
258 desired->userdata=NULL;
259
260
261 if (SDL_BuildAudioCVT(&cvt,
262 loaded.format, loaded.channels, loaded.freq,
263 desired->format, desired->channels, desired->freq) < 0)
264 {
265 PError::SignalFatalError(Variant("Unable to convert sound: ") + Variant(SDL_GetError()));
266 }
267
268 if(cvt.needed==0)
269 {
270 PError::SignalWarning(Variant("Unable to convert sound. Be sure all of your sounds are saved in the same format.") + Variant(SDL_GetError()));
271 }
272
273 //set cvt.len to the size of the sourcedata.
274 cvt.len = mWave.audiolen;
275
276 //Allocate a big enough buffer to do the conversion:
277 new_buf = (Uint8 *) malloc(cvt.len * cvt.len_mult);
278 if (new_buf == NULL)
279 {
280 PError::SignalFatalError("Memory allocation failed in PlatformAudioOut::ConvertAudio");
281 }
282
283 /* Copy the sound samples into the new buffer. */
284 memcpy(new_buf, mWave.audio, mWave.audiolen);
285
286 /* Perform the conversion on the new buffer. */
287 cvt.buf = new_buf;
288
289
290
291#if 0
292 cerr << "Conversion information: " ;
293 std::cerr <<"Needed: "<< cvt.needed << std::endl;
294 std::cerr <<"srcformat: "<< cvt.src_format << std::endl;
295 // std::cerr <<"destformat: "<< cvt.dest_format << std::endl;
296 std::cerr <<"rate_incr: "<< cvt.rate_incr << std::endl;
297 std::cerr <<"len: "<< cvt.len << std::endl;
298 std::cerr <<"len_cvt: "<< cvt.len_cvt << std::endl;
299 std::cerr <<"len_mult: "<< cvt.len_mult<< std::endl;
300 std::cerr <<"ratio: "<< cvt.len_ratio<< std::endl;
301
302 cerr << "CONVERTING\n";
303#endif
304
305 if (SDL_ConvertAudio(&cvt) < 0)
306 {
307
308 PError::SignalFatalError(Variant("Audio conversion error:")+ Variant(SDL_GetError()));
309 }
310
311
312 /* Swap the converted data for the original. */
313 SDL_FreeWAV(mWave.audio);
314
315
316 mWave.audio = new_buf;
317 mWave.audiolen = mWave.audiolen * cvt.len_mult;
318
319
320 mWave.spec.freq=info.spec.freq;
321 mWave.spec.format=info.spec.format;
322 mWave.spec.channels=info.spec.channels;
323 mWave.spec.silence=info.spec.silence;
324 // mWave.spec.samples=info.spec.samples;
325 // mWave.spec.size=info.spec.size;
326
327
328#if 1
329 switch(mWave.spec.format)
330 {
331
332 case AUDIO_U8:
333 mWave.bytesPerSample = 8;
334 break;
335
336 case AUDIO_U16:
337 mWave.bytesPerSample = 2;
338 break;
339
340
341 case AUDIO_S8:
342 mWave.bytesPerSample = 1;
343 break;
344
345 case AUDIO_S16:
346 mWave.bytesPerSample = 2;
347 break;
348
349
350 default:
351 mWave.bytesPerSample = 2;
352 }
353
354#endif
355
356
357
358 return true;
359 }
#define NULL
Definition BinReloc.cpp:317
void SignalWarning(const std::string &message)
Definition PError.cpp:119
unsigned int bytesPerSample
SDL_AudioSpec spec
Uint32 audiolen

References AudioInfo::audio, AudioInfo::audiolen, AudioInfo::bytesPerSample, NULL, PError::SignalFatalError(), PError::SignalWarning(), and AudioInfo::spec.

◆ CreateChirp() [1/2]

bool PlatformAudioOut::CreateChirp ( )

◆ CreateChirp() [2/2]

bool PlatformAudioOut::CreateChirp ( )

◆ CreateSawtoothWave() [1/2]

bool PlatformAudioOut::CreateSawtoothWave ( float  freq,
double  length,
int  amplitude 
)

◆ CreateSawtoothWave() [2/2]

bool PlatformAudioOut::CreateSawtoothWave ( float  freq,
double  length,
int  amplitude 
)

◆ CreateSineWave() [1/3]

bool PlatformAudioOut::CreateSineWave ( float  freq,
double  length,
int  amplitude 
)

◆ CreateSineWave() [2/3]

bool PlatformAudioOut::CreateSineWave ( float  freq,
double  length,
int  amplitude 
)

◆ CreateSineWave() [3/3]

bool PlatformAudioOut::CreateSineWave ( float  freq,
long unsigned int  length,
long double  volume 
)
virtual

Reimplemented from PAudioOut.

Definition at line 362 of file sdl/PlatformAudioOut.cpp.

363{
364
365
366#ifdef PEBL_MIXER
367 return false;
368#else
369 /* Allocate a desired SDL_AudioSpec */
370 SDL_AudioSpec *spec = (SDL_AudioSpec *) malloc(sizeof(SDL_AudioSpec));
371
372
373 if(gWaveStream)
374 {
375 //Use the already-available spec.
376 //cerr <<"using preloaded sound spec\n";
377
378 memcpy(spec,&(gWaveStream->spec),sizeof(SDL_AudioSpec));
379
380 }
381 else
382 {
383 //Create a new spec
384
385 /* Allocate space for the obtained SDL_AudioSpec */
386 // obtained = (SDL_AudioSpec *) malloc(sizeof(SDL_AudioSpec));
387
388 spec->freq =44100;
389 spec->format=AUDIO_U8;
390 spec->channels=1;
391 spec->silence=0x80;
392 spec->samples=4096;
393 spec->callback= PlayCallBack;
394 spec->userdata=&mWave;
395 }
396
397 //mslength is time in ms.
398 //compute length in samples
399
400 int bits=0;
401 if((spec->format == AUDIO_U8) |
402 (spec->format == AUDIO_S8) )
403 {
404 bits=1;
405
406 }else if((spec->format == AUDIO_S16 )|
407 (spec->format == AUDIO_U16))
408 {
409 bits =2;
410
411 }
412
413 long unsigned int length = mslength/1000.0*spec->freq*spec->channels*bits;
414
415 Uint8 *data = new Uint8[length];
416 int dat;
417 double base=0.0;
418
419 for(unsigned int i=0; i<length;i+=spec->channels)
420 {
421
422 if(spec->format==AUDIO_U8)
423 {
424 //base needs to be different for different formats
425 base = (sin(i*6.28/(spec->freq/freq))*amplitude+1)/2;
426 }
427
428 if(base<0)base=0;
429 if(base>1)base=1;
430 //base is bounded between 0 and 1
431 dat = int(base*256);
432 //cerr << base << "," << amplitude << ","<< dat << endl;
433
434 //Copy dat to each channel
435 for(int j = 0; j < spec->channels;j+=bits)
436 data[i+j] = dat;
437 }
438
439
440
441 LoadSoundFromData(data,length,spec);
442
443 return true;
444#endif
445}
bool LoadSoundFromData(Uint8 *buffer, long unsigned int size, SDL_AudioSpec *spec, Uint32 recordpos=0)
friend void PlayCallBack(void *dummy, Uint8 *stream, int len)
AudioInfo * gWaveStream

References gWaveStream, LoadSoundFromData(), PlayCallBack, and AudioInfo::spec.

◆ CreateSquareWave() [1/2]

bool PlatformAudioOut::CreateSquareWave ( float  freq,
double  length,
int  amplitude 
)

◆ CreateSquareWave() [2/2]

bool PlatformAudioOut::CreateSquareWave ( float  freq,
double  length,
int  amplitude 
)

◆ GetAudioInfo()

counted_ptr< AudioInfo > PlatformAudioOut::GetAudioInfo ( )

Definition at line 980 of file sdl/PlatformAudioOut.cpp.

981{
982#ifdef PEBL_MIXER
983 // When using SDL_mixer, extract audio data from Mix_Chunk
984 if(!mMixerSample) {
985 PError::SignalWarning("No audio loaded in GetAudioInfo()");
986 return counted_ptr<AudioInfo>(); // Return NULL counted_ptr
987 }
988
989 AudioInfo * tmp = new AudioInfo();
990
991 // Mix_Chunk contains: Uint8 *abuf, Uint32 alen, int volume
992 tmp->audio = mMixerSample->abuf;
993 tmp->audiolen = mMixerSample->alen;
994 tmp->audiopos = 0;
995 tmp->volume = mMixerSample->volume;
996
997 // Get the audio spec from SDL_mixer
998 int freq, channels;
999 Uint16 format;
1000 Mix_QuerySpec(&freq, &format, &channels);
1001
1002 tmp->spec.freq = freq;
1003 tmp->spec.format = format;
1004 tmp->spec.channels = channels;
1005 tmp->spec.silence = (format == AUDIO_U8) ? 0x80 : 0;
1006 tmp->spec.samples = 4096; // Standard buffer size
1007 tmp->spec.callback = NULL;
1008 tmp->spec.userdata = NULL;
1009
1010 // Calculate bytes per sample
1011 switch(format) {
1012 case AUDIO_U8:
1013 case AUDIO_S8:
1014 tmp->bytesPerSample = 1;
1015 break;
1016 case AUDIO_U16LSB:
1017 case AUDIO_S16LSB:
1018 case AUDIO_U16MSB:
1019 case AUDIO_S16MSB:
1020 tmp->bytesPerSample = 2;
1021 break;
1022 default:
1023 tmp->bytesPerSample = 2;
1024 }
1025
1026 tmp->recordpos = mRecordPos; // Return the actual recorded position
1027 tmp->counter = 0;
1028 tmp->name = mFilename.c_str();
1029
1030 // CRITICAL: Mark that AudioInfo does NOT own this buffer
1031 // The buffer is shared with mMixerSample->abuf and will be freed by Mix_FreeChunk
1032 // or by PlatformAudioOut destructor (which sets abuf=NULL before freeing)
1033 tmp->ownsBuffer = false;
1034
1035 // Wrap in counted_ptr before returning
1036 return counted_ptr<AudioInfo>(tmp);
1037#else
1038 // Original non-mixer implementation
1039 AudioInfo * tmp = new AudioInfo(mWave);
1040#if 0
1041
1042 cerr << "---------------------------\n";
1043 cerr << "getting info in pao:getaudioinfo\n";
1044 cerr << "freq "<<mWave.spec.freq << " -- " << tmp->spec.freq <<endl;
1045 cerr << "length: " <<mWave.audiolen<< "--" << tmp->audiolen << endl;
1046 cerr << "---------------------------\n";
1047#endif
1048
1049 // Wrap in counted_ptr before returning
1050 return counted_ptr<AudioInfo>(tmp);
1051#endif
1052};
const char * name

References AudioInfo::audio, AudioInfo::audiolen, AudioInfo::audiopos, AudioInfo::bytesPerSample, AudioInfo::counter, AudioInfo::name, NULL, AudioInfo::ownsBuffer, AudioInfo::recordpos, PError::SignalWarning(), AudioInfo::spec, and AudioInfo::volume.

Referenced by PEBLObjects::GetVocalResponseTime(), and PEBLObjects::RecordToBuffer().

◆ Initialize() [1/3]

bool PlatformAudioOut::Initialize ( )
virtual

Reimplemented from PAudioOut.

Definition at line 108 of file portaudio/PlatformAudioOut.cpp.

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}

References AudioInfo::audiopos, NULL, and AudioInfo::spec.

Referenced by PEBLObjects::MakeAudioInputBuffer(), PEBLObjects::MakeSineWave(), PlatformAudioOut(), Play(), and PlayForeground().

◆ Initialize() [2/3]

bool PlatformAudioOut::Initialize ( )
virtual

Reimplemented from PAudioOut.

◆ Initialize() [3/3]

virtual bool PlatformAudioOut::Initialize ( )
virtual

Reimplemented from PAudioOut.

◆ LoadSoundFile() [1/4]

bool PlatformAudioOut::LoadSoundFile ( const char *  filename)

Definition at line 74 of file portaudio/PlatformAudioOut.cpp.

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}

References AudioInfo::audio, AudioInfo::audiolen, PEBLPath::FindFile(), Evaluator::gPath, NULL, PlayCallBack, PError::SignalFatalError(), and AudioInfo::spec.

Referenced by PEBLObjects::LoadSound(), main(), and PlatformAudioOut().

◆ LoadSoundFile() [2/4]

bool PlatformAudioOut::LoadSoundFile ( const char *  filename)

◆ LoadSoundFile() [3/4]

bool PlatformAudioOut::LoadSoundFile ( const std::string &  filename)
virtual

Reimplemented from PAudioOut.

Definition at line 8 of file validator/PlatformAudioOut.cpp.

8{ return true; }

◆ LoadSoundFile() [4/4]

virtual bool PlatformAudioOut::LoadSoundFile ( const std::string &  filename)
virtual

Reimplemented from PAudioOut.

◆ LoadSoundFromData()

bool PlatformAudioOut::LoadSoundFromData ( Uint8 *  buffer,
long unsigned int  size,
SDL_AudioSpec *  spec,
Uint32  recordpos = 0 
)

Definition at line 451 of file sdl/PlatformAudioOut.cpp.

455{
456
457#ifdef PEBL_MIXER
458 // Create a Mix_Chunk from the raw audio buffer
459 // This is needed for audio input buffers to work with SDL_mixer
460
461 mMixerSample = (Mix_Chunk*)malloc(sizeof(Mix_Chunk));
462 if(!mMixerSample) {
463 PError::SignalWarning("Failed to allocate Mix_Chunk in LoadSoundFromData()");
464 return false;
465 }
466
467 // For audio input buffers, we DON'T copy the buffer - we share it!
468 // The recording callback will write directly to this buffer.
469 // IMPORTANT: We must NOT free this buffer in the destructor since it's owned by AudioInfo
470 mMixerSample->abuf = buffer; // Share the buffer, don't copy
471 mMixerSample->alen = size;
472 mMixerSample->volume = MIX_MAX_VOLUME; // Default to max volume (128)
473
474 // Store the actual recorded position
475 // If recordpos is 0 (default), use the full buffer size
476 mRecordPos = (recordpos > 0) ? recordpos : size;
477
478 // Store the original audio spec from recording (contains correct channel count)
479 // This is critical for saving WAV files with the correct format
480 if(spec) {
481 mOriginalSpec = *spec;
482 }
483
484 mFilename = "<INTERNALLY GENERATED>";
485 mLoaded = true;
486
487 cerr << "------------------------------------\n";
488 cerr << "Loading Sound Data from buffer.\n";
489 cerr << "Buffer address: " << (void*)buffer << "\n";
490 cerr << "Buffer size: " << size << " bytes\n";
491 cerr << "Recorded size: " << mRecordPos << " bytes\n";
492 cerr << "Original spec: " << spec->freq << "Hz, " << (int)spec->channels << " channels, format=" << spec->format << "\n";
493 cerr << "------------------------------------\n";
494
495 return true;
496#else
497
498 /* setup audio */
499 //SDL_AudioSpec spec;
500 // SDL_AudioSpec obtained;
501
502
503 /* Allocate a desired SDL_AudioSpec */
504 SDL_AudioSpec *spec2 = (SDL_AudioSpec *) malloc(sizeof(SDL_AudioSpec));
505 memcpy(spec2,spec,sizeof(SDL_AudioSpec));
506
507 /* Allocate space for the obtained SDL_AudioSpec */
508 // obtained = (SDL_AudioSpec *) malloc(sizeof(SDL_AudioSpec));
509
510
511 /*
512 spec.freq =freq;
513 spec.format=AUDIO_U8;
514 spec.channels=1;
515 spec.silence=0x80;
516 spec.samples=4096;
517 spec.callback= PlayCallBack;
518 spec.userdata=&mWave;
519 */
520
521
522 mWave.spec = *spec2;
523 mWave.audio=buffer;
524 mWave.audiopos=0;
525 mWave.audiolen=(unsigned int)size;
526 mWave.volume=100;
527 mWave.name="Generated data";
528
529
530 /* Load the wave file into memory */
531 // if ( SDL_LoadWAV_RW(rw,1, &mWave.spec, &mWave.audio, &mWave.audiolen) == NULL )
532 // {
533 // std::cerr << "Couldn't load created audio data: " << SDL_GetError() << std::endl;
534 // return false;
535 // }
536
537
538 cerr << "------------------------------------\n";
539 cerr << "Loading Sound Data.\n";
541 mLoaded = true;
542
543
544
545
546 //Check to see if we can find the sound file; if not, call everything off.
547 mFilename = "<INTERNALLY GENERATED>";
548
549
550 mWave.name = mFilename.c_str();
551 mWave.spec.callback = PlayCallBack;
552 mWave.spec.userdata = &mWave;
553
554
555 //Set the global playback wave to the current wave.
556 if(!gWaveStream)
557 {
558 gWaveStream = &mWave;
559 }
560
561 return true;
562#endif
563}

References AudioInfo::audio, AudioInfo::audiolen, AudioInfo::audiopos, gWaveStream, AudioInfo::name, PlayCallBack, PrintAudioInfo(), PError::SignalWarning(), AudioInfo::spec, and AudioInfo::volume.

Referenced by CreateSineWave(), and PEBLObjects::MakeAudioInputBuffer().

◆ MixTracks() [1/2]

Uint8 * PlatformAudioOut::MixTracks ( )

◆ MixTracks() [2/2]

Uint8 * PlatformAudioOut::MixTracks ( )

◆ Play() [1/4]

bool PlatformAudioOut::Play ( )
virtual

Reimplemented from PAudioOut.

Definition at line 123 of file portaudio/PlatformAudioOut.cpp.

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}

References Initialize().

Referenced by PEBLObjects::PlayBackground().

◆ Play() [2/4]

bool PlatformAudioOut::Play ( )
virtual

Reimplemented from PAudioOut.

◆ Play() [3/4]

virtual bool PlatformAudioOut::Play ( )
virtual

Reimplemented from PAudioOut.

◆ Play() [4/4]

virtual bool PlatformAudioOut::Play ( )
virtual

Reimplemented from PAudioOut.

◆ PlayForeground() [1/3]

bool PlatformAudioOut::PlayForeground ( )
virtual

Reimplemented from PAudioOut.

Definition at line 135 of file portaudio/PlatformAudioOut.cpp.

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}

References Initialize().

Referenced by main(), and PEBLObjects::PlayForeground().

◆ PlayForeground() [2/3]

bool PlatformAudioOut::PlayForeground ( )
virtual

Reimplemented from PAudioOut.

◆ PlayForeground() [3/3]

virtual bool PlatformAudioOut::PlayForeground ( )
virtual

Reimplemented from PAudioOut.

◆ PrintAudioInfo()

void PlatformAudioOut::PrintAudioInfo ( )

Definition at line 1100 of file sdl/PlatformAudioOut.cpp.

1101{
1102
1103 cerr << "------------------------------------\n";
1104 cerr << "Filename : " << mFilename << endl;
1105 cerr << "Audio specs:\n";
1106 cerr << "Frequency: [" << mWave.spec.freq << "]\n";
1107 Variant form = "";
1108 switch(mWave.spec.format)
1109 {
1110
1111 case AUDIO_U8:
1112 form="AUDIO_U8";
1113 break;
1114
1115 case AUDIO_U16LSB:
1116 form = "AUDIO_U16LSB";
1117 break;
1118
1119
1120 case AUDIO_S8:
1121 form="AUDIO_S8";
1122 break;
1123
1124 case AUDIO_S16:
1125 form="AUDIO_S16";
1126 break;
1127
1128
1129 default:
1130 form = "UNKNOWN";
1131
1132 }
1133
1134
1135
1136 cerr << "Format: [" << form << "]\n";
1137 cerr << "Channels: [" << (int)(mWave.spec.channels) << "]\n";
1138 cerr << "Silence: [" << mWave.spec.silence << "]\n";
1139 cerr << "Samples: [" << mWave.spec.samples << "]\n";
1140 cerr << "Size: [" << mWave.spec.size << "]\n";
1141 cerr << "Length(bytes)["<<mWave.audiolen<<"]\n";
1142 cerr << "Bytes per sample: [" << mWave.bytesPerSample <<"]\n";
1143 cerr << "Total samples: [" << (double)mWave.audiolen/mWave.bytesPerSample <<"]\n";
1144 cerr << "Playback: ["<<mWave.audiopos<<"]\n";
1145 cerr << "------------------------------------\n";
1146
1147}

References AudioInfo::audiolen, AudioInfo::audiopos, AudioInfo::bytesPerSample, and AudioInfo::spec.

Referenced by LoadSoundFromData().

◆ RemoveTrack() [1/2]

void PlatformAudioOut::RemoveTrack ( char *  handle)

◆ RemoveTrack() [2/2]

void PlatformAudioOut::RemoveTrack ( char *  handle)

◆ SaveBufferToWave() [1/2]

virtual int PlatformAudioOut::SaveBufferToWave ( const std::string &  filename)
inlinevirtual

Definition at line 16 of file validator/PlatformAudioOut.h.

16{ return 0; } // Stub for validator

◆ SaveBufferToWave() [2/2]

void PlatformAudioOut::SaveBufferToWave ( Variant  filename)

Definition at line 569 of file sdl/PlatformAudioOut.cpp.

570{
571#ifdef PEBL_MIXER
572 std::cerr << "=== ENTERING SaveBufferToWave ===\n";
573 std::cerr << "mRecordPos at function entry: " << mRecordPos << "\n";
574 std::cerr << "mMixerSample pointer: " << (void*)mMixerSample << "\n";
575
576 // SDL_mixer mode: extract audio data from Mix_Chunk and write to WAV file
577 if(!mMixerSample) {
578 PError::SignalWarning("No audio buffer to save in SaveBufferToWave()");
579 return;
580 }
581
582 std::cerr << "mMixerSample->alen: " << mMixerSample->alen << "\n";
583 std::cerr << "mMixerSample->abuf: " << (void*)mMixerSample->abuf << "\n";
584
585 // Use the original audio spec from recording (not Mix_QuerySpec which returns playback format)
586 // For audio input buffers, mOriginalSpec contains the correct recording format (e.g., mono)
587 // Mix_QuerySpec() returns the playback format which is stereo (2 channels)
588 int freq = mOriginalSpec.freq;
589 Uint16 format = mOriginalSpec.format;
590 int channels = mOriginalSpec.channels;
591
592 std::cerr << "Using original recording spec: " << freq << "Hz, " << channels << " channels, format=" << format << "\n";
593
594 // Calculate bits per sample
595 int bitsPerSample = 16; // Default to 16-bit
596 switch(format) {
597 case AUDIO_U8:
598 case AUDIO_S8:
599 bitsPerSample = 8;
600 break;
601 case AUDIO_U16LSB:
602 case AUDIO_S16LSB:
603 case AUDIO_U16MSB:
604 case AUDIO_S16MSB:
605 bitsPerSample = 16;
606 break;
607 }
608
609 int bytesPerSample = bitsPerSample / 8;
610 int subchunk1size = 16;
611 int numChannels = channels;
612 int subchunk2size = mRecordPos; // Use actual recorded size, not full buffer
613 int chunksize = 36 + subchunk2size;
614 int audioFormat = 1; // PCM
615 int sampleRate = freq;
616 int byteRate = freq * numChannels * bitsPerSample / 8;
617 int blockAlign = numChannels * bitsPerSample / 8;
618
619 cerr << "--------------------------------------------\n";
620 cerr << "saving file [" << filename << "]\n";
621 cerr << "bitspersample: " << bitsPerSample << endl;
622 cerr << "Channels: " << numChannels << endl;
623 cerr << "frequency: " << sampleRate << endl;
624 cerr << "byterate: " << byteRate << endl;
625 cerr << "buffer size: " << mMixerSample->alen << " bytes" << endl;
626 cerr << "recorded size: " << mRecordPos << " bytes" << endl;
627
628 std::fstream myFile(filename.GetString().c_str(), ios::out | ios::binary);
629 if(!myFile.is_open()) {
630 PError::SignalWarning(Variant("Failed to open file for writing: ") + filename);
631 return;
632 }
633
634 // write the wav file per the wav file format
635 myFile.seekp(0, ios::beg);
636 myFile.write("RIFF", 4); // chunk id
637 myFile.write((char*)&chunksize, 4); // chunk size (36 + SubChunk2Size)
638 myFile.write("WAVE", 4); // format
639 myFile.write("fmt ", 4); // subchunk1ID
640 myFile.write((char*)&subchunk1size, 4); // subchunk1size (16 for PCM)
641 myFile.write((char*)&audioFormat, 2); // AudioFormat (1 for PCM)
642 myFile.write((char*)&numChannels, 2); // NumChannels
643 myFile.write((char*)&sampleRate, 4); // sample rate
644 myFile.write((char*)&byteRate, 4); // byte rate
645 myFile.write((char*)&blockAlign, 2); // block align
646 myFile.write((char*)&bitsPerSample, 2); // bits per sample
647 myFile.write("data", 4); // subchunk2ID
648
649 std::cerr << "About to write data chunk header. subchunk2size = " << subchunk2size << "\n";
650 std::cerr << "About to write audio data. mRecordPos = " << mRecordPos << "\n";
651
652 myFile.write((char*)&subchunk2size, 4); // subchunk2size
653
654 std::cerr << "File position before audio data write: " << myFile.tellp() << "\n";
655 std::cerr << "About to write " << mRecordPos << " bytes from buffer at " << (void*)(mMixerSample->abuf) << "\n";
656
657 // Check buffer validity before writing
658 if(mMixerSample->abuf == NULL) {
659 std::cerr << "ERROR: Buffer is NULL!\n";
660 } else {
661 std::cerr << "Buffer appears valid, first byte value: " << (int)(mMixerSample->abuf[0]) << "\n";
662 }
663
664 myFile.write((char*)(mMixerSample->abuf), mRecordPos); // Write only recorded data
665
666 std::cerr << "File position after audio data write: " << myFile.tellp() << "\n";
667 if(myFile.fail()) {
668 std::cerr << "FILE WRITE FAILED! Error state detected.\n";
669 std::cerr << "errno: " << errno << " (" << strerror(errno) << ")\n";
670 }
671 std::cerr << "File good state: " << myFile.good() << "\n";
672 std::cerr << "File fail state: " << myFile.fail() << "\n";
673 std::cerr << "File bad state: " << myFile.bad() << "\n";
674
675 myFile.close();
676 cerr << "File saved successfully.\n";
677 cerr << "--------------------------------------------\n";
678
679#else
680 //Code here adapted from
681 //http://www.codeproject.com/Messages/3208219/How-to-write-mic-data-to-wav-file.aspx
682
683 int bitsPerSample = mWave.bytesPerSample*8;
684
685 //Unclear about these chunk things:
686 int subchunk1size = 16;
687 int numChannels = mWave.spec.channels;
688
689 int subchunk2size = mWave.audiolen;
690 int chunksize = 36+subchunk2size;
691
692
693 int audioFormat = 1; //PCM
694
695 int sampleRate = mWave
696 .spec.freq;
697 int byteRate = mWave.spec.freq*numChannels*bitsPerSample/8;
698 int blockAlign = numChannels*bitsPerSample/8;
699
700
701 cerr <<"--------------------------------------------\n";
702 cerr << "saving file ["<< filename<<"]\n";
703 cerr << "bitspersample: " << bitsPerSample <<endl;
704 cerr << "Channels: " << numChannels <<endl;
705 cerr << "frequency: " << sampleRate << endl;
706 cerr << "byterate: " << byteRate << endl;
707
708
709 std::fstream myFile (filename.GetString().c_str(), ios::out | ios::binary);
710
711 // write the wav file per the wav file format
712 myFile.seekp (0, ios::beg);
713 myFile.write ("RIFF", 4); // chunk id
714 myFile.write ((char*) &chunksize, 4); // chunk size (36 + SubChunk2Size))
715 myFile.write ("WAVE", 4); // format
716 myFile.write ("fmt ", 4); // subchunk1ID
717 myFile.write ((char*) &subchunk1size, 4); // subchunk1size (16 for PCM)
718 myFile.write ((char*) &audioFormat, 2); // AudioFormat (1 for PCM)
719 myFile.write ((char*) &numChannels, 2); // NumChannels
720 myFile.write ((char*) &sampleRate, 4); // sample rate
721 myFile.write ((char*) &byteRate, 4); // byte rate (SampleRate * NumChannels * BitsPerSample/8)
722 myFile.write ((char*) &blockAlign, 2); // block align (NumChannels * BitsPerSample/8)
723 myFile.write ((char*) &bitsPerSample, 2); // bits per sample
724
725 myFile.write ("data", 4); // subchunk2ID
726 myFile.write ((char*) &subchunk2size, 4); // subchunk2size (NumSamples * NumChannels * BitsPerSample/8)
727
728 myFile.write ((char*)(mWave.audio), mWave.audiolen); // data
729
730#endif
731}

References AudioInfo::audio, AudioInfo::audiolen, AudioInfo::bytesPerSample, Variant::GetString(), NULL, PError::SignalWarning(), and AudioInfo::spec.

Referenced by PEBLObjects::SaveAudioToWaveFile().

◆ SendToStream()

std::ostream & PlatformAudioOut::SendToStream ( std::ostream &  out) const
protectedvirtual

Reimplemented from PDevice.

Definition at line 12 of file validator/PlatformAudioOut.cpp.

12 {
13 out << "PlatformAudioOut (validator)";
14 return out;
15}

◆ Stop() [1/4]

bool PlatformAudioOut::Stop ( )
virtual

Reimplemented from PAudioOut.

Definition at line 151 of file portaudio/PlatformAudioOut.cpp.

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}

References AudioInfo::audiopos.

Referenced by PEBLObjects::Stop().

◆ Stop() [2/4]

bool PlatformAudioOut::Stop ( )
virtual

Reimplemented from PAudioOut.

◆ Stop() [3/4]

virtual bool PlatformAudioOut::Stop ( )
virtual

Reimplemented from PAudioOut.

◆ Stop() [4/4]

virtual bool PlatformAudioOut::Stop ( )
virtual

Reimplemented from PAudioOut.

Friends And Related Symbol Documentation

◆ PlayCallBack [1/2]

void PlayCallBack ( void *  dummy,
Uint8 *  stream,
int  len 
)
friend

Definition at line 160 of file portaudio/PlatformAudioOut.cpp.

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}

Referenced by CreateSineWave(), LoadSoundFile(), and LoadSoundFromData().

◆ PlayCallBack [2/2]

void PlayCallBack ( void *  dummy,
Uint8 *  stream,
int  len 
)
friend

Definition at line 160 of file portaudio/PlatformAudioOut.cpp.

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}

The documentation for this class was generated from the following files: