154 lines
4.1 KiB
C++
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;
|
|
}
|
|
}
|
|
}
|