[DEV] set windows ds interface work (in theory) build is ok

This commit is contained in:
Edouard DUPIN 2015-02-12 21:02:51 +01:00
parent 1a24bb9254
commit 4fc9a3e05f
3 changed files with 160 additions and 235 deletions

View File

@ -56,6 +56,19 @@ static inline DWORD dsPointerBetween(DWORD _pointer, DWORD _laterPointer, DWORD
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 api {
@ -70,7 +83,7 @@ namespace airtaudio {
DWORD dsBufferSize[2];
DWORD dsPointerLeadTime[2]; // the number of bytes ahead of the safe pointer to lead by.
HANDLE condition;
std::vector<DsDevice> dsDevices;
DsPrivate() :
drainCounter(0),
internalDrain(false) {
@ -96,23 +109,9 @@ static BOOL CALLBACK deviceQueryCallback(LPGUID _lpguid,
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 {
bool isInput;
std::vector<struct DsDevice>* dsDevices;
std::vector<DsDevice>* dsDevices;
};
airtaudio::api::Ds::Ds() :
@ -149,13 +148,13 @@ uint32_t airtaudio::api::Ds::getDefaultInputDevice() {
uint32_t airtaudio::api::Ds::getDeviceCount() {
// Set query flag for previously found devices to false, so that we
// can check for any devices that have disappeared.
for (uint32_t i=0; i<dsDevices.size(); i++) {
dsDevices[i].found = false;
for (size_t iii=0; iii<m_private->dsDevices.size(); ++iii) {
m_private->dsDevices[iii].found = false;
}
// Query DirectSound devices.
struct DsProbeData probeInfo;
probeInfo.isInput = false;
probeInfo.dsDevices = &dsDevices;
probeInfo.dsDevices = &m_private->dsDevices;
HRESULT result = DirectSoundEnumerate((LPDSENUMCALLBACK) deviceQueryCallback, &probeInfo);
if (FAILED(result)) {
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.
std::vector< int32_t > indices;
for (uint32_t i=0; i<dsDevices.size(); i++) {
if (dsDevices[i].found == false) {
for (uint32_t i=0; i<m_private->dsDevices.size(); i++) {
if (m_private->dsDevices[i].found == false) {
indices.push_back(i);
}
}
uint32_t nErased = 0;
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) {
rtaudio::DeviceInfo info;
airtaudio::DeviceInfo airtaudio::api::Ds::getDeviceInfo(uint32_t _device) {
airtaudio::DeviceInfo info;
info.probed = false;
if (dsDevices.size() == 0) {
if (m_private->dsDevices.size() == 0) {
// Force a query of all devices
getDeviceCount();
if (dsDevices.size() == 0) {
if (m_private->dsDevices.size() == 0) {
ATA_ERROR("no devices found!");
return info;
}
}
if (_device >= dsDevices.size()) {
if (_device >= m_private->dsDevices.size()) {
ATA_ERROR("device ID is invalid!");
return info;
}
HRESULT result;
if (dsDevices[ _device ].validId[0] == false) {
if (m_private->dsDevices[ _device ].validId[0] == false) {
goto probeInput;
}
LPDIRECTSOUND output;
DSCAPS outCaps;
result = DirectSoundCreate(dsDevices[ _device ].id[0], &output, nullptr);
result = DirectSoundCreate(m_private->dsDevices[ _device ].id[0], &output, nullptr);
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;
}
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;
// Get sample rate information.
info.sampleRates.clear();
for (uint32_t k=0; k<MAX_SAMPLE_RATES; k++) {
if ( SAMPLE_RATES[k] >= (uint32_t) outCaps.dwMinSecondarySampleRate
&& SAMPLE_RATES[k] <= (uint32_t) outCaps.dwMaxSecondarySampleRate) {
info.sampleRates.push_back(SAMPLE_RATES[k]);
for (auto &it : airtaudio::genericSampleRate()) {
if ( it >= outCaps.dwMinSecondarySampleRate
&& it <= outCaps.dwMaxSecondarySampleRate) {
info.sampleRates.push_back(it);
}
}
// Get format information.
@ -236,16 +235,16 @@ rtaudio::DeviceInfo airtaudio::api::Ds::getDeviceInfo(uint32_t _device) {
if (getDefaultOutputDevice() == _device) {
info.isDefaultOutput = true;
}
if (dsDevices[ _device ].validId[1] == false) {
info.name = dsDevices[ _device ].name;
if (m_private->dsDevices[ _device ].validId[1] == false) {
info.name = m_private->dsDevices[ _device ].name;
info.probed = true;
return info;
}
probeInput:
LPDIRECTSOUNDCAPTURE input;
result = DirectSoundCaptureCreate(dsDevices[ _device ].id[1], &input, nullptr);
result = DirectSoundCaptureCreate(m_private->dsDevices[ _device ].id[1], &input, nullptr);
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;
}
DSCCAPS inCaps;
@ -253,7 +252,7 @@ probeInput:
result = input->GetCaps(&inCaps);
if (FAILED(result)) {
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;
}
// Get input channel information.
@ -261,108 +260,62 @@ probeInput:
// Get sample rate and format information.
std::vector<uint32_t> rates;
if (inCaps.dwChannels >= 2) {
if (inCaps.dwFormats & WAVE_FORMAT_1S16) {
info.nativeFormats |= RTAUDIO_SINT16;
if ( (inCaps.dwFormats & WAVE_FORMAT_1S16)
|| (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) {
info.nativeFormats |= RTAUDIO_SINT16;
if ( (inCaps.dwFormats & WAVE_FORMAT_1S08)
|| (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) {
info.nativeFormats |= RTAUDIO_SINT16;
if ( (inCaps.dwFormats & WAVE_FORMAT_1S16)
|| (inCaps.dwFormats & WAVE_FORMAT_1S08) ){
rates.push_back(11025);
}
if (inCaps.dwFormats & WAVE_FORMAT_96S16) {
info.nativeFormats |= RTAUDIO_SINT16;
if ( (inCaps.dwFormats & WAVE_FORMAT_2S16)
|| (inCaps.dwFormats & WAVE_FORMAT_2S08) ){
rates.push_back(22050);
}
if (inCaps.dwFormats & WAVE_FORMAT_1S08) {
info.nativeFormats |= RTAUDIO_SINT8;
if ( (inCaps.dwFormats & WAVE_FORMAT_4S16)
|| (inCaps.dwFormats & WAVE_FORMAT_4S08) ){
rates.push_back(44100);
}
if (inCaps.dwFormats & WAVE_FORMAT_2S08) {
info.nativeFormats |= RTAUDIO_SINT8;
}
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);
}
if ( (inCaps.dwFormats & WAVE_FORMAT_96S16)
|| (inCaps.dwFormats & WAVE_FORMAT_96S08) ){
rates.push_back(96000);
}
} else if (inCaps.dwChannels == 1) {
if (inCaps.dwFormats & WAVE_FORMAT_1M16) {
info.nativeFormats |= RTAUDIO_SINT16;
if ( (inCaps.dwFormats & WAVE_FORMAT_1M16)
|| (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) {
info.nativeFormats |= RTAUDIO_SINT16;
if ( (inCaps.dwFormats & WAVE_FORMAT_1M08)
|| (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) {
info.nativeFormats |= RTAUDIO_SINT16;
if ( (inCaps.dwFormats & WAVE_FORMAT_1M16)
|| (inCaps.dwFormats & WAVE_FORMAT_1M08) ){
rates.push_back(11025);
}
if (inCaps.dwFormats & WAVE_FORMAT_96M16) {
info.nativeFormats |= RTAUDIO_SINT16;
if ( (inCaps.dwFormats & WAVE_FORMAT_2M16)
|| (inCaps.dwFormats & WAVE_FORMAT_2M08) ){
rates.push_back(22050);
}
if (inCaps.dwFormats & WAVE_FORMAT_1M08) {
info.nativeFormats |= RTAUDIO_SINT8;
if ( (inCaps.dwFormats & WAVE_FORMAT_4M16)
|| (inCaps.dwFormats & WAVE_FORMAT_4M08) ){
rates.push_back(44100);
}
if (inCaps.dwFormats & WAVE_FORMAT_2M08) {
info.nativeFormats |= RTAUDIO_SINT8;
}
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);
}
if ( (inCaps.dwFormats & WAVE_FORMAT_96M16)
|| (inCaps.dwFormats & WAVE_FORMAT_96M08) ){
rates.push_back(96000);
}
} else {
// technically, this would be an error
@ -384,7 +337,7 @@ probeInput:
}
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 (info.outputChannels > 0 && info.inputChannels > 0) {
info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
@ -393,24 +346,24 @@ probeInput:
info.isDefaultInput = true;
}
// Copy name and return.
info.name = dsDevices[ _device ].name;
info.name = m_private->dsDevices[ _device ].name;
info.probed = true;
return info;
}
bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
StreamMode _mode,
enum airtaudio::mode _mode,
uint32_t _channels,
uint32_t _firstChannel,
uint32_t _sampleRate,
rtaudio::format _format,
enum audio::format _format,
uint32_t *_bufferSize,
rtaudio::StreamOptions *_options) {
airtaudio::StreamOptions *_options) {
if (_channels + _firstChannel > 2) {
ATA_ERROR("DirectSound does not support more than 2 channels per device.");
return false;
}
uint32_t nDevices = dsDevices.size();
uint32_t nDevices = m_private->dsDevices.size();
if (nDevices == 0) {
// This should not happen because a check is made before this function is called.
ATA_ERROR("no devices found!");
@ -422,12 +375,12 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
return false;
}
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!");
return false;
}
} 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!");
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
// low for capture, but it should work for playback.
int32_t nBuffers = 0;
/*
if (_options != nullptr) {
nBuffers = _options->numberOfBuffers;
}
*/
if ( _options!= nullptr
&& _options->flags.m_minimizeLatency == true) {
nBuffers = 2;
}
*/
if (nBuffers < 2) {
nBuffers = 3;
}
@ -477,9 +431,9 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
HRESULT result;
if (_mode == airtaudio::mode_output) {
LPDIRECTSOUND output;
result = DirectSoundCreate(dsDevices[ _device ].id[0], &output, nullptr);
result = DirectSoundCreate(m_private->dsDevices[ _device ].id[0], &output, nullptr);
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;
}
DSCAPS outCaps;
@ -487,24 +441,24 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
result = output->GetCaps(&outCaps);
if (FAILED(result)) {
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;
}
// Check channel information.
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;
}
// Check format information. Use 16-bit format unless not
// supported or user requests 8-bit.
if ( outCaps.dwFlags & DSCAPS_PRIMARY16BIT
&& !( _format == RTAUDIO_SINT8
&& !( _format == audio::format_int8
&& outCaps.dwFlags & DSCAPS_PRIMARY8BIT)) {
waveFormat.wBitsPerSample = 16;
m_deviceFormat[modeToIdTable(_mode)] = RTAUDIO_SINT16;
m_deviceFormat[modeToIdTable(_mode)] = audio::format_int16;
} else {
waveFormat.wBitsPerSample = 8;
m_deviceFormat[modeToIdTable(_mode)] = RTAUDIO_SINT8;
m_deviceFormat[modeToIdTable(_mode)] = audio::format_int8;
}
m_userFormat = _format;
// 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);
if (FAILED(result)) {
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;
}
// 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);
if (FAILED(result)) {
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;
}
// Set the primary DS buffer sound format.
result = buffer->SetFormat(&waveFormat);
if (FAILED(result)) {
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;
}
// Setup the secondary DS buffer description.
@ -567,7 +521,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
result = output->CreateSoundBuffer(&bufferDescription, &buffer, nullptr);
if (FAILED(result)) {
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;
}
}
@ -578,7 +532,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
if (FAILED(result)) {
output->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;
}
dsBufferSize = dsbcaps.dwBufferBytes;
@ -589,7 +543,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
if (FAILED(result)) {
output->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;
}
// Zero the DS buffer
@ -599,7 +553,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
if (FAILED(result)) {
output->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;
}
ohandle = (void *) output;
@ -607,9 +561,9 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
}
if (_mode == airtaudio::mode_input) {
LPDIRECTSOUNDCAPTURE input;
result = DirectSoundCaptureCreate(dsDevices[ _device ].id[1], &input, nullptr);
result = DirectSoundCaptureCreate(m_private->dsDevices[ _device ].id[1], &input, nullptr);
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;
}
DSCCAPS inCaps;
@ -617,7 +571,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
result = input->GetCaps(&inCaps);
if (FAILED(result)) {
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;
}
// Check channel information.
@ -630,22 +584,22 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
DWORD deviceFormats;
if (_channels + _firstChannel == 2) {
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;
m_deviceFormat[modeToIdTable(_mode)] = RTAUDIO_SINT8;
m_deviceFormat[modeToIdTable(_mode)] = audio::format_int8;
} else { // assume 16-bit is supported
waveFormat.wBitsPerSample = 16;
m_deviceFormat[modeToIdTable(_mode)] = RTAUDIO_SINT16;
m_deviceFormat[modeToIdTable(_mode)] = audio::format_int16;
}
} else { // channel == 1
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;
m_deviceFormat[modeToIdTable(_mode)] = RTAUDIO_SINT8;
m_deviceFormat[modeToIdTable(_mode)] = audio::format_int8;
}
else { // assume 16-bit is supported
waveFormat.wBitsPerSample = 16;
m_deviceFormat[modeToIdTable(_mode)] = RTAUDIO_SINT16;
m_deviceFormat[modeToIdTable(_mode)] = audio::format_int16;
}
}
m_userFormat = _format;
@ -670,7 +624,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
result = input->CreateCaptureBuffer(&bufferDescription, &buffer, nullptr);
if (FAILED(result)) {
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;
}
// 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)) {
input->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;
}
dsBufferSize = dscbcaps.dwBufferBytes;
@ -695,7 +649,7 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
if (FAILED(result)) {
input->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;
}
// Zero the buffer
@ -705,14 +659,13 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
if (FAILED(result)) {
input->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;
}
ohandle = (void *) input;
bhandle = (void *) buffer;
}
// Set various stream parameters
DsHandle *handle = 0;
m_nDeviceChannels[modeToIdTable(_mode)] = _channels + _firstChannel;
m_nUserChannels[modeToIdTable(_mode)] = _channels;
m_bufferSize = *_bufferSize;
@ -732,8 +685,8 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
}
// Allocate necessary internal buffers
long bufferBytes = m_nUserChannels[modeToIdTable(_mode)] * *_bufferSize * audio::getFormatBytes(m_userFormat);
m_userBuffer[modeToIdTable(_mode)] = (char *) calloc(bufferBytes, 1);
if (m_userBuffer[modeToIdTable(_mode)] == nullptr) {
m_userBuffer[modeToIdTable(_mode)].resize(bufferBytes, 0);
if (m_userBuffer[modeToIdTable(_mode)].size() == 0) {
ATA_ERROR("error allocating user buffer memory.");
goto error;
}
@ -786,16 +739,9 @@ bool airtaudio::api::Ds::probeDeviceOpen(uint32_t _device,
}
// Setup the callback thread.
if (m_callbackInfo.isRunning == false) {
unsigned threadId;
m_callbackInfo.isRunning = true;
m_callbackInfo.object = (void *) this;
m_callbackInfo.thread = _beginthreadex(nullptr,
0,
&callbackHandler,
&m_callbackInfo,
0,
&threadId);
if (m_callbackInfo.thread == 0) {
m_callbackInfo.thread = new std::thread(&airtaudio::api::Ds::dsCallbackEvent, this);
if (m_callbackInfo.thread == nullptr) {
ATA_ERROR("error creating callback thread!");
goto error;
}
@ -821,11 +767,8 @@ error:
}
}
CloseHandle(m_private->condition);
for (int32_t i=0; i<2; i++) {
if (m_userBuffer[i]) {
free(m_userBuffer[i]);
m_userBuffer[i] = 0;
}
for (size_t iii=0; iii<2; ++iii) {
m_userBuffer[iii].clear();
}
if (m_deviceBuffer) {
free(m_deviceBuffer);
@ -863,11 +806,8 @@ enum airtaudio::error airtaudio::api::Ds::closeStream() {
object->Release();
}
CloseHandle(m_private->condition);
for (int32_t i=0; i<2; i++) {
if (m_userBuffer[i]) {
free(m_userBuffer[i]);
m_userBuffer[i] = 0;
}
for (size_t iii=0; iii<2; ++iii) {
m_userBuffer[iii].clear();
}
if (m_deviceBuffer) {
free(m_deviceBuffer);
@ -1043,19 +983,19 @@ void airtaudio::api::Ds::callbackEvent() {
// draining stream.
if (m_private->drainCounter == 0) {
std::chrono::system_clock::time_point streamTime = getStreamTime();
rtaudio::streamStatus status = 0;
airtaudio::status status = airtaudio::status_ok;
if ( m_mode != airtaudio::mode_input
&& m_private->xrun[0] == true) {
status |= RTAUDIO_airtaudio::status_underflow;
status = airtaudio::status_underflow;
m_private->xrun[0] = false;
}
if ( m_mode != airtaudio::mode_output
&& m_private->xrun[1] == true) {
status |= RTAUDIO_airtaudio::mode_input_OVERFLOW;
status = airtaudio::status_overflow;
m_private->xrun[1] = false;
}
int32_t cbReturnValue = info->callback(m_userBuffer[0],
m_userBuffer[1],
int32_t cbReturnValue = info->callback(&m_userBuffer[0][0],
&m_userBuffer[1][0],
m_bufferSize,
streamTime,
status);
@ -1151,16 +1091,16 @@ void airtaudio::api::Ds::callbackEvent() {
if (m_private->drainCounter > 1) { // write zeros to the output stream
bufferBytes = m_bufferSize * m_nUserChannels[0];
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.
if (m_doConvertBuffer[0]) {
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 *= audio::getFormatBytes(m_deviceFormat[0]);
} else {
buffer = m_userBuffer[0];
buffer = &m_userBuffer[0][0];
bufferBytes = m_bufferSize * m_nUserChannels[0];
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
// unsigned. So, we need to convert our signed 8-bit data here to
// unsigned.
if (m_deviceFormat[0] == RTAUDIO_SINT8) {
for (int32_t i=0; i<bufferBytes; i++) {
buffer[i] = (unsigned char) (buffer[i] + 128);
if (m_deviceFormat[0] == audio::format_int8) {
for (size_t iii=0; iii<bufferBytes; ++iii) {
buffer[iii] = buffer[iii] + 128;
}
}
DWORD dsBufferSize = m_private->dsBufferSize[0];
@ -1258,7 +1198,7 @@ void airtaudio::api::Ds::callbackEvent() {
bufferBytes = m_bufferSize * m_nDeviceChannels[1];
bufferBytes *= audio::getFormatBytes(m_deviceFormat[1]);
} else {
buffer = m_userBuffer[1];
buffer = &m_userBuffer[1][0];
bufferBytes = m_bufferSize * m_nUserChannels[1];
bufferBytes *= audio::getFormatBytes(m_userFormat);
}
@ -1372,31 +1312,25 @@ void airtaudio::api::Ds::callbackEvent() {
m_private->bufferPointer[1] = nextReadPointer;
// No byte swapping necessary in DirectSound implementation.
// If necessary, convert 8-bit data from unsigned to signed.
if (m_deviceFormat[1] == RTAUDIO_SINT8) {
for (int32_t j=0; j<bufferBytes; j++) {
buffer[j] = (signed char) (buffer[j] - 128);
if (m_deviceFormat[1] == audio::format_int8) {
for (size_t jjj=0; jjj<bufferBytes; ++jjj) {
buffer[jjj] = (signed char) (buffer[jjj] - 128);
}
}
// Do buffer conversion if necessary.
if (m_doConvertBuffer[1]) {
convertBuffer(m_userBuffer[1], m_deviceBuffer, m_convertInfo[1]);
convertBuffer(&m_userBuffer[1][0], m_deviceBuffer, m_convertInfo[1]);
}
}
unlock:
airtaudio::Api::tickStreamTime();
}
// Definitions for utility functions and callbacks
// specific to the DirectSound implementation.
static unsigned __stdcall callbackHandler(void *_ptr) {
CallbackInfo* info = (CallbackInfo*)_ptr;
RtApiDs* object = (RtApiDs*)info->object;
bool* isRunning = &info->isRunning;
while (*isRunning == true) {
object->callbackEvent();
void airtaudio::api::Ds::dsCallbackEvent(void *_userData) {
airtaudio::api::Ds* myClass = reinterpret_cast<airtaudio::api::Ds*>(_userData);
while (myClass->m_callbackInfo.isRunning == true) {
myClass->callbackEvent();
}
_endthreadex(0);
return 0;
}
#include "tchar.h"
@ -1416,7 +1350,7 @@ static BOOL CALLBACK deviceQueryCallback(LPGUID _lpguid,
LPCTSTR _module,
LPVOID _lpContext) {
struct DsProbeData& probeInfo = *(struct DsProbeData*) _lpContext;
std::vector<struct DsDevice>& dsDevices = *probeInfo.dsDevices;
std::vector<DsDevice>& dsDevices = *probeInfo.dsDevices;
HRESULT hr;
bool validDevice = false;
if (probeInfo.isInput == true) {
@ -1458,7 +1392,7 @@ static BOOL CALLBACK deviceQueryCallback(LPGUID _lpguid,
name = "Default Device";
}
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) {
dsDevices[i].found = true;
if (probeInfo.isInput) {

View File

@ -35,17 +35,17 @@ namespace airtaudio {
// will most likely produce highly undesireable results!
void callbackEvent();
private:
static void dsCallbackEvent(void *_userData);
std::unique_ptr<DsPrivate> m_private;
bool m_coInitialized;
bool m_buffersRolling;
long m_duplexPrerollBytes;
std::vector<struct DsDevice> dsDevices;
bool probeDeviceOpen(uint32_t _device,
airtaudio::mode _mode,
enum airtaudio::mode _mode,
uint32_t _channels,
uint32_t _firstChannel,
uint32_t _sampleRate,
audio::format _format,
enum audio::format _format,
uint32_t *_bufferSize,
airtaudio::StreamOptions *_options);
};

View File

@ -24,19 +24,19 @@ def create(target):
'airtaudio/api/Dummy.cpp'
])
myModule.add_module_depend(['audio', 'etk'])
# add all the time the dummy interface
myModule.add_export_flag_CC(['-D__DUMMY__'])
# TODO : Add a FILE interface:
if target.name=="Windows":
myModule.add_src_file([
'airtaudio/api/Asio.cpp',
'airtaudio/api/Ds.cpp',
])
# ASIO API on Windows
myModule.add_export_flag_CC(['__WINDOWS_ASIO__'])
# Windows DirectSound API
#myModule.add_export_flag_CC(['__WINDOWS_DS__'])
myModule.add_module_depend(['etk'])
# load optionnal API:
myModule.add_optionnal_module_depend('asio', "__WINDOWS_ASIO__")
myModule.add_optionnal_module_depend('ds', "__WINDOWS_DS__")
myModule.add_optionnal_module_depend('wasapi', "__WINDOWS_WASAPI__")
elif target.name=="Linux":
myModule.add_src_file([
'airtaudio/api/Alsa.cpp',
@ -66,7 +66,7 @@ def create(target):
#myModule.add_export_flag_LD("-framework AudioToolbox")
elif target.name=="Android":
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_export_flag_CC(['-D__ANDROID_JAVA__'])
#myModule.add_module_depend(['ewol'])
@ -75,16 +75,7 @@ def create(target):
myModule.add_export_path(tools.get_current_path(__file__))
# add the currrent module at the
return myModule