Skip to content

Commit

Permalink
gh-696 Add ChannelSet::set_count() and use in sndio backends
Browse files Browse the repository at this point in the history
To initialize channels in sndio backends, we now use:

    channel_set().set_count(count)

instead of:

    channel_set().set_range(0, count-1)

The new version tries to find a sensible mask for given count.
E.g. for 2 channels, set_range() call above would set FL+FC,
and set_count() would set FL+FR (stereo).

This is an intermediate solution, for appropriate surround support
we'll need to update backends to map channels from file/device
to channel set. set_count() is just a fallback for backends that
don't (yet) have proper support.
  • Loading branch information
gavv committed Apr 9, 2024
1 parent 608963d commit 71b4749
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 33 deletions.
84 changes: 57 additions & 27 deletions src/internal_modules/roc_audio/channel_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ ChannelSet::ChannelSet()
, last_chan_(0)
, layout_(ChanLayout_None)
, order_(ChanOrder_None) {
memset(words_, 0, sizeof(words_));
clear_chans_();
index_chans_();
}

ChannelSet::ChannelSet(const ChannelLayout layout,
Expand All @@ -44,12 +45,9 @@ ChannelSet::ChannelSet(const ChannelLayout layout,
channel_layout_to_str(layout), (unsigned long)mask);
}

clear_chans_();
words_[0] = mask;
for (size_t n = 1; n < NumWords; n++) {
words_[n] = 0;
}

update_();
index_chans_();
}

bool ChannelSet::operator==(const ChannelSet& other) const {
Expand Down Expand Up @@ -95,9 +93,8 @@ void ChannelSet::clear() {
layout_ = ChanLayout_None;
order_ = ChanOrder_None;

memset(words_, 0, sizeof(words_));

update_();
clear_chans_();
index_chans_();
}

ChannelLayout ChannelSet::layout() const {
Expand Down Expand Up @@ -178,17 +175,11 @@ bool ChannelSet::is_superset(ChannelMask mask) const {
}

void ChannelSet::set_mask(const ChannelMask mask) {
if (mask == 0) {
roc_panic("channel set: invalid channel mask");
}

for (size_t n = 0; n < NumWords; n++) {
words_[n] = 0;
}
clear_chans_();

words_[0] = mask;

update_();
index_chans_();
}

void ChannelSet::set_range(size_t from, size_t to) {
Expand All @@ -201,15 +192,50 @@ void ChannelSet::set_range(size_t from, size_t to) {
(unsigned long)to);
}

for (size_t n = 0; n < NumWords; n++) {
words_[n] = 0;
}
clear_chans_();

for (size_t n = from; n <= to; n++) {
words_[n / WordBits] |= (word_t(1) << (n % WordBits));
}

update_();
index_chans_();
}

void ChannelSet::set_count(size_t count) {
if (count >= MaxChannels) {
roc_panic("channel set: subscript out of range: count=%lu max_channels=%lu",
(unsigned long)count, (unsigned long)MaxChannels);
}

switch (count) {
case 0:
set_mask(0);
break;
case 1:
set_mask(ChanMask_Surround_Mono);
break;
case 2:
set_mask(ChanMask_Surround_Stereo);
break;
case 3:
set_mask(ChanMask_Surround_3_0);
break;
case 4:
set_mask(ChanMask_Surround_4_0);
break;
case 5:
set_mask(ChanMask_Surround_5_0);
break;
case 6:
set_mask(ChanMask_Surround_6_0);
break;
case 7:
set_mask(ChanMask_Surround_7_0);
break;
default:
set_range(0, count - 1);
break;
}
}

void ChannelSet::toggle_channel(const size_t n, const bool enabled) {
Expand All @@ -224,7 +250,7 @@ void ChannelSet::toggle_channel(const size_t n, const bool enabled) {
words_[n / WordBits] &= ~(word_t(1) << (n % WordBits));
}

update_();
index_chans_();
}

void ChannelSet::toggle_channel_range(const size_t from,
Expand All @@ -247,31 +273,31 @@ void ChannelSet::toggle_channel_range(const size_t from,
}
}

update_();
index_chans_();
}

void ChannelSet::bitwise_and(const ChannelSet& other) {
for (size_t n = 0; n < NumWords; n++) {
words_[n] &= other.words_[n];
}

update_();
index_chans_();
}

void ChannelSet::bitwise_or(const ChannelSet& other) {
for (size_t n = 0; n < NumWords; n++) {
words_[n] |= other.words_[n];
}

update_();
index_chans_();
}

void ChannelSet::bitwise_xor(const ChannelSet& other) {
for (size_t n = 0; n < NumWords; n++) {
words_[n] ^= other.words_[n];
}

update_();
index_chans_();
}

size_t ChannelSet::num_bytes() const {
Expand All @@ -287,7 +313,11 @@ uint8_t ChannelSet::byte_at(size_t n) const {
return (words_[n / WordBytes] >> ((n % WordBytes) * 8)) & 0xff;
}

void ChannelSet::update_() {
void ChannelSet::clear_chans_() {
memset(words_, 0, sizeof(words_));
}

void ChannelSet::index_chans_() {
num_chans_ = first_chan_ = last_chan_ = 0;

bool has_first = false;
Expand Down
9 changes: 8 additions & 1 deletion src/internal_modules/roc_audio/channel_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ class ChannelSet {
//! All other channels are disabled.
void set_range(size_t from, size_t to);

//! Set channel mask based on channel count.
//! @remarks
//! Tries to find a mask that looks most appropriate for given channel count.
//! Falls back to just enabling first N channels and disabling others.
void set_count(size_t count);

//! Enable/disable given channel.
void toggle_channel(size_t n, bool enabled);

Expand Down Expand Up @@ -150,7 +156,8 @@ class ChannelSet {
NumWords = MaxChannels / WordBits
};

void update_();
void clear_chans_();
void index_chans_();

word_t words_[NumWords];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ bool PulseaudioDevice::load_device_params_(const pa_sample_spec& device_spec) {
if (!sample_spec_.channel_set().is_valid()) {
sample_spec_.channel_set().set_layout(audio::ChanLayout_Surround);
sample_spec_.channel_set().set_order(audio::ChanOrder_Smpte);
sample_spec_.channel_set().set_range(0, device_spec.channels - 1);
sample_spec_.channel_set().set_count(device_spec.channels);
}

if (!sample_spec_.is_valid()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ bool SndfileSource::open_() {
sample_spec_.set_sample_rate((size_t)file_info_.samplerate);
sample_spec_.channel_set().set_layout(audio::ChanLayout_Surround);
sample_spec_.channel_set().set_order(audio::ChanOrder_Smpte);
sample_spec_.channel_set().set_range(0, (size_t)file_info_.channels - 1);
sample_spec_.channel_set().set_count((size_t)file_info_.channels);

roc_log(LogInfo, "sndfile source: opened: %s",
audio::sample_spec_to_str(sample_spec_).c_str());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ bool SoxSink::open_(const char* driver, const char* path) {
sample_spec_.set_sample_rate(actual_rate);
sample_spec_.channel_set().set_layout(audio::ChanLayout_Surround);
sample_spec_.channel_set().set_order(audio::ChanOrder_Smpte);
sample_spec_.channel_set().set_range(0, actual_chans - 1);
sample_spec_.channel_set().set_count(actual_chans);

roc_log(LogInfo,
"sox sink:"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ bool SoxSource::open_() {
sample_spec_.set_sample_rate(actual_rate);
sample_spec_.channel_set().set_layout(audio::ChanLayout_Surround);
sample_spec_.channel_set().set_order(audio::ChanOrder_Smpte);
sample_spec_.channel_set().set_range(0, actual_chans - 1);
sample_spec_.channel_set().set_count(actual_chans);

roc_log(LogInfo,
"sox source:"
Expand Down
2 changes: 1 addition & 1 deletion src/internal_modules/roc_sndio/wav_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ audio::SampleSpec WavSource::sample_spec() const {
audio::ChannelSet channel_set;
channel_set.set_layout(audio::ChanLayout_Surround);
channel_set.set_order(audio::ChanOrder_Smpte);
channel_set.set_range(0, wav_.channels - 1);
channel_set.set_count(wav_.channels);

return audio::SampleSpec(size_t(wav_.sampleRate), audio::Sample_RawFormat,
channel_set);
Expand Down
10 changes: 10 additions & 0 deletions src/tests/roc_audio/test_channel_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,16 @@ TEST(channel_set, set_range) {
}
}

TEST(channel_set, set_count) {
for (size_t count = 0; count < ChannelSet::max_channels(); count++) {
ChannelSet ch_set;

ch_set.set_count(count);

UNSIGNED_LONGS_EQUAL(count, ch_set.num_channels());
}
}

TEST(channel_set, toggle_channel) {
{ // set small
ChannelSet ch_set;
Expand Down

0 comments on commit 71b4749

Please sign in to comment.