diff --git a/airtaudio/api/Ds.cpp b/airtaudio/api/Ds.cpp index 7f6900d..ac6af72 100644 --- a/airtaudio/api/Ds.cpp +++ b/airtaudio/api/Ds.cpp @@ -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 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* dsDevices; + std::vector* 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; idsDevices.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; idsDevices.size(); i++) { + if (m_private->dsDevices[i].found == false) { indices.push_back(i); } } uint32_t nErased = 0; for (uint32_t i=0; idsDevices.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= (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 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; idsBufferSize[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; jobject; - bool* isRunning = &info->isRunning; - while (*isRunning == true) { - object->callbackEvent(); +void airtaudio::api::Ds::dsCallbackEvent(void *_userData) { + airtaudio::api::Ds* myClass = reinterpret_cast(_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& dsDevices = *probeInfo.dsDevices; + std::vector& 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 m_private; bool m_coInitialized; bool m_buffersRolling; long m_duplexPrerollBytes; - std::vector 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); }; diff --git a/lutin_airtaudio.py b/lutin_airtaudio.py index 1544c9a..ef2aea6 100644 --- a/lutin_airtaudio.py +++ b/lutin_airtaudio.py @@ -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 - - - - - - -