Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tsound_t.h"
Toshihiro Shimizu 890ddd
#include "texception.h"
Toshihiro Shimizu 890ddd
#include "tthread.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <errno.h></errno.h>
Toshihiro Shimizu 890ddd
#include <audio.h></audio.h>
Toshihiro Shimizu 890ddd
#include <unistd.h></unistd.h>
Toshihiro Shimizu 890ddd
#include <queue></queue>
Toshihiro Shimizu 890ddd
#include <set></set>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//forward declaration
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
bool isInterfaceSupported(int deviceType, int interfaceType);
Toshihiro Shimizu 890ddd
bool setDefaultInput(TSoundInputDevice::Source type);
Toshihiro Shimizu 890ddd
bool setDefaultOutput();
Toshihiro Shimizu 890ddd
bool isChangeOutput(ULONG sampleRate);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TSoundOutputDeviceImp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ALport m_port;
Toshihiro Shimizu 890ddd
	bool m_stopped;
Toshihiro Shimizu 890ddd
	bool m_isPlaying;
Toshihiro Shimizu 890ddd
	bool m_looped;
Toshihiro Shimizu 890ddd
	TSoundTrackFormat m_currentFormat;
Toshihiro Shimizu 890ddd
	std::queue<tsoundtrackp> m_queuedSoundTracks;</tsoundtrackp>
Toshihiro Shimizu 890ddd
	std::set<int> m_supportedRate;</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThread::Executor m_executor;
Toshihiro Shimizu 890ddd
	TThread::Mutex m_mutex;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TSoundOutputDeviceImp()
Toshihiro Shimizu 890ddd
		: m_stopped(false), m_isPlaying(false), m_looped(false), m_port(NULL), m_queuedSoundTracks(), m_supportedRate(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~TSoundOutputDeviceImp(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool doOpenDevice(const TSoundTrackFormat &format);
Toshihiro Shimizu 890ddd
	void insertAllRate();
Toshihiro Shimizu 890ddd
	bool verifyRate();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDeviceImp::doOpenDevice(const TSoundTrackFormat &format)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALconfig config;
Toshihiro Shimizu 890ddd
	ALpv pvbuf[3];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_currentFormat = format;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// AL_MONITOR_CTL fa parte dei vecchi andrebbero trovati quelli nuovi
Toshihiro Shimizu 890ddd
	pvbuf[0].param = AL_PORT_COUNT;
Toshihiro Shimizu 890ddd
	pvbuf[1].param = AL_MONITOR_CTL;
Toshihiro Shimizu 890ddd
	if (alGetParams(AL_DEFAULT_OUTPUT, pvbuf, 2) < 0)
Toshihiro Shimizu 890ddd
		if (oserror() == AL_BAD_DEVICE_ACCESS)
Toshihiro Shimizu 890ddd
			return false; //throw TException("Could not access audio hardware.");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!isInterfaceSupported(AL_DEFAULT_OUTPUT, AL_SPEAKER_IF_TYPE))
Toshihiro Shimizu 890ddd
		return false; //throw TException("Speakers are not supported");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int dev = alGetResourceByName(AL_SYSTEM, (char *)"Headphone/Speaker", AL_DEVICE_TYPE);
Toshihiro Shimizu 890ddd
	if (!dev)
Toshihiro Shimizu 890ddd
		return false; //throw TException("invalid device speakers");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pvbuf[0].param = AL_DEFAULT_OUTPUT;
Toshihiro Shimizu 890ddd
	pvbuf[0].value.i = dev;
Toshihiro Shimizu 890ddd
	alSetParams(AL_SYSTEM, pvbuf, 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ALfixed buf[2] = {alDoubleToFixed(0), alDoubleToFixed(0)};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	config = alNewConfig();
Toshihiro Shimizu 890ddd
	// qui devo metterci gli altoparlanti e poi setto i valori per il default output
Toshihiro Shimizu 890ddd
	pvbuf[0].param = AL_RATE;
Toshihiro Shimizu 890ddd
	pvbuf[0].value.ll = alDoubleToFixed((double)format.m_sampleRate);
Toshihiro Shimizu 890ddd
	pvbuf[1].param = AL_GAIN;
Toshihiro Shimizu 890ddd
	pvbuf[1].value.ptr = buf;
Toshihiro Shimizu 890ddd
	pvbuf[1].sizeIn = 8;
Toshihiro Shimizu 890ddd
	pvbuf[2].param = AL_INTERFACE;
Toshihiro Shimizu 890ddd
	pvbuf[2].value.i = AL_SPEAKER_IF_TYPE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (alSetParams(AL_DEFAULT_OUTPUT, pvbuf, 3) < 0)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	//throw TException("Unable to set params for output device");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (alSetChannels(config, format.m_channelCount) == -1)
Toshihiro Shimizu 890ddd
		return false; //throw TException("Error to setting audio hardware.");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int bytePerSample = format.m_bitPerSample >> 3;
Toshihiro Shimizu 890ddd
	switch (bytePerSample) {
Toshihiro Shimizu 890ddd
	case 3:
Toshihiro Shimizu 890ddd
		bytePerSample++;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	default:
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (alSetWidth(config, bytePerSample) == -1)
Toshihiro Shimizu 890ddd
		return false; //throw TException("Error to setting audio hardware.");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (alSetSampFmt(config, AL_SAMPFMT_TWOSCOMP) == -1)
Toshihiro Shimizu 890ddd
		return false; //throw TException("Error to setting audio hardware.");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (alSetQueueSize(config, (TINT32)format.m_sampleRate) == -1)
Toshihiro Shimizu 890ddd
		return false; //throw TException("Error to setting audio hardware.");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_port = alOpenPort("AudioOutput", "w", config);
Toshihiro Shimizu 890ddd
	if (!m_port)
Toshihiro Shimizu 890ddd
		return false; //throw TException("Could not open audio port.");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	alFreeConfig(config);
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundOutputDeviceImp::insertAllRate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(8000);
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(11025);
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(16000);
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(22050);
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(32000);
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(44100);
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(48000);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDeviceImp::verifyRate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Sample Rate
Toshihiro Shimizu 890ddd
	ALparamInfo pinfo;
Toshihiro Shimizu 890ddd
	int ret = alGetParamInfo(AL_DEFAULT_OUTPUT, AL_RATE, &pinfo);
Toshihiro Shimizu 890ddd
	if (ret != -1 && pinfo.elementType == AL_FIXED_ELEM) {
Toshihiro Shimizu 890ddd
		int min = (int)alFixedToDouble(pinfo.min.ll);
Toshihiro Shimizu 890ddd
		int max = (int)alFixedToDouble(pinfo.max.ll);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::set<int>::iterator it;</int>
Toshihiro Shimizu 890ddd
		for (it = m_supportedRate.begin(); it != m_supportedRate.end(); ++it)
Toshihiro Shimizu 890ddd
			if (*it < min || *it > max)
Toshihiro Shimizu 890ddd
				m_supportedRate.erase(*it);
Toshihiro Shimizu 890ddd
		if (m_supportedRate.end() == m_supportedRate.begin())
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
	} else if (ret == AL_BAD_PARAM)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class PlayTask : public TThread::Runnable
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	TSoundOutputDeviceImp *m_devImp;
Toshihiro Shimizu 890ddd
	TSoundTrackP m_sndtrack;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	PlayTask(TSoundOutputDeviceImp *devImp, const TSoundTrackP &st)
Toshihiro Shimizu 890ddd
		: TThread::Runnable(), m_devImp(devImp), m_sndtrack(st){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~PlayTask(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void run();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void PlayTask::run()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int leftToPlay = m_sndtrack->getSampleCount();
Toshihiro Shimizu 890ddd
	int i = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_devImp->m_port ||
Toshihiro Shimizu 890ddd
		(m_devImp->m_currentFormat != m_sndtrack->getFormat()) ||
Toshihiro Shimizu 890ddd
		isChangeOutput(m_sndtrack->getSampleRate()))
Toshihiro Shimizu 890ddd
		if (!m_devImp->doOpenDevice(m_sndtrack->getFormat()))
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while ((leftToPlay > 0) && m_devImp->m_isPlaying) {
Toshihiro Shimizu 890ddd
		int fillable = alGetFillable(m_devImp->m_port);
Toshihiro Shimizu 890ddd
		if (!fillable)
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (fillable < leftToPlay) {
Toshihiro Shimizu 890ddd
			alWriteFrames(m_devImp->m_port, (void *)(m_sndtrack->getRawData() + i), fillable);
Toshihiro Shimizu 890ddd
			// ricorda getSampleSize restituisce m_sampleSize che comprende gia'
Toshihiro Shimizu 890ddd
			// la moltiplicazione per il numero dei canali
Toshihiro Shimizu 890ddd
			i += fillable * m_sndtrack->getSampleSize();
Toshihiro Shimizu 890ddd
			leftToPlay -= fillable;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			alWriteFrames(m_devImp->m_port, (void *)(m_sndtrack->getRawData() + i), leftToPlay);
Toshihiro Shimizu 890ddd
			leftToPlay = 0;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_devImp->m_stopped) {
Toshihiro Shimizu 890ddd
		while (ALgetfilled(m_devImp->m_port) > 0)
Toshihiro Shimizu 890ddd
			sginap(1);
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			TThread::ScopedLock sl(m_devImp->m_mutex);
Toshihiro Shimizu 890ddd
			if (!m_devImp->m_looped)
Toshihiro Shimizu 890ddd
				m_devImp->m_queuedSoundTracks.pop();
Toshihiro Shimizu 890ddd
			if (m_devImp->m_queuedSoundTracks.empty()) {
Toshihiro Shimizu 890ddd
				m_devImp->m_isPlaying = false;
Toshihiro Shimizu 890ddd
				m_devImp->m_stopped = true;
Toshihiro Shimizu 890ddd
				m_devImp->m_looped = false;
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
				m_devImp->m_executor.addTask(
Toshihiro Shimizu 890ddd
					new PlayTask(m_devImp, m_devImp->m_queuedSoundTracks.front()));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		alDiscardFrames(m_devImp->m_port, alGetFilled(m_devImp->m_port));
Toshihiro Shimizu 890ddd
		while (!m_devImp->m_queuedSoundTracks.empty())
Toshihiro Shimizu 890ddd
			m_devImp->m_queuedSoundTracks.pop();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundOutputDevice::TSoundOutputDevice() : m_imp(new TSoundOutputDeviceImp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!setDefaultOutput())
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableSetDevice, "Speaker not supported");
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		supportsVolume();
Toshihiro Shimizu 890ddd
	} catch (TSoundDeviceException &e) {
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(e.getType(), e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	m_imp->insertAllRate();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundOutputDevice::~TSoundOutputDevice()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	close();
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::installed()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (alQueryValues(AL_SYSTEM, AL_DEFAULT_OUTPUT, 0, 0, 0, 0) <= 0)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::open(const TSoundTrackP &st)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_imp->doOpenDevice(st->getFormat()))
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableOpenDevice,
Toshihiro Shimizu 890ddd
			"Problem to open the output device or set some params");
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::close()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	stop();
Toshihiro Shimizu 890ddd
	if (m_imp->m_port)
Toshihiro Shimizu 890ddd
		alClosePort(m_imp->m_port);
Toshihiro Shimizu 890ddd
	m_imp->m_port = NULL;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundOutputDevice::play(const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop, bool scrubbing)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!st->getSampleCount())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TThread::ScopedLock sl(m_imp->m_mutex);
Toshihiro Shimizu 890ddd
		if (m_imp->m_looped)
Toshihiro Shimizu 890ddd
			throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
				TSoundDeviceException::Busy,
Toshihiro Shimizu 890ddd
				"Unable to queue another playback when the sound player is looping");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_imp->m_isPlaying = true;
Toshihiro Shimizu 890ddd
		m_imp->m_stopped = false;
Toshihiro Shimizu 890ddd
		m_imp->m_looped = loop;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TSoundTrackFormat fmt;
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		fmt = getPreferredFormat(st->getFormat());
Toshihiro Shimizu 890ddd
		if (fmt != st->getFormat()) {
Toshihiro Shimizu 890ddd
			throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
				TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
				"Unsupported Format");
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} catch (TSoundDeviceException &e) {
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
			e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(s1 >= s0);
Toshihiro Shimizu 890ddd
	TSoundTrackP subTrack = st->extract(s0, s1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//far partire il thread
Toshihiro Shimizu 890ddd
	if (m_imp->m_queuedSoundTracks.empty()) {
Toshihiro Shimizu 890ddd
		m_imp->m_queuedSoundTracks.push(subTrack);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_imp->m_executor.addTask(new PlayTask(m_imp, subTrack));
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		m_imp->m_queuedSoundTracks.push(subTrack);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundOutputDevice::stop()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_imp->m_isPlaying)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThread::ScopedLock sl(m_imp->m_mutex);
Toshihiro Shimizu 890ddd
	m_imp->m_isPlaying = false;
Toshihiro Shimizu 890ddd
	m_imp->m_stopped = true;
Toshihiro Shimizu 890ddd
	m_imp->m_looped = false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TSoundOutputDevice::getVolume()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALpv pv[1];
Toshihiro Shimizu 890ddd
	ALfixed value[2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		supportsVolume();
Toshihiro Shimizu 890ddd
	} catch (TSoundDeviceException &e) {
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(e.getType(), e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pv[0].param = AL_GAIN;
Toshihiro Shimizu 890ddd
	pv[0].value.ptr = value;
Toshihiro Shimizu 890ddd
	pv[0].sizeIn = 8;
Toshihiro Shimizu 890ddd
	alGetParams(AL_DEFAULT_OUTPUT, pv, 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double val = (((alFixedToDouble(value[0]) + alFixedToDouble(value[1])) / 2.) + 60.) / 8.05;
Toshihiro Shimizu 890ddd
	return val;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::setVolume(double volume)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALpv pv[1];
Toshihiro Shimizu 890ddd
	ALfixed value[2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		supportsVolume();
Toshihiro Shimizu 890ddd
	} catch (TSoundDeviceException &e) {
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(e.getType(), e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double val = -60. + 8.05 * volume;
Toshihiro Shimizu 890ddd
	value[0] = alDoubleToFixed(val);
Toshihiro Shimizu 890ddd
	value[1] = alDoubleToFixed(val);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pv[0].param = AL_GAIN;
Toshihiro Shimizu 890ddd
	pv[0].value.ptr = value;
Toshihiro Shimizu 890ddd
	pv[0].sizeIn = 8;
Toshihiro Shimizu 890ddd
	if (alSetParams(AL_DEFAULT_OUTPUT, pv, 1) < 0)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::supportsVolume()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALparamInfo pinfo;
Toshihiro Shimizu 890ddd
	int ret;
Toshihiro Shimizu 890ddd
	ret = alGetParamInfo(AL_DEFAULT_OUTPUT, AL_GAIN, &pinfo);
Toshihiro Shimizu 890ddd
	double min = alFixedToDouble(pinfo.min.ll);
Toshihiro Shimizu 890ddd
	double max = alFixedToDouble(pinfo.max.ll);
Toshihiro Shimizu 890ddd
	if ((ret != -1) && (min != max) && (max != 0.0))
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	else if ((ret == AL_BAD_PARAM) || ((min == max) && (max == 0.0)))
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableVolume,
Toshihiro Shimizu 890ddd
			"It is impossible to chamge setting of volume");
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::NoMixer, "Output device is not accessible");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::isPlaying() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_isPlaying;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::isLooping()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThread::ScopedLock sl(m_imp->m_mutex);
Toshihiro Shimizu 890ddd
	return m_imp->m_looped;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundOutputDevice::setLooping(bool loop)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThread::ScopedLock sl(m_imp->m_mutex);
Toshihiro Shimizu 890ddd
	m_imp->m_looped = loop;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(
Toshihiro Shimizu 890ddd
	ULONG sampleRate, int channelCount, int bitPerSample)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TSoundTrackFormat fmt;
Toshihiro Shimizu 890ddd
	int ret;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_imp->verifyRate())
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
			"There isn't any support rate");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_imp->m_supportedRate.find((int)sampleRate) ==
Toshihiro Shimizu 890ddd
		m_imp->m_supportedRate.end()) {
Toshihiro Shimizu 890ddd
		std::set<int>::iterator it =</int>
Toshihiro Shimizu 890ddd
			m_imp->m_supportedRate.lower_bound((int)sampleRate);
Toshihiro Shimizu 890ddd
		if (it == m_imp->m_supportedRate.end()) {
Toshihiro Shimizu 890ddd
			it = std::max_element(m_imp->m_supportedRate.begin(),
Toshihiro Shimizu 890ddd
								  m_imp->m_supportedRate.end());
Toshihiro Shimizu 890ddd
			if (it != m_imp->m_supportedRate.end())
Toshihiro Shimizu 890ddd
				sampleRate = *(m_imp->m_supportedRate.rbegin());
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
					TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
					"There isn't a supported rate");
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			sampleRate = *it;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int value;
Toshihiro Shimizu 890ddd
	ALvalue vals[32];
Toshihiro Shimizu 890ddd
	if ((ret = alQueryValues(AL_DEFAULT_OUTPUT, AL_CHANNELS, vals, 32, 0, 0)) > 0)
Toshihiro Shimizu 890ddd
		for (int i = 0; i < ret; ++i)
Toshihiro Shimizu 890ddd
			value = vals[i].i;
Toshihiro Shimizu 890ddd
	else if (oserror() == AL_BAD_PARAM)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::NoMixer,
Toshihiro Shimizu 890ddd
			"It is impossible ask for the max numbers of channels supported");
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::NoMixer,
Toshihiro Shimizu 890ddd
			"It is impossibile information about ouput device");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (value > 2)
Toshihiro Shimizu 890ddd
		value = 2;
Toshihiro Shimizu 890ddd
	if (channelCount > value)
Toshihiro Shimizu 890ddd
		channelCount = value;
Toshihiro Shimizu 890ddd
	else if (channelCount <= 0)
Toshihiro Shimizu 890ddd
		channelCount = 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (bitPerSample <= 8)
Toshihiro Shimizu 890ddd
		bitPerSample = 8;
Toshihiro Shimizu 890ddd
	else if (bitPerSample <= 16)
Toshihiro Shimizu 890ddd
		bitPerSample = 16;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		bitPerSample = 24;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fmt.m_bitPerSample = bitPerSample;
Toshihiro Shimizu 890ddd
	fmt.m_channelCount = channelCount;
Toshihiro Shimizu 890ddd
	fmt.m_sampleRate = sampleRate;
Toshihiro Shimizu 890ddd
	fmt.m_signedSample = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return fmt;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundTrackFormat TSoundOutputDevice::getPreferredFormat(const TSoundTrackFormat &format)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		return getPreferredFormat(
Toshihiro Shimizu 890ddd
			format.m_sampleRate, format.m_channelCount, format.m_bitPerSample);
Toshihiro Shimizu 890ddd
	} catch (TSoundDeviceException &e) {
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(e.getType(), e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//                REGISTRAZIONE
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TSoundInputDeviceImp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ALport m_port;
Toshihiro Shimizu 890ddd
	bool m_stopped;
Toshihiro Shimizu 890ddd
	bool m_isRecording;
Toshihiro Shimizu 890ddd
	bool m_oneShotRecording;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TINT32 m_recordedSampleCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vector<char *=""> m_recordedBlocks;</char>
Toshihiro Shimizu 890ddd
	vector<int> m_samplePerBlocks;</int>
Toshihiro Shimizu 890ddd
	TSoundTrackFormat m_currentFormat;
Toshihiro Shimizu 890ddd
	TSoundTrackP m_st;
Toshihiro Shimizu 890ddd
	std::set<int> m_supportedRate;</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThread::Executor m_executor;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TSoundInputDeviceImp()
Toshihiro Shimizu 890ddd
		: m_stopped(false), m_isRecording(false), m_port(NULL), m_recordedBlocks(), m_samplePerBlocks(), m_recordedSampleCount(0), m_oneShotRecording(false), m_st(0), m_supportedRate(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~TSoundInputDeviceImp(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool doOpenDevice(const TSoundTrackFormat &format,
Toshihiro Shimizu 890ddd
					  TSoundInputDevice::Source devType);
Toshihiro Shimizu 890ddd
	void insertAllRate();
Toshihiro Shimizu 890ddd
	bool verifyRate();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundInputDeviceImp::doOpenDevice(const TSoundTrackFormat &format,
Toshihiro Shimizu 890ddd
										TSoundInputDevice::Source devType)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALconfig config;
Toshihiro Shimizu 890ddd
	ALpv pvbuf[2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_currentFormat = format;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// AL_MONITOR_CTL fa parte dei vecchi andrebbero trovati quelli nuovi
Toshihiro Shimizu 890ddd
	pvbuf[0].param = AL_PORT_COUNT;
Toshihiro Shimizu 890ddd
	pvbuf[1].param = AL_MONITOR_CTL;
Toshihiro Shimizu 890ddd
	if (alGetParams(AL_DEFAULT_INPUT, pvbuf, 2) < 0)
Toshihiro Shimizu 890ddd
		if (oserror() == AL_BAD_DEVICE_ACCESS)
Toshihiro Shimizu 890ddd
			return false; //throw TException("Could not access audio hardware.");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	config = alNewConfig();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!setDefaultInput(devType))
Toshihiro Shimizu 890ddd
		return false; //throw TException("Could not set the input device specified");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pvbuf[0].param = AL_RATE;
Toshihiro Shimizu 890ddd
	pvbuf[0].value.ll = alDoubleToFixed(format.m_sampleRate);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ALfixed buf[2] = {alDoubleToFixed(0), alDoubleToFixed(0)};
Toshihiro Shimizu 890ddd
	pvbuf[1].param = AL_GAIN;
Toshihiro Shimizu 890ddd
	pvbuf[1].value.ptr = buf;
Toshihiro Shimizu 890ddd
	pvbuf[1].sizeIn = 8;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (alSetParams(AL_DEFAULT_INPUT, pvbuf, 2) < 0)
Toshihiro Shimizu 890ddd
		return false; //throw TException("Problem to set params ");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (alSetChannels(config, format.m_channelCount) == -1)
Toshihiro Shimizu 890ddd
		return false; //throw TException("Error to setting audio hardware.");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int bytePerSample = format.m_bitPerSample >> 3;
Toshihiro Shimizu 890ddd
	switch (bytePerSample) {
Toshihiro Shimizu 890ddd
	case 3:
Toshihiro Shimizu 890ddd
		bytePerSample++;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	default:
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (alSetWidth(config, bytePerSample) == -1)
Toshihiro Shimizu 890ddd
		return false; //throw TException("Error to setting audio hardware.");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (alSetSampFmt(config, AL_SAMPFMT_TWOSCOMP) == -1)
Toshihiro Shimizu 890ddd
		return false; //throw TException("Error to setting audio hardware.");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (alSetQueueSize(config, (TINT32)format.m_sampleRate) == -1)
Toshihiro Shimizu 890ddd
		return false; //throw TException("Error to setting audio hardware.");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	alSetDevice(config, AL_DEFAULT_INPUT);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_port = alOpenPort("AudioInput", "r", config);
Toshihiro Shimizu 890ddd
	if (!m_port)
Toshihiro Shimizu 890ddd
		return false; //throw TException("Could not open audio port.");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	alFreeConfig(config);
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundInputDeviceImp::insertAllRate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(8000);
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(11025);
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(16000);
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(22050);
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(32000);
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(44100);
Toshihiro Shimizu 890ddd
	m_supportedRate.insert(48000);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundInputDeviceImp::verifyRate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Sample Rate
Toshihiro Shimizu 890ddd
	ALparamInfo pinfo;
Toshihiro Shimizu 890ddd
	int ret = alGetParamInfo(AL_DEFAULT_INPUT, AL_RATE, &pinfo);
Toshihiro Shimizu 890ddd
	if (ret != -1 && pinfo.elementType == AL_FIXED_ELEM) {
Toshihiro Shimizu 890ddd
		int min = (int)alFixedToDouble(pinfo.min.ll);
Toshihiro Shimizu 890ddd
		int max = (int)alFixedToDouble(pinfo.max.ll);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		std::set<int>::iterator it;</int>
Toshihiro Shimizu 890ddd
		for (it = m_supportedRate.begin(); it != m_supportedRate.end(); ++it)
Toshihiro Shimizu 890ddd
			if (*it < min || *it > max)
Toshihiro Shimizu 890ddd
				m_supportedRate.erase(*it);
Toshihiro Shimizu 890ddd
		if (m_supportedRate.end() == m_supportedRate.begin())
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
	} else if (ret == AL_BAD_PARAM)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class RecordTask : public TThread::Runnable
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	TSoundInputDeviceImp *m_devImp;
Toshihiro Shimizu 890ddd
	int m_ByteToSample;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	RecordTask(TSoundInputDeviceImp *devImp, int numByte)
Toshihiro Shimizu 890ddd
		: TThread::Runnable(), m_devImp(devImp), m_ByteToSample(numByte){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~RecordTask(){};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void run();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RecordTask::run()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TINT32 byteRecordedSample = 0;
Toshihiro Shimizu 890ddd
	int filled = alGetFilled(m_devImp->m_port);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_devImp->m_oneShotRecording) {
Toshihiro Shimizu 890ddd
		char *rawData = m_devImp->m_recordedBlocks.front();
Toshihiro Shimizu 890ddd
		int sampleSize;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if ((m_devImp->m_currentFormat.m_bitPerSample >> 3) == 3)
Toshihiro Shimizu 890ddd
			sampleSize = 4;
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			sampleSize = (m_devImp->m_currentFormat.m_bitPerSample >> 3);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		sampleSize *= m_devImp->m_currentFormat.m_channelCount;
Toshihiro Shimizu 890ddd
		while ((byteRecordedSample <= (m_ByteToSample - filled * sampleSize)) && m_devImp->m_isRecording) {
Toshihiro Shimizu 890ddd
			alReadFrames(m_devImp->m_port, (void *)(rawData + byteRecordedSample), filled);
Toshihiro Shimizu 890ddd
			byteRecordedSample += filled * sampleSize;
Toshihiro Shimizu 890ddd
			filled = alGetFilled(m_devImp->m_port);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_devImp->m_isRecording) {
Toshihiro Shimizu 890ddd
			alReadFrames(m_devImp->m_port, (void *)(rawData + byteRecordedSample),
Toshihiro Shimizu 890ddd
						 (m_ByteToSample - byteRecordedSample) / sampleSize);
Toshihiro Shimizu 890ddd
			while (alGetFillable(m_devImp->m_port) > 0)
Toshihiro Shimizu 890ddd
				sginap(1);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		while (m_devImp->m_isRecording) {
Toshihiro Shimizu 890ddd
			filled = alGetFilled(m_devImp->m_port);
Toshihiro Shimizu 890ddd
			if (filled > 0) {
Toshihiro Shimizu 890ddd
				char *dataBuffer = new char[filled * m_ByteToSample];
Toshihiro Shimizu 890ddd
				m_devImp->m_recordedBlocks.push_back(dataBuffer);
Toshihiro Shimizu 890ddd
				m_devImp->m_samplePerBlocks.push_back(filled * m_ByteToSample);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				alReadFrames(m_devImp->m_port, (void *)dataBuffer, filled);
Toshihiro Shimizu 890ddd
				m_devImp->m_recordedSampleCount += filled;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		while (alGetFillable(m_devImp->m_port) > 0)
Toshihiro Shimizu 890ddd
			sginap(1);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	alClosePort(m_devImp->m_port);
Toshihiro Shimizu 890ddd
	m_devImp->m_port = 0;
Toshihiro Shimizu 890ddd
	m_devImp->m_stopped = true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundInputDevice::TSoundInputDevice() : m_imp(new TSoundInputDeviceImp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundInputDevice::~TSoundInputDevice()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_imp->m_port)
Toshihiro Shimizu 890ddd
		alClosePort(m_imp->m_port);
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundInputDevice::installed()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, 0, 0, 0, 0) <= 0)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundInputDevice::record(const TSoundTrackFormat &format, TSoundInputDevice::Source type)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_imp->m_isRecording == true)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::Busy,
Toshihiro Shimizu 890ddd
			"Just another recoding is in progress");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_recordedBlocks.clear();
Toshihiro Shimizu 890ddd
	m_imp->m_samplePerBlocks.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//registra creando una nuova traccia
Toshihiro Shimizu 890ddd
	m_imp->m_oneShotRecording = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!setDefaultInput(type))
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableSetDevice,
Toshihiro Shimizu 890ddd
			"Error to set the input device");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->insertAllRate();
Toshihiro Shimizu 890ddd
	TSoundTrackFormat fmt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		fmt = getPreferredFormat(format);
Toshihiro Shimizu 890ddd
		if (fmt != format) {
Toshihiro Shimizu 890ddd
			throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
				TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
				"Unsupported Format");
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} catch (TSoundDeviceException &e) {
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
			e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_imp->m_port)
Toshihiro Shimizu 890ddd
		m_imp->doOpenDevice(format, type);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_currentFormat = format;
Toshihiro Shimizu 890ddd
	m_imp->m_isRecording = true;
Toshihiro Shimizu 890ddd
	m_imp->m_stopped = false;
Toshihiro Shimizu 890ddd
	m_imp->m_recordedSampleCount = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int bytePerSample = format.m_bitPerSample >> 3;
Toshihiro Shimizu 890ddd
	switch (bytePerSample) {
Toshihiro Shimizu 890ddd
	case 3:
Toshihiro Shimizu 890ddd
		bytePerSample++;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	default:
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	bytePerSample *= format.m_channelCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//far partire il thread
Toshihiro Shimizu 890ddd
	/*TRecordThread *recordThread = new TRecordThread(m_imp, bytePerSample);
Toshihiro Shimizu 890ddd
	if (!recordThread)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
  	m_imp->m_isRecording = false;
Toshihiro Shimizu 890ddd
  	m_imp->m_stopped = true;
Toshihiro Shimizu 890ddd
    throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
      TSoundDeviceException::UnablePrepare,
Toshihiro Shimizu 890ddd
      "Unable to create the recording thread");	
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
  recordThread->start();*/
Toshihiro Shimizu 890ddd
	m_imp->m_executor.addTask(new RecordTask(m_imp, bytePerSample));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundInputDevice::record(const TSoundTrackP &st, TSoundInputDevice::Source type)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_imp->m_isRecording == true)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::Busy,
Toshihiro Shimizu 890ddd
			"Just another recoding is in progress");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_recordedBlocks.clear();
Toshihiro Shimizu 890ddd
	m_imp->m_samplePerBlocks.clear();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!setDefaultInput(type))
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableSetDevice,
Toshihiro Shimizu 890ddd
			"Error to set the input device");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->insertAllRate();
Toshihiro Shimizu 890ddd
	TSoundTrackFormat fmt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		fmt = getPreferredFormat(st->getFormat());
Toshihiro Shimizu 890ddd
		if (fmt != st->getFormat()) {
Toshihiro Shimizu 890ddd
			throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
				TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
				"Unsupported Format");
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} catch (TSoundDeviceException &e) {
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
			e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_imp->m_port)
Toshihiro Shimizu 890ddd
		if (!m_imp->doOpenDevice(st->getFormat(), type))
Toshihiro Shimizu 890ddd
			throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
				TSoundDeviceException::UnableOpenDevice,
Toshihiro Shimizu 890ddd
				"Unable to open input device");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Sovrascive un'intera o parte di traccia gia' esistente
Toshihiro Shimizu 890ddd
	m_imp->m_oneShotRecording = true;
Toshihiro Shimizu 890ddd
	m_imp->m_currentFormat = st->getFormat();
Toshihiro Shimizu 890ddd
	m_imp->m_isRecording = true;
Toshihiro Shimizu 890ddd
	m_imp->m_stopped = false;
Toshihiro Shimizu 890ddd
	m_imp->m_recordedSampleCount = 0;
Toshihiro Shimizu 890ddd
	m_imp->m_st = st;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_recordedBlocks.push_back((char *)st->getRawData());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int totByteToSample = st->getSampleCount() * st->getSampleSize();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//far partire il thread
Toshihiro Shimizu 890ddd
	/*TRecordThread *recordThread = new TRecordThread(m_imp, totByteToSample);
Toshihiro Shimizu 890ddd
	if (!recordThread)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
  	m_imp->m_isRecording = false;
Toshihiro Shimizu 890ddd
  	m_imp->m_stopped = true;
Toshihiro Shimizu 890ddd
    throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
      TSoundDeviceException::UnablePrepare,
Toshihiro Shimizu 890ddd
      "Unable to create the recording thread");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
  recordThread->start();*/
Toshihiro Shimizu 890ddd
	m_imp->m_executor.addTask(new RecordTask(m_imp, totByteToSample));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundTrackP TSoundInputDevice::stop()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TSoundTrackP st;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_imp->m_isRecording)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnablePrepare,
Toshihiro Shimizu 890ddd
			"No recording process is in execution");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_isRecording = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	alDiscardFrames(m_imp->m_port, alGetFilled(m_imp->m_port));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (!m_imp->m_stopped)
Toshihiro Shimizu 890ddd
		sginap(1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_imp->m_oneShotRecording)
Toshihiro Shimizu 890ddd
		st = m_imp->m_st;
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		st = TSoundTrack::create(m_imp->m_currentFormat, m_imp->m_recordedSampleCount);
Toshihiro Shimizu 890ddd
		TINT32 bytesCopied = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (int i = 0; i < (int)m_imp->m_recordedBlocks.size(); ++i) {
Toshihiro Shimizu 890ddd
			memcpy(
Toshihiro Shimizu 890ddd
				(void *)(st->getRawData() + bytesCopied),
Toshihiro Shimizu 890ddd
				m_imp->m_recordedBlocks[i],
Toshihiro Shimizu 890ddd
				m_imp->m_samplePerBlocks[i]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			delete[] m_imp->m_recordedBlocks[i];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			bytesCopied += m_imp->m_samplePerBlocks[i];
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		m_imp->m_samplePerBlocks.clear();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return st;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TSoundInputDevice::getVolume()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALpv pv[1];
Toshihiro Shimizu 890ddd
	ALfixed value[2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		supportsVolume();
Toshihiro Shimizu 890ddd
	} catch (TSoundDeviceException &e) {
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(e.getType(), e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pv[0].param = AL_GAIN;
Toshihiro Shimizu 890ddd
	pv[0].value.ptr = value;
Toshihiro Shimizu 890ddd
	pv[0].sizeIn = 8;
Toshihiro Shimizu 890ddd
	alGetParams(AL_DEFAULT_INPUT, pv, 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double val = (((alFixedToDouble(value[0]) + alFixedToDouble(value[1])) / 2.) + 60.) / 8.05;
Toshihiro Shimizu 890ddd
	return val;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundInputDevice::setVolume(double volume)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALpv pv[1];
Toshihiro Shimizu 890ddd
	ALfixed value[2];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		supportsVolume();
Toshihiro Shimizu 890ddd
	} catch (TSoundDeviceException &e) {
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(e.getType(), e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double val = -60. + 8.05 * volume;
Toshihiro Shimizu 890ddd
	value[0] = alDoubleToFixed(val);
Toshihiro Shimizu 890ddd
	value[1] = alDoubleToFixed(val);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pv[0].param = AL_GAIN;
Toshihiro Shimizu 890ddd
	pv[0].value.ptr = value;
Toshihiro Shimizu 890ddd
	pv[0].sizeIn = 8;
Toshihiro Shimizu 890ddd
	alSetParams(AL_DEFAULT_INPUT, pv, 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundInputDevice::supportsVolume()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALparamInfo pinfo;
Toshihiro Shimizu 890ddd
	int ret;
Toshihiro Shimizu 890ddd
	ret = alGetParamInfo(AL_DEFAULT_INPUT, AL_GAIN, &pinfo);
Toshihiro Shimizu 890ddd
	double min = alFixedToDouble(pinfo.min.ll);
Toshihiro Shimizu 890ddd
	double max = alFixedToDouble(pinfo.max.ll);
Toshihiro Shimizu 890ddd
	if ((ret != -1) && (min != max) && (max != 0.0))
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	else if ((ret == AL_BAD_PARAM) || ((min == max) && (max == 0.0)))
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableVolume,
Toshihiro Shimizu 890ddd
			"It is impossible to chamge setting of volume");
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::NoMixer, "Output device is not accessible");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundTrackFormat TSoundInputDevice::getPreferredFormat(
Toshihiro Shimizu 890ddd
	ULONG sampleRate, int channelCount, int bitPerSample)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TSoundTrackFormat fmt;
Toshihiro Shimizu 890ddd
	int ret;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_imp->verifyRate())
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
			"There isn't any support rate");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_imp->m_supportedRate.find((int)sampleRate) ==
Toshihiro Shimizu 890ddd
		m_imp->m_supportedRate.end()) {
Toshihiro Shimizu 890ddd
		std::set<int>::iterator it =</int>
Toshihiro Shimizu 890ddd
			m_imp->m_supportedRate.lower_bound((int)sampleRate);
Toshihiro Shimizu 890ddd
		if (it == m_imp->m_supportedRate.end()) {
Toshihiro Shimizu 890ddd
			it = std::max_element(m_imp->m_supportedRate.begin(),
Toshihiro Shimizu 890ddd
								  m_imp->m_supportedRate.end());
Toshihiro Shimizu 890ddd
			if (it != m_imp->m_supportedRate.end())
Toshihiro Shimizu 890ddd
				sampleRate = *(m_imp->m_supportedRate.rbegin());
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
					TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
					"There isn't a supported rate");
Toshihiro Shimizu 890ddd
		} else
Toshihiro Shimizu 890ddd
			sampleRate = *it;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int value;
Toshihiro Shimizu 890ddd
	ALvalue vals[32];
Toshihiro Shimizu 890ddd
	if ((ret = alQueryValues(AL_DEFAULT_INPUT, AL_CHANNELS, vals, 32, 0, 0)) > 0)
Toshihiro Shimizu 890ddd
		for (int i = 0; i < ret; ++i)
Toshihiro Shimizu 890ddd
			value = vals[i].i;
Toshihiro Shimizu 890ddd
	else if (oserror() == AL_BAD_PARAM)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::NoMixer,
Toshihiro Shimizu 890ddd
			"It is impossible ask for the max nembers of channels supported");
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::NoMixer,
Toshihiro Shimizu 890ddd
			"It is impossibile information about ouput device");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (value > 2)
Toshihiro Shimizu 890ddd
		value = 2;
Toshihiro Shimizu 890ddd
	if (channelCount > value)
Toshihiro Shimizu 890ddd
		channelCount = value;
Toshihiro Shimizu 890ddd
	else if (channelCount <= 0)
Toshihiro Shimizu 890ddd
		channelCount = 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (bitPerSample <= 8)
Toshihiro Shimizu 890ddd
		bitPerSample = 8;
Toshihiro Shimizu 890ddd
	else if (bitPerSample <= 16)
Toshihiro Shimizu 890ddd
		bitPerSample = 16;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		bitPerSample = 24;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	fmt.m_bitPerSample = bitPerSample;
Toshihiro Shimizu 890ddd
	fmt.m_channelCount = channelCount;
Toshihiro Shimizu 890ddd
	fmt.m_sampleRate = sampleRate;
Toshihiro Shimizu 890ddd
	fmt.m_signedSample = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return fmt;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundTrackFormat TSoundInputDevice::getPreferredFormat(const TSoundTrackFormat &format)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		return getPreferredFormat(
Toshihiro Shimizu 890ddd
			format.m_sampleRate, format.m_channelCount, format.m_bitPerSample);
Toshihiro Shimizu 890ddd
	} catch (TSoundDeviceException &e) {
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(e.getType(), e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundInputDevice::isRecording()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_isRecording;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
//						funzioni per l'interazione con la libreria audio
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
//******************************************************************************
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
bool isInterfaceSupported(int deviceType, int interfaceType)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALvalue vals[16];
Toshihiro Shimizu 890ddd
	int devNum;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((devNum = alQueryValues(AL_SYSTEM, deviceType, vals, 16, 0, 0)) > 0) {
Toshihiro Shimizu 890ddd
		int i;
Toshihiro Shimizu 890ddd
		for (i = 0; i < devNum; ++i) {
Toshihiro Shimizu 890ddd
			ALpv quals[2];
Toshihiro Shimizu 890ddd
			quals[0].param = AL_TYPE;
Toshihiro Shimizu 890ddd
			quals[0].value.i = interfaceType;
Toshihiro Shimizu 890ddd
			if (alQueryValues(vals[i].i, AL_INTERFACE, 0, 0, quals, 1) > 0)
Toshihiro Shimizu 890ddd
				return true;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool setDefaultInput(TSoundInputDevice::Source type)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	string label;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	switch (type) {
Toshihiro Shimizu 890ddd
	case TSoundInputDevice::LineIn:
Toshihiro Shimizu 890ddd
		label = "Line In";
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TSoundInputDevice::DigitalIn:
Toshihiro Shimizu 890ddd
		label = "AES Input";
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	default:
Toshihiro Shimizu 890ddd
		label = "Microphone";
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int dev = alGetResourceByName(AL_SYSTEM, (char *)label.c_str(), AL_DEVICE_TYPE);
Toshihiro Shimizu 890ddd
	if (!dev)
Toshihiro Shimizu 890ddd
		return false; //throw TException("Error to set input device");
Toshihiro Shimizu 890ddd
	int itf;
Toshihiro Shimizu 890ddd
	if (itf = alGetResourceByName(AL_SYSTEM, (char *)label.c_str(), AL_INTERFACE_TYPE)) {
Toshihiro Shimizu 890ddd
		ALpv p;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		p.param = AL_INTERFACE;
Toshihiro Shimizu 890ddd
		p.value.i = itf;
Toshihiro Shimizu 890ddd
		if (alSetParams(dev, &p, 1) < 0 || p.sizeOut < 0)
Toshihiro Shimizu 890ddd
			return false; //throw TException("Error to set input device");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ALpv param;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	param.param = AL_DEFAULT_INPUT;
Toshihiro Shimizu 890ddd
	param.value.i = dev;
Toshihiro Shimizu 890ddd
	if (alSetParams(AL_SYSTEM, ¶m, 1) < 0)
Toshihiro Shimizu 890ddd
		return false; //throw TException("Error to set input device");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool setDefaultOutput()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALpv pvbuf[1];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!isInterfaceSupported(AL_DEFAULT_OUTPUT, AL_SPEAKER_IF_TYPE))
Toshihiro Shimizu 890ddd
		return false; //throw TException("Speakers are not supported");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int dev = alGetResourceByName(AL_SYSTEM, (char *)"Headphone/Speaker", AL_DEVICE_TYPE);
Toshihiro Shimizu 890ddd
	if (!dev)
Toshihiro Shimizu 890ddd
		return false; //throw TException("invalid device speakers");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pvbuf[0].param = AL_DEFAULT_OUTPUT;
Toshihiro Shimizu 890ddd
	pvbuf[0].value.i = dev;
Toshihiro Shimizu 890ddd
	alSetParams(AL_SYSTEM, pvbuf, 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// qui devo metterci gli altoparlanti e poi setto i valori per il default output
Toshihiro Shimizu 890ddd
	pvbuf[0].param = AL_INTERFACE;
Toshihiro Shimizu 890ddd
	pvbuf[0].value.i = AL_SPEAKER_IF_TYPE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (alSetParams(AL_DEFAULT_OUTPUT, pvbuf, 1) < 0)
Toshihiro Shimizu 890ddd
		return false; // throw TException("Unable to set output device params");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//return the indexes of all input device of a particular type
Toshihiro Shimizu 890ddd
list<int> getInputDevice(int deviceType)</int>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALvalue vals[16];
Toshihiro Shimizu 890ddd
	ALpv quals[1];
Toshihiro Shimizu 890ddd
	list<int> devList;</int>
Toshihiro Shimizu 890ddd
	int devNum;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	quals[0].param = AL_TYPE;
Toshihiro Shimizu 890ddd
	quals[0].value.i = deviceType;
Toshihiro Shimizu 890ddd
	if ((devNum = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, vals, 16, quals, 1)) > 0) {
Toshihiro Shimizu 890ddd
		int i;
Toshihiro Shimizu 890ddd
		for (i = 0; i < devNum; ++i) {
Toshihiro Shimizu 890ddd
			int itf;
Toshihiro Shimizu 890ddd
			ALvalue val[16];
Toshihiro Shimizu 890ddd
			if ((itf = alQueryValues(i, AL_INTERFACE, val, 16, 0, 0)) > 0) {
Toshihiro Shimizu 890ddd
				int j;
Toshihiro Shimizu 890ddd
				for (j = 0; j < itf; ++j)
Toshihiro Shimizu 890ddd
					devList.push_back(vals[j].i);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return devList;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//return the indexes of all input device of a particular type and interface
Toshihiro Shimizu 890ddd
list<int> getInputDevice(int deviceType, int itfType)</int>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALvalue vals[16];
Toshihiro Shimizu 890ddd
	ALpv quals[1];
Toshihiro Shimizu 890ddd
	list<int> devList;</int>
Toshihiro Shimizu 890ddd
	int devNum;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	quals[0].param = AL_TYPE;
Toshihiro Shimizu 890ddd
	quals[0].value.i = deviceType;
Toshihiro Shimizu 890ddd
	if ((devNum = alQueryValues(AL_SYSTEM, AL_DEFAULT_INPUT, vals, 16, quals, 1)) > 0) {
Toshihiro Shimizu 890ddd
		int i;
Toshihiro Shimizu 890ddd
		for (i = 0; i < devNum; ++i) {
Toshihiro Shimizu 890ddd
			int itf;
Toshihiro Shimizu 890ddd
			ALvalue val[16];
Toshihiro Shimizu 890ddd
			quals[0].param = AL_TYPE;
Toshihiro Shimizu 890ddd
			quals[0].value.i = itfType;
Toshihiro Shimizu 890ddd
			if ((itf = alQueryValues(i, AL_INTERFACE, val, 16, quals, 1)) > 0) {
Toshihiro Shimizu 890ddd
				int j;
Toshihiro Shimizu 890ddd
				for (j = 0; j < itf; ++j)
Toshihiro Shimizu 890ddd
					devList.push_back(vals[j].i);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return devList;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
string getResourceLabel(int resourceID)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALpv par[1];
Toshihiro Shimizu 890ddd
	char l[32];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	par[0].param = AL_LABEL;
Toshihiro Shimizu 890ddd
	par[0].value.ptr = l;
Toshihiro Shimizu 890ddd
	par[0].sizeIn = 32;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	alGetParams(resourceID, par, 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return string(l);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// verify the samplerate of the select device is changed from another application
Toshihiro Shimizu 890ddd
bool isChangeOutput(ULONG sampleRate)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	ALpv par[2];
Toshihiro Shimizu 890ddd
	char l[32];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	par[0].param = AL_LABEL;
Toshihiro Shimizu 890ddd
	par[0].value.ptr = l;
Toshihiro Shimizu 890ddd
	par[0].sizeIn = 32;
Toshihiro Shimizu 890ddd
	par[1].param = AL_RATE;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	alGetParams(AL_DEFAULT_OUTPUT, par, 2);
Toshihiro Shimizu 890ddd
	if ((strcmp(l, "Analog Out") != 0) || (alFixedToDouble(par[1].value.ll) != sampleRate))
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}