Support minimal dependency linux build.
This commit is contained in:
parent
92a35a5bc9
commit
7ce29ce8ae
14 changed files with 421 additions and 176 deletions
|
@ -3,17 +3,26 @@ set(platform_HEADERS "")
|
|||
set(platform_INCLUDES "")
|
||||
|
||||
if (UNIX)
|
||||
find_package(ALSA REQUIRED)
|
||||
list(APPEND platform_HEADERS
|
||||
audio_interfaces/AlsaInterface.h
|
||||
${ALSA_INCLUDE_DIRS}
|
||||
)
|
||||
list(APPEND platform_INCLUDES
|
||||
audio_interfaces/AlsaInterface.cpp
|
||||
)
|
||||
list(APPEND platform_LIBS
|
||||
${ALSA_LIBRARIES}
|
||||
)
|
||||
find_package(ALSA QUIET)
|
||||
if(ALSA_FOUND)
|
||||
list(APPEND platform_HEADERS
|
||||
audio_interfaces/AlsaInterface.h
|
||||
${ALSA_INCLUDE_DIRS})
|
||||
list(APPEND platform_INCLUDES
|
||||
audio_interfaces/AlsaInterface.cpp
|
||||
)
|
||||
list(APPEND platform_LIBS
|
||||
${ALSA_LIBRARIES}
|
||||
)
|
||||
else()
|
||||
message(STATUS "ALSA package not found - not building audio interface.")
|
||||
list(APPEND platform_HEADERS
|
||||
audio_interfaces/NullAudioInterface.h
|
||||
)
|
||||
list(APPEND platform_INCLUDES
|
||||
audio_interfaces/NullAudioInterface.cpp
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
list(APPEND platform_HEADERS
|
||||
audio_interfaces/WasapiInterface.h
|
||||
|
|
141
src/audio/audio_interfaces/NullAudioInterface.cpp
Normal file
141
src/audio/audio_interfaces/NullAudioInterface.cpp
Normal file
|
@ -0,0 +1,141 @@
|
|||
#include "AlsaInterface.h"
|
||||
#include "FileLogger.h"
|
||||
|
||||
#include "AudioSynth.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
AlsaInterface::AlsaInterface()
|
||||
:mHandle(),
|
||||
mHardwareParams(),
|
||||
mPeriodSize(8192)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AlsaInterface::~AlsaInterface()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<AlsaInterface> AlsaInterface::Create()
|
||||
{
|
||||
return std::make_unique<AlsaInterface>();
|
||||
}
|
||||
|
||||
void AlsaInterface::OpenDevice(const AudioDevicePtr& device)
|
||||
{
|
||||
MLOG_INFO("Opening Device");
|
||||
snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
|
||||
if (snd_pcm_open(&mHandle, device->GetName().c_str(), stream, 0) < 0)
|
||||
{
|
||||
MLOG_ERROR("Error opening PCM device: " + device->GetName());
|
||||
return;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_alloca(&mHardwareParams);
|
||||
if (snd_pcm_hw_params_any(mHandle, mHardwareParams) < 0)
|
||||
{
|
||||
MLOG_ERROR("Can not configure this PCM device.");
|
||||
return;
|
||||
}
|
||||
|
||||
SetAccessType(device);
|
||||
SetSampleFormat(device);
|
||||
SetSampleRate(device);
|
||||
SetPeriod(device);
|
||||
SetBufferSize(device);
|
||||
SetChannelNumber(device);
|
||||
|
||||
/* Apply HW parameter settings to */
|
||||
/* PCM device and prepare device */
|
||||
if (snd_pcm_hw_params(mHandle, mHardwareParams) < 0) {
|
||||
MLOG_ERROR("Error setting HW params.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AlsaInterface::SetAccessType(const AudioDevicePtr& device)
|
||||
{
|
||||
if (snd_pcm_hw_params_set_access(mHandle, mHardwareParams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
|
||||
MLOG_ERROR("Error setting device access.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AlsaInterface::SetSampleFormat(const AudioDevicePtr& device)
|
||||
{
|
||||
/* Set sample format */
|
||||
if (snd_pcm_hw_params_set_format(mHandle, mHardwareParams, SND_PCM_FORMAT_S16_LE) < 0) {
|
||||
MLOG_ERROR("Error setting format. ");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AlsaInterface::SetSampleRate(const AudioDevicePtr& device)
|
||||
{
|
||||
unsigned rate = device->GetSampleRate();
|
||||
unsigned exact_rate = rate;
|
||||
if (snd_pcm_hw_params_set_rate_near(mHandle, mHardwareParams, &exact_rate, 0) < 0)
|
||||
{
|
||||
MLOG_ERROR("Error setting rate. ");
|
||||
return;
|
||||
}
|
||||
if (rate != exact_rate) {
|
||||
MLOG_ERROR("The rate is not supported by your hardware.");
|
||||
}
|
||||
}
|
||||
|
||||
void AlsaInterface::SetPeriod(const AudioDevicePtr& device)
|
||||
{
|
||||
/* Set number of periods. Periods used to be called fragments. */
|
||||
if (snd_pcm_hw_params_set_periods(mHandle, mHardwareParams, device->GetPeriod(), 0) < 0)
|
||||
{
|
||||
MLOG_ERROR("Error setting periods. ");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AlsaInterface::SetBufferSize(const AudioDevicePtr& device)
|
||||
{
|
||||
int periods = static_cast<int>(device->GetPeriod());
|
||||
|
||||
/* Set buffer size (in frames). The resulting latency is given by */
|
||||
/* latency = periodsize * periods / (rate * bytes_per_frame) */
|
||||
if (snd_pcm_hw_params_set_buffer_size(mHandle, mHardwareParams, (mPeriodSize * periods)>>2) < 0)
|
||||
{
|
||||
MLOG_ERROR("Error setting buffersize. ");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AlsaInterface::SetChannelNumber(const AudioDevicePtr& device)
|
||||
{
|
||||
/* Set number of channels */
|
||||
if (snd_pcm_hw_params_set_channels(mHandle, mHardwareParams, device->GetNumChannels()) < 0)
|
||||
{
|
||||
MLOG_ERROR("Error setting channels");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AlsaInterface::Play(const AudioDevicePtr& device)
|
||||
{
|
||||
MLOG_INFO("Playing audio");
|
||||
AudioSynth synth;
|
||||
const unsigned duration = 100;
|
||||
double freq = 440;
|
||||
auto data = synth.GetSineWave(freq, duration)->GetChannelData(0);
|
||||
|
||||
int numFrames = mPeriodSize >> 2;
|
||||
for(int count = 0; count < duration; count++)
|
||||
{
|
||||
const auto offset= count*4*numFrames;
|
||||
unsigned char frame[4] = {data[offset], data[offset+1], data[offset+2], data[offset+3]};
|
||||
while ((snd_pcm_writei(mHandle, frame, numFrames)) < 0)
|
||||
{
|
||||
snd_pcm_prepare(mHandle);
|
||||
MLOG_ERROR("<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>");
|
||||
}
|
||||
}
|
||||
}
|
40
src/audio/audio_interfaces/NullAudioInterface.h
Normal file
40
src/audio/audio_interfaces/NullAudioInterface.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include "IAudioInterface.h"
|
||||
#include "AudioDevice.h"
|
||||
|
||||
#include <memory>
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
class AlsaInterface : public IAudioInterface
|
||||
{
|
||||
snd_pcm_t* mHandle;
|
||||
snd_pcm_hw_params_t* mHardwareParams;
|
||||
snd_pcm_uframes_t mPeriodSize;
|
||||
|
||||
public:
|
||||
|
||||
AlsaInterface();
|
||||
|
||||
~AlsaInterface();
|
||||
|
||||
static std::unique_ptr<AlsaInterface> Create();
|
||||
|
||||
void OpenDevice(const AudioDevicePtr& device) override;
|
||||
|
||||
void SetAccessType(const AudioDevicePtr& device);
|
||||
|
||||
void SetSampleFormat(const AudioDevicePtr& device);
|
||||
|
||||
void SetSampleRate(const AudioDevicePtr& device);
|
||||
|
||||
void SetPeriod(const AudioDevicePtr& device);
|
||||
|
||||
void SetBufferSize(const AudioDevicePtr& device);
|
||||
|
||||
void SetChannelNumber(const AudioDevicePtr& device);
|
||||
|
||||
void Play(const AudioDevicePtr& device) override;
|
||||
};
|
||||
|
||||
using AlsaInterfacePtr = std::shared_ptr<AlsaInterface>;
|
Loading…
Add table
Add a link
Reference in a new issue