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