123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- /**
- * Copyright (c) 2006-2013 LOVE Development Team
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- **/
- #include "Audio.h"
- #include "common/delay.h"
- #include "sound/Decoder.h"
- #include <cstdlib>
- namespace love
- {
- namespace audio
- {
- namespace openal
- {
- Audio::PoolThread::PoolThread(Pool *pool)
- : pool(pool)
- , finish(false)
- {
- mutex = thread::newMutex();
- }
- Audio::PoolThread::~PoolThread()
- {
- delete mutex;
- }
- void Audio::PoolThread::threadFunction()
- {
- while (true)
- {
- {
- thread::Lock lock(mutex);
- if (finish)
- {
- return;
- }
- }
- pool->update();
- delay(5);
- }
- }
- void Audio::PoolThread::setFinish()
- {
- thread::Lock lock(mutex);
- finish = true;
- }
- Audio::Audio() : distanceModel(DISTANCE_INVERSE_CLAMPED)
- {
- // Passing zero for default device.
- device = alcOpenDevice(0);
- if (device == 0)
- throw love::Exception("Could not open device.");
- context = alcCreateContext(device, 0);
- if (context == 0)
- throw love::Exception("Could not create context.");
- alcMakeContextCurrent(context);
- if (alcGetError(device) != ALC_NO_ERROR)
- throw love::Exception("Could not make context current.");
- /*std::string captureName(alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
- const ALCchar * devices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
- while (*devices)
- {
- std::string device(devices);
- devices += device.size() + 1;
- if (device.find("Mic") != std::string::npos || device.find("mic") != std::string::npos)
- {
- captureName = device;
- }
- }
- capture = alcCaptureOpenDevice(captureName.c_str(), 8000, AL_FORMAT_MONO16, 262144); // about 32 seconds
- if (!capture)
- {
- // We're not going to prevent LOVE from running without a microphone, but we should warn, at least
- std::cerr << "Warning, couldn't open capture device! No audio input!" << std::endl;
- }*/
- // pool must be allocated after AL context.
- pool = new Pool();
- poolThread = new PoolThread(pool);
- poolThread->start();
- }
- Audio::~Audio()
- {
- poolThread->setFinish();
- poolThread->wait();
- delete poolThread;
- delete pool;
- alcMakeContextCurrent(0);
- alcDestroyContext(context);
- //if (capture) alcCaptureCloseDevice(capture);
- alcCloseDevice(device);
- }
- const char *Audio::getName() const
- {
- return "love.audio.openal";
- }
- love::audio::Source *Audio::newSource(love::sound::Decoder *decoder)
- {
- return new Source(pool, decoder);
- }
- love::audio::Source *Audio::newSource(love::sound::SoundData *soundData)
- {
- return new Source(pool, soundData);
- }
- int Audio::getNumSources() const
- {
- return pool->getNumSources();
- }
- int Audio::getMaxSources() const
- {
- return pool->getMaxSources();
- }
- void Audio::play(love::audio::Source *source)
- {
- source->play();
- }
- void Audio::stop(love::audio::Source *source)
- {
- source->stop();
- }
- void Audio::stop()
- {
- pool->stop();
- }
- void Audio::pause(love::audio::Source *source)
- {
- source->pause();
- }
- void Audio::pause()
- {
- pool->pause();
- }
- void Audio::resume(love::audio::Source *source)
- {
- source->resume();
- }
- void Audio::resume()
- {
- pool->resume();
- }
- void Audio::rewind(love::audio::Source *source)
- {
- source->rewind();
- }
- void Audio::rewind()
- {
- pool->rewind();
- }
- void Audio::setVolume(float volume)
- {
- alListenerf(AL_GAIN, volume);
- }
- float Audio::getVolume() const
- {
- ALfloat volume;
- alGetListenerf(AL_GAIN, &volume);
- return volume;
- }
- void Audio::getPosition(float *v) const
- {
- alGetListenerfv(AL_POSITION, v);
- }
- void Audio::setPosition(float *v)
- {
- alListenerfv(AL_POSITION, v);
- }
- void Audio::getOrientation(float *v) const
- {
- alGetListenerfv(AL_ORIENTATION, v);
- }
- void Audio::setOrientation(float *v)
- {
- alListenerfv(AL_ORIENTATION, v);
- }
- void Audio::getVelocity(float *v) const
- {
- alGetListenerfv(AL_VELOCITY, v);
- }
- void Audio::setVelocity(float *v)
- {
- alListenerfv(AL_VELOCITY, v);
- }
- void Audio::record()
- {
- if (!canRecord()) return;
- alcCaptureStart(capture);
- }
- love::sound::SoundData *Audio::getRecordedData()
- {
- if (!canRecord())
- return NULL;
- int samplerate = 8000;
- ALCint samples;
- alcGetIntegerv(capture, ALC_CAPTURE_SAMPLES, 4, &samples);
- void *data = malloc(samples * (2/sizeof(char)));
- alcCaptureSamples(capture, data, samples);
- love::sound::SoundData *sd = new love::sound::SoundData(data, samples, samplerate, 16, 1);
- free(data);
- return sd;
- }
- love::sound::SoundData *Audio::stopRecording(bool returnData)
- {
- if (!canRecord())
- return NULL;
- love::sound::SoundData *sd = NULL;
- if (returnData)
- {
- sd = getRecordedData();
- }
- alcCaptureStop(capture);
- return sd;
- }
- bool Audio::canRecord()
- {
- return (capture != NULL);
- }
- Audio::DistanceModel Audio::getDistanceModel() const
- {
- return this->distanceModel;
- }
- void Audio::setDistanceModel(DistanceModel distanceModel)
- {
- this->distanceModel = distanceModel;
- switch (distanceModel)
- {
- case DISTANCE_NONE:
- alDistanceModel(AL_NONE);
- break;
- case DISTANCE_INVERSE:
- alDistanceModel(AL_INVERSE_DISTANCE);
- break;
- case DISTANCE_INVERSE_CLAMPED:
- alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
- break;
- case DISTANCE_LINEAR:
- alDistanceModel(AL_LINEAR_DISTANCE);
- break;
- case DISTANCE_LINEAR_CLAMPED:
- alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
- break;
- case DISTANCE_EXPONENT:
- alDistanceModel(AL_EXPONENT_DISTANCE);
- break;
- case DISTANCE_EXPONENT_CLAMPED:
- alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED);
- break;
- default:
- break;
- }
- }
- } // openal
- } // audio
- } // love
|