p26001-store-acs-soc-fw-app/video/alsa/Util.cpp
2026-09-28 21:33:04 +08:00

154 lines
4.1 KiB
C++

/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "Util.h"
#include "Logger.h"
#include <cstdint>
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<int>(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;
}
}
}