29#include "../../devices/PAudioOut.h"
31#include "../../utility/PEBLPath.h"
32#include "../../utility/PError.h"
33#include "../../libs/PEBLEnvironment.h"
37#include "../../base/Evaluator-es.h"
39#include "../../base/Evaluator.h"
69bool PlatformAudioOut::mLoaded =
false;
85 SDL_zero(mOriginalSpec);
89 int result = Mix_OpenAudio(44100, AUDIO_S16SYS, 2, 512);
92 fprintf(stderr,
"Unable to open audio: %s\n", SDL_GetError());
116 LoadSoundFile(mFilename);
128 if(mFilename ==
"<INTERNALLY GENERATED>") {
129 mMixerSample->abuf =
NULL;
131 Mix_FreeChunk(mMixerSample);
139 SDL_FreeWAV(mWave.
audio);
159 char * copy = (
char*)malloc(strlen(mFilename.c_str()) + 1);
160 strcpy(copy, mFilename.c_str());
164 mMixerSample = Mix_LoadWAV(mFilename.c_str());
167 if (mMixerSample ==
NULL)
169 std::cerr <<
"Couldn't load " << copy <<
": " << SDL_GetError() << std::endl;
180 std::cerr <<
"Couldn't load " << mFilename <<
": " << SDL_GetError() << std::endl;
200 if(!(samefreq & sameformat&samechannels & samechannels))
212 mWave.
name = mFilename.c_str();
214 mWave.
spec.userdata = &mWave;
240 SDL_AudioSpec loaded = mWave.
spec;
241 SDL_AudioSpec target = info.
spec;
249 std::cerr <<
"Converting from " << loaded.format<<
"|"<<(int)loaded.channels<<
"|"<< loaded.freq<<
"to "<<
250 target.format<<
"|"<< (
int)target.channels<<
"|"<<target.freq<<std::endl;
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;
261 if (SDL_BuildAudioCVT(&cvt,
262 loaded.format, loaded.channels, loaded.freq,
263 desired->format, desired->channels, desired->freq) < 0)
277 new_buf = (Uint8 *) malloc(cvt.len * cvt.len_mult);
292 cerr <<
"Conversion information: " ;
293 std::cerr <<
"Needed: "<< cvt.needed << std::endl;
294 std::cerr <<
"srcformat: "<< cvt.src_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;
302 cerr <<
"CONVERTING\n";
305 if (SDL_ConvertAudio(&cvt) < 0)
313 SDL_FreeWAV(mWave.
audio);
316 mWave.
audio = new_buf;
322 mWave.
spec.channels=info.
spec.channels;
323 mWave.
spec.silence=info.
spec.silence;
329 switch(mWave.
spec.format)
370 SDL_AudioSpec *spec = (SDL_AudioSpec *) malloc(
sizeof(SDL_AudioSpec));
389 spec->format=AUDIO_U8;
394 spec->userdata=&mWave;
401 if((spec->format == AUDIO_U8) |
402 (spec->format == AUDIO_S8) )
406 }
else if((spec->format == AUDIO_S16 )|
407 (spec->format == AUDIO_U16))
413 long unsigned int length = mslength/1000.0*spec->freq*spec->channels*bits;
415 Uint8 *data =
new Uint8[length];
419 for(
unsigned int i=0; i<length;i+=spec->channels)
422 if(spec->format==AUDIO_U8)
425 base = (sin(i*6.28/(spec->freq/freq))*amplitude+1)/2;
435 for(
int j = 0; j < spec->channels;j+=bits)
452 long unsigned int size,
461 mMixerSample = (Mix_Chunk*)malloc(
sizeof(Mix_Chunk));
470 mMixerSample->abuf = buffer;
471 mMixerSample->alen = size;
472 mMixerSample->volume = MIX_MAX_VOLUME;
476 mRecordPos = (recordpos > 0) ? recordpos : size;
481 mOriginalSpec = *spec;
484 mFilename =
"<INTERNALLY GENERATED>";
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";
504 SDL_AudioSpec *spec2 = (SDL_AudioSpec *) malloc(
sizeof(SDL_AudioSpec));
505 memcpy(spec2,spec,
sizeof(SDL_AudioSpec));
527 mWave.
name=
"Generated data";
538 cerr <<
"------------------------------------\n";
539 cerr <<
"Loading Sound Data.\n";
547 mFilename =
"<INTERNALLY GENERATED>";
550 mWave.
name = mFilename.c_str();
552 mWave.
spec.userdata = &mWave;
572 std::cerr <<
"=== ENTERING SaveBufferToWave ===\n";
573 std::cerr <<
"mRecordPos at function entry: " << mRecordPos <<
"\n";
574 std::cerr <<
"mMixerSample pointer: " << (
void*)mMixerSample <<
"\n";
582 std::cerr <<
"mMixerSample->alen: " << mMixerSample->alen <<
"\n";
583 std::cerr <<
"mMixerSample->abuf: " << (
void*)mMixerSample->abuf <<
"\n";
588 int freq = mOriginalSpec.freq;
589 Uint16 format = mOriginalSpec.format;
590 int channels = mOriginalSpec.channels;
592 std::cerr <<
"Using original recording spec: " << freq <<
"Hz, " << channels <<
" channels, format=" << format <<
"\n";
595 int bitsPerSample = 16;
609 int bytesPerSample = bitsPerSample / 8;
610 int subchunk1size = 16;
611 int numChannels = channels;
612 int subchunk2size = mRecordPos;
613 int chunksize = 36 + subchunk2size;
615 int sampleRate = freq;
616 int byteRate = freq * numChannels * bitsPerSample / 8;
617 int blockAlign = numChannels * bitsPerSample / 8;
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;
628 std::fstream myFile(filename.
GetString().c_str(), ios::out | ios::binary);
629 if(!myFile.is_open()) {
635 myFile.seekp(0, ios::beg);
636 myFile.write(
"RIFF", 4);
637 myFile.write((
char*)&chunksize, 4);
638 myFile.write(
"WAVE", 4);
639 myFile.write(
"fmt ", 4);
640 myFile.write((
char*)&subchunk1size, 4);
641 myFile.write((
char*)&audioFormat, 2);
642 myFile.write((
char*)&numChannels, 2);
643 myFile.write((
char*)&sampleRate, 4);
644 myFile.write((
char*)&byteRate, 4);
645 myFile.write((
char*)&blockAlign, 2);
646 myFile.write((
char*)&bitsPerSample, 2);
647 myFile.write(
"data", 4);
649 std::cerr <<
"About to write data chunk header. subchunk2size = " << subchunk2size <<
"\n";
650 std::cerr <<
"About to write audio data. mRecordPos = " << mRecordPos <<
"\n";
652 myFile.write((
char*)&subchunk2size, 4);
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";
658 if(mMixerSample->abuf ==
NULL) {
659 std::cerr <<
"ERROR: Buffer is NULL!\n";
661 std::cerr <<
"Buffer appears valid, first byte value: " << (int)(mMixerSample->abuf[0]) <<
"\n";
664 myFile.write((
char*)(mMixerSample->abuf), mRecordPos);
666 std::cerr <<
"File position after audio data write: " << myFile.tellp() <<
"\n";
668 std::cerr <<
"FILE WRITE FAILED! Error state detected.\n";
669 std::cerr <<
"errno: " << errno <<
" (" << strerror(errno) <<
")\n";
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";
676 cerr <<
"File saved successfully.\n";
677 cerr <<
"--------------------------------------------\n";
686 int subchunk1size = 16;
687 int numChannels = mWave.
spec.channels;
690 int chunksize = 36+subchunk2size;
695 int sampleRate = mWave
697 int byteRate = mWave.
spec.freq*numChannels*bitsPerSample/8;
698 int blockAlign = numChannels*bitsPerSample/8;
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;
709 std::fstream myFile (filename.
GetString().c_str(), ios::out | ios::binary);
712 myFile.seekp (0, ios::beg);
713 myFile.write (
"RIFF", 4);
714 myFile.write ((
char*) &chunksize, 4);
715 myFile.write (
"WAVE", 4);
716 myFile.write (
"fmt ", 4);
717 myFile.write ((
char*) &subchunk1size, 4);
718 myFile.write ((
char*) &audioFormat, 2);
719 myFile.write ((
char*) &numChannels, 2);
720 myFile.write ((
char*) &sampleRate, 4);
721 myFile.write ((
char*) &byteRate, 4);
722 myFile.write ((
char*) &blockAlign, 2);
723 myFile.write ((
char*) &bitsPerSample, 2);
725 myFile.write (
"data", 4);
726 myFile.write ((
char*) &subchunk2size, 4);
753 int flags=MIX_INIT_OGG|MIX_INIT_MP3|MIX_INIT_FLAC|MIX_INIT_MOD;
754 int initted = Mix_Init(flags);
756 cerr <<
"Attempted: " << flags << endl;
757 cerr <<
"support code: " << initted << endl;
759 std::string supportOGG = (initted & MIX_INIT_OGG)?
"yes":
"no";
760 std::string supportMP3 = (initted & MIX_INIT_MP3)?
"yes":
"no";
761 std::string supportFLAC = (initted & MIX_INIT_FLAC)?
"yes":
"no";
762 std::string supportMOD = (initted & MIX_INIT_MOD)?
"yes":
"no";
766 int numtimesopened, frequency, channels;
768 numtimesopened=Mix_QuerySpec(&frequency, &format, &channels);
769 if(!numtimesopened) {
770 printf(
"Mix_QuerySpec: %s\n",Mix_GetError());
773 std::string format_str=
"Unknown";
777 case AUDIO_U8: format_str=
"U8";
break;
778 case AUDIO_S8: format_str=
"S8";
break;
779 case AUDIO_U16LSB: format_str=
"U16LSB";
break;
780 case AUDIO_S16LSB: format_str=
"S16LSB";
break;
781 case AUDIO_U16MSB: format_str=
"U16MSB";
break;
782 case AUDIO_S16MSB: format_str=
"S16MSB";
break;
785 std::cerr <<
"------------------------------------------------\n";
786 std::cerr <<
"Loading PEBL Audio Framework using SDL_Mixer\n";
787 std::cerr <<
"Opened (times): [" << numtimesopened <<
"]" << endl;
788 std::cerr <<
"Frequency (Hz): [" << frequency <<
"]" <<endl;
789 std::cerr <<
"Format: [" << format_str <<
"]" << endl;
790 std::cerr <<
"Channels: [" << channels <<
"]" << endl;
791 std::cerr <<
"\nFile formats supported:\n";
792 std::cerr <<
" .wav: (builtin) [yes]\n";
793 std::cerr <<
" .mp3: (mpg123) ["<< supportMP3<<
"]\n";
794 std::cerr <<
" .ogg: (libvorbis) ["<< supportOGG<<
"]\n";
795 std::cerr <<
" .flac: (libflac) ["<< supportFLAC<<
"]\n";
796 std::cerr <<
" .midi (libmikmod) ["<< supportMOD<<
"]\n";
797 std::cerr <<
"------------------------------------------------\n";
804 Mix_AllocateChannels(16);
809 if (mLoaded && SDL_OpenAudio(&mWave.
spec,
NULL) < 0 ) {
810 fprintf(stderr,
"Couldn't open audio: %s\n", SDL_GetError());
840 if(!Mix_SetPanning(
mChannel, lefti,righti)) {
841 printf(
"BG Mix_SetPanning: %s\n", Mix_GetError());
876 if(!Mix_SetPanning(
mChannel, lefti,righti)) {
877 printf(
"FG Mix_SetPanning: %s\n", Mix_GetError());
904 while(SDL_GetAudioStatus() == SDL_AUDIO_PLAYING)
945 if(!Mix_SetPanning(
mChannel, lefti,righti)) {
946 printf(
"Live Mix_SetPanning on channel [%d]: %s\n",
mChannel,Mix_GetError());
979#if !defined(PEBL_MIXER) || defined(PEBL_AUDIOIN)
992 tmp->
audio = mMixerSample->abuf;
995 tmp->
volume = mMixerSample->volume;
1000 Mix_QuerySpec(&freq, &format, &channels);
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;
1028 tmp->
name = mFilename.c_str();
1042 cerr <<
"---------------------------\n";
1043 cerr <<
"getting info in pao:getaudioinfo\n";
1044 cerr <<
"freq "<<mWave.
spec.freq <<
" -- " << tmp->
spec.freq <<endl;
1046 cerr <<
"---------------------------\n";
1060 SDL_memset(stream, 0, len);
1077 SDL_MixAudio(stream, waveptr, len, SDL_MIX_MAXVOLUME);
1086 SDL_MixAudio(stream, waveptr, waveleft, SDL_MIX_MAXVOLUME);
1103 cerr <<
"------------------------------------\n";
1104 cerr <<
"Filename : " << mFilename << endl;
1105 cerr <<
"Audio specs:\n";
1106 cerr <<
"Frequency: [" << mWave.
spec.freq <<
"]\n";
1108 switch(mWave.
spec.format)
1116 form =
"AUDIO_U16LSB";
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";
1144 cerr <<
"Playback: ["<<mWave.
audiopos<<
"]\n";
1145 cerr <<
"------------------------------------\n";
virtual bool SetPanning(const double left, const double right)
long double mAmplitudeRight
long double mAmplitudeLeft
std::string FindFile(const string &filename)
std::string GetString() const
void SignalWarning(const std::string &message)
void SignalFatalError(const std::string &message)
unsigned int bytesPerSample