|
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 |
}
|