[DEV] set windows ds interface work (in theory) build is ok
This commit is contained in:
parent
1a24bb9254
commit
4fc9a3e05f
@ -56,6 +56,19 @@ static inline DWORD dsPointerBetween(DWORD _pointer, DWORD _laterPointer, DWORD
|
|||||||
return _pointer >= _earlierPointer && _pointer < _laterPointer;
|
return _pointer >= _earlierPointer && _pointer < _laterPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DsDevice {
|
||||||
|
public:
|
||||||
|
LPGUID id[2];
|
||||||
|
bool validId[2];
|
||||||
|
bool found;
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
DsDevice() :
|
||||||
|
found(false) {
|
||||||
|
validId[0] = false;
|
||||||
|
validId[1] = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
namespace airtaudio {
|
namespace airtaudio {
|
||||||
namespace api {
|
namespace api {
|
||||||
@ -70,7 +83,7 @@ namespace airtaudio {
|
|||||||
DWORD dsBufferSize[2];
|
DWORD dsBufferSize[2];
|
||||||
DWORD dsPointerLeadTime[2]; // the number of bytes ahead of the safe pointer to lead by.
|
DWORD dsPointerLeadTime[2]; // the number of bytes ahead of the safe pointer to lead by.
|
||||||
HANDLE condition;
|
HANDLE condition;
|
||||||
|
std::vector<DsDevice> dsDevices;
|
||||||
DsPrivate() :
|
DsPrivate() :
|
||||||
drainCounter(0),
|
drainCounter(0),
|
||||||
internalDrain(false) {
|
internalDrain(false) {
|
||||||
@ -96,23 +109,9 @@ static BOOL CALLBACK deviceQueryCallback(LPGUID _lpguid,
|
|||||||
|
|
||||||
static const char* getErrorString(int32_t _code);
|
static const char* getErrorString(int32_t _code);
|
||||||
|
|
||||||
static unsigned __stdcall callbackHandler(void* _ptr);
|
|
||||||
|
|
||||||
struct DsDevice {
|
|
||||||
LPGUID id[2];
|
|
||||||
bool validId[2];
|
|
||||||
bool found;
|
|
||||||
std::string name;
|
|
||||||
DsDevice() :
|
|
||||||
found(false) {
|
|
||||||
validId[0] = false;
|
|
||||||
validId[1] = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DsProbeData {
|
struct DsProbeData {
|
||||||
bool isInput;
|
bool isInput;
|
||||||
std::vector<struct DsDevice>* dsDevices;
|
std::vector<DsDevice>* dsDevices;
|
||||||
};
|
};
|
||||||
|
|
||||||
airtaudio::api::Ds::Ds() :
|
airtaudio::api::Ds::Ds() :
|
||||||
@ -149,13 +148,13 @@ uint32_t airtaudio::api::Ds::getDefaultInputDevice() {
|
|||||||
uint32_t airtaudio::api::Ds::getDeviceCount() {
|
uint32_t airtaudio::api::Ds::getDeviceCount() {
|
||||||
// Set query flag for previously found devices to false, so that we
|
// Set query flag for previously found devices to false, so that we
|
||||||
// can check for any devices that have disappeared.
|
// can check for any devices that have disappeared.
|
||||||
for (uint32_t i=0; i<dsDevices.size(); i++) {
|
for (size_t iii=0; iii<m_private->dsDevices.size(); ++iii) {
|
||||||
dsDevices[i].found = false;
|
m_private->dsDevices[iii].found = false;
|
||||||
}
|
}
|
||||||
// Query DirectSound devices.
|
// Query DirectSound devices.
|
||||||
struct DsProbeData probeInfo;
|
struct DsProbeData probeInfo;
|
||||||
probeInfo.isInput = false;
|
probeInfo.isInput = false;
|
||||||
probeInfo.dsDevices = &dsDevices;
|
probeInfo.dsDevices = &m_private->dsDevices;
|
||||||
HRESULT result = DirectSoundEnumerate((LPDSENUMCALLBACK) deviceQueryCallback, &probeInfo);
|
HRESULT result = DirectSoundEnumerate((LPDSENUMCALLBACK) deviceQueryCallback, &probeInfo);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") enumerating output devices!");
|
ATA_ERROR("error (" << getErrorString(result) << ") enumerating output devices!");
|
||||||
@ -170,42 +169,42 @@ uint32_t airtaudio::api::Ds::getDeviceCount() {
|
|||||||
}
|
}
|
||||||
// Clean out any devices that may have disappeared.
|
// Clean out any devices that may have disappeared.
|
||||||
std::vector< int32_t > indices;
|
std::vector< int32_t > indices;
|
||||||
for (uint32_t i=0; i<dsDevices.size(); i++) {
|
for (uint32_t i=0; i<m_private->dsDevices.size(); i++) {
|
||||||
if (dsDevices[i].found == false) {
|
if (m_private->dsDevices[i].found == false) {
|
||||||
indices.push_back(i);
|
indices.push_back(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint32_t nErased = 0;
|
uint32_t nErased = 0;
|
||||||
for (uint32_t i=0; i<indices.size(); i++) {
|
for (uint32_t i=0; i<indices.size(); i++) {
|
||||||
dsDevices.erase(dsDevices.begin()-nErased++);
|
m_private->dsDevices.erase(m_private->dsDevices.begin()-nErased++);
|
||||||
}
|
}
|
||||||
return dsDevices.size();
|
return m_private->dsDevices.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
rtaudio::DeviceInfo airtaudio::api::Ds::getDeviceInfo(uint32_t _device) {
|
airtaudio::DeviceInfo airtaudio::api::Ds::getDeviceInfo(uint32_t _device) {
|
||||||
rtaudio::DeviceInfo info;
|
airtaudio::DeviceInfo info;
|
||||||
info.probed = false;
|
info.probed = false;
|
||||||
if (dsDevices.size() == 0) {
|
if (m_private->dsDevices.size() == 0) {
|
||||||
// Force a query of all devices
|
// Force a query of all devices
|
||||||
getDeviceCount();
|
getDeviceCount();
|
||||||
if (dsDevices.size() == 0) {
|
if (m_private->dsDevices.size() == 0) {
|
||||||
ATA_ERROR("no devices found!");
|
ATA_ERROR("no devices found!");
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_device >= dsDevices.size()) {
|
if (_device >= m_private->dsDevices.size()) {
|
||||||
ATA_ERROR("device ID is invalid!");
|
ATA_ERROR("device ID is invalid!");
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
if (dsDevices[ _device ].validId[0] == false) {
|
if (m_private->dsDevices[ _device ].validId[0] == false) {
|
||||||
goto probeInput;
|
goto probeInput;
|
||||||
}
|
}
|
||||||
LPDIRECTSOUND output;
|
LPDIRECTSOUND output;
|
||||||
DSCAPS outCaps;
|
DSCAPS outCaps;
|
||||||
result = DirectSoundCreate(dsDevices[ _device ].id[0], &output, nullptr);
|
result = DirectSoundCreate(m_private->dsDevices[ _device ].id[0], &output, nullptr);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") opening output device (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") opening output device (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
goto probeInput;
|
goto probeInput;
|
||||||
}
|
}
|
||||||
outCaps.dwSize = sizeof(outCaps);
|
outCaps.dwSize = sizeof(outCaps);
|
||||||
@ -219,10 +218,10 @@ rtaudio::DeviceInfo airtaudio::api::Ds::getDeviceInfo(uint32_t _device) {
|
|||||||
info.outputChannels = (outCaps.dwFlags & DSCAPS_PRIMARYSTEREO) ? 2 : 1;
|
info.outputChannels = (outCaps.dwFlags & DSCAPS_PRIMARYSTEREO) ? 2 : 1;
|
||||||
// Get sample rate information.
|
// Get sample rate information.
|
||||||
info.sampleRates.clear();
|
info.sampleRates.clear();
|
||||||
for (uint32_t k=0; k<MAX_SAMPLE_RATES; k++) {
|
for (auto &it : airtaudio::genericSampleRate()) {
|
||||||
if ( SAMPLE_RATES[k] >= (uint32_t) outCaps.dwMinSecondarySampleRate
|
if ( it >= outCaps.dwMinSecondarySampleRate
|
||||||
&& SAMPLE_RATES[k] <= (uint32_t) outCaps.dwMaxSecondarySampleRate) {
|
&& it <= outCaps.dwMaxSecondarySampleRate) {
|
||||||
info.sampleRates.push_back(SAMPLE_RATES[k]);
|
info.sampleRates.push_back(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Get format information.
|
// Get format information.
|
||||||
@ -236,16 +235,16 @@ rtaudio::DeviceInfo airtaudio::api::Ds::getDeviceInfo(uint32_t _device) {
|
|||||||
if (getDefaultOutputDevice() == _device) {
|
if (getDefaultOutputDevice() == _device) {
|
||||||
info.isDefaultOutput = true;
|
info.isDefaultOutput = true;
|
||||||
}
|
}
|
||||||
if (dsDevices[ _device ].validId[1] == false) {
|
if (m_private->dsDevices[ _device ].validId[1] == false) {
|
||||||
info.name = dsDevices[ _device ].name;
|
info.name = m_private->dsDevices[ _device ].name;
|
||||||
info.probed = true;
|
info.probed = true;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
probeInput:
|
probeInput:
|
||||||
LPDIRECTSOUNDCAPTURE input;
|
LPDIRECTSOUNDCAPTURE input;
|
||||||
result = DirectSoundCaptureCreate(dsDevices[ _device ].id[1], &input, nullptr);
|
result = DirectSoundCaptureCreate(m_private->dsDevices[ _device ].id[1], &input, nullptr);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") opening input device (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") opening input device (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
DSCCAPS inCaps;
|
DSCCAPS inCaps;
|
||||||
@ -253,7 +252,7 @@ probeInput:
|
|||||||
result = input->GetCaps(&inCaps);
|
result = input->GetCaps(&inCaps);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
input->Release();
|
input->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") getting object capabilities (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") getting object capabilities (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
// Get input channel information.
|
// Get input channel information.
|
||||||
@ -261,108 +260,62 @@ probeInput:
|
|||||||
// Get sample rate and format information.
|
// Get sample rate and format information.
|
||||||
std::vector<uint32_t> rates;
|
std::vector<uint32_t> rates;
|
||||||
if (inCaps.dwChannels >= 2) {
|
if (inCaps.dwChannels >= 2) {
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_1S16) {
|
if ( (inCaps.dwFormats & WAVE_FORMAT_1S16)
|
||||||
info.nativeFormats |= RTAUDIO_SINT16;
|
|| (inCaps.dwFormats & WAVE_FORMAT_2S16)
|
||||||
|
|| (inCaps.dwFormats & WAVE_FORMAT_4S16)
|
||||||
|
|| (inCaps.dwFormats & WAVE_FORMAT_96S16) ) {
|
||||||
|
info.nativeFormats.push_back(audio::format_int16);
|
||||||
}
|
}
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_2S16) {
|
if ( (inCaps.dwFormats & WAVE_FORMAT_1S08)
|
||||||
info.nativeFormats |= RTAUDIO_SINT16;
|
|| (inCaps.dwFormats & WAVE_FORMAT_2S08)
|
||||||
|
|| (inCaps.dwFormats & WAVE_FORMAT_4S08)
|
||||||
|
|| (inCaps.dwFormats & WAVE_FORMAT_96S08) ) {
|
||||||
|
info.nativeFormats.push_back(audio::format_int8);
|
||||||
}
|
}
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_4S16) {
|
if ( (inCaps.dwFormats & WAVE_FORMAT_1S16)
|
||||||
info.nativeFormats |= RTAUDIO_SINT16;
|
|| (inCaps.dwFormats & WAVE_FORMAT_1S08) ){
|
||||||
|
rates.push_back(11025);
|
||||||
}
|
}
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_96S16) {
|
if ( (inCaps.dwFormats & WAVE_FORMAT_2S16)
|
||||||
info.nativeFormats |= RTAUDIO_SINT16;
|
|| (inCaps.dwFormats & WAVE_FORMAT_2S08) ){
|
||||||
|
rates.push_back(22050);
|
||||||
}
|
}
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_1S08) {
|
if ( (inCaps.dwFormats & WAVE_FORMAT_4S16)
|
||||||
info.nativeFormats |= RTAUDIO_SINT8;
|
|| (inCaps.dwFormats & WAVE_FORMAT_4S08) ){
|
||||||
|
rates.push_back(44100);
|
||||||
}
|
}
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_2S08) {
|
if ( (inCaps.dwFormats & WAVE_FORMAT_96S16)
|
||||||
info.nativeFormats |= RTAUDIO_SINT8;
|
|| (inCaps.dwFormats & WAVE_FORMAT_96S08) ){
|
||||||
}
|
rates.push_back(96000);
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_4S08) {
|
|
||||||
info.nativeFormats |= RTAUDIO_SINT8;
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_96S08) {
|
|
||||||
info.nativeFormats |= RTAUDIO_SINT8;
|
|
||||||
}
|
|
||||||
if (info.nativeFormats & RTAUDIO_SINT16) {
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_1S16) {
|
|
||||||
rates.push_back(11025);
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_2S16) {
|
|
||||||
rates.push_back(22050);
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_4S16) {
|
|
||||||
rates.push_back(44100);
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_96S16) {
|
|
||||||
rates.push_back(96000);
|
|
||||||
}
|
|
||||||
} else if (info.nativeFormats & RTAUDIO_SINT8) {
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_1S08) {
|
|
||||||
rates.push_back(11025);
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_2S08) {
|
|
||||||
rates.push_back(22050);
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_4S08) {
|
|
||||||
rates.push_back(44100);
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_96S08) {
|
|
||||||
rates.push_back(96000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (inCaps.dwChannels == 1) {
|
} else if (inCaps.dwChannels == 1) {
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_1M16) {
|
if ( (inCaps.dwFormats & WAVE_FORMAT_1M16)
|
||||||
info.nativeFormats |= RTAUDIO_SINT16;
|
|| (inCaps.dwFormats & WAVE_FORMAT_2M16)
|
||||||
|
|| (inCaps.dwFormats & WAVE_FORMAT_4M16)
|
||||||
|
|| (inCaps.dwFormats & WAVE_FORMAT_96M16) ) {
|
||||||
|
info.nativeFormats.push_back(audio::format_int16);
|
||||||
}
|
}
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_2M16) {
|
if ( (inCaps.dwFormats & WAVE_FORMAT_1M08)
|
||||||
info.nativeFormats |= RTAUDIO_SINT16;
|
|| (inCaps.dwFormats & WAVE_FORMAT_2M08)
|
||||||
|
|| (inCaps.dwFormats & WAVE_FORMAT_4M08)
|
||||||
|
|| (inCaps.dwFormats & WAVE_FORMAT_96M08) ) {
|
||||||
|
info.nativeFormats.push_back(audio::format_int8);
|
||||||
}
|
}
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_4M16) {
|
if ( (inCaps.dwFormats & WAVE_FORMAT_1M16)
|
||||||
info.nativeFormats |= RTAUDIO_SINT16;
|
|| (inCaps.dwFormats & WAVE_FORMAT_1M08) ){
|
||||||
|
rates.push_back(11025);
|
||||||
}
|
}
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_96M16) {
|
if ( (inCaps.dwFormats & WAVE_FORMAT_2M16)
|
||||||
info.nativeFormats |= RTAUDIO_SINT16;
|
|| (inCaps.dwFormats & WAVE_FORMAT_2M08) ){
|
||||||
|
rates.push_back(22050);
|
||||||
}
|
}
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_1M08) {
|
if ( (inCaps.dwFormats & WAVE_FORMAT_4M16)
|
||||||
info.nativeFormats |= RTAUDIO_SINT8;
|
|| (inCaps.dwFormats & WAVE_FORMAT_4M08) ){
|
||||||
|
rates.push_back(44100);
|
||||||
}
|
}
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_2M08) {
|
if ( (inCaps.dwFormats & WAVE_FORMAT_96M16)
|
||||||
info.nativeFormats |= RTAUDIO_SINT8;
|
|| (inCaps.dwFormats & WAVE_FORMAT_96M08) ){
|
||||||
}
|
rates.push_back(96000);
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_4M08) {
|
|
||||||
info.nativeFormats |= RTAUDIO_SINT8;
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_96M08) {
|
|
||||||
info.nativeFormats |= RTAUDIO_SINT8;
|
|
||||||
}
|
|
||||||
if (info.nativeFormats & RTAUDIO_SINT16) {
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_1M16) {
|
|
||||||
rates.push_back(11025);
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_2M16) {
|
|
||||||
rates.push_back(22050);
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_4M16) {
|
|
||||||
rates.push_back(44100);
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_96M16) {
|
|
||||||
rates.push_back(96000);
|
|
||||||
}
|
|
||||||
} else if (info.nativeFormats & RTAUDIO_SINT8) {
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_1M08) {
|
|
||||||
rates.push_back(11025);
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_2M08) {
|
|
||||||
rates.push_back(22050);
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_4M08) {
|
|
||||||
rates.push_back(44100);
|
|
||||||
}
|
|
||||||
if (inCaps.dwFormats & WAVE_FORMAT_96M08) {
|
|
||||||
rates.push_back(96000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// technically, this would be an error
|
// technically, this would be an error
|
||||||
@ -384,7 +337,7 @@ probeInput:
|
|||||||
}
|
}
|
||||||
if (found == false) info.sampleRates.push_back(rates[i]);
|
if (found == false) info.sampleRates.push_back(rates[i]);
|
||||||
}
|
}
|
||||||
etk::sort(info.sampleRates.begin(), info.sampleRates.end());
|
std::sort(info.sampleRates.begin(), info.sampleRates.end());
|
||||||
// If device opens for both playback and capture, we determine the channels.
|
// If device opens for both playback and capture, we determine the channels.
|
||||||
if (info.outputChannels > 0 && info.inputChannels > 0) {
|
if (info.outputChannels > 0 && info.inputChannels > 0) {
|
||||||
info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
|
info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
|
||||||
@ -393,24 +346,24 @@ probeInput:
|
|||||||
info.isDefaultInput = true;
|
info.isDefaultInput = true;
|
||||||
}
|
}
|
||||||
// Copy name and return.
|
// Copy name and return.
|
||||||
info.name = dsDevices[ _device ].name;
|
info.name = m_private->dsDevices[ _device ].name;
|
||||||
info.probed = true;
|
info.probed = true;
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
||||||
StreamMode _mode,
|
enum airtaudio::mode _mode,
|
||||||
uint32_t _channels,
|
uint32_t _channels,
|
||||||
uint32_t _firstChannel,
|
uint32_t _firstChannel,
|
||||||
uint32_t _sampleRate,
|
uint32_t _sampleRate,
|
||||||
rtaudio::format _format,
|
enum audio::format _format,
|
||||||
uint32_t *_bufferSize,
|
uint32_t *_bufferSize,
|
||||||
rtaudio::StreamOptions *_options) {
|
airtaudio::StreamOptions *_options) {
|
||||||
if (_channels + _firstChannel > 2) {
|
if (_channels + _firstChannel > 2) {
|
||||||
ATA_ERROR("DirectSound does not support more than 2 channels per device.");
|
ATA_ERROR("DirectSound does not support more than 2 channels per device.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint32_t nDevices = dsDevices.size();
|
uint32_t nDevices = m_private->dsDevices.size();
|
||||||
if (nDevices == 0) {
|
if (nDevices == 0) {
|
||||||
// This should not happen because a check is made before this function is called.
|
// This should not happen because a check is made before this function is called.
|
||||||
ATA_ERROR("no devices found!");
|
ATA_ERROR("no devices found!");
|
||||||
@ -422,12 +375,12 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (_mode == airtaudio::mode_output) {
|
if (_mode == airtaudio::mode_output) {
|
||||||
if (dsDevices[ _device ].validId[0] == false) {
|
if (m_private->dsDevices[ _device ].validId[0] == false) {
|
||||||
ATA_ERROR("device (" << _device << ") does not support output!");
|
ATA_ERROR("device (" << _device << ") does not support output!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else { // _mode == airtaudio::mode_input
|
} else { // _mode == airtaudio::mode_input
|
||||||
if (dsDevices[ _device ].validId[1] == false) {
|
if (m_private->dsDevices[ _device ].validId[1] == false) {
|
||||||
ATA_ERROR("device (" << _device << ") does not support input!");
|
ATA_ERROR("device (" << _device << ") does not support input!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -445,14 +398,15 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
// two. This is a judgement call and a value of two is probably too
|
// two. This is a judgement call and a value of two is probably too
|
||||||
// low for capture, but it should work for playback.
|
// low for capture, but it should work for playback.
|
||||||
int32_t nBuffers = 0;
|
int32_t nBuffers = 0;
|
||||||
|
/*
|
||||||
if (_options != nullptr) {
|
if (_options != nullptr) {
|
||||||
nBuffers = _options->numberOfBuffers;
|
nBuffers = _options->numberOfBuffers;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if ( _options!= nullptr
|
if ( _options!= nullptr
|
||||||
&& _options->flags.m_minimizeLatency == true) {
|
&& _options->flags.m_minimizeLatency == true) {
|
||||||
nBuffers = 2;
|
nBuffers = 2;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
if (nBuffers < 2) {
|
if (nBuffers < 2) {
|
||||||
nBuffers = 3;
|
nBuffers = 3;
|
||||||
}
|
}
|
||||||
@ -477,9 +431,9 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
HRESULT result;
|
HRESULT result;
|
||||||
if (_mode == airtaudio::mode_output) {
|
if (_mode == airtaudio::mode_output) {
|
||||||
LPDIRECTSOUND output;
|
LPDIRECTSOUND output;
|
||||||
result = DirectSoundCreate(dsDevices[ _device ].id[0], &output, nullptr);
|
result = DirectSoundCreate(m_private->dsDevices[ _device ].id[0], &output, nullptr);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") opening output device (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") opening output device (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DSCAPS outCaps;
|
DSCAPS outCaps;
|
||||||
@ -487,24 +441,24 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
result = output->GetCaps(&outCaps);
|
result = output->GetCaps(&outCaps);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
output->Release();
|
output->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") getting capabilities (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") getting capabilities (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Check channel information.
|
// Check channel information.
|
||||||
if (_channels + _firstChannel == 2 && !(outCaps.dwFlags & DSCAPS_PRIMARYSTEREO)) {
|
if (_channels + _firstChannel == 2 && !(outCaps.dwFlags & DSCAPS_PRIMARYSTEREO)) {
|
||||||
ATA_ERROR("the output device (" << dsDevices[ _device ].name << ") does not support stereo playback.");
|
ATA_ERROR("the output device (" << m_private->dsDevices[ _device ].name << ") does not support stereo playback.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Check format information. Use 16-bit format unless not
|
// Check format information. Use 16-bit format unless not
|
||||||
// supported or user requests 8-bit.
|
// supported or user requests 8-bit.
|
||||||
if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT
|
if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT
|
||||||
&& !( _format == RTAUDIO_SINT8
|
&& !( _format == audio::format_int8
|
||||||
&& outCaps.dwFlags & DSCAPS_PRIMARY8BIT)) {
|
&& outCaps.dwFlags & DSCAPS_PRIMARY8BIT)) {
|
||||||
waveFormat.wBitsPerSample = 16;
|
waveFormat.wBitsPerSample = 16;
|
||||||
m_deviceFormat[modeToIdTable(_mode)] = RTAUDIO_SINT16;
|
m_deviceFormat[modeToIdTable(_mode)] = audio::format_int16;
|
||||||
} else {
|
} else {
|
||||||
waveFormat.wBitsPerSample = 8;
|
waveFormat.wBitsPerSample = 8;
|
||||||
m_deviceFormat[modeToIdTable(_mode)] = RTAUDIO_SINT8;
|
m_deviceFormat[modeToIdTable(_mode)] = audio::format_int8;
|
||||||
}
|
}
|
||||||
m_userFormat = _format;
|
m_userFormat = _format;
|
||||||
// Update wave format structure and buffer information.
|
// Update wave format structure and buffer information.
|
||||||
@ -521,7 +475,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
result = output->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
|
result = output->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
output->Release();
|
output->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") setting cooperative level (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") setting cooperative level (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Even though we will write to the secondary buffer, we need to
|
// Even though we will write to the secondary buffer, we need to
|
||||||
@ -537,14 +491,14 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
result = output->CreateSoundBuffer(&bufferDescription, &buffer, nullptr);
|
result = output->CreateSoundBuffer(&bufferDescription, &buffer, nullptr);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
output->Release();
|
output->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") accessing primary buffer (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") accessing primary buffer (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Set the primary DS buffer sound format.
|
// Set the primary DS buffer sound format.
|
||||||
result = buffer->SetFormat(&waveFormat);
|
result = buffer->SetFormat(&waveFormat);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
output->Release();
|
output->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") setting primary buffer format (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") setting primary buffer format (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Setup the secondary DS buffer description.
|
// Setup the secondary DS buffer description.
|
||||||
@ -567,7 +521,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
result = output->CreateSoundBuffer(&bufferDescription, &buffer, nullptr);
|
result = output->CreateSoundBuffer(&bufferDescription, &buffer, nullptr);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
output->Release();
|
output->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") creating secondary buffer (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") creating secondary buffer (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -578,7 +532,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
output->Release();
|
output->Release();
|
||||||
buffer->Release();
|
buffer->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") getting buffer settings (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") getting buffer settings (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
dsBufferSize = dsbcaps.dwBufferBytes;
|
dsBufferSize = dsbcaps.dwBufferBytes;
|
||||||
@ -589,7 +543,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
output->Release();
|
output->Release();
|
||||||
buffer->Release();
|
buffer->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") locking buffer (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") locking buffer (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Zero the DS buffer
|
// Zero the DS buffer
|
||||||
@ -599,7 +553,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
output->Release();
|
output->Release();
|
||||||
buffer->Release();
|
buffer->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") unlocking buffer (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") unlocking buffer (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ohandle = (void *) output;
|
ohandle = (void *) output;
|
||||||
@ -607,9 +561,9 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
}
|
}
|
||||||
if (_mode == airtaudio::mode_input) {
|
if (_mode == airtaudio::mode_input) {
|
||||||
LPDIRECTSOUNDCAPTURE input;
|
LPDIRECTSOUNDCAPTURE input;
|
||||||
result = DirectSoundCaptureCreate(dsDevices[ _device ].id[1], &input, nullptr);
|
result = DirectSoundCaptureCreate(m_private->dsDevices[ _device ].id[1], &input, nullptr);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") opening input device (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") opening input device (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DSCCAPS inCaps;
|
DSCCAPS inCaps;
|
||||||
@ -617,7 +571,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
result = input->GetCaps(&inCaps);
|
result = input->GetCaps(&inCaps);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
input->Release();
|
input->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") getting input capabilities (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") getting input capabilities (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Check channel information.
|
// Check channel information.
|
||||||
@ -630,22 +584,22 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
DWORD deviceFormats;
|
DWORD deviceFormats;
|
||||||
if (_channels + _firstChannel == 2) {
|
if (_channels + _firstChannel == 2) {
|
||||||
deviceFormats = WAVE_FORMAT_1S08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_96S08;
|
deviceFormats = WAVE_FORMAT_1S08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_96S08;
|
||||||
if (format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats) {
|
if (_format == audio::format_int8 && inCaps.dwFormats & deviceFormats) {
|
||||||
waveFormat.wBitsPerSample = 8;
|
waveFormat.wBitsPerSample = 8;
|
||||||
m_deviceFormat[modeToIdTable(_mode)] = RTAUDIO_SINT8;
|
m_deviceFormat[modeToIdTable(_mode)] = audio::format_int8;
|
||||||
} else { // assume 16-bit is supported
|
} else { // assume 16-bit is supported
|
||||||
waveFormat.wBitsPerSample = 16;
|
waveFormat.wBitsPerSample = 16;
|
||||||
m_deviceFormat[modeToIdTable(_mode)] = RTAUDIO_SINT16;
|
m_deviceFormat[modeToIdTable(_mode)] = audio::format_int16;
|
||||||
}
|
}
|
||||||
} else { // channel == 1
|
} else { // channel == 1
|
||||||
deviceFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 | WAVE_FORMAT_4M08 | WAVE_FORMAT_96M08;
|
deviceFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_2M08 | WAVE_FORMAT_4M08 | WAVE_FORMAT_96M08;
|
||||||
if (format == RTAUDIO_SINT8 && inCaps.dwFormats & deviceFormats) {
|
if (_format == audio::format_int8 && inCaps.dwFormats & deviceFormats) {
|
||||||
waveFormat.wBitsPerSample = 8;
|
waveFormat.wBitsPerSample = 8;
|
||||||
m_deviceFormat[modeToIdTable(_mode)] = RTAUDIO_SINT8;
|
m_deviceFormat[modeToIdTable(_mode)] = audio::format_int8;
|
||||||
}
|
}
|
||||||
else { // assume 16-bit is supported
|
else { // assume 16-bit is supported
|
||||||
waveFormat.wBitsPerSample = 16;
|
waveFormat.wBitsPerSample = 16;
|
||||||
m_deviceFormat[modeToIdTable(_mode)] = RTAUDIO_SINT16;
|
m_deviceFormat[modeToIdTable(_mode)] = audio::format_int16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_userFormat = _format;
|
m_userFormat = _format;
|
||||||
@ -670,7 +624,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
result = input->CreateCaptureBuffer(&bufferDescription, &buffer, nullptr);
|
result = input->CreateCaptureBuffer(&bufferDescription, &buffer, nullptr);
|
||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
input->Release();
|
input->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") creating input buffer (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") creating input buffer (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Get the buffer size ... might be different from what we specified.
|
// Get the buffer size ... might be different from what we specified.
|
||||||
@ -680,7 +634,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
input->Release();
|
input->Release();
|
||||||
buffer->Release();
|
buffer->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") getting buffer settings (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") getting buffer settings (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
dsBufferSize = dscbcaps.dwBufferBytes;
|
dsBufferSize = dscbcaps.dwBufferBytes;
|
||||||
@ -695,7 +649,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
input->Release();
|
input->Release();
|
||||||
buffer->Release();
|
buffer->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") locking input buffer (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") locking input buffer (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Zero the buffer
|
// Zero the buffer
|
||||||
@ -705,14 +659,13 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
if (FAILED(result)) {
|
if (FAILED(result)) {
|
||||||
input->Release();
|
input->Release();
|
||||||
buffer->Release();
|
buffer->Release();
|
||||||
ATA_ERROR("error (" << getErrorString(result) << ") unlocking input buffer (" << dsDevices[ _device ].name << ")!");
|
ATA_ERROR("error (" << getErrorString(result) << ") unlocking input buffer (" << m_private->dsDevices[ _device ].name << ")!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ohandle = (void *) input;
|
ohandle = (void *) input;
|
||||||
bhandle = (void *) buffer;
|
bhandle = (void *) buffer;
|
||||||
}
|
}
|
||||||
// Set various stream parameters
|
// Set various stream parameters
|
||||||
DsHandle *handle = 0;
|
|
||||||
m_nDeviceChannels[modeToIdTable(_mode)] = _channels + _firstChannel;
|
m_nDeviceChannels[modeToIdTable(_mode)] = _channels + _firstChannel;
|
||||||
m_nUserChannels[modeToIdTable(_mode)] = _channels;
|
m_nUserChannels[modeToIdTable(_mode)] = _channels;
|
||||||
m_bufferSize = *_bufferSize;
|
m_bufferSize = *_bufferSize;
|
||||||
@ -732,8 +685,8 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
}
|
}
|
||||||
// Allocate necessary internal buffers
|
// Allocate necessary internal buffers
|
||||||
long bufferBytes = m_nUserChannels[modeToIdTable(_mode)] * *_bufferSize * audio::getFormatBytes(m_userFormat);
|
long bufferBytes = m_nUserChannels[modeToIdTable(_mode)] * *_bufferSize * audio::getFormatBytes(m_userFormat);
|
||||||
m_userBuffer[modeToIdTable(_mode)] = (char *) calloc(bufferBytes, 1);
|
m_userBuffer[modeToIdTable(_mode)].resize(bufferBytes, 0);
|
||||||
if (m_userBuffer[modeToIdTable(_mode)] == nullptr) {
|
if (m_userBuffer[modeToIdTable(_mode)].size() == 0) {
|
||||||
ATA_ERROR("error allocating user buffer memory.");
|
ATA_ERROR("error allocating user buffer memory.");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -786,16 +739,9 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
|
|||||||
}
|
}
|
||||||
// Setup the callback thread.
|
// Setup the callback thread.
|
||||||
if (m_callbackInfo.isRunning == false) {
|
if (m_callbackInfo.isRunning == false) {
|
||||||
unsigned threadId;
|
|
||||||
m_callbackInfo.isRunning = true;
|
m_callbackInfo.isRunning = true;
|
||||||
m_callbackInfo.object = (void *) this;
|
m_callbackInfo.thread = new std::thread(&airtaudio::api::Ds::dsCallbackEvent, this);
|
||||||
m_callbackInfo.thread = _beginthreadex(nullptr,
|
if (m_callbackInfo.thread == nullptr) {
|
||||||
0,
|
|
||||||
&callbackHandler,
|
|
||||||
&m_callbackInfo,
|
|
||||||
0,
|
|
||||||
&threadId);
|
|
||||||
if (m_callbackInfo.thread == 0) {
|
|
||||||
ATA_ERROR("error creating callback thread!");
|
ATA_ERROR("error creating callback thread!");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -821,11 +767,8 @@ error:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CloseHandle(m_private->condition);
|
CloseHandle(m_private->condition);
|
||||||
for (int32_t i=0; i<2; i++) {
|
for (size_t iii=0; iii<2; ++iii) {
|
||||||
if (m_userBuffer[i]) {
|
m_userBuffer[iii].clear();
|
||||||
free(m_userBuffer[i]);
|
|
||||||
m_userBuffer[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (m_deviceBuffer) {
|
if (m_deviceBuffer) {
|
||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
@ -863,11 +806,8 @@ enum airtaudio::error airtaudio::api::Ds::closeStream() {
|
|||||||
object->Release();
|
object->Release();
|
||||||
}
|
}
|
||||||
CloseHandle(m_private->condition);
|
CloseHandle(m_private->condition);
|
||||||
for (int32_t i=0; i<2; i++) {
|
for (size_t iii=0; iii<2; ++iii) {
|
||||||
if (m_userBuffer[i]) {
|
m_userBuffer[iii].clear();
|
||||||
free(m_userBuffer[i]);
|
|
||||||
m_userBuffer[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (m_deviceBuffer) {
|
if (m_deviceBuffer) {
|
||||||
free(m_deviceBuffer);
|
free(m_deviceBuffer);
|
||||||
@ -1043,19 +983,19 @@ void airtaudio::api::Ds::callbackEvent() {
|
|||||||
// draining stream.
|
// draining stream.
|
||||||
if (m_private->drainCounter == 0) {
|
if (m_private->drainCounter == 0) {
|
||||||
std::chrono::system_clock::time_point streamTime = getStreamTime();
|
std::chrono::system_clock::time_point streamTime = getStreamTime();
|
||||||
rtaudio::streamStatus status = 0;
|
airtaudio::status status = airtaudio::status_ok;
|
||||||
if ( m_mode != airtaudio::mode_input
|
if ( m_mode != airtaudio::mode_input
|
||||||
&& m_private->xrun[0] == true) {
|
&& m_private->xrun[0] == true) {
|
||||||
status |= RTAUDIO_airtaudio::status_underflow;
|
status = airtaudio::status_underflow;
|
||||||
m_private->xrun[0] = false;
|
m_private->xrun[0] = false;
|
||||||
}
|
}
|
||||||
if ( m_mode != airtaudio::mode_output
|
if ( m_mode != airtaudio::mode_output
|
||||||
&& m_private->xrun[1] == true) {
|
&& m_private->xrun[1] == true) {
|
||||||
status |= RTAUDIO_airtaudio::mode_input_OVERFLOW;
|
status = airtaudio::status_overflow;
|
||||||
m_private->xrun[1] = false;
|
m_private->xrun[1] = false;
|
||||||
}
|
}
|
||||||
int32_t cbReturnValue = info->callback(m_userBuffer[0],
|
int32_t cbReturnValue = info->callback(&m_userBuffer[0][0],
|
||||||
m_userBuffer[1],
|
&m_userBuffer[1][0],
|
||||||
m_bufferSize,
|
m_bufferSize,
|
||||||
streamTime,
|
streamTime,
|
||||||
status);
|
status);
|
||||||
@ -1151,16 +1091,16 @@ void airtaudio::api::Ds::callbackEvent() {
|
|||||||
if (m_private->drainCounter > 1) { // write zeros to the output stream
|
if (m_private->drainCounter > 1) { // write zeros to the output stream
|
||||||
bufferBytes = m_bufferSize * m_nUserChannels[0];
|
bufferBytes = m_bufferSize * m_nUserChannels[0];
|
||||||
bufferBytes *= audio::getFormatBytes(m_userFormat);
|
bufferBytes *= audio::getFormatBytes(m_userFormat);
|
||||||
memset(m_userBuffer[0], 0, bufferBytes);
|
memset(&m_userBuffer[0][0], 0, bufferBytes);
|
||||||
}
|
}
|
||||||
// Setup parameters and do buffer conversion if necessary.
|
// Setup parameters and do buffer conversion if necessary.
|
||||||
if (m_doConvertBuffer[0]) {
|
if (m_doConvertBuffer[0]) {
|
||||||
buffer = m_deviceBuffer;
|
buffer = m_deviceBuffer;
|
||||||
convertBuffer(buffer, m_userBuffer[0], m_convertInfo[0]);
|
convertBuffer(buffer, &m_userBuffer[0][0], m_convertInfo[0]);
|
||||||
bufferBytes = m_bufferSize * m_nDeviceChannels[0];
|
bufferBytes = m_bufferSize * m_nDeviceChannels[0];
|
||||||
bufferBytes *= audio::getFormatBytes(m_deviceFormat[0]);
|
bufferBytes *= audio::getFormatBytes(m_deviceFormat[0]);
|
||||||
} else {
|
} else {
|
||||||
buffer = m_userBuffer[0];
|
buffer = &m_userBuffer[0][0];
|
||||||
bufferBytes = m_bufferSize * m_nUserChannels[0];
|
bufferBytes = m_bufferSize * m_nUserChannels[0];
|
||||||
bufferBytes *= audio::getFormatBytes(m_userFormat);
|
bufferBytes *= audio::getFormatBytes(m_userFormat);
|
||||||
}
|
}
|
||||||
@ -1168,9 +1108,9 @@ void airtaudio::api::Ds::callbackEvent() {
|
|||||||
// Ahhh ... windoze. 16-bit data is signed but 8-bit data is
|
// Ahhh ... windoze. 16-bit data is signed but 8-bit data is
|
||||||
// unsigned. So, we need to convert our signed 8-bit data here to
|
// unsigned. So, we need to convert our signed 8-bit data here to
|
||||||
// unsigned.
|
// unsigned.
|
||||||
if (m_deviceFormat[0] == RTAUDIO_SINT8) {
|
if (m_deviceFormat[0] == audio::format_int8) {
|
||||||
for (int32_t i=0; i<bufferBytes; i++) {
|
for (size_t iii=0; iii<bufferBytes; ++iii) {
|
||||||
buffer[i] = (unsigned char) (buffer[i] + 128);
|
buffer[iii] = buffer[iii] + 128;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DWORD dsBufferSize = m_private->dsBufferSize[0];
|
DWORD dsBufferSize = m_private->dsBufferSize[0];
|
||||||
@ -1258,7 +1198,7 @@ void airtaudio::api::Ds::callbackEvent() {
|
|||||||
bufferBytes = m_bufferSize * m_nDeviceChannels[1];
|
bufferBytes = m_bufferSize * m_nDeviceChannels[1];
|
||||||
bufferBytes *= audio::getFormatBytes(m_deviceFormat[1]);
|
bufferBytes *= audio::getFormatBytes(m_deviceFormat[1]);
|
||||||
} else {
|
} else {
|
||||||
buffer = m_userBuffer[1];
|
buffer = &m_userBuffer[1][0];
|
||||||
bufferBytes = m_bufferSize * m_nUserChannels[1];
|
bufferBytes = m_bufferSize * m_nUserChannels[1];
|
||||||
bufferBytes *= audio::getFormatBytes(m_userFormat);
|
bufferBytes *= audio::getFormatBytes(m_userFormat);
|
||||||
}
|
}
|
||||||
@ -1372,31 +1312,25 @@ void airtaudio::api::Ds::callbackEvent() {
|
|||||||
m_private->bufferPointer[1] = nextReadPointer;
|
m_private->bufferPointer[1] = nextReadPointer;
|
||||||
// No byte swapping necessary in DirectSound implementation.
|
// No byte swapping necessary in DirectSound implementation.
|
||||||
// If necessary, convert 8-bit data from unsigned to signed.
|
// If necessary, convert 8-bit data from unsigned to signed.
|
||||||
if (m_deviceFormat[1] == RTAUDIO_SINT8) {
|
if (m_deviceFormat[1] == audio::format_int8) {
|
||||||
for (int32_t j=0; j<bufferBytes; j++) {
|
for (size_t jjj=0; jjj<bufferBytes; ++jjj) {
|
||||||
buffer[j] = (signed char) (buffer[j] - 128);
|
buffer[jjj] = (signed char) (buffer[jjj] - 128);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Do buffer conversion if necessary.
|
// Do buffer conversion if necessary.
|
||||||
if (m_doConvertBuffer[1]) {
|
if (m_doConvertBuffer[1]) {
|
||||||
convertBuffer(m_userBuffer[1], m_deviceBuffer, m_convertInfo[1]);
|
convertBuffer(&m_userBuffer[1][0], m_deviceBuffer, m_convertInfo[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unlock:
|
unlock:
|
||||||
airtaudio::Api::tickStreamTime();
|
airtaudio::Api::tickStreamTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Definitions for utility functions and callbacks
|
void airtaudio::api::Ds::dsCallbackEvent(void *_userData) {
|
||||||
// specific to the DirectSound implementation.
|
airtaudio::api::Ds* myClass = reinterpret_cast<airtaudio::api::Ds*>(_userData);
|
||||||
static unsigned __stdcall callbackHandler(void *_ptr) {
|
while (myClass->m_callbackInfo.isRunning == true) {
|
||||||
CallbackInfo* info = (CallbackInfo*)_ptr;
|
myClass->callbackEvent();
|
||||||
RtApiDs* object = (RtApiDs*)info->object;
|
|
||||||
bool* isRunning = &info->isRunning;
|
|
||||||
while (*isRunning == true) {
|
|
||||||
object->callbackEvent();
|
|
||||||
}
|
}
|
||||||
_endthreadex(0);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "tchar.h"
|
#include "tchar.h"
|
||||||
@ -1416,7 +1350,7 @@ static BOOL CALLBACK deviceQueryCallback(LPGUID _lpguid,
|
|||||||
LPCTSTR _module,
|
LPCTSTR _module,
|
||||||
LPVOID _lpContext) {
|
LPVOID _lpContext) {
|
||||||
struct DsProbeData& probeInfo = *(struct DsProbeData*) _lpContext;
|
struct DsProbeData& probeInfo = *(struct DsProbeData*) _lpContext;
|
||||||
std::vector<struct DsDevice>& dsDevices = *probeInfo.dsDevices;
|
std::vector<DsDevice>& dsDevices = *probeInfo.dsDevices;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
bool validDevice = false;
|
bool validDevice = false;
|
||||||
if (probeInfo.isInput == true) {
|
if (probeInfo.isInput == true) {
|
||||||
@ -1458,7 +1392,7 @@ static BOOL CALLBACK deviceQueryCallback(LPGUID _lpguid,
|
|||||||
name = "Default Device";
|
name = "Default Device";
|
||||||
}
|
}
|
||||||
if (validDevice) {
|
if (validDevice) {
|
||||||
for (uint32_t i=0; i<dsDevices.size(); i++) {
|
for (size_t i=0; i<dsDevices.size(); i++) {
|
||||||
if (dsDevices[i].name == name) {
|
if (dsDevices[i].name == name) {
|
||||||
dsDevices[i].found = true;
|
dsDevices[i].found = true;
|
||||||
if (probeInfo.isInput) {
|
if (probeInfo.isInput) {
|
||||||
|
@ -35,17 +35,17 @@ namespace airtaudio {
|
|||||||
// will most likely produce highly undesireable results!
|
// will most likely produce highly undesireable results!
|
||||||
void callbackEvent();
|
void callbackEvent();
|
||||||
private:
|
private:
|
||||||
|
static void dsCallbackEvent(void *_userData);
|
||||||
std::unique_ptr<DsPrivate> m_private;
|
std::unique_ptr<DsPrivate> m_private;
|
||||||
bool m_coInitialized;
|
bool m_coInitialized;
|
||||||
bool m_buffersRolling;
|
bool m_buffersRolling;
|
||||||
long m_duplexPrerollBytes;
|
long m_duplexPrerollBytes;
|
||||||
std::vector<struct DsDevice> dsDevices;
|
|
||||||
bool probeDeviceOpen(uint32_t _device,
|
bool probeDeviceOpen(uint32_t _device,
|
||||||
airtaudio::mode _mode,
|
enum airtaudio::mode _mode,
|
||||||
uint32_t _channels,
|
uint32_t _channels,
|
||||||
uint32_t _firstChannel,
|
uint32_t _firstChannel,
|
||||||
uint32_t _sampleRate,
|
uint32_t _sampleRate,
|
||||||
audio::format _format,
|
enum audio::format _format,
|
||||||
uint32_t *_bufferSize,
|
uint32_t *_bufferSize,
|
||||||
airtaudio::StreamOptions *_options);
|
airtaudio::StreamOptions *_options);
|
||||||
};
|
};
|
||||||
|
@ -24,19 +24,19 @@ def create(target):
|
|||||||
'airtaudio/api/Dummy.cpp'
|
'airtaudio/api/Dummy.cpp'
|
||||||
])
|
])
|
||||||
myModule.add_module_depend(['audio', 'etk'])
|
myModule.add_module_depend(['audio', 'etk'])
|
||||||
|
# add all the time the dummy interface
|
||||||
myModule.add_export_flag_CC(['-D__DUMMY__'])
|
myModule.add_export_flag_CC(['-D__DUMMY__'])
|
||||||
|
# TODO : Add a FILE interface:
|
||||||
|
|
||||||
if target.name=="Windows":
|
if target.name=="Windows":
|
||||||
myModule.add_src_file([
|
myModule.add_src_file([
|
||||||
'airtaudio/api/Asio.cpp',
|
'airtaudio/api/Asio.cpp',
|
||||||
'airtaudio/api/Ds.cpp',
|
'airtaudio/api/Ds.cpp',
|
||||||
])
|
])
|
||||||
# ASIO API on Windows
|
# load optionnal API:
|
||||||
myModule.add_export_flag_CC(['__WINDOWS_ASIO__'])
|
myModule.add_optionnal_module_depend('asio', "__WINDOWS_ASIO__")
|
||||||
# Windows DirectSound API
|
myModule.add_optionnal_module_depend('ds', "__WINDOWS_DS__")
|
||||||
#myModule.add_export_flag_CC(['__WINDOWS_DS__'])
|
myModule.add_optionnal_module_depend('wasapi', "__WINDOWS_WASAPI__")
|
||||||
myModule.add_module_depend(['etk'])
|
|
||||||
elif target.name=="Linux":
|
elif target.name=="Linux":
|
||||||
myModule.add_src_file([
|
myModule.add_src_file([
|
||||||
'airtaudio/api/Alsa.cpp',
|
'airtaudio/api/Alsa.cpp',
|
||||||
@ -66,7 +66,7 @@ def create(target):
|
|||||||
#myModule.add_export_flag_LD("-framework AudioToolbox")
|
#myModule.add_export_flag_LD("-framework AudioToolbox")
|
||||||
elif target.name=="Android":
|
elif target.name=="Android":
|
||||||
myModule.add_src_file('airtaudio/api/Android.cpp')
|
myModule.add_src_file('airtaudio/api/Android.cpp')
|
||||||
# MacOsX core
|
# specidic java interface for android:
|
||||||
myModule.add_optionnal_module_depend('ewolAndroidAudio', "__ANDROID_JAVA__")
|
myModule.add_optionnal_module_depend('ewolAndroidAudio', "__ANDROID_JAVA__")
|
||||||
#myModule.add_export_flag_CC(['-D__ANDROID_JAVA__'])
|
#myModule.add_export_flag_CC(['-D__ANDROID_JAVA__'])
|
||||||
#myModule.add_module_depend(['ewol'])
|
#myModule.add_module_depend(['ewol'])
|
||||||
@ -75,16 +75,7 @@ def create(target):
|
|||||||
|
|
||||||
myModule.add_export_path(tools.get_current_path(__file__))
|
myModule.add_export_path(tools.get_current_path(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# add the currrent module at the
|
# add the currrent module at the
|
||||||
return myModule
|
return myModule
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user