Skip to content

Commit

Permalink
define custom driver priority order
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastian-heinz committed Apr 21, 2021
1 parent ec3e47a commit 85b3e79
Show file tree
Hide file tree
Showing 11 changed files with 168 additions and 52 deletions.
15 changes: 8 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(LOWL_PA_DEFAULT_DRIVER_PRIORITY "ASIO,WASAPI,WMME,DSOUND,WDMKS,ALSA,OSS,JACK,ASIHPI,COREAUDIO")

set(LOWL_SOURCES
src/lowl.cpp
src/lowl_audio_source.cpp
Expand Down Expand Up @@ -39,17 +41,16 @@ set(LOWL_SOURCES
add_library(${PROJECT_NAME} ${LOWL_SOURCES})
set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
target_include_directories(${PROJECT_NAME} PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>" "$<INSTALL_INTERFACE:include>")

add_definitions(-DLOWL_DRIVER_DUMMY)
add_definitions(-DLOWL_DRIVER_PORTAUDIO)
add_definitions(-DLOWL_PROFILING)
target_compile_definitions(${PROJECT_NAME} PRIVATE LOWL_DRIVER_DUMMY)
target_compile_definitions(${PROJECT_NAME} PRIVATE LOWL_DRIVER_PORTAUDIO)
target_compile_definitions(${PROJECT_NAME} PRIVATE LOWL_PROFILING)
target_compile_definitions(${PROJECT_NAME} PRIVATE "LOWL_PA_DEFAULT_DRIVER_PRIORITY=\"${LOWL_PA_DEFAULT_DRIVER_PRIORITY}\"")

IF (WIN32)
add_definitions(-DLOWL_WIN)
target_compile_definitions(${PROJECT_NAME} PRIVATE LOWL_WIN)
ENDIF ()

IF (UNIX)
add_definitions(-DLOWL_UNIX)
target_compile_definitions(${PROJECT_NAME} PRIVATE LOWL_UNIX)
ENDIF ()

# readerwriterqueue
Expand Down
16 changes: 9 additions & 7 deletions demo/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ void play(std::shared_ptr<Lowl::Device> device) {
return;
}

while (data->frames_remaining() > 0) {
while (data->get_frames_remaining() > 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "==PLAYING==\n";
std::cout << "frames remaining: \n" + std::to_string(data->frames_remaining()) + "\n";
std::cout << "frames remaining: \n" + std::to_string(data->get_frames_remaining()) + "\n";
#ifdef LOWL_PROFILING
// std::cout << "LOWL_PROFILING: produce_count:" + std::to_string(stream->produce_count) + "\n";
// std::cout << "LOWL_PROFILING: produce_total_duration:" + std::to_string(stream->produce_total_duration) + "\n";
Expand Down Expand Up @@ -79,10 +79,10 @@ void node(std::shared_ptr<Lowl::Device> device) {
return;
}

while (out->get_stream()->frames_remaining() > 0) {
while (out->get_stream()->get_frames_remaining() > 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "==PLAYING==\n";
std::cout << "frames remaining: \n" + std::to_string(out->get_stream()->frames_remaining()) + "\n";
std::cout << "frames remaining: \n" + std::to_string(out->get_stream()->get_frames_remaining()) + "\n";
}
}

Expand Down Expand Up @@ -121,10 +121,10 @@ void mix(std::shared_ptr<Lowl::Device> device) {
return;
}

while (mixer->frames_remaining() > 0) {
while (mixer->get_frames_remaining() > 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "==PLAYING==\n";
std::cout << "frames remaining: \n" + std::to_string(mixer->frames_remaining()) + "\n";
std::cout << "frames remaining: \n" + std::to_string(mixer->get_frames_remaining()) + "\n";
}
}

Expand Down Expand Up @@ -162,11 +162,13 @@ void space(std::shared_ptr<Lowl::Device> device) {
if (selected_id <= Lowl::Space::InvalidSpaceId) {
std::cout << "Stop Selecting SpaceId\n";
break;
} else if (selected_id == 3) {
space->stop(1);
} else {
space->play(selected_id);
}

std::cout << "frames remaining: \n" + std::to_string(space->get_mixer()->frames_remaining()) + "\n";
std::cout << "frames remaining: \n" + std::to_string(space->get_mixer()->get_frames_remaining()) + "\n";
}

device->stop(error);
Expand Down
2 changes: 1 addition & 1 deletion src/lowl_audio_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ void Lowl::AudioData::set_in_mixer(bool p_in_mixer) {
in_mixer = p_in_mixer;
}

Lowl::size_l Lowl::AudioData::frames_remaining() const {
Lowl::size_l Lowl::AudioData::get_frames_remaining() const {
int remaining = frames.size() - position;
if (remaining < 0) {
remaining = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/lowl_audio_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ namespace Lowl {
*/
virtual bool read(AudioFrame &audio_frame) override;

virtual size_l frames_remaining() const override;
virtual size_l get_frames_remaining() const override;

AudioData(std::vector<Lowl::AudioFrame> p_audio_frames, SampleRate p_sample_rate, Channel p_channel);

Expand Down
66 changes: 42 additions & 24 deletions src/lowl_audio_mixer.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "lowl_audio_mixer.h"

#include "lowl_logger.h"

#ifdef LOWL_PROFILING

Expand All @@ -15,6 +16,7 @@ Lowl::AudioMixer::AudioMixer(SampleRate p_sample_rate, Channel p_channel)
data = std::vector<std::shared_ptr<AudioData>>();
mixers = std::vector<std::shared_ptr<AudioMixer>>();
events = std::make_unique<moodycamel::ConcurrentQueue<AudioMixerEvent>>();
frames_remaining.store(0, std::memory_order_relaxed);
}

bool Lowl::AudioMixer::read(Lowl::AudioFrame &audio_frame) {
Expand All @@ -28,19 +30,35 @@ bool Lowl::AudioMixer::read(Lowl::AudioFrame &audio_frame) {
case AudioMixerEvent::MixAudioStream: {
std::shared_ptr<AudioStream> audio_stream = std::static_pointer_cast<AudioStream>(event.ptr);
streams.push_back(audio_stream);

size_l remaining = audio_stream->get_frames_remaining();
if (remaining > frames_remaining.load(std::memory_order_relaxed)) {
frames_remaining.store(remaining, std::memory_order_relaxed);
}
break;
}
case AudioMixerEvent::MixAudioData: {
std::shared_ptr<AudioData> audio_data = std::static_pointer_cast<AudioData>(event.ptr);
if (!audio_data->is_in_mixer()) {
audio_data->set_in_mixer(true);
data.push_back(audio_data);

// TODO audio data can be cancelled mid way or reset, causing incorrect frame count
size_l remaining = audio_data->get_frames_remaining();
if (remaining > frames_remaining.load(std::memory_order_relaxed)) {
frames_remaining.store(remaining, std::memory_order_relaxed);
}
}
break;
}
case AudioMixerEvent::MixAudioMixer: {
std::shared_ptr<AudioMixer> audio_mixer = std::static_pointer_cast<AudioMixer>(event.ptr);
mixers.push_back(audio_mixer);

size_l remaining = audio_mixer->get_frames_remaining();
if (remaining > frames_remaining.load(std::memory_order_relaxed)) {
frames_remaining.store(remaining, std::memory_order_relaxed);
}
break;
}
}
Expand Down Expand Up @@ -96,6 +114,10 @@ bool Lowl::AudioMixer::read(Lowl::AudioFrame &audio_frame) {
}
audio_frame = mix_frame;

if (frames_remaining.load(std::memory_order_relaxed) > 0) {
frames_remaining.fetch_sub(1, std::memory_order_relaxed);
}

#ifdef LOWL_PROFILING
auto t2 = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> ms_double = t2 - t1;
Expand All @@ -115,50 +137,46 @@ bool Lowl::AudioMixer::read(Lowl::AudioFrame &audio_frame) {
}

void Lowl::AudioMixer::mix_stream(std::shared_ptr<AudioStream> p_audio_stream) {
// TODO validate input stream sample rate - perhaps warning - #ifdef to enable warnings
if (p_audio_stream->get_sample_rate() != sample_rate) {
Logger::log(Logger::Level::Warn,
"Lowl::AudioMixer::mix_stream: p_audio_stream(" + std::to_string(sample_rate) +
") does not match mixer(" + std::to_string(sample_rate) + ") sample rate."
);
}
AudioMixerEvent event = {};
event.type = AudioMixerEvent::MixAudioStream;
event.ptr = p_audio_stream;
events->enqueue(event);
}

void Lowl::AudioMixer::mix_data(std::shared_ptr<AudioData> p_audio_data) {
// TODO validate input stream sample rate - perhaps warning - #ifdef to enable warnings
if (p_audio_data->get_sample_rate() != sample_rate) {
Logger::log(Logger::Level::Warn,
"Lowl::AudioMixer::mix_data: p_audio_data(" + std::to_string(sample_rate) +
") does not match mixer(" + std::to_string(sample_rate) + ") sample rate."
);
}
AudioMixerEvent event = {};
event.type = AudioMixerEvent::MixAudioData;
event.ptr = p_audio_data;
events->enqueue(event);
}

void Lowl::AudioMixer::mix_mixer(std::shared_ptr<AudioMixer> p_audio_mixer) {
// TODO validate input stream sample rate - perhaps warning - #ifdef to enable warnings
if (p_audio_mixer->get_sample_rate() != sample_rate) {
Logger::log(Logger::Level::Warn,
"Lowl::AudioMixer::mix_mixer: p_audio_mixer(" + std::to_string(sample_rate) +
") does not match mixer(" + std::to_string(sample_rate) + ") sample rate."
);
}
AudioMixerEvent event = {};
event.type = AudioMixerEvent::MixAudioMixer;
event.ptr = p_audio_mixer;
events->enqueue(event);
}

Lowl::size_l Lowl::AudioMixer::frames_remaining() const {
// TODO don't access lists outside of read() call as it runs on audio thread.
// this needs to be reworked, perhaps counting needs to happen on mixer thread,
// or when adding data via event remember the highest input and count down.
int remaining = 0;
for (const std::shared_ptr<AudioStream> &stream : streams) {
if (stream->frames_remaining() > remaining) {
remaining = stream->frames_remaining();
}
}
for (const std::shared_ptr<AudioData> &audio_data : data) {
if (audio_data->frames_remaining() > remaining) {
remaining = audio_data->frames_remaining();
}
}
for (const std::shared_ptr<AudioMixer> &mixer : mixers) {
if (mixer->frames_remaining() > remaining) {
remaining = mixer->frames_remaining();
}
}
return remaining;
Lowl::size_l Lowl::AudioMixer::get_frames_remaining() const {
return frames_remaining.load(std::memory_order_relaxed);
}

void Lowl::AudioMixer::mix(std::shared_ptr<AudioSource> p_audio_source) {
Expand Down
3 changes: 2 additions & 1 deletion src/lowl_audio_mixer.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ namespace Lowl {
std::vector<std::shared_ptr<AudioData>> data;
std::vector<std::shared_ptr<AudioMixer>> mixers;
std::unique_ptr<moodycamel::ConcurrentQueue<AudioMixerEvent>> events;
std::atomic<size_l> frames_remaining;

public:
virtual size_l frames_remaining() const override;
virtual size_l get_frames_remaining() const override;

/**
* mixes a single frame from all sources
Expand Down
2 changes: 1 addition & 1 deletion src/lowl_audio_source.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace Lowl {

virtual bool read(AudioFrame &audio_frame) = 0;

virtual size_l frames_remaining() const = 0;
virtual size_l get_frames_remaining() const = 0;

SampleRate get_sample_rate() const;

Expand Down
2 changes: 1 addition & 1 deletion src/lowl_audio_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ uint32_t Lowl::AudioStream::get_num_frame_write() const {
return frames_in;
}

Lowl::size_l Lowl::AudioStream::frames_remaining() const {
Lowl::size_l Lowl::AudioStream::get_frames_remaining() const {
return frame_queue->size_approx();
}
2 changes: 1 addition & 1 deletion src/lowl_audio_stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace Lowl {

uint32_t get_num_frame_read() const;

virtual size_l frames_remaining() const override;
virtual size_l get_frames_remaining() const override;

virtual bool read(AudioFrame &audio_frame) override;

Expand Down
Loading

0 comments on commit 85b3e79

Please sign in to comment.