Remove unused `ChannelPosition` API (update all backends and examples accordingly) (#198)

* Remove ChannelPosition API

This removes the ChannelPosition API from the lib root and updates the
ALSA backend and examples accordingly. The other backends have not yet
been updated.

Related discussion at #187.

* Update windows backend to removal of ChannelPosition API

The windows backend now assumes the channel position order is equal to
the channel position mask order. E.g. channel 0 will always be front
left, channel 1 will always be front right, etc.

Compiled and ran both examples successfully.

* Update coreaudio backend to removal of ChannelPosition API

Compiled and ran both examples successfully.

* Update emscriptem backend for removal of ChannelPosition API

* Update CHANGELOG for ChannelPosition removal
This commit is contained in:
mitchmindtree 2018-02-04 20:38:06 +11:00 committed by Pierre Krieger
parent 6bf65f589d
commit f2728f6bdf
8 changed files with 45 additions and 172 deletions

View File

@ -1,5 +1,6 @@
# Unreleased
- Remove unused ChannelPosition API.
- Implement Endpoint and Format Enumeration for macos.
- Implement format handling for macos `build_voice` method.

View File

@ -25,7 +25,7 @@ fn main() {
event_loop.run(move |_, buffer| {
match buffer {
cpal::UnknownTypeBuffer::U16(mut buffer) => {
for sample in buffer.chunks_mut(format.channels.len()) {
for sample in buffer.chunks_mut(format.channels as usize) {
let value = ((next_value() * 0.5 + 0.5) * std::u16::MAX as f32) as u16;
for out in sample.iter_mut() {
*out = value;
@ -34,7 +34,7 @@ fn main() {
},
cpal::UnknownTypeBuffer::I16(mut buffer) => {
for sample in buffer.chunks_mut(format.channels.len()) {
for sample in buffer.chunks_mut(format.channels as usize) {
let value = (next_value() * std::i16::MAX as f32) as i16;
for out in sample.iter_mut() {
*out = value;
@ -43,7 +43,7 @@ fn main() {
},
cpal::UnknownTypeBuffer::F32(mut buffer) => {
for sample in buffer.chunks_mut(format.channels.len()) {
for sample in buffer.chunks_mut(format.channels as usize) {
let value = next_value();
for out in sample.iter_mut() {
*out = value;

View File

@ -3,7 +3,7 @@ extern crate libc;
pub use self::enumerate::{EndpointsIterator, default_endpoint};
use ChannelPosition;
use ChannelsCount;
use CreationError;
use Format;
use FormatsEnumerationError;
@ -206,19 +206,7 @@ impl Endpoint {
num,
) == 0
{
Some(
[
ChannelPosition::FrontLeft,
ChannelPosition::FrontRight,
ChannelPosition::BackLeft,
ChannelPosition::BackRight,
ChannelPosition::FrontCenter,
ChannelPosition::LowFrequency,
].iter()
.take(num as usize)
.cloned()
.collect::<Vec<_>>(),
)
Some(num as ChannelsCount)
} else {
None
})
@ -569,11 +557,11 @@ impl EventLoop {
.expect("sample rate could not be set");
check_errors(alsa::snd_pcm_hw_params_set_channels(playback_handle,
hw_params.0,
format.channels.len() as
format.channels as
libc::c_uint))
.expect("channel count could not be set");
let mut max_buffer_size = format.samples_rate.0 as alsa::snd_pcm_uframes_t /
format.channels.len() as alsa::snd_pcm_uframes_t /
format.channels as alsa::snd_pcm_uframes_t /
5; // 200ms of buffer
check_errors(alsa::snd_pcm_hw_params_set_buffer_size_max(playback_handle,
hw_params.0,
@ -602,8 +590,8 @@ impl EventLoop {
sw_params,
period))
.unwrap();
let buffer = buffer as usize * format.channels.len();
let period = period as usize * format.channels.len();
let buffer = buffer as usize * format.channels as usize;
let period = period as usize * format.channels as usize;
(buffer, period)
};
@ -625,7 +613,7 @@ impl EventLoop {
channel: playback_handle,
sample_format: format.data_type,
num_descriptors: num_descriptors,
num_channels: format.channels.len() as u16,
num_channels: format.channels as u16,
buffer_len: buffer_len,
period_len: period_len,
can_pause: can_pause,

View File

@ -1,7 +1,7 @@
extern crate coreaudio;
extern crate core_foundation_sys;
use ChannelPosition;
use ChannelsCount;
use CreationError;
use Format;
use FormatsEnumerationError;
@ -108,26 +108,6 @@ impl Endpoint {
for buffer in buffers {
n_channels += buffer.mNumberChannels as usize;
}
const CHANNEL_POSITIONS: &'static [ChannelPosition] = &[
ChannelPosition::FrontLeft,
ChannelPosition::FrontRight,
ChannelPosition::FrontCenter,
ChannelPosition::LowFrequency,
ChannelPosition::BackLeft,
ChannelPosition::BackRight,
ChannelPosition::FrontLeftOfCenter,
ChannelPosition::FrontRightOfCenter,
ChannelPosition::BackCenter,
ChannelPosition::SideLeft,
ChannelPosition::SideRight,
ChannelPosition::TopCenter,
ChannelPosition::TopFrontLeft,
ChannelPosition::TopFrontCenter,
ChannelPosition::TopFrontRight,
ChannelPosition::TopBackLeft,
ChannelPosition::TopBackCenter,
ChannelPosition::TopBackRight,
];
// AFAIK the sample format should always be f32 on macos and i16 on iOS? Feel free to
// fix this if more pcm formats are supported.
@ -170,13 +150,8 @@ impl Endpoint {
// Collect the supported formats for the device.
let mut fmts = vec![];
for range in ranges {
let channels = CHANNEL_POSITIONS.iter()
.cloned()
.cycle()
.take(n_channels)
.collect::<Vec<_>>();
let fmt = SupportedFormat {
channels: channels.clone(),
channels: n_channels as ChannelsCount,
min_samples_rate: SamplesRate(range.mMinimum as _),
max_samples_rate: SamplesRate(range.mMaximum as _),
data_type: sample_format,
@ -306,7 +281,7 @@ impl EventLoop {
)?;
// Set the stream in interleaved mode.
let n_channels = format.channels.len();
let n_channels = format.channels as usize;
let sample_rate = format.samples_rate.0;
let bytes_per_channel = format.data_type.sample_size();
let bits_per_channel = bytes_per_channel * 8;

View File

@ -183,7 +183,7 @@ impl Endpoint {
Ok(
vec![
SupportedFormat {
channels: vec![::ChannelPosition::BackLeft, ::ChannelPosition::BackRight],
channels: 2,
min_samples_rate: ::SamplesRate(44100),
max_samples_rate: ::SamplesRate(44100),
data_type: ::SampleFormat::F32,

View File

@ -240,29 +240,6 @@ impl Endpoint {
/// Number of channels.
pub type ChannelsCount = u16;
/// Possible position of a channel.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ChannelPosition {
FrontLeft,
FrontRight,
FrontCenter,
LowFrequency,
BackLeft,
BackRight,
FrontLeftOfCenter,
FrontRightOfCenter,
BackCenter,
SideLeft,
SideRight,
TopCenter,
TopFrontLeft,
TopFrontCenter,
TopFrontRight,
TopBackLeft,
TopBackCenter,
TopBackRight,
}
///
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct SamplesRate(pub u32);
@ -270,7 +247,7 @@ pub struct SamplesRate(pub u32);
/// Describes a format.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Format {
pub channels: Vec<ChannelPosition>,
pub channels: ChannelsCount,
pub samples_rate: SamplesRate,
pub data_type: SampleFormat,
}
@ -297,7 +274,7 @@ impl Iterator for SupportedFormatsIterator {
/// Describes a range of supported formats.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SupportedFormat {
pub channels: Vec<ChannelPosition>,
pub channels: ChannelsCount,
/// Minimum value for the samples rate of the supported formats.
pub min_samples_rate: SamplesRate,
/// Maximum value for the samples rate of the supported formats.

View File

@ -7,7 +7,7 @@ use std::ptr;
use std::slice;
use std::sync::{Arc, Mutex, MutexGuard};
use ChannelPosition;
use ChannelsCount;
use FormatsEnumerationError;
use SampleFormat;
use SamplesRate;
@ -140,75 +140,11 @@ impl Endpoint {
let format = {
let (channels, data_type) = match (*format_ptr).wFormatTag {
winapi::WAVE_FORMAT_PCM => {
(vec![ChannelPosition::FrontLeft, ChannelPosition::FrontRight],
SampleFormat::I16)
(2, SampleFormat::I16)
},
winapi::WAVE_FORMAT_EXTENSIBLE => {
let format_ptr = format_ptr as *const winapi::WAVEFORMATEXTENSIBLE;
let channels = {
let mut channels = Vec::new();
let mask = (*format_ptr).dwChannelMask;
if (mask & winapi::SPEAKER_FRONT_LEFT) != 0 {
channels.push(ChannelPosition::FrontLeft);
}
if (mask & winapi::SPEAKER_FRONT_RIGHT) != 0 {
channels.push(ChannelPosition::FrontRight);
}
if (mask & winapi::SPEAKER_FRONT_CENTER) != 0 {
channels.push(ChannelPosition::FrontCenter);
}
if (mask & winapi::SPEAKER_LOW_FREQUENCY) != 0 {
channels.push(ChannelPosition::LowFrequency);
}
if (mask & winapi::SPEAKER_BACK_LEFT) != 0 {
channels.push(ChannelPosition::BackLeft);
}
if (mask & winapi::SPEAKER_BACK_RIGHT) != 0 {
channels.push(ChannelPosition::BackRight);
}
if (mask & winapi::SPEAKER_FRONT_LEFT_OF_CENTER) != 0 {
channels.push(ChannelPosition::FrontLeftOfCenter);
}
if (mask & winapi::SPEAKER_FRONT_RIGHT_OF_CENTER) != 0 {
channels.push(ChannelPosition::FrontRightOfCenter);
}
if (mask & winapi::SPEAKER_BACK_CENTER) != 0 {
channels.push(ChannelPosition::BackCenter);
}
if (mask & winapi::SPEAKER_SIDE_LEFT) != 0 {
channels.push(ChannelPosition::SideLeft);
}
if (mask & winapi::SPEAKER_SIDE_RIGHT) != 0 {
channels.push(ChannelPosition::SideRight);
}
if (mask & winapi::SPEAKER_TOP_CENTER) != 0 {
channels.push(ChannelPosition::TopCenter);
}
if (mask & winapi::SPEAKER_TOP_FRONT_LEFT) != 0 {
channels.push(ChannelPosition::TopFrontLeft);
}
if (mask & winapi::SPEAKER_TOP_FRONT_CENTER) != 0 {
channels.push(ChannelPosition::TopFrontCenter);
}
if (mask & winapi::SPEAKER_TOP_FRONT_RIGHT) != 0 {
channels.push(ChannelPosition::TopFrontRight);
}
if (mask & winapi::SPEAKER_TOP_BACK_LEFT) != 0 {
channels.push(ChannelPosition::TopBackLeft);
}
if (mask & winapi::SPEAKER_TOP_BACK_CENTER) != 0 {
channels.push(ChannelPosition::TopBackCenter);
}
if (mask & winapi::SPEAKER_TOP_BACK_RIGHT) != 0 {
channels.push(ChannelPosition::TopBackRight);
}
assert_eq!((*format_ptr).Format.nChannels as usize, channels.len());
channels
};
let channels = (*format_ptr).Format.nChannels as ChannelsCount;
let format = {
fn cmp_guid(a: &winapi::GUID, b: &winapi::GUID) -> bool {
a.Data1 == b.Data1 && a.Data2 == b.Data2 && a.Data3 == b.Data3 &&

View File

@ -13,7 +13,6 @@ use std::sync::Mutex;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use ChannelPosition;
use CreationError;
use Format;
use SampleFormat;
@ -472,12 +471,12 @@ fn format_to_waveformatextensible(format: &Format)
SampleFormat::F32 => winapi::WAVE_FORMAT_EXTENSIBLE,
SampleFormat::U16 => return Err(CreationError::FormatNotSupported),
},
nChannels: format.channels.len() as winapi::WORD,
nChannels: format.channels as winapi::WORD,
nSamplesPerSec: format.samples_rate.0 as winapi::DWORD,
nAvgBytesPerSec: format.channels.len() as winapi::DWORD *
nAvgBytesPerSec: format.channels as winapi::DWORD *
format.samples_rate.0 as winapi::DWORD *
format.data_type.sample_size() as winapi::DWORD,
nBlockAlign: format.channels.len() as winapi::WORD *
nBlockAlign: format.channels as winapi::WORD *
format.data_type.sample_size() as winapi::WORD,
wBitsPerSample: 8 * format.data_type.sample_size() as winapi::WORD,
cbSize: match format.data_type {
@ -491,33 +490,30 @@ fn format_to_waveformatextensible(format: &Format)
Samples: 8 * format.data_type.sample_size() as winapi::WORD,
dwChannelMask: {
let mut mask = 0;
for &channel in format.channels.iter() {
let raw_value = match channel {
ChannelPosition::FrontLeft => winapi::SPEAKER_FRONT_LEFT,
ChannelPosition::FrontRight => winapi::SPEAKER_FRONT_RIGHT,
ChannelPosition::FrontCenter => winapi::SPEAKER_FRONT_CENTER,
ChannelPosition::LowFrequency => winapi::SPEAKER_LOW_FREQUENCY,
ChannelPosition::BackLeft => winapi::SPEAKER_BACK_LEFT,
ChannelPosition::BackRight => winapi::SPEAKER_BACK_RIGHT,
ChannelPosition::FrontLeftOfCenter => winapi::SPEAKER_FRONT_LEFT_OF_CENTER,
ChannelPosition::FrontRightOfCenter => winapi::SPEAKER_FRONT_RIGHT_OF_CENTER,
ChannelPosition::BackCenter => winapi::SPEAKER_BACK_CENTER,
ChannelPosition::SideLeft => winapi::SPEAKER_SIDE_LEFT,
ChannelPosition::SideRight => winapi::SPEAKER_SIDE_RIGHT,
ChannelPosition::TopCenter => winapi::SPEAKER_TOP_CENTER,
ChannelPosition::TopFrontLeft => winapi::SPEAKER_TOP_FRONT_LEFT,
ChannelPosition::TopFrontCenter => winapi::SPEAKER_TOP_FRONT_CENTER,
ChannelPosition::TopFrontRight => winapi::SPEAKER_TOP_FRONT_RIGHT,
ChannelPosition::TopBackLeft => winapi::SPEAKER_TOP_BACK_LEFT,
ChannelPosition::TopBackCenter => winapi::SPEAKER_TOP_BACK_CENTER,
ChannelPosition::TopBackRight => winapi::SPEAKER_TOP_BACK_RIGHT,
};
// channels must be in the right order
if raw_value <= mask {
return Err(CreationError::FormatNotSupported);
}
const CHANNEL_POSITIONS: &'static [winapi::DWORD] = &[
winapi::SPEAKER_FRONT_LEFT,
winapi::SPEAKER_FRONT_RIGHT,
winapi::SPEAKER_FRONT_CENTER,
winapi::SPEAKER_LOW_FREQUENCY,
winapi::SPEAKER_BACK_LEFT,
winapi::SPEAKER_BACK_RIGHT,
winapi::SPEAKER_FRONT_LEFT_OF_CENTER,
winapi::SPEAKER_FRONT_RIGHT_OF_CENTER,
winapi::SPEAKER_BACK_CENTER,
winapi::SPEAKER_SIDE_LEFT,
winapi::SPEAKER_SIDE_RIGHT,
winapi::SPEAKER_TOP_CENTER,
winapi::SPEAKER_TOP_FRONT_LEFT,
winapi::SPEAKER_TOP_FRONT_CENTER,
winapi::SPEAKER_TOP_FRONT_RIGHT,
winapi::SPEAKER_TOP_BACK_LEFT,
winapi::SPEAKER_TOP_BACK_CENTER,
winapi::SPEAKER_TOP_BACK_RIGHT,
];
for i in 0..format.channels {
let raw_value = CHANNEL_POSITIONS[i as usize];
mask = mask | raw_value;
}