bool AudioDevOSS::uninit() { QMutexLocker mutexLockeer(&this->m_mutex); this->m_deviceFile.close(); this->m_curCaps = AkAudioCaps(); return true; }
void AudioDeviceElement::resetCaps() { this->m_mutexLib.lock(); auto preferredFormat = this->m_audioDevice->preferredFormat(this->m_device); this->m_mutexLib.unlock(); auto audioCaps = this->m_device == DUMMY_OUTPUT_DEVICE? AkAudioCaps("audio/x-raw," "format=s16," "bps=2," "channels=2," "rate=44100," "layout=stereo," "align=false"): preferredFormat; this->setCaps(audioCaps.toCaps()); }
void AudioDeviceElement::setDevice(const QString &device) { if (this->m_device == device) return; this->m_device = device; emit this->deviceChanged(device); this->m_mutexLib.lock(); auto preferredFormat = this->m_audioDevice->preferredFormat(device); this->m_mutexLib.unlock(); AkAudioCaps audioCaps = device == DUMMY_OUTPUT_DEVICE? AkAudioCaps("audio/x-raw," "format=s16," "bps=2," "channels=2," "rate=44100," "layout=stereo," "align=false"): preferredFormat; this->setCaps(audioCaps.toCaps()); }
AkAudioCaps AudioDevOSS::deviceCaps(const QString &device, int *fragmentSize) const { QFile pcmFile(QString(device) .remove(QRegExp(":Input$|:Output$"))); if (!pcmFile.open(device.endsWith(":Input")? QIODevice::ReadOnly: QIODevice::WriteOnly)) return AkAudioCaps(); int formats = AFMT_QUERY; if (ioctl(pcmFile.handle(), SNDCTL_DSP_GETFMTS, &formats) < 0) goto deviceCaps_fail; static const QVector<int> preferredFormats = { AFMT_S16_NE, AFMT_S16_LE, AFMT_S16_BE, AFMT_U16_LE, AFMT_U16_BE, AFMT_S8, AFMT_U8 }; int format; format = AFMT_QUERY; for (const auto &fmt: preferredFormats) if (formats & fmt) { format = fmt; break; } if (format == AFMT_QUERY) goto deviceCaps_fail; if (ioctl(pcmFile.handle(), SNDCTL_DSP_SETFMT, &format) < 0) goto deviceCaps_fail; int stereo; stereo = 1; if (ioctl(pcmFile.handle(), SNDCTL_DSP_STEREO, &stereo) < 0) goto deviceCaps_fail; static const QVector<int> preferredSampleRates { 48000, 44100, 22050, 11025, 8000 }; int sampleRate; sampleRate = 0; for (int rate: preferredSampleRates) if (ioctl(pcmFile.handle(), SNDCTL_DSP_SPEED, &rate) >= 0){ sampleRate = rate; break; } if (sampleRate < 1) goto deviceCaps_fail; int channels; channels = stereo? 2: 1; AkAudioCaps::SampleFormat sampleFormat; sampleFormat = sampleFormats->key(format, AkAudioCaps::SampleFormat_none); if (fragmentSize && device.endsWith(":Output")) { // Set the buffer to a maximum of 1024 samples. int bufferSize; bufferSize = BUFFER_SIZE * channels * AkAudioCaps::bitsPerSample(sampleFormat) / 8; // Let's try setting the fragmet to just 2 pieces, and the half of the // buffer size, for low latency. int fragment; fragment = (2 << 16) | (bufferSize / 2); ioctl(pcmFile.handle(), SNDCTL_DSP_SETFRAGMENT, &fragment); // Let's see what OSS did actually set, audio_buf_info info; ioctl(pcmFile.handle(), SNDCTL_DSP_GETOSPACE, &info); *fragmentSize = info.fragsize > 0? ((bufferSize / info.fragsize) << 16) | info.fragsize: 0; } pcmFile.close(); { AkAudioCaps audioCaps; audioCaps.isValid() = true; audioCaps.format() = sampleFormat; audioCaps.bps() = AkAudioCaps::bitsPerSample(audioCaps.format()); audioCaps.channels() = channels; audioCaps.rate() = int(sampleRate); audioCaps.layout() = AkAudioCaps::defaultChannelLayout(audioCaps.channels()); audioCaps.align() = false; return audioCaps; } deviceCaps_fail: pcmFile.close(); return AkAudioCaps(); }