Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tsound.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
#include "tthread.h"
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
#include "tsop.h"
Toshihiro Shimizu 890ddd
#include <set></set>
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//forward declarations
Toshihiro Shimizu 890ddd
class TSoundOutputDeviceImp;
Toshihiro Shimizu 890ddd
class TSoundInputDeviceImp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
void CALLBACK recordCB(
Toshihiro Shimizu 890ddd
	HWAVEIN hwi,
Toshihiro Shimizu 890ddd
	UINT uMsg,
Toshihiro Shimizu 890ddd
	DWORD dwInstance,
Toshihiro Shimizu 890ddd
	DWORD dwParam1,
Toshihiro Shimizu 890ddd
	DWORD dwParam2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool setRecordLine(TSoundInputDevice::Source typeInput);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MMRESULT getLineInfo(
Toshihiro Shimizu 890ddd
	HMIXEROBJ hMixer,
Toshihiro Shimizu 890ddd
	DWORD dwComponentType,
Toshihiro Shimizu 890ddd
	MIXERLINE &mxl);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MMRESULT getLineControl(
Toshihiro Shimizu 890ddd
	MIXERCONTROL &mxc,
Toshihiro Shimizu 890ddd
	HMIXEROBJ hMixer,
Toshihiro Shimizu 890ddd
	DWORD dwLineID,
Toshihiro Shimizu 890ddd
	DWORD dwControlType);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MMRESULT setControlDetails(
Toshihiro Shimizu 890ddd
	HMIXEROBJ hMixer,
Toshihiro Shimizu 890ddd
	DWORD dwSelectControlID,
Toshihiro Shimizu 890ddd
	DWORD dwMultipleItems,
Toshihiro Shimizu 890ddd
	MIXERCONTROLDETAILS_UNSIGNED *mxcdSelectValue);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MMRESULT getControlDetails(
Toshihiro Shimizu 890ddd
	HMIXEROBJ hMixer,
Toshihiro Shimizu 890ddd
	DWORD dwSelectControlID,
Toshihiro Shimizu 890ddd
	DWORD dwMultipleItems,
Toshihiro Shimizu 890ddd
	MIXERCONTROLDETAILS_UNSIGNED *mxcdSelectValue);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MMRESULT isaFormatSupported(
Toshihiro Shimizu 890ddd
	int sampleRate, int channelCount, int bitPerSample, bool input);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DWORD WINAPI MyWaveOutCallbackThread(LPVOID lpParameter);
Toshihiro Shimizu 890ddd
void getAmplitude(int &litude, const TSoundTrackP st, TINT32 sample);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//     Class to send the message that a playback is completed
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
#ifndef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
class EndPlayMsg : public TThread::Message
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	EndPlayMsg(TSoundOutputDeviceListener *notifier)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_listener = notifier;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThread::Message *clone() const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		return new EndPlayMsg(*this);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void onDeliver()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_listener->onPlayCompleted();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	TSoundOutputDeviceListener *m_listener;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int makeDWORD(const short lo, const short hi)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int dw = hi << 16;
Toshihiro Shimizu 890ddd
	dw |= lo;
Toshihiro Shimizu 890ddd
	return dw;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
class WavehdrQueue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TSoundOutputDeviceImp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	HWAVEOUT m_wout;
Toshihiro Shimizu 890ddd
	WavehdrQueue *m_whdrQueue;
Toshihiro Shimizu 890ddd
	TSoundTrackFormat m_currentFormat;
Toshihiro Shimizu 890ddd
	std::set<int> m_supportedRate;</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThread::Mutex m_mutex;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool m_stopped;
Toshihiro Shimizu 890ddd
	bool m_isPlaying;
Toshihiro Shimizu 890ddd
	bool m_looped;
Toshihiro Shimizu 890ddd
	bool m_scrubbing;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::set<tsoundoutputdevicelistener *=""> m_listeners;</tsoundoutputdevicelistener>
Toshihiro Shimizu 890ddd
	DWORD m_notifyThreadId;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	HANDLE m_closeDevice;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TSoundOutputDeviceImp();
Toshihiro Shimizu 890ddd
	~TSoundOutputDeviceImp();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool doOpenDevice(const TSoundTrackFormat &format);
Toshihiro Shimizu 890ddd
	bool doPlay(WAVEHDR *whdr, const TSoundTrackFormat format);
Toshihiro Shimizu 890ddd
	bool doCloseDevice();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool verifyRate();
Toshihiro Shimizu 890ddd
	void insertAllRate();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class WavehdrQueue
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	WavehdrQueue(TSoundOutputDeviceImp *devImp, int slotCount)
Toshihiro Shimizu 890ddd
		: m_devImp(devImp), m_items(), m_queuedItems(), m_slotCount(slotCount), m_mutex(), m_lastOffset(0)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~WavehdrQueue() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void put(TSoundTrackP &subTrack);
Toshihiro Shimizu 890ddd
	WAVEHDR *get();
Toshihiro Shimizu 890ddd
	bool popFront(int count);
Toshihiro Shimizu 890ddd
	void pushBack(WAVEHDR *whdr, TSoundTrackP st);
Toshihiro Shimizu 890ddd
	int size();
Toshihiro Shimizu 890ddd
	void clear();
Toshihiro Shimizu 890ddd
	bool isAllQueuedItemsPlayed();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	std::list<std::pair<wavehdr *,="" tsoundtrackp="">> m_items;</std::pair<wavehdr>
Toshihiro Shimizu 890ddd
	std::list<wavehdr *=""> m_queuedItems;</wavehdr>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThread::Mutex m_mutex;
Toshihiro Shimizu 890ddd
	int m_slotCount;
Toshihiro Shimizu 890ddd
	int m_lastOffset;
Toshihiro Shimizu 890ddd
	TSoundOutputDeviceImp *m_devImp;
Toshihiro Shimizu 890ddd
	TSoundTrackP m_lastTrack;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
WAVEHDR *prepareWaveHeader(HWAVEOUT wout, const TSoundTrackP &subTrack, ULONG &count)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	WAVEHDR *whdr = new WAVEHDR;
Toshihiro Shimizu 890ddd
	memset(whdr, 0, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
	whdr->dwBufferLength = subTrack->getSampleSize() * subTrack->getSampleCount();
Toshihiro Shimizu 890ddd
	whdr->lpData = new char[whdr->dwBufferLength];
Toshihiro Shimizu 890ddd
	whdr->dwFlags = 0;
Toshihiro Shimizu 890ddd
	whdr->dwUser = count;
Toshihiro Shimizu 890ddd
	memcpy(whdr->lpData, subTrack->getRawData(), whdr->dwBufferLength);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	MMRESULT ret = waveOutPrepareHeader(wout, whdr, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
		delete[] whdr->lpData;
Toshihiro Shimizu 890ddd
		delete whdr;
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	++count;
Toshihiro Shimizu 890ddd
	return whdr;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void WavehdrQueue::put(TSoundTrackP &subTrack)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(subTrack->getRawData());
Toshihiro Shimizu 890ddd
	static ULONG count = 1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//codice messo per tab: facendo il play al rilascio del mouse e su piu'
Toshihiro Shimizu 890ddd
	//colonne in cui le traccie potrebbe avere diversi formati siccome qui in
Toshihiro Shimizu 890ddd
	//alcune situazioni si fa subito waveOutWrite c'e' bisogno di controllare
Toshihiro Shimizu 890ddd
	//se il formato con cui e' stato aperto in precedenza il device e' uguale
Toshihiro Shimizu 890ddd
	//a quello della traccia
Toshihiro Shimizu 890ddd
	if (m_devImp->m_wout && m_devImp->m_currentFormat != subTrack->getFormat()) {
Toshihiro Shimizu 890ddd
		m_devImp->doCloseDevice();
Toshihiro Shimizu 890ddd
		TSystem::sleep(300);
Toshihiro Shimizu 890ddd
		m_devImp->doOpenDevice(subTrack->getFormat());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThread::MutexLocker sl(&m_mutex);
Toshihiro Shimizu 890ddd
	if (!m_devImp->m_scrubbing) {
Toshihiro Shimizu 890ddd
		WAVEHDR *whdr2 = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//traccia
Toshihiro Shimizu 890ddd
		whdr2 = prepareWaveHeader(m_devImp->m_wout, subTrack, count);
Toshihiro Shimizu 890ddd
		getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		MMRESULT ret = MMSYSERR_NOERROR;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (whdr2 && whdr2->dwFlags & WHDR_PREPARED) {
Toshihiro Shimizu 890ddd
			ret = waveOutWrite(m_devImp->m_wout, whdr2, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
			if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
				pushBack(whdr2, subTrack);
Toshihiro Shimizu 890ddd
				getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L);
Toshihiro Shimizu 890ddd
				TThread::MutexLocker sl(&m_devImp->m_mutex);
Toshihiro Shimizu 890ddd
				m_devImp->m_isPlaying = true;
Toshihiro Shimizu 890ddd
				m_devImp->m_stopped = false;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_queuedItems.size() == 0) {
Toshihiro Shimizu 890ddd
		WAVEHDR *whdr1 = 0;
Toshihiro Shimizu 890ddd
		WAVEHDR *whdr2 = 0;
Toshihiro Shimizu 890ddd
		WAVEHDR *whdr3 = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		MMRESULT ret;
Toshihiro Shimizu 890ddd
		TSoundTrackP riseTrack, decayTrack;
Toshihiro Shimizu 890ddd
		int sampleSize = subTrack->getSampleSize();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//cresce
Toshihiro Shimizu 890ddd
		riseTrack = TSop::fadeIn(subTrack, 0.9);
Toshihiro Shimizu 890ddd
		whdr1 = prepareWaveHeader(m_devImp->m_wout, riseTrack, count);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//traccia
Toshihiro Shimizu 890ddd
		whdr2 = prepareWaveHeader(m_devImp->m_wout, subTrack, count);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//decresce
Toshihiro Shimizu 890ddd
		decayTrack = 0;
Toshihiro Shimizu 890ddd
		if (m_lastOffset) {
Toshihiro Shimizu 890ddd
			decayTrack = TSop::fadeOut(subTrack, 0.9);
Toshihiro Shimizu 890ddd
			whdr3 = prepareWaveHeader(m_devImp->m_wout, decayTrack, count);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (whdr1 && (whdr1->dwFlags & WHDR_PREPARED)) {
Toshihiro Shimizu 890ddd
			ret = waveOutWrite(m_devImp->m_wout, whdr1, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
			if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
				pushBack(whdr1, riseTrack);
Toshihiro Shimizu 890ddd
				getAmplitude(m_lastOffset, riseTrack, riseTrack->getSampleCount() - 1L);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (whdr2 && (whdr2->dwFlags & WHDR_PREPARED)) {
Toshihiro Shimizu 890ddd
			ret = waveOutWrite(m_devImp->m_wout, whdr2, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
			if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
				pushBack(whdr2, subTrack);
Toshihiro Shimizu 890ddd
				getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L);
Toshihiro Shimizu 890ddd
				TThread::MutexLocker sl(&m_devImp->m_mutex);
Toshihiro Shimizu 890ddd
				m_devImp->m_isPlaying = true;
Toshihiro Shimizu 890ddd
				m_devImp->m_stopped = false;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (whdr3 && (whdr3->dwFlags & WHDR_PREPARED)) {
Toshihiro Shimizu 890ddd
			ret = waveOutWrite(m_devImp->m_wout, whdr3, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
			if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
				pushBack(whdr3, decayTrack);
Toshihiro Shimizu 890ddd
				if (decayTrack->isSampleSigned())
Toshihiro Shimizu 890ddd
					m_lastOffset = 0;
Toshihiro Shimizu 890ddd
				else
Toshihiro Shimizu 890ddd
					m_lastOffset = 127;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_queuedItems.size() < 10) {
Toshihiro Shimizu 890ddd
		WAVEHDR *whdr1 = 0;
Toshihiro Shimizu 890ddd
		WAVEHDR *whdr2 = 0;
Toshihiro Shimizu 890ddd
		WAVEHDR *whdr = new WAVEHDR;
Toshihiro Shimizu 890ddd
		memset(whdr, 0, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
		whdr->dwBufferLength = subTrack->getSampleSize() * subTrack->getSampleCount();
Toshihiro Shimizu 890ddd
		whdr->lpData = new char[whdr->dwBufferLength];
Toshihiro Shimizu 890ddd
		whdr->dwFlags = 0;
Toshihiro Shimizu 890ddd
		memcpy(whdr->lpData, subTrack->getRawData(), whdr->dwBufferLength);
Toshihiro Shimizu 890ddd
		int sampleSize = subTrack->getSampleSize();
Toshihiro Shimizu 890ddd
		TSoundTrackP riseTrack = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_lastOffset) ///devo fare ilcross fade
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			int offset;
Toshihiro Shimizu 890ddd
			getAmplitude(offset, subTrack, 0L);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			offset = m_lastOffset - offset;
Toshihiro Shimizu 890ddd
			if (offset) {
Toshihiro Shimizu 890ddd
				TSoundTrackP st = TSop::crossFade(m_lastTrack, subTrack, 0.3);
Toshihiro Shimizu 890ddd
				memcpy(whdr->lpData, st->getRawData(), st->getSampleCount() * sampleSize);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		} else // e' zero ma ne metto uno che cresce faccio il fadeIn
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			riseTrack = TSop::fadeIn(subTrack, 0.3);
Toshihiro Shimizu 890ddd
			whdr1 = prepareWaveHeader(m_devImp->m_wout, riseTrack, count);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		whdr->dwUser = count;
Toshihiro Shimizu 890ddd
		++count;
Toshihiro Shimizu 890ddd
		MMRESULT ret = waveOutPrepareHeader(m_devImp->m_wout, whdr, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
		if (ret != MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
			delete[] whdr->lpData;
Toshihiro Shimizu 890ddd
			delete whdr;
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TSoundTrackP decayTrack = 0;
Toshihiro Shimizu 890ddd
		if (m_queuedItems.size() <= 7) {
Toshihiro Shimizu 890ddd
			if (m_lastOffset) //devo fare il fadeOut
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				decayTrack = TSop::fadeOut(subTrack, 0.3);
Toshihiro Shimizu 890ddd
				whdr2 = prepareWaveHeader(m_devImp->m_wout, decayTrack, count);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (whdr1 && whdr1->dwFlags & WHDR_PREPARED) {
Toshihiro Shimizu 890ddd
			ret = waveOutWrite(m_devImp->m_wout, whdr1, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
			if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
				pushBack(whdr1, riseTrack);
Toshihiro Shimizu 890ddd
				getAmplitude(m_lastOffset, riseTrack, riseTrack->getSampleCount() - 1L);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (whdr && whdr->dwFlags & WHDR_PREPARED) {
Toshihiro Shimizu 890ddd
			ret = waveOutWrite(m_devImp->m_wout, whdr, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
			if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
				pushBack(whdr, subTrack);
Toshihiro Shimizu 890ddd
				getAmplitude(m_lastOffset, subTrack, subTrack->getSampleCount() - 1L);
Toshihiro Shimizu 890ddd
				{
Toshihiro Shimizu 890ddd
					TThread::MutexLocker sl(&m_devImp->m_mutex);
Toshihiro Shimizu 890ddd
					m_devImp->m_isPlaying = true;
Toshihiro Shimizu 890ddd
					m_devImp->m_stopped = false;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (whdr2 && whdr2->dwFlags & WHDR_PREPARED) {
Toshihiro Shimizu 890ddd
			ret = waveOutWrite(m_devImp->m_wout, whdr2, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
			if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
				pushBack(whdr2, decayTrack);
Toshihiro Shimizu 890ddd
				if (decayTrack->isSampleSigned())
Toshihiro Shimizu 890ddd
					m_lastOffset = 0;
Toshihiro Shimizu 890ddd
				else
Toshihiro Shimizu 890ddd
					m_lastOffset = 127;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((int)m_items.size() == m_slotCount) {
Toshihiro Shimizu 890ddd
		WAVEHDR *item = m_items.front().first;
Toshihiro Shimizu 890ddd
		MMRESULT ret = waveOutUnprepareHeader(
Toshihiro Shimizu 890ddd
			m_devImp->m_wout, item, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
			delete[] item->lpData;
Toshihiro Shimizu 890ddd
			delete item;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_items.pop_front();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_queuedItems.size() != 0) {
Toshihiro Shimizu 890ddd
			WAVEHDR *item = m_items.front().first;
Toshihiro Shimizu 890ddd
			int sampleSize = m_items.front().second->getSampleSize();
Toshihiro Shimizu 890ddd
			int offset;
Toshihiro Shimizu 890ddd
			getAmplitude(offset, m_items.front().second, 0L);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			offset = m_lastOffset - offset;
Toshihiro Shimizu 890ddd
			if (offset) {
Toshihiro Shimizu 890ddd
				TSoundTrackP st = TSop::crossFade(
Toshihiro Shimizu 890ddd
					m_lastTrack, m_items.front().second, 0.3);
Toshihiro Shimizu 890ddd
				memcpy(item->lpData, st->getRawData(), st->getSampleCount() * sampleSize);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	WAVEHDR *whdr = prepareWaveHeader(m_devImp->m_wout, subTrack, count);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	assert(whdr && whdr->dwFlags & WHDR_PREPARED);
Toshihiro Shimizu 890ddd
	m_items.push_back(std::make_pair(whdr, subTrack));
Toshihiro Shimizu 890ddd
	assert((int)m_items.size() <= m_slotCount);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// restituisce il piu' vecchio WAVEHDR il cui stato e' prepared && !done
Toshihiro Shimizu 890ddd
WAVEHDR *WavehdrQueue::get()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThread::MutexLocker sl(&m_mutex);
Toshihiro Shimizu 890ddd
	if (m_items.size() == 0)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	WAVEHDR *whdr = m_items.front().first;
Toshihiro Shimizu 890ddd
	assert(whdr->dwFlags & WHDR_PREPARED);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	pushBack(whdr, m_items.front().second);
Toshihiro Shimizu 890ddd
	getAmplitude(
Toshihiro Shimizu 890ddd
		m_lastOffset, m_items.front().second, m_items.front().second->getSampleCount() - 1L);
Toshihiro Shimizu 890ddd
	m_items.pop_front();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return whdr;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// rimuove dalla coda il piu' vecchio WAVEHDR il cui stato e' done
Toshihiro Shimizu 890ddd
bool WavehdrQueue::popFront(int count)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThread::MutexLocker sl(&m_mutex);
Toshihiro Shimizu 890ddd
	//assert(m_queuedItems.size() > 0);
Toshihiro Shimizu 890ddd
	if (m_queuedItems.size() <= 0)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	WAVEHDR *whdr = m_queuedItems.front();
Toshihiro Shimizu 890ddd
	// controllo introdotto pr via che su win2k si perde alcune
Toshihiro Shimizu 890ddd
	// notifiche di WHDR_DONE
Toshihiro Shimizu 890ddd
	while ((DWORD)count > whdr->dwUser) {
Toshihiro Shimizu 890ddd
		MMRESULT ret = waveOutUnprepareHeader(
Toshihiro Shimizu 890ddd
			m_devImp->m_wout, whdr, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
		if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
			m_queuedItems.pop_front();
Toshihiro Shimizu 890ddd
			delete[] whdr->lpData;
Toshihiro Shimizu 890ddd
			delete whdr;
Toshihiro Shimizu 890ddd
			whdr = m_queuedItems.front();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	assert(whdr->dwFlags & WHDR_DONE);
Toshihiro Shimizu 890ddd
	m_queuedItems.pop_front();
Toshihiro Shimizu 890ddd
	delete[] whdr->lpData;
Toshihiro Shimizu 890ddd
	delete whdr;
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void WavehdrQueue::pushBack(WAVEHDR *whdr, TSoundTrackP st)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThread::MutexLocker sl(&m_mutex);
Toshihiro Shimizu 890ddd
	m_queuedItems.push_back(whdr);
Toshihiro Shimizu 890ddd
	m_lastTrack = st;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int WavehdrQueue::size()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThread::MutexLocker sl(&m_mutex);
Toshihiro Shimizu 890ddd
	int size = m_queuedItems.size();
Toshihiro Shimizu 890ddd
	return size;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void WavehdrQueue::clear()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThread::MutexLocker sl(&m_mutex);
Toshihiro Shimizu 890ddd
	m_items.clear();
Toshihiro Shimizu 890ddd
	m_lastTrack = TSoundTrackP();
Toshihiro Shimizu 890ddd
	std::list<wavehdr *="">::iterator it;</wavehdr>
Toshihiro Shimizu 890ddd
	for (it = m_queuedItems.begin(); it != m_queuedItems.end(); it++) {
Toshihiro Shimizu 890ddd
		WAVEHDR *wvhdr = *it;
Toshihiro Shimizu 890ddd
		delete[] wvhdr->lpData;
Toshihiro Shimizu 890ddd
		delete wvhdr;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	m_queuedItems.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool WavehdrQueue::isAllQueuedItemsPlayed()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::list<wavehdr *="">::iterator it;</wavehdr>
Toshihiro Shimizu 890ddd
	bool finished = true;
Toshihiro Shimizu 890ddd
	for (it = m_queuedItems.begin(); it != m_queuedItems.end(); it++) {
Toshihiro Shimizu 890ddd
		WAVEHDR *wvhdr = *it;
Toshihiro Shimizu 890ddd
		finished = finished && (wvhdr->dwFlags & WHDR_DONE);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return finished;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundOutputDeviceImp::TSoundOutputDeviceImp()
Toshihiro Shimizu 890ddd
	: m_stopped(true), m_isPlaying(false), m_looped(false), m_scrubbing(false), m_wout(0)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_whdrQueue = new WavehdrQueue(this, 4);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	insertAllRate();
Toshihiro Shimizu 890ddd
	if (!verifyRate())
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::FailedInit,
Toshihiro Shimizu 890ddd
			"Unable to verify supported rates");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_closeDevice = CreateEvent(
Toshihiro Shimizu 890ddd
		NULL,  // no security attributes
Toshihiro Shimizu 890ddd
		FALSE, // auto-reset event
Toshihiro Shimizu 890ddd
		FALSE, // initial state is not signaled
Toshihiro Shimizu 890ddd
		NULL); // object not named
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundOutputDeviceImp::~TSoundOutputDeviceImp()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_whdrQueue;
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
	WAVEFORMATEX wf;
Toshihiro Shimizu 890ddd
	wf.wFormatTag = WAVE_FORMAT_PCM;
Toshihiro Shimizu 890ddd
	wf.nChannels = format.m_channelCount;
Toshihiro Shimizu 890ddd
	wf.nSamplesPerSec = format.m_sampleRate;
Toshihiro Shimizu 890ddd
	wf.wBitsPerSample = format.m_bitPerSample;
Toshihiro Shimizu 890ddd
	wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) >> 3;
Toshihiro Shimizu 890ddd
	wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
Toshihiro Shimizu 890ddd
	wf.cbSize = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TThread::MutexLocker sl(&m_mutex);
Toshihiro Shimizu 890ddd
	CloseHandle(CreateThread(NULL, 0, MyWaveOutCallbackThread, (LPVOID) this, 0, &m_notifyThreadId));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	if ((ret = waveOutOpen(&m_wout, WAVE_MAPPER,
Toshihiro Shimizu 890ddd
						   &wf, (DWORD)m_notifyThreadId, (DWORD) this, CALLBACK_THREAD)) != MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
		while (!PostThreadMessage(m_notifyThreadId, WM_QUIT, 0, 0))
Toshihiro Shimizu 890ddd
			;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	m_currentFormat = format;
Toshihiro Shimizu 890ddd
	return (ret == MMSYSERR_NOERROR);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDeviceImp::doPlay(WAVEHDR *whdr, const TSoundTrackFormat format)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThread::MutexLocker sl(&m_mutex);
Toshihiro Shimizu 890ddd
	if (!m_wout || (m_wout && m_currentFormat != format))
Toshihiro Shimizu 890ddd
		doOpenDevice(format);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	ret = waveOutWrite(m_wout, whdr, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	m_stopped = false;
Toshihiro Shimizu 890ddd
	m_isPlaying = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDeviceImp::doCloseDevice()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TThread::MutexLocker sl(&m_mutex);
Toshihiro Shimizu 890ddd
	if (m_wout) {
Toshihiro Shimizu 890ddd
		MMRESULT ret = waveOutReset(m_wout);
Toshihiro Shimizu 890ddd
		if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		ret = waveOutClose(m_wout);
Toshihiro Shimizu 890ddd
		if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		m_wout = 0;
Toshihiro Shimizu 890ddd
		m_stopped = true;
Toshihiro Shimizu 890ddd
		m_isPlaying = false;
Toshihiro Shimizu 890ddd
		m_looped = false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	PostThreadMessage(m_notifyThreadId, WM_QUIT, 0, 0);
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
	std::set<int>::iterator it;</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (it = m_supportedRate.begin();
Toshihiro Shimizu 890ddd
		 it != m_supportedRate.end();) {
Toshihiro Shimizu 890ddd
		MMRESULT ret;
Toshihiro Shimizu 890ddd
		WAVEFORMATEX wf;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		wf.wFormatTag = WAVE_FORMAT_PCM;
Toshihiro Shimizu 890ddd
		wf.nChannels = 1;
Toshihiro Shimizu 890ddd
		wf.nSamplesPerSec = *it;
Toshihiro Shimizu 890ddd
		wf.wBitsPerSample = 8;
Toshihiro Shimizu 890ddd
		wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) >> 3;
Toshihiro Shimizu 890ddd
		wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
Toshihiro Shimizu 890ddd
		wf.cbSize = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		ret = waveOutOpen(NULL, WAVE_MAPPER, &wf, NULL, NULL, WAVE_FORMAT_QUERY);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
			++it;
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (ret == WAVERR_BADFORMAT)
Toshihiro Shimizu 890ddd
			it = m_supportedRate.erase(it);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (m_supportedRate.end() == m_supportedRate.begin())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
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
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundOutputDevice::~TSoundOutputDevice()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	close();
Toshihiro Shimizu 890ddd
	WaitForSingleObject(m_imp->m_closeDevice, INFINITE);
Toshihiro Shimizu 890ddd
	CloseHandle(m_imp->m_closeDevice);
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
DWORD WINAPI MyWaveOutCallbackThread(LPVOID lpParameter)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TSoundOutputDeviceImp *devImp = (TSoundOutputDeviceImp *)lpParameter;
Toshihiro Shimizu 890ddd
	if (!devImp)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	MSG msg;
Toshihiro Shimizu 890ddd
	BOOL bRet;
Toshihiro Shimizu 890ddd
	while (bRet = GetMessage(&msg, NULL, 0, 0)) {
Toshihiro Shimizu 890ddd
		if (bRet == -1) {
Toshihiro Shimizu 890ddd
			// si e' verificato un errore
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		switch (msg.message) {
Toshihiro Shimizu 890ddd
		case MM_WOM_DONE: {
Toshihiro Shimizu 890ddd
			WAVEHDR *pWaveHdr = ((WAVEHDR *)msg.lParam);
Toshihiro Shimizu 890ddd
			{
Toshihiro Shimizu 890ddd
				TThread::MutexLocker sl(&devImp->m_mutex);
Toshihiro Shimizu 890ddd
				if (devImp->m_looped) {
Toshihiro Shimizu 890ddd
					devImp->doPlay(pWaveHdr, devImp->m_currentFormat);
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			WAVEHDR *whdr = 0;
Toshihiro Shimizu 890ddd
			if (devImp->m_whdrQueue->popFront(pWaveHdr->dwUser)) {
Toshihiro Shimizu 890ddd
				whdr = devImp->m_whdrQueue->get();
Toshihiro Shimizu 890ddd
				if (whdr)
Toshihiro Shimizu 890ddd
					devImp->doPlay(whdr, devImp->m_currentFormat);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				WaitForSingleObject(devImp->m_closeDevice, INFINITE);
Toshihiro Shimizu 890ddd
				CloseHandle(devImp->m_closeDevice);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				MMRESULT ret = waveOutUnprepareHeader(
Toshihiro Shimizu 890ddd
					devImp->m_wout, pWaveHdr, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
				if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
					delete pWaveHdr->lpData;
Toshihiro Shimizu 890ddd
					delete pWaveHdr;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (!whdr && devImp->m_whdrQueue->size() == 0) {
Toshihiro Shimizu 890ddd
				std::set<tsoundoutputdevicelistener *="">::iterator it = devImp->m_listeners.begin();</tsoundoutputdevicelistener>
Toshihiro Shimizu 890ddd
				for (; it != devImp->m_listeners.end(); ++it) {
Toshihiro Shimizu 890ddd
#ifndef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
					EndPlayMsg *event = new EndPlayMsg(*it);
Toshihiro Shimizu 890ddd
					event->send();
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
					assert(false);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				devImp->doCloseDevice();
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		case MM_WOM_CLOSE:
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		default:
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	SetEvent(devImp->m_closeDevice);
Toshihiro Shimizu 890ddd
	return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void getAmplitude(int &litude, const TSoundTrackP st, TINT32 sample)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TSoundTrackP snd = st;
Toshihiro Shimizu 890ddd
	amplitude = 0;
Toshihiro Shimizu 890ddd
	int k = 0;
Toshihiro Shimizu 890ddd
	for (k = 0; k < snd->getChannelCount(); ++k)
Toshihiro Shimizu 890ddd
		amplitude += (int)snd->getPressure(sample, k);
Toshihiro Shimizu 890ddd
	amplitude /= k;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::installed()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int ndev = waveOutGetNumDevs();
Toshihiro Shimizu 890ddd
	if (ndev <= 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
	return m_imp->doOpenDevice(st->getFormat());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundOutputDevice::attach(TSoundOutputDeviceListener *listener)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_listeners.insert(listener);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundOutputDevice::detach(TSoundOutputDeviceListener *listener)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_listeners.erase(listener);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundOutputDevice::play(
Toshihiro Shimizu 890ddd
	const TSoundTrackP &st, TINT32 s0, TINT32 s1, bool loop, bool scrubbing)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert((scrubbing && !loop) || !scrubbing);
Toshihiro Shimizu 890ddd
	if (!st->getSampleCount())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	TSoundTrackFormat format;
Toshihiro Shimizu 890ddd
	TSoundTrackP subTrack;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		TThread::MutexLocker 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
		format = st->getFormat();
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			TSoundTrackFormat 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
		assert(s1 >= s0);
Toshihiro Shimizu 890ddd
		subTrack = st->extract(s0, s1);
Toshihiro Shimizu 890ddd
		m_imp->m_looped = loop;
Toshihiro Shimizu 890ddd
		m_imp->m_scrubbing = scrubbing;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!m_imp->m_wout)
Toshihiro Shimizu 890ddd
		m_imp->doOpenDevice(format);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_whdrQueue->put(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_wout) && m_imp->m_isPlaying) {
Toshihiro Shimizu 890ddd
		MMRESULT ret = waveOutReset(m_imp->m_wout);
Toshihiro Shimizu 890ddd
		if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TThread::MutexLocker sl(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
		m_imp->m_looped = false;
Toshihiro Shimizu 890ddd
		m_imp->m_stopped = true;
Toshihiro Shimizu 890ddd
		m_imp->m_isPlaying = false;
Toshihiro Shimizu 890ddd
		m_imp->m_whdrQueue->clear();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundOutputDevice::close()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->doCloseDevice();
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::isAllQueuedItemsPlayed()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_whdrQueue->isAllQueuedItemsPlayed();
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::MutexLocker 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::MutexLocker 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
	TUINT32 sampleRate, int channelCount, int bitPerSample)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TSoundTrackFormat fmt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//avvvicinarsi al sample rate => dovrebbe esser OK avendo selezionato i piu' vicini
Toshihiro Shimizu 890ddd
	std::set<int>::iterator it = m_imp->m_supportedRate.lower_bound(sampleRate);</int>
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 format");
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		sampleRate = *it;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (bitPerSample <= 8)
Toshihiro Shimizu 890ddd
		bitPerSample = 8;
Toshihiro Shimizu 890ddd
	else if ((bitPerSample > 8 && bitPerSample < 16) || bitPerSample >= 16)
Toshihiro Shimizu 890ddd
		bitPerSample = 16;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (bitPerSample >= 16)
Toshihiro Shimizu 890ddd
		fmt.m_signedSample = true;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		fmt.m_signedSample = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//switch mono/stereo
Toshihiro Shimizu 890ddd
	if (channelCount <= 1)
Toshihiro Shimizu 890ddd
		channelCount = 1;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		channelCount = 2;
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
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(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
			e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
// Classi per la gestione della registrazione
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class WaveFormat : public WAVEFORMATEX
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	WaveFormat(){};
Toshihiro Shimizu 890ddd
	WaveFormat(unsigned char channelCount,
Toshihiro Shimizu 890ddd
			   unsigned TINT32 sampleRate,
Toshihiro Shimizu 890ddd
			   unsigned char bitPerSample);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~WaveFormat(){};
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
WaveFormat::WaveFormat(unsigned char channelCount,
Toshihiro Shimizu 890ddd
					   unsigned TINT32 sampleRate,
Toshihiro Shimizu 890ddd
					   unsigned char bitPerSample)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	wFormatTag = WAVE_FORMAT_PCM;
Toshihiro Shimizu 890ddd
	nChannels = channelCount;
Toshihiro Shimizu 890ddd
	nSamplesPerSec = sampleRate;
Toshihiro Shimizu 890ddd
	wBitsPerSample = bitPerSample;
Toshihiro Shimizu 890ddd
	nBlockAlign = (channelCount * bitPerSample) >> 3;
Toshihiro Shimizu 890ddd
	nAvgBytesPerSec = nBlockAlign * sampleRate;
Toshihiro Shimizu 890ddd
	cbSize = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class WinSoundInputDevice
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	WinSoundInputDevice();
Toshihiro Shimizu 890ddd
	~WinSoundInputDevice();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void open(const WaveFormat &wf);
Toshihiro Shimizu 890ddd
	void close();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void prepareHeader(char *sampleBuffer,
Toshihiro Shimizu 890ddd
					   unsigned TINT32 sampleBufferSize,
Toshihiro Shimizu 890ddd
					   WAVEHDR &whdr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void unprepareHeader(WAVEHDR &whdr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void addBlock(WAVEHDR &whdr);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void start();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void reset();
Toshihiro Shimizu 890ddd
	void stop();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	HANDLE m_hBlockDone;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Toshihiro Shimizu 890ddd
	HWAVEIN m_hWaveIn;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
WinSoundInputDevice::WinSoundInputDevice()
Toshihiro Shimizu 890ddd
	: m_hWaveIn(0)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_hBlockDone = CreateEvent(
Toshihiro Shimizu 890ddd
		NULL,  // no security attributes
Toshihiro Shimizu 890ddd
		FALSE, // auto-reset event
Toshihiro Shimizu 890ddd
		FALSE, // initial state is not signaled
Toshihiro Shimizu 890ddd
		NULL); // object not named
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
WinSoundInputDevice::~WinSoundInputDevice()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	CloseHandle(m_hBlockDone);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void WinSoundInputDevice::open(const WaveFormat &wf)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_hWaveIn)
Toshihiro Shimizu 890ddd
		close();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	MMRESULT ret = waveInOpen(
Toshihiro Shimizu 890ddd
		&m_hWaveIn, WAVE_MAPPER,
Toshihiro Shimizu 890ddd
		&wf, (DWORD)recordCB,
Toshihiro Shimizu 890ddd
		(DWORD)m_hBlockDone, CALLBACK_FUNCTION);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
		throw TException("Error to open the input device");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void WinSoundInputDevice::close()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_hWaveIn)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	MMRESULT ret = waveInClose(m_hWaveIn);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
		throw TException("Error to close the input device");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	m_hWaveIn = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void WinSoundInputDevice::prepareHeader(char *sampleBuffer,
Toshihiro Shimizu 890ddd
										unsigned TINT32 sampleBufferSize,
Toshihiro Shimizu 890ddd
										WAVEHDR &whdr)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	whdr.lpData = sampleBuffer;
Toshihiro Shimizu 890ddd
	whdr.dwBufferLength = sampleBufferSize; // numero di byte
Toshihiro Shimizu 890ddd
	whdr.dwFlags = 0;
Toshihiro Shimizu 890ddd
	whdr.dwLoops = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	MMRESULT ret = waveInPrepareHeader(m_hWaveIn, &whdr, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
		throw TException("Unable to prepare a wave header");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void WinSoundInputDevice::unprepareHeader(WAVEHDR &whdr)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MMRESULT ret = waveInUnprepareHeader(m_hWaveIn, &whdr, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
		throw TException("Unable to unprepare a wave header");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void WinSoundInputDevice::addBlock(WAVEHDR &whdr)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MMRESULT ret = waveInAddBuffer(m_hWaveIn, &whdr, sizeof(WAVEHDR));
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
		throw TException("Unable to add a waveheader");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void WinSoundInputDevice::start()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int ret = waveInStart(m_hWaveIn);
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
		throw TException("Unable to add a waveheader");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void WinSoundInputDevice::reset()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_hWaveIn)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	MMRESULT ret = waveInReset(m_hWaveIn);
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
		throw TException("Unable to add a waveheader");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void WinSoundInputDevice::stop()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MMRESULT ret = waveInStop(m_hWaveIn);
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
		throw TException("Unable to add a waveheader");
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//====================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
class RecordTask : public TThread::Runnable
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	RecordTask(TSoundInputDeviceImp *dev)
Toshihiro Shimizu 890ddd
		: Runnable(), m_dev(dev) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~RecordTask() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void run();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TSoundInputDeviceImp *m_dev;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//====================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TSoundInputDeviceImp : public WinSoundInputDevice
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	bool m_allocateBuff;
Toshihiro Shimizu 890ddd
	bool m_isRecording;
Toshihiro Shimizu 890ddd
	bool m_supportVolume;
Toshihiro Shimizu 890ddd
	int m_index;
Toshihiro Shimizu 890ddd
	TINT32 m_byteRecorded;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TSoundTrackP m_st;
Toshihiro Shimizu 890ddd
	TSoundTrackFormat m_format;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
	TThread::Executor m_executor;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
	vector<wavehdr> m_whdr;</wavehdr>
Toshihiro Shimizu 890ddd
	vector<char *=""> m_recordedBlocks;</char>
Toshihiro Shimizu 890ddd
	std::set<int> m_supportedRate;</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	HANDLE m_hLastBlockDone;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TSoundInputDeviceImp();
Toshihiro Shimizu 890ddd
	~TSoundInputDeviceImp();
Toshihiro Shimizu 890ddd
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
TSoundInputDeviceImp::TSoundInputDeviceImp()
Toshihiro Shimizu 890ddd
	: m_allocateBuff(false), m_isRecording(false), m_supportVolume(false), m_index(0), m_byteRecorded(0), m_format(), m_whdr(3), m_recordedBlocks(), m_supportedRate()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_hLastBlockDone = CreateEvent(
Toshihiro Shimizu 890ddd
		NULL,  // no security attributes
Toshihiro Shimizu 890ddd
		FALSE, // is manual-reset event?
Toshihiro Shimizu 890ddd
		FALSE, // is signaled?
Toshihiro Shimizu 890ddd
		NULL); // object not named
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundInputDeviceImp::~TSoundInputDeviceImp()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_isRecording) {
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			reset();
Toshihiro Shimizu 890ddd
			WaitForSingleObject(m_hLastBlockDone, INFINITE);
Toshihiro Shimizu 890ddd
			int i;
Toshihiro Shimizu 890ddd
			for (i = 0; i < (int)m_recordedBlocks.size(); ++i)
Toshihiro Shimizu 890ddd
				delete[] m_recordedBlocks[i];
Toshihiro Shimizu 890ddd
			close();
Toshihiro Shimizu 890ddd
		} catch (TException &) {
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	CloseHandle(m_hLastBlockDone);
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
	std::set<int>::iterator it;</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (it = m_supportedRate.begin();
Toshihiro Shimizu 890ddd
		 it != m_supportedRate.end();) {
Toshihiro Shimizu 890ddd
		MMRESULT ret;
Toshihiro Shimizu 890ddd
		WAVEFORMATEX wf;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		wf.wFormatTag = WAVE_FORMAT_PCM;
Toshihiro Shimizu 890ddd
		wf.nChannels = 1;
Toshihiro Shimizu 890ddd
		wf.nSamplesPerSec = *it;
Toshihiro Shimizu 890ddd
		wf.wBitsPerSample = 8;
Toshihiro Shimizu 890ddd
		wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) >> 3;
Toshihiro Shimizu 890ddd
		wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
Toshihiro Shimizu 890ddd
		wf.cbSize = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		ret = waveInOpen(NULL, WAVE_MAPPER, &wf, NULL, NULL, WAVE_FORMAT_QUERY);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
			++it;
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (ret == WAVERR_BADFORMAT)
Toshihiro Shimizu 890ddd
			it = m_supportedRate.erase(it);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (m_supportedRate.end() == m_supportedRate.begin())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//====================================================================
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
void CALLBACK recordCB(
Toshihiro Shimizu 890ddd
	HWAVEIN hwi,
Toshihiro Shimizu 890ddd
	UINT uMsg,
Toshihiro Shimizu 890ddd
	DWORD dwInstance,
Toshihiro Shimizu 890ddd
	DWORD dwParam1,
Toshihiro Shimizu 890ddd
	DWORD dwParam2)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	WAVEHDR *whdr = (WAVEHDR *)dwParam1;
Toshihiro Shimizu 890ddd
	HANDLE *blockDone = (HANDLE *)dwInstance;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (uMsg != MM_WIM_DATA)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	SetEvent(blockDone);
Toshihiro Shimizu 890ddd
}
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
	m_imp->insertAllRate();
Toshihiro Shimizu 890ddd
	if (!m_imp->verifyRate())
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::FailedInit,
Toshihiro Shimizu 890ddd
			"Unable to verify supported rates");
Toshihiro Shimizu 890ddd
	if (supportsVolume())
Toshihiro Shimizu 890ddd
		m_imp->m_supportVolume = true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundInputDevice::~TSoundInputDevice()
Toshihiro Shimizu 890ddd
{
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
	int ndev = waveInGetNumDevs();
Toshihiro Shimizu 890ddd
	if (ndev <= 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
#ifndef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundInputDevice::record(const TSoundTrackFormat &format, Source devtype)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_imp->m_isRecording)
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
	/*if ((format.m_bitPerSample == 8 && format.m_signedSample) ||
Toshihiro Shimizu 890ddd
      (format.m_bitPerSample == 24))
Toshihiro Shimizu 890ddd
    throw TException("This format is not supported for recording");*/
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		TSoundTrackFormat 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 (!setRecordLine(devtype))
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableSetDevice,
Toshihiro Shimizu 890ddd
			"Problems to set input source line to record");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_format = format;
Toshihiro Shimizu 890ddd
	m_imp->m_st = 0;
Toshihiro Shimizu 890ddd
	ResetEvent(m_imp->m_hLastBlockDone);
Toshihiro Shimizu 890ddd
	ResetEvent(m_imp->m_hBlockDone);
Toshihiro Shimizu 890ddd
	m_imp->m_allocateBuff = true;
Toshihiro Shimizu 890ddd
	m_imp->m_isRecording = true;
Toshihiro Shimizu 890ddd
	m_imp->m_index = 0;
Toshihiro Shimizu 890ddd
	m_imp->m_recordedBlocks.clear();
Toshihiro Shimizu 890ddd
	m_imp->m_byteRecorded = 0;
Toshihiro Shimizu 890ddd
	TINT32 bytePerSec = format.m_sampleRate * ((format.m_bitPerSample * format.m_channelCount) >> 3);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		WaveFormat wf(m_imp->m_format.m_channelCount,
Toshihiro Shimizu 890ddd
					  m_imp->m_format.m_sampleRate,
Toshihiro Shimizu 890ddd
					  m_imp->m_format.m_bitPerSample);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_imp->open(wf);
Toshihiro Shimizu 890ddd
	} catch (TException &e) {
Toshihiro Shimizu 890ddd
		m_imp->m_isRecording = false;
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableOpenDevice, e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	for (; m_imp->m_index < (int)(m_imp->m_whdr.size() - 1); ++m_imp->m_index) {
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			m_imp->prepareHeader(new char[bytePerSec],
Toshihiro Shimizu 890ddd
								 bytePerSec,
Toshihiro Shimizu 890ddd
								 m_imp->m_whdr[m_imp->m_index]);
Toshihiro Shimizu 890ddd
			m_imp->addBlock(m_imp->m_whdr[m_imp->m_index]);
Toshihiro Shimizu 890ddd
		} catch (TException &e) {
Toshihiro Shimizu 890ddd
			m_imp->m_isRecording = false;
Toshihiro Shimizu 890ddd
			for (int j = 0; j < (int)(m_imp->m_whdr.size() - 1); ++j) {
Toshihiro Shimizu 890ddd
				if (m_imp->m_whdr[j].dwFlags & WHDR_PREPARED) {
Toshihiro Shimizu 890ddd
					try {
Toshihiro Shimizu 890ddd
						m_imp->unprepareHeader(m_imp->m_whdr[j]);
Toshihiro Shimizu 890ddd
					} catch (TException &e) {
Toshihiro Shimizu 890ddd
						throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
							TSoundDeviceException::UnableCloseDevice, e.getMessage());
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
					delete[] m_imp->m_whdr[j].lpData;
Toshihiro Shimizu 890ddd
				} else if (j == m_imp->m_index)
Toshihiro Shimizu 890ddd
					delete[] m_imp->m_whdr[j].lpData;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
				TSoundDeviceException::UnablePrepare, e.getMessage());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_executor.addTask(new RecordTask(m_imp));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TSoundInputDevice::record(const TSoundTrackP &st, Source devtype)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_imp->m_isRecording)
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_format = st->getFormat();
Toshihiro Shimizu 890ddd
	/*if ((m_imp->m_format.m_bitPerSample == 8 && m_imp->m_format.m_signedSample) ||
Toshihiro Shimizu 890ddd
      (m_imp->m_format.m_bitPerSample == 24))
Toshihiro Shimizu 890ddd
    throw TException("This format is not supported for recording");*/
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		TSoundTrackFormat 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 (!setRecordLine(devtype))
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableSetDevice,
Toshihiro Shimizu 890ddd
			"Problems to set input source line to record");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_st = st;
Toshihiro Shimizu 890ddd
	m_imp->m_allocateBuff = false;
Toshihiro Shimizu 890ddd
	m_imp->m_isRecording = true;
Toshihiro Shimizu 890ddd
	ResetEvent(m_imp->m_hLastBlockDone);
Toshihiro Shimizu 890ddd
	ResetEvent(m_imp->m_hBlockDone);
Toshihiro Shimizu 890ddd
	m_imp->m_index = 0;
Toshihiro Shimizu 890ddd
	m_imp->m_recordedBlocks.clear();
Toshihiro Shimizu 890ddd
	m_imp->m_byteRecorded = 0;
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		WaveFormat wf(m_imp->m_format.m_channelCount,
Toshihiro Shimizu 890ddd
					  m_imp->m_format.m_sampleRate,
Toshihiro Shimizu 890ddd
					  m_imp->m_format.m_bitPerSample);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_imp->open(wf);
Toshihiro Shimizu 890ddd
		m_imp->prepareHeader((char *)st->getRawData(),
Toshihiro Shimizu 890ddd
							 st->getSampleCount() * ((st->getBitPerSample() * st->getChannelCount()) >> 3),
Toshihiro Shimizu 890ddd
							 m_imp->m_whdr[m_imp->m_index]);
Toshihiro Shimizu 890ddd
		m_imp->addBlock(m_imp->m_whdr[m_imp->m_index]);
Toshihiro Shimizu 890ddd
	} catch (TException &e) {
Toshihiro Shimizu 890ddd
		m_imp->m_isRecording = false;
Toshihiro Shimizu 890ddd
		if (m_imp->m_whdr[m_imp->m_index].dwFlags & WHDR_PREPARED)
Toshihiro Shimizu 890ddd
			m_imp->unprepareHeader(m_imp->m_whdr[m_imp->m_index]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnablePrepare, e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_executor.addTask(new RecordTask(m_imp));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSoundTrackP TSoundInputDevice::stop()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_imp->m_isRecording)
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_imp->m_isRecording = false;
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		m_imp->reset();
Toshihiro Shimizu 890ddd
	} catch (TException &e) {
Toshihiro Shimizu 890ddd
		for (int j = 0; j < (int)m_imp->m_whdr.size(); ++j) {
Toshihiro Shimizu 890ddd
			if (m_imp->m_whdr[j].dwFlags & WHDR_PREPARED) {
Toshihiro Shimizu 890ddd
				try {
Toshihiro Shimizu 890ddd
					m_imp->unprepareHeader(m_imp->m_whdr[j]);
Toshihiro Shimizu 890ddd
				} catch (TException &e) {
Toshihiro Shimizu 890ddd
					throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
						TSoundDeviceException::UnablePrepare, e.getMessage());
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
				delete[] m_imp->m_whdr[j].lpData;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableCloseDevice, e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_imp->m_allocateBuff) {
Toshihiro Shimizu 890ddd
		WaitForSingleObject(m_imp->m_hLastBlockDone, INFINITE);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TSoundTrackP st = TSoundTrack::create(
Toshihiro Shimizu 890ddd
			m_imp->m_format,
Toshihiro Shimizu 890ddd
			m_imp->m_byteRecorded / ((m_imp->m_format.m_bitPerSample * m_imp->m_format.m_channelCount) >> 3));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TINT32 bytePerSec = m_imp->m_format.m_sampleRate *
Toshihiro Shimizu 890ddd
							((m_imp->m_format.m_bitPerSample * m_imp->m_format.m_channelCount) >> 3);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int i;
Toshihiro Shimizu 890ddd
		for (i = 0; i < (int)(m_imp->m_recordedBlocks.size() - 1); ++i) {
Toshihiro Shimizu 890ddd
			memcpy(
Toshihiro Shimizu 890ddd
				(void *)(st->getRawData() + bytePerSec * i),
Toshihiro Shimizu 890ddd
				m_imp->m_recordedBlocks[i],
Toshihiro Shimizu 890ddd
				bytePerSec);
Toshihiro Shimizu 890ddd
			delete[] m_imp->m_recordedBlocks[i];
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TINT32 lastBlockSize = m_imp->m_byteRecorded - (bytePerSec * i);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (lastBlockSize != 0) {
Toshihiro Shimizu 890ddd
			memcpy((void *)(st->getRawData() + bytePerSec * i),
Toshihiro Shimizu 890ddd
				   m_imp->m_recordedBlocks[i],
Toshihiro Shimizu 890ddd
				   lastBlockSize);
Toshihiro Shimizu 890ddd
			delete[] m_imp->m_recordedBlocks[i];
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			m_imp->close();
Toshihiro Shimizu 890ddd
		} catch (TException &e) {
Toshihiro Shimizu 890ddd
			throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
				TSoundDeviceException::UnableCloseDevice, e.getMessage());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		return st;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		WaitForSingleObject(m_imp->m_hLastBlockDone, INFINITE);
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			m_imp->close();
Toshihiro Shimizu 890ddd
		} catch (TException &e) {
Toshihiro Shimizu 890ddd
			throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
				TSoundDeviceException::UnableCloseDevice, e.getMessage());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		return m_imp->m_st;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
#ifndef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void RecordTask::run()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_dev->start();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_dev->m_allocateBuff) {
Toshihiro Shimizu 890ddd
		TINT32 bytePerSec = m_dev->m_format.m_sampleRate *
Toshihiro Shimizu 890ddd
							((m_dev->m_format.m_bitPerSample * m_dev->m_format.m_channelCount) >> 3);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		while (m_dev->m_whdr[(m_dev->m_index + 1) % m_dev->m_whdr.size()].dwFlags & WHDR_PREPARED) {
Toshihiro Shimizu 890ddd
			if (m_dev->m_isRecording)
Toshihiro Shimizu 890ddd
				WaitForSingleObject(m_dev->m_hBlockDone, INFINITE);
Toshihiro Shimizu 890ddd
			int indexToPrepare = m_dev->m_index;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			// calcolo l'indice successivo per far l'unprepare
Toshihiro Shimizu 890ddd
			m_dev->m_index = (m_dev->m_index + 1) % m_dev->m_whdr.size();
Toshihiro Shimizu 890ddd
			if (m_dev->m_whdr[m_dev->m_index].dwFlags & WHDR_DONE) {
Toshihiro Shimizu 890ddd
				TINT32 byteRecorded = m_dev->m_whdr[m_dev->m_index].dwBytesRecorded;
Toshihiro Shimizu 890ddd
				if (byteRecorded) {
Toshihiro Shimizu 890ddd
					m_dev->m_recordedBlocks.push_back(m_dev->m_whdr[m_dev->m_index].lpData);
Toshihiro Shimizu 890ddd
					m_dev->m_byteRecorded += byteRecorded;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				try {
Toshihiro Shimizu 890ddd
					m_dev->unprepareHeader(m_dev->m_whdr[m_dev->m_index]);
Toshihiro Shimizu 890ddd
				} catch (TException &) {
Toshihiro Shimizu 890ddd
					for (int i = 0; i < (int)m_dev->m_recordedBlocks.size(); ++i)
Toshihiro Shimizu 890ddd
						delete[] m_dev->m_recordedBlocks[i];
Toshihiro Shimizu 890ddd
					return;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (byteRecorded == 0) {
Toshihiro Shimizu 890ddd
					delete[] m_dev->m_whdr[m_dev->m_index].lpData;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				// con questo controllo si evita che vengano accodati nuovi blocchi
Toshihiro Shimizu 890ddd
				// dopo che e' stata chiamata la waveInReset
Toshihiro Shimizu 890ddd
				if (m_dev->m_isRecording) {
Toshihiro Shimizu 890ddd
					try {
Toshihiro Shimizu 890ddd
						m_dev->prepareHeader(new char[bytePerSec],
Toshihiro Shimizu 890ddd
											 bytePerSec,
Toshihiro Shimizu 890ddd
											 m_dev->m_whdr[indexToPrepare]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
						m_dev->addBlock(m_dev->m_whdr[indexToPrepare]);
Toshihiro Shimizu 890ddd
					} catch (TException &) {
Toshihiro Shimizu 890ddd
						m_dev->m_isRecording = false;
Toshihiro Shimizu 890ddd
						for (int i = 0; i < (int)m_dev->m_recordedBlocks.size(); ++i)
Toshihiro Shimizu 890ddd
							delete[] m_dev->m_recordedBlocks[i];
Toshihiro Shimizu 890ddd
						return;
Toshihiro Shimizu 890ddd
					}
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			} else
Toshihiro Shimizu 890ddd
				m_dev->m_index = indexToPrepare;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		if (m_dev->m_isRecording)
Toshihiro Shimizu 890ddd
			WaitForSingleObject(m_dev->m_hBlockDone, INFINITE);
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			m_dev->unprepareHeader(m_dev->m_whdr[m_dev->m_index]);
Toshihiro Shimizu 890ddd
			m_dev->m_isRecording = false;
Toshihiro Shimizu 890ddd
		} catch (TException &) {
Toshihiro Shimizu 890ddd
			m_dev->m_isRecording = false;
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	SetEvent(m_dev->m_hLastBlockDone);
Toshihiro Shimizu 890ddd
	return;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
double TSoundInputDevice::getVolume()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	DWORD dwVolumeControlID;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT nNumMixers;
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	MIXERLINE mxl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	nNumMixers = mixerGetNumDevs();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (nNumMixers == 0)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::NoMixer,
Toshihiro Shimizu 890ddd
			"Doesn't exist a audio mixer device");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// get dwLineID
Toshihiro Shimizu 890ddd
	ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl);
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableVolume,
Toshihiro Shimizu 890ddd
			"Error to obtain info by mixer");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// get dwControlID
Toshihiro Shimizu 890ddd
	MIXERCONTROL mxc;
Toshihiro Shimizu 890ddd
	ret = getLineControl(mxc, (HMIXEROBJ)0, mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_VOLUME);
Toshihiro Shimizu 890ddd
	if (ret == MIXERR_INVALCONTROL)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableVolume,
Toshihiro Shimizu 890ddd
			"Is not possible to obtain info of volume by mixer");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableVolume,
Toshihiro Shimizu 890ddd
			"Error to obtain info by mixer");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	dwVolumeControlID = mxc.dwControlID;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	MIXERCONTROLDETAILS_UNSIGNED mxcdVolume;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ret = getControlDetails((HMIXEROBJ)0,
Toshihiro Shimizu 890ddd
							dwVolumeControlID,
Toshihiro Shimizu 890ddd
							mxc.cMultipleItems,
Toshihiro Shimizu 890ddd
							&mxcdVolume);
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableVolume,
Toshihiro Shimizu 890ddd
			"Error to obtain info by mixer");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	DWORD dwVal = mxcdVolume.dwValue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return (double)dwVal * 10.0 / (double)mxc.Bounds.dwMaximum;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TSoundInputDevice::setVolume(double value)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	DWORD dwVolumeControlID,
Toshihiro Shimizu 890ddd
		dwMaximum;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT nNumMixers;
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	MIXERLINE mxl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	nNumMixers = mixerGetNumDevs();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (nNumMixers == 0)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::NoMixer,
Toshihiro Shimizu 890ddd
			"Doesn't exist a audio mixer device");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// get dwLineID
Toshihiro Shimizu 890ddd
	ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl);
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		throw TException("Error to obtain info by mixer");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// get dwControlID
Toshihiro Shimizu 890ddd
	MIXERCONTROL mxc;
Toshihiro Shimizu 890ddd
	ret = getLineControl(mxc, (HMIXEROBJ)0, mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_VOLUME);
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableVolume,
Toshihiro Shimizu 890ddd
			"Error to obtain info by mixer");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	dwMaximum = mxc.Bounds.dwMaximum;
Toshihiro Shimizu 890ddd
	dwVolumeControlID = mxc.dwControlID;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int newValue;
Toshihiro Shimizu 890ddd
	double fattProp = ((double)(mxc.Metrics.cSteps - 1) * value) / 10;
Toshihiro Shimizu 890ddd
	double delta = (double)(dwMaximum / (mxc.Metrics.cSteps - 1));
Toshihiro Shimizu 890ddd
	newValue = (int)(tround(fattProp) * delta);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	MIXERCONTROLDETAILS_UNSIGNED mxcdVolume = {newValue};
Toshihiro Shimizu 890ddd
	ret = setControlDetails((HMIXEROBJ)0,
Toshihiro Shimizu 890ddd
							dwVolumeControlID,
Toshihiro Shimizu 890ddd
							mxc.cMultipleItems,
Toshihiro Shimizu 890ddd
							&mxcdVolume);
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableVolume,
Toshihiro Shimizu 890ddd
			"Error to obtain info by mixer");
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
	UINT nNumMixers;
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	MIXERLINE mxl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	nNumMixers = mixerGetNumDevs();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (nNumMixers == 0)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::NoMixer,
Toshihiro Shimizu 890ddd
			"Doesn't exist a audio mixer device");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// get dwLineID
Toshihiro Shimizu 890ddd
	ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl);
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableVolume,
Toshihiro Shimizu 890ddd
			"Error to obtain info by mixer");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// get dwControlID
Toshihiro Shimizu 890ddd
	MIXERCONTROL mxc;
Toshihiro Shimizu 890ddd
	ret = getLineControl(mxc, (HMIXEROBJ)0, mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_VOLUME);
Toshihiro Shimizu 890ddd
	if (ret == MIXERR_INVALCONTROL)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnableVolume,
Toshihiro Shimizu 890ddd
			"Error to obtain info by mixer");
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::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
/*TSoundTrackFormat TSoundInputDevice::getPreferredFormat(
Toshihiro Shimizu 890ddd
      ULONG sampleRate, int channelCount, int bitPerSample)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  MMRESULT ret;
Toshihiro Shimizu 890ddd
  TSoundTrackFormat fmt;
Toshihiro Shimizu 890ddd
 
Toshihiro Shimizu 890ddd
  ret = isaFormatSupported(sampleRate, channelCount, bitPerSample, true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  if (ret == MMSYSERR_NOERROR)
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
Toshihiro Shimizu 890ddd
    if (bitPerSample >= 16)
Toshihiro Shimizu 890ddd
      fmt.m_signedSample = true;
Toshihiro Shimizu 890ddd
    else
Toshihiro Shimizu 890ddd
      fmt.m_signedSample = false;
Toshihiro Shimizu 890ddd
    return fmt;
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
  if (ret == WAVERR_BADFORMAT)
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    //avvvicinarsi al sample rate => dovrebbe esser OK avendo selezionato i piu' vicini
Toshihiro Shimizu 890ddd
    std::set<int>::iterator it = m_imp->m_supportedRate.lower_bound(sampleRate);</int>
Toshihiro Shimizu 890ddd
    if (it == m_imp->m_supportedRate.end())
Toshihiro Shimizu 890ddd
    {
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 format");
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    else
Toshihiro Shimizu 890ddd
      sampleRate = *it;
Toshihiro Shimizu 890ddd
    ret = isaFormatSupported(sampleRate, channelCount, bitPerSample, true);
Toshihiro Shimizu 890ddd
    if (ret == MMSYSERR_NOERROR)
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
Toshihiro Shimizu 890ddd
      if (bitPerSample >= 16)
Toshihiro Shimizu 890ddd
        fmt.m_signedSample = true;
Toshihiro Shimizu 890ddd
      else
Toshihiro Shimizu 890ddd
        fmt.m_signedSample = false;
Toshihiro Shimizu 890ddd
      return fmt;
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
    if (ret == WAVERR_BADFORMAT)
Toshihiro Shimizu 890ddd
    {
Toshihiro Shimizu 890ddd
      //cambiare bps
Toshihiro Shimizu 890ddd
      if (bitPerSample <= 8)
Toshihiro Shimizu 890ddd
        bitPerSample = 8;
Toshihiro Shimizu 890ddd
      else if ((bitPerSample > 8 && bitPerSample < 16) || bitPerSample >= 16)
Toshihiro Shimizu 890ddd
        bitPerSample = 16;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
      ret = isaFormatSupported(sampleRate, channelCount, bitPerSample, true);
Toshihiro Shimizu 890ddd
      if (ret == MMSYSERR_NOERROR)
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
Toshihiro Shimizu 890ddd
        if (bitPerSample >= 16)
Toshihiro Shimizu 890ddd
          fmt.m_signedSample = true;
Toshihiro Shimizu 890ddd
        else
Toshihiro Shimizu 890ddd
          fmt.m_signedSample = false;
Toshihiro Shimizu 890ddd
        return fmt;
Toshihiro Shimizu 890ddd
      }
Toshihiro Shimizu 890ddd
      if (ret == WAVERR_BADFORMAT)
Toshihiro Shimizu 890ddd
      {
Toshihiro Shimizu 890ddd
        //switch mono/stereo
Toshihiro Shimizu 890ddd
        if (channelCount <= 1)
Toshihiro Shimizu 890ddd
          channelCount = 1;
Toshihiro Shimizu 890ddd
        else 
Toshihiro Shimizu 890ddd
          channelCount = 2;
Toshihiro Shimizu 890ddd
     
Toshihiro Shimizu 890ddd
        ret = isaFormatSupported(sampleRate, channelCount, bitPerSample, true);
Toshihiro Shimizu 890ddd
        if (ret == MMSYSERR_NOERROR)
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
Toshihiro Shimizu 890ddd
          if (bitPerSample >= 16)
Toshihiro Shimizu 890ddd
            fmt.m_signedSample = true;
Toshihiro Shimizu 890ddd
          else
Toshihiro Shimizu 890ddd
            fmt.m_signedSample = false;
Toshihiro Shimizu 890ddd
          return fmt;
Toshihiro Shimizu 890ddd
        }
Toshihiro Shimizu 890ddd
        if (ret == WAVERR_BADFORMAT)
Toshihiro Shimizu 890ddd
        {
Toshihiro Shimizu 890ddd
          throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
            TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
            "Doesn't exist a preferred format");
Toshihiro Shimizu 890ddd
        }
Toshihiro Shimizu 890ddd
      }
Toshihiro Shimizu 890ddd
    }
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
  throw TSoundDeviceException(
Toshihiro Shimizu 890ddd
    TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
    "Error to query supported format");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
TSoundTrackFormat TSoundInputDevice::getPreferredFormat(
Toshihiro Shimizu 890ddd
	TUINT32 sampleRate, int channelCount, int bitPerSample)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TSoundTrackFormat fmt;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//avvvicinarsi al sample rate => dovrebbe esser OK avendo selezionato i piu' vicini
Toshihiro Shimizu 890ddd
	std::set<int>::iterator it = m_imp->m_supportedRate.lower_bound(sampleRate);</int>
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 format");
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		sampleRate = *it;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (bitPerSample <= 8)
Toshihiro Shimizu 890ddd
		bitPerSample = 8;
Toshihiro Shimizu 890ddd
	else if ((bitPerSample > 8 && bitPerSample < 16) || bitPerSample >= 16)
Toshihiro Shimizu 890ddd
		bitPerSample = 16;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (bitPerSample >= 16)
Toshihiro Shimizu 890ddd
		fmt.m_signedSample = true;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		fmt.m_signedSample = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//switch mono/stereo
Toshihiro Shimizu 890ddd
	if (channelCount <= 1)
Toshihiro Shimizu 890ddd
		channelCount = 1;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		channelCount = 2;
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
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(
Toshihiro Shimizu 890ddd
			TSoundDeviceException::UnsupportedFormat,
Toshihiro Shimizu 890ddd
			e.getMessage());
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
// Funzioni per l'interazione con il mixer device
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
//==============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// restituisce dentro la struttura mxc le informazioni relative
Toshihiro Shimizu 890ddd
// al controllo di tipo dwControlType associato alla linea
Toshihiro Shimizu 890ddd
// identificata da dwLineID
Toshihiro Shimizu 890ddd
MMRESULT getLineControl(MIXERCONTROL &mxc,
Toshihiro Shimizu 890ddd
						HMIXEROBJ hMixer,
Toshihiro Shimizu 890ddd
						DWORD dwLineID,
Toshihiro Shimizu 890ddd
						DWORD dwControlType)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MIXERLINECONTROLS mxlc;
Toshihiro Shimizu 890ddd
	mxlc.cbStruct = sizeof(MIXERLINECONTROLS);
Toshihiro Shimizu 890ddd
	mxlc.dwLineID = dwLineID;
Toshihiro Shimizu 890ddd
	mxlc.dwControlType = dwControlType;
Toshihiro Shimizu 890ddd
	mxlc.cControls = 1;
Toshihiro Shimizu 890ddd
	mxlc.cbmxctrl = sizeof(MIXERCONTROL);
Toshihiro Shimizu 890ddd
	mxlc.pamxctrl = &mxc;
Toshihiro Shimizu 890ddd
	MMRESULT ret = mixerGetLineControls((HMIXEROBJ)hMixer,
Toshihiro Shimizu 890ddd
										&mxlc,
Toshihiro Shimizu 890ddd
										MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE);
Toshihiro Shimizu 890ddd
	return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// restituisce nella struttura mxl le informazioni relative alla linea
Toshihiro Shimizu 890ddd
// sorgente individuata dagli estremi destination e source
Toshihiro Shimizu 890ddd
MMRESULT getLineInfo(HMIXEROBJ hMixer,
Toshihiro Shimizu 890ddd
					 MIXERLINE &mxl,
Toshihiro Shimizu 890ddd
					 DWORD destination,
Toshihiro Shimizu 890ddd
					 DWORD source)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	mxl.cbStruct = sizeof(mxl);
Toshihiro Shimizu 890ddd
	mxl.dwDestination = destination;
Toshihiro Shimizu 890ddd
	mxl.dwSource = source;
Toshihiro Shimizu 890ddd
	ret = mixerGetLineInfo(0, &mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_SOURCE);
Toshihiro Shimizu 890ddd
	return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// restituisce nella struttura mxl le informazioni relative alla linea
Toshihiro Shimizu 890ddd
// individuata da dwLineID
Toshihiro Shimizu 890ddd
MMRESULT getLineInfo(HMIXEROBJ hMixer,
Toshihiro Shimizu 890ddd
					 MIXERLINE &mxl,
Toshihiro Shimizu 890ddd
					 DWORD dwLineID)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	mxl.cbStruct = sizeof(mxl);
Toshihiro Shimizu 890ddd
	mxl.dwLineID = dwLineID;
Toshihiro Shimizu 890ddd
	ret = mixerGetLineInfo((HMIXEROBJ)hMixer,
Toshihiro Shimizu 890ddd
						   &mxl,
Toshihiro Shimizu 890ddd
						   MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_LINEID);
Toshihiro Shimizu 890ddd
	return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// restituisce nella struttura mxl le informazioni relative alla linea
Toshihiro Shimizu 890ddd
// individuata dal tipo specificato in dwComponentType
Toshihiro Shimizu 890ddd
MMRESULT getLineInfo(HMIXEROBJ hMixer,
Toshihiro Shimizu 890ddd
					 DWORD dwComponentType,
Toshihiro Shimizu 890ddd
					 MIXERLINE &mxl)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	mxl.cbStruct = sizeof(MIXERLINE);
Toshihiro Shimizu 890ddd
	mxl.dwComponentType = dwComponentType;
Toshihiro Shimizu 890ddd
	ret = mixerGetLineInfo((HMIXEROBJ)hMixer,
Toshihiro Shimizu 890ddd
						   &mxl,
Toshihiro Shimizu 890ddd
						   MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE);
Toshihiro Shimizu 890ddd
	return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// consente di settare il valore booleano specificato in mxcdSelectValue
Toshihiro Shimizu 890ddd
// relativo al controllo specificato in dwSelectControlID
Toshihiro Shimizu 890ddd
MMRESULT setControlDetails(HMIXEROBJ hMixer,
Toshihiro Shimizu 890ddd
						   DWORD dwSelectControlID,
Toshihiro Shimizu 890ddd
						   DWORD dwMultipleItems,
Toshihiro Shimizu 890ddd
						   MIXERCONTROLDETAILS_BOOLEAN *mxcdSelectValue)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	MIXERCONTROLDETAILS mxcd;
Toshihiro Shimizu 890ddd
	mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
Toshihiro Shimizu 890ddd
	mxcd.dwControlID = dwSelectControlID;
Toshihiro Shimizu 890ddd
	mxcd.cChannels = 1;
Toshihiro Shimizu 890ddd
	mxcd.cMultipleItems = dwMultipleItems;
Toshihiro Shimizu 890ddd
	mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
Toshihiro Shimizu 890ddd
	mxcd.paDetails = mxcdSelectValue;
Toshihiro Shimizu 890ddd
	ret = mixerSetControlDetails((HMIXEROBJ)hMixer,
Toshihiro Shimizu 890ddd
								 &mxcd,
Toshihiro Shimizu 890ddd
								 MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE);
Toshihiro Shimizu 890ddd
	return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// consente di settare il valore UNSIGNED specificato in mxcdSelectValue
Toshihiro Shimizu 890ddd
// relativo al controllo specificato in dwSelectControlID
Toshihiro Shimizu 890ddd
MMRESULT setControlDetails(HMIXEROBJ hMixer,
Toshihiro Shimizu 890ddd
						   DWORD dwSelectControlID,
Toshihiro Shimizu 890ddd
						   DWORD dwMultipleItems,
Toshihiro Shimizu 890ddd
						   MIXERCONTROLDETAILS_UNSIGNED *mxcdSelectValue)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	MIXERCONTROLDETAILS mxcd;
Toshihiro Shimizu 890ddd
	mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
Toshihiro Shimizu 890ddd
	mxcd.dwControlID = dwSelectControlID;
Toshihiro Shimizu 890ddd
	mxcd.cChannels = 1;
Toshihiro Shimizu 890ddd
	mxcd.cMultipleItems = dwMultipleItems;
Toshihiro Shimizu 890ddd
	mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
Toshihiro Shimizu 890ddd
	mxcd.paDetails = mxcdSelectValue;
Toshihiro Shimizu 890ddd
	ret = mixerSetControlDetails((HMIXEROBJ)hMixer,
Toshihiro Shimizu 890ddd
								 &mxcd,
Toshihiro Shimizu 890ddd
								 MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE);
Toshihiro Shimizu 890ddd
	return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// consente di ottenere il valore UNSIGNED specificato in mxcdSelectValue
Toshihiro Shimizu 890ddd
// relativo al controllo specificato in dwSelectControlID
Toshihiro Shimizu 890ddd
MMRESULT getControlDetails(HMIXEROBJ hMixer,
Toshihiro Shimizu 890ddd
						   DWORD dwSelectControlID,
Toshihiro Shimizu 890ddd
						   DWORD dwMultipleItems,
Toshihiro Shimizu 890ddd
						   MIXERCONTROLDETAILS_UNSIGNED *mxcdSelectValue)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	MIXERCONTROLDETAILS mxcd;
Toshihiro Shimizu 890ddd
	mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
Toshihiro Shimizu 890ddd
	mxcd.dwControlID = dwSelectControlID;
Toshihiro Shimizu 890ddd
	mxcd.cChannels = 1;
Toshihiro Shimizu 890ddd
	mxcd.cMultipleItems = dwMultipleItems;
Toshihiro Shimizu 890ddd
	mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
Toshihiro Shimizu 890ddd
	mxcd.paDetails = mxcdSelectValue;
Toshihiro Shimizu 890ddd
	ret = mixerGetControlDetails((HMIXEROBJ)hMixer,
Toshihiro Shimizu 890ddd
								 &mxcd,
Toshihiro Shimizu 890ddd
								 MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE);
Toshihiro Shimizu 890ddd
	return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// consente di ottenere la lista di informazioni in pmxcdSelectText
Toshihiro Shimizu 890ddd
// relativo al controllo specificato in dwSelectControlID
Toshihiro Shimizu 890ddd
MMRESULT getControlDetails(HMIXEROBJ hMixer,
Toshihiro Shimizu 890ddd
						   DWORD dwSelectControlID,
Toshihiro Shimizu 890ddd
						   DWORD dwMultipleItems,
Toshihiro Shimizu 890ddd
						   MIXERCONTROLDETAILS_LISTTEXT *pmxcdSelectText)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	MIXERCONTROLDETAILS mxcd;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
Toshihiro Shimizu 890ddd
	mxcd.dwControlID = dwSelectControlID;
Toshihiro Shimizu 890ddd
	mxcd.cChannels = 1;
Toshihiro Shimizu 890ddd
	mxcd.cMultipleItems = dwMultipleItems;
Toshihiro Shimizu 890ddd
	mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXT);
Toshihiro Shimizu 890ddd
	mxcd.paDetails = pmxcdSelectText;
Toshihiro Shimizu 890ddd
	ret = mixerGetControlDetails((HMIXEROBJ)0,
Toshihiro Shimizu 890ddd
								 &mxcd,
Toshihiro Shimizu 890ddd
								 MIXER_GETCONTROLDETAILSF_LISTTEXT);
Toshihiro Shimizu 890ddd
	return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// restituiscei l nome della linea identificata da lineID
Toshihiro Shimizu 890ddd
string getMixerLineName(DWORD lineID)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MIXERLINE mxl;
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ret = getLineInfo((HMIXEROBJ)0, mxl, lineID);
Toshihiro Shimizu 890ddd
#ifdef TNZCORE_LIGHT
Toshihiro Shimizu 890ddd
	assert(false);
Toshihiro Shimizu 890ddd
	return "";
Toshihiro Shimizu 890ddd
#else
Toshihiro Shimizu 890ddd
	return string(mxl.szName);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// restituisce la lista degli identificativi delle linee sorgente associate
Toshihiro Shimizu 890ddd
// alla destinazione di tipo dstComponentType
Toshihiro Shimizu 890ddd
list<dword> getMixerSrcLines(DWORD dstComponentType)</dword>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	list<dword> srcList;</dword>
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	MIXERLINE mxl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl);
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		//forse bisognerebbe lanciare un'eccezione
Toshihiro Shimizu 890ddd
		return srcList; //non ha linea di dst per la registrazione
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int v;
Toshihiro Shimizu 890ddd
	for (v = 0; v < (int)mxl.cConnections; v++) {
Toshihiro Shimizu 890ddd
		MIXERLINE mxl1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		ret = getLineInfo((HMIXEROBJ)0, mxl1, mxl.dwDestination, v);
Toshihiro Shimizu 890ddd
		if (ret == MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
			srcList.push_back(mxl1.dwLineID);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return srcList;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// restituisce la lista degli identificativi delle linee sorgente di tipo
Toshihiro Shimizu 890ddd
// srcComponentType associate alla destinazione di tipo dstComponentType
Toshihiro Shimizu 890ddd
list<dword> getMixerSrcLines(DWORD dstComponentType, DWORD srcComponentType)</dword>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	list<dword> srcList;</dword>
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	MIXERLINE mxl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl);
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		//forse bisognerebbe lanciare un'eccezione
Toshihiro Shimizu 890ddd
		return srcList; //non ha linea di dst per la registrazione
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int v;
Toshihiro Shimizu 890ddd
	for (v = 0; v < (int)mxl.cConnections; v++) {
Toshihiro Shimizu 890ddd
		MIXERLINE mxl1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		ret = getLineInfo((HMIXEROBJ)0, mxl1, mxl.dwDestination, v);
Toshihiro Shimizu 890ddd
		if (ret == MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
			if (mxl1.dwComponentType == srcComponentType)
Toshihiro Shimizu 890ddd
				srcList.push_back(mxl1.dwLineID);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return srcList;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// restituisce true sse la linea destinazione di tipo dstComponentType
Toshihiro Shimizu 890ddd
// supporta una linea sorgente di tipo srcComponentType
Toshihiro Shimizu 890ddd
bool isSrcLineSupported(DWORD dstComponentType, DWORD srcComponentType)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// ci possono essere piu' linee sorgente dello stesso tipo in
Toshihiro Shimizu 890ddd
	// corrispondenza di una data linea destinazione ?
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	MIXERLINE mxl;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl);
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		return false; //non ha linea di dst per la registrazione
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int v;
Toshihiro Shimizu 890ddd
	for (v = 0; v < (int)mxl.cConnections; v++) {
Toshihiro Shimizu 890ddd
		MIXERLINE mxl1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		ret = getLineInfo((HMIXEROBJ)0, mxl1, mxl.dwDestination, v);
Toshihiro Shimizu 890ddd
		if (ret == MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
			if (mxl1.dwComponentType == srcComponentType)
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 activateSrcLine(const MIXERLINE &mxlDst, DWORD componentTypeSrc)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!isSrcLineSupported(mxlDst.dwComponentType, componentTypeSrc))
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool bRetVal = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (DWORD v = 0; v < mxlDst.cConnections; v++) {
Toshihiro Shimizu 890ddd
		MIXERLINE mxlSrc;
Toshihiro Shimizu 890ddd
		MMRESULT ret = getLineInfo((HMIXEROBJ)0, mxlSrc, mxlDst.dwDestination, v);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
			// chiedo il controllo di tipo MUTE della linea sorgente
Toshihiro Shimizu 890ddd
			MIXERCONTROL mxc;
Toshihiro Shimizu 890ddd
			ret = getLineControl(
Toshihiro Shimizu 890ddd
				mxc, (HMIXEROBJ)0, mxlSrc.dwLineID,
Toshihiro Shimizu 890ddd
				MIXERCONTROL_CONTROLTYPE_MUTE);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
				MIXERCONTROLDETAILS_BOOLEAN mxcdSelectValue;
Toshihiro Shimizu 890ddd
				mxcdSelectValue.fValue = mxlSrc.dwComponentType == componentTypeSrc ? 0L : 1L;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				ret = setControlDetails((HMIXEROBJ)0, mxc.dwControlID,
Toshihiro Shimizu 890ddd
										mxc.cMultipleItems, &mxcdSelectValue);
Toshihiro Shimizu 890ddd
				if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
					bRetVal = false;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return bRetVal;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool setSrcMixMuxControl(MIXERCONTROL mxc, DWORD componentTypeSrc)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	DWORD dwIndexLine;
Toshihiro Shimizu 890ddd
	bool found = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// mantengo nota del ID del controllo dsst individuato e
Toshihiro Shimizu 890ddd
	// del numero di linee src ad esso associate
Toshihiro Shimizu 890ddd
	DWORD dwSelectControlID = mxc.dwControlID;
Toshihiro Shimizu 890ddd
	DWORD dwMultipleItems = mxc.cMultipleItems;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (dwMultipleItems == 0)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// determino l'indice dell'item corrispondente alla linea sorgente
Toshihiro Shimizu 890ddd
	// di tipo componentTypeSrc
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	MIXERCONTROLDETAILS_LISTTEXT *pmxcdSelectText =
Toshihiro Shimizu 890ddd
		new MIXERCONTROLDETAILS_LISTTEXT[dwMultipleItems];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (pmxcdSelectText != NULL) {
Toshihiro Shimizu 890ddd
		// estraggo le info su tutte le linee associate al controllo
Toshihiro Shimizu 890ddd
		ret = getControlDetails((HMIXEROBJ)0, dwSelectControlID,
Toshihiro Shimizu 890ddd
								dwMultipleItems, pmxcdSelectText);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (ret == MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
			for (DWORD dwi = 0; dwi < dwMultipleItems; dwi++) {
Toshihiro Shimizu 890ddd
				// prendo le info su ogni linea e verifico se e' del giusto tipo
Toshihiro Shimizu 890ddd
				MIXERLINE mxl;
Toshihiro Shimizu 890ddd
				ret = getLineInfo((HMIXEROBJ)0, mxl, pmxcdSelectText[dwi].dwParam1);
Toshihiro Shimizu 890ddd
				if (ret == MMSYSERR_NOERROR && mxl.dwComponentType == componentTypeSrc) {
Toshihiro Shimizu 890ddd
					dwIndexLine = dwi;
Toshihiro Shimizu 890ddd
					found = true;
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		delete[] pmxcdSelectText;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!found)
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (dwIndexLine >= dwMultipleItems)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool bRetVal = false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	MIXERCONTROLDETAILS_BOOLEAN *pmxcdSelectValue =
Toshihiro Shimizu 890ddd
		new MIXERCONTROLDETAILS_BOOLEAN[dwMultipleItems];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (pmxcdSelectValue != NULL) {
Toshihiro Shimizu 890ddd
		::ZeroMemory(pmxcdSelectValue, dwMultipleItems * sizeof(MIXERCONTROLDETAILS_BOOLEAN));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// impostazione del valore
Toshihiro Shimizu 890ddd
		pmxcdSelectValue[dwIndexLine].fValue = (TINT32)1; // lVal; //dovrebbe esser uno
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		ret = setControlDetails((HMIXEROBJ)0,
Toshihiro Shimizu 890ddd
								dwSelectControlID,
Toshihiro Shimizu 890ddd
								dwMultipleItems,
Toshihiro Shimizu 890ddd
								pmxcdSelectValue);
Toshihiro Shimizu 890ddd
		if (ret == MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
			bRetVal = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		delete[] pmxcdSelectValue;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return bRetVal;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool setRecordLine(TSoundInputDevice::Source typeInput)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	DWORD dwComponentTypeSrc;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	UINT nNumMixers;
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
	MIXERLINE mxl = {0};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	switch (typeInput) {
Toshihiro Shimizu 890ddd
	case TSoundInputDevice::LineIn:
Toshihiro Shimizu 890ddd
		dwComponentTypeSrc = MIXERLINE_COMPONENTTYPE_SRC_LINE /*|
Toshihiro Shimizu 890ddd
                             MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY |
Toshihiro Shimizu 890ddd
                             MIXERLINE_COMPONENTTYPE_SRC_ANALOG*/;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TSoundInputDevice::DigitalIn:
Toshihiro Shimizu 890ddd
		dwComponentTypeSrc = MIXERLINE_COMPONENTTYPE_SRC_DIGITAL;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	case TSoundInputDevice::CdAudio:
Toshihiro Shimizu 890ddd
		dwComponentTypeSrc = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
Toshihiro Shimizu 890ddd
		break;
Toshihiro Shimizu 890ddd
	default:
Toshihiro Shimizu 890ddd
		dwComponentTypeSrc = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	nNumMixers = mixerGetNumDevs();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (nNumMixers == 0)
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// utilizziamo il MIXER di default identificato dall'indice 0
Toshihiro Shimizu 890ddd
	// vedo se il device ha una linea dst per il wave_input
Toshihiro Shimizu 890ddd
	ret = getLineInfo((HMIXEROBJ)0, MIXERLINE_COMPONENTTYPE_DST_WAVEIN, mxl);
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR)
Toshihiro Shimizu 890ddd
		return false; //non ha linea di dst per la registrazione
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//vediamo che tipo controllo ha questa linea dst
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// sara' un MIXER?
Toshihiro Shimizu 890ddd
	MIXERCONTROL mxc = {0};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ret = getLineControl(mxc,
Toshihiro Shimizu 890ddd
						 (HMIXEROBJ)0,
Toshihiro Shimizu 890ddd
						 mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_MIXER);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (ret != MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
		// no mixer, try MUX
Toshihiro Shimizu 890ddd
		ret = getLineControl(mxc,
Toshihiro Shimizu 890ddd
							 (HMIXEROBJ)0,
Toshihiro Shimizu 890ddd
							 mxl.dwLineID, MIXERCONTROL_CONTROLTYPE_MUX);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (ret != MMSYSERR_NOERROR) {
Toshihiro Shimizu 890ddd
			// vediamo se e' uno di quei device ne' MIXER ne' MUX
Toshihiro Shimizu 890ddd
			return activateSrcLine(mxl, dwComponentTypeSrc);
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			// la linea ha un controllo di tipo MUX
Toshihiro Shimizu 890ddd
			return setSrcMixMuxControl(mxc, dwComponentTypeSrc);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		// la linea ha un controllo di tipo MIXER
Toshihiro Shimizu 890ddd
		return setSrcMixMuxControl(mxc, dwComponentTypeSrc);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MMRESULT isaFormatSupported(
Toshihiro Shimizu 890ddd
	int sampleRate, int channelCount, int bitPerSample, bool input)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	WAVEFORMATEX wf;
Toshihiro Shimizu 890ddd
	MMRESULT ret;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	wf.wFormatTag = WAVE_FORMAT_PCM;
Toshihiro Shimizu 890ddd
	wf.nChannels = channelCount;
Toshihiro Shimizu 890ddd
	wf.nSamplesPerSec = sampleRate;
Toshihiro Shimizu 890ddd
	wf.wBitsPerSample = bitPerSample;
Toshihiro Shimizu 890ddd
	wf.nBlockAlign = (wf.nChannels * wf.wBitsPerSample) >> 3;
Toshihiro Shimizu 890ddd
	wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
Toshihiro Shimizu 890ddd
	wf.cbSize = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (input)
Toshihiro Shimizu 890ddd
		ret = waveInOpen(NULL, WAVE_MAPPER, &wf, NULL, NULL, WAVE_FORMAT_QUERY);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		ret = waveOutOpen(NULL, WAVE_MAPPER, &wf, NULL, NULL, WAVE_FORMAT_QUERY);
Toshihiro Shimizu 890ddd
	return ret;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}