/* ******************************************************************************* * INCLUDE ******************************************************************************* */ #include "Util.h" #include "Logger.h" #include namespace Video { namespace ALSA { /* ******************************************************************************* * CLASS DEFINE ******************************************************************************* */ uint32_t Util::getSuitableSampleRate(SoundCard::Ptr pCard, uint32_t target) { uint32_t suitable = target; if (!pCard->info().sampleRates.empty()) { for (auto sr : pCard->info().sampleRates) { if (sr % target == 0 || target % sr == 0) { suitable = sr; goto out; } } int minDiff = __INT32_MAX__; for (auto sr : pCard->info().sampleRates) { int diff = std::abs(static_cast(sr - target)); if (diff < minDiff || (diff == minDiff && sr > suitable)) { minDiff = diff; suitable = sr; } } } out: return suitable; } snd_pcm_format_t Util::getSuitableSampleFormat(SoundCard::Ptr pCard, Core::SampleFormat refer) { auto target = convertSampleFormat(refer); if (pCard->info().formats.empty()) return SND_PCM_FORMAT_S16_LE; for (auto& fmt : pCard->info().formats) { if (fmt == (int)target) return target; } target = *(pCard->info().formats.begin()); return target; } snd_pcm_access_t Util::getSuitableAccess(SoundCard::Ptr pCard, bool planar) { if (planar && (pCard->info().access[SND_PCM_ACCESS_RW_NONINTERLEAVED])) return SND_PCM_ACCESS_RW_NONINTERLEAVED; return SND_PCM_ACCESS_RW_INTERLEAVED; } snd_pcm_format_t Util::convertSampleFormat(Core::SampleFormat format) { switch (sampleFormatGetPlanarFormat(format)) { case Core::SampleFormat::U8P: return SND_PCM_FORMAT_U8; case Core::SampleFormat::S16P: return SND_PCM_FORMAT_S16_LE; case Core::SampleFormat::S32P: return SND_PCM_FORMAT_S32_LE; case Core::SampleFormat::FLTP: return SND_PCM_FORMAT_FLOAT_LE; case Core::SampleFormat::DBLP: return SND_PCM_FORMAT_FLOAT64_LE; default: return SND_PCM_FORMAT_S16_LE; } } Core::SampleFormat Util::convertSampleFormat(snd_pcm_format_t format, bool interleaved) { Core::SampleFormat result; switch (format) { case SND_PCM_FORMAT_U8: result = Core::SampleFormat::U8P; break; case SND_PCM_FORMAT_S8: result = Core::SampleFormat::U8P; break; case SND_PCM_FORMAT_S16_LE: result = Core::SampleFormat::S16P; break; case SND_PCM_FORMAT_S16_BE: result = Core::SampleFormat::S16P; break; case SND_PCM_FORMAT_S32_LE: result = Core::SampleFormat::S32P; break; case SND_PCM_FORMAT_S32_BE: result = Core::SampleFormat::S32P; break; case SND_PCM_FORMAT_FLOAT_LE: result = Core::SampleFormat::FLTP; break; case SND_PCM_FORMAT_FLOAT_BE: result = Core::SampleFormat::FLTP; break; case SND_PCM_FORMAT_FLOAT64_LE: result = Core::SampleFormat::DBLP; break; case SND_PCM_FORMAT_FLOAT64_BE: result = Core::SampleFormat::DBLP; break; case SND_PCM_FORMAT_SPECIAL: case SND_PCM_FORMAT_S24_3LE: case SND_PCM_FORMAT_S24_3BE: case SND_PCM_FORMAT_U24_3LE: case SND_PCM_FORMAT_U24_3BE: case SND_PCM_FORMAT_S20_3LE: case SND_PCM_FORMAT_S20_3BE: case SND_PCM_FORMAT_U20_3LE: case SND_PCM_FORMAT_U20_3BE: case SND_PCM_FORMAT_S18_3LE: case SND_PCM_FORMAT_S18_3BE: case SND_PCM_FORMAT_U18_3LE: default: logger().warning(": Unsupported format: %s", std::string(snd_pcm_format_name(format))); result = Core::SampleFormat::S32P; break; } if (interleaved) result = Core::sampleFormatGetPackedFormat(result); return result; } } }