Skip to content
This repository has been archived by the owner on Nov 21, 2020. It is now read-only.

Commit

Permalink
Finish methods involving sample type and channel config
Browse files Browse the repository at this point in the history
Also move cdef helpers to the end of the module
  • Loading branch information
McSinyx committed Feb 15, 2020
1 parent 19ac906 commit aac24f9
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 91 deletions.
5 changes: 2 additions & 3 deletions examples/palace-hrtf.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,8 @@ def hrtf(files: Iterable[str], device: str, hrtf_name: str,
stderr.write(f'Failed to open file: {filename}\n')
continue
decoder.play(12000, 4, src)
print(f'Playing {filename} ({decoder.sample_type_name},',
f'{decoder.channel_config_name},',
f'{decoder.frequency} Hz)')
print(f'Playing {filename} ({decoder.sample_type},',
f'{decoder.channel_config}, {decoder.frequency} Hz)')

for i in takewhile(lambda i: src.playing,
count(step=PERIOD)):
Expand Down
4 changes: 2 additions & 2 deletions examples/palace-play.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ def play(files: Iterable[str], device: str) -> None:
stderr.write(f'Failed to open file: {filename}\n')
continue
with buffer, buffer.play() as src:
print(f'Playing {filename} ({buffer.sample_type_name},',
f'{buffer.channel_config_name}, {buffer.frequency} Hz)')
print(f'Playing {filename} ({buffer.sample_type},',
f'{buffer.channel_config}, {buffer.frequency} Hz)')

for i in takewhile(lambda i: src.playing, count()):
print(f' {pretty_time(src.offset_seconds)} /'
Expand Down
32 changes: 24 additions & 8 deletions src/alure.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ cdef extern from 'alure2-aliases.h' namespace 'alure' nogil:
cdef extern from 'alure2.h' namespace 'alure' nogil:
# Type aliases:
# char*: string
# ALbyte: signed char
# ALfloat: float
# ALsizei: int
# ALuint: unsigned
Expand All @@ -70,13 +71,25 @@ cdef extern from 'alure2.h' namespace 'alure' nogil:
unsigned send 'mSend'

# Enum classes:
cdef cppclass SampleType:
pass
cdef enum SampleType:
UInt8 'alure::SampleType::UInt8' # Unsigned 8-bit
Int16 'alure::SampleType::Int16' # Signed 16-bit
Float32 'alure::SampleType::Float32' # 32-bit float
Mulaw 'alure::SampleType::Mulaw' # Mulaw

cdef enum ChannelConfig:
Mono 'alure::ChannelConfig::Mono' # Mono
Stereo 'alure::ChannelConfig::Stereo' # Stereo
Rear 'alure::ChannelConfig::Rear' # Rear
Quad 'alure::ChannelConfig::Quad' # Quadrophonic
X51 'alure::ChannelConfig::X51' # 5.1 Surround
X61 'alure::ChannelConfig::X61' # 6.1 Surround
X71 'alure::ChannelConfig::X71' # 7.1 Surround
BFormat2D 'alure::ChannelConfig::BFormat2D' # B-Format 2D
BFormat3D 'alure::ChannelConfig::BFormat3D' # B-Format 3D

# The following relies on C++ implicit conversion from char* to string.
cdef const string get_sample_type_name 'GetSampleTypeName'(SampleType) except +

cdef cppclass ChannelConfig:
pass
cdef const string get_channel_config_name 'GetChannelConfigName'(ChannelConfig) except +
cdef unsigned frames_to_bytes 'FramesToBytes'(unsigned, ChannelConfig, SampleType) except +
cdef unsigned bytes_to_frames 'BytesToFrames'(unsigned, ChannelConfig, SampleType)
Expand Down Expand Up @@ -235,15 +248,12 @@ cdef extern from 'alure2.h' namespace 'alure' nogil:

void destroy() except +

Device get_device 'getDevice'() except +

void start_batch 'startBatch'() except +
void end_batch 'endBatch'() except +

Listener get_listener 'getListener'() except +

shared_ptr[MessageHandler] set_message_handler 'setMessageHandler'(shared_ptr[MessageHandler]) except +
shared_ptr[MessageHandler] get_message_handler 'getMessageHandler'() except +

void set_async_wake_interval 'setAsyncWakeInterval'(milliseconds) except +
milliseconds get_async_wake_interval 'getAsyncWakeInterval'() except +
Expand Down Expand Up @@ -578,3 +588,9 @@ cdef extern from 'alure2.h' namespace 'alure' nogil:

cdef cppclass MessageHandler:
pass


# GIL is needed for operations with Python objects.
cdef extern from 'bases.h' namespace 'palace':
cdef cppclass BaseMessageHandler(MessageHandler):
pass
30 changes: 0 additions & 30 deletions src/bases.pxd

This file was deleted.

149 changes: 104 additions & 45 deletions src/palace.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,31 @@ device_names : Dict[str, List[str]]
Dictionary of available device names corresponding to each type.
device_name_default : Dict[str, str]
Dictionary of the default device name corresponding to each type.
sample_types : FrozenSet[str]
Set of sample types.
channel_configs : FrozenSet[str]
Set of channel configurations.
"""

__all__ = ['ALC_FALSE', 'ALC_TRUE', 'ALC_HRTF_SOFT', 'ALC_HRTF_ID_SOFT',
'device_name_default', 'device_names',
'query_extension', 'use_context',
'Device', 'Context', 'Buffer', 'Source', 'SourceGroup',
'AuxiliaryEffectSlot', 'Decoder', 'MessageHandler']
__all__ = [
'ALC_FALSE', 'ALC_TRUE', 'ALC_HRTF_SOFT', 'ALC_HRTF_ID_SOFT',
'device_name_default', 'device_names', 'sample_types', 'channel_configs',
'query_extension', 'use_context',
'Device', 'Context', 'Buffer', 'Source', 'SourceGroup',
'AuxiliaryEffectSlot', 'Decoder', 'MessageHandler']


from types import TracebackType
from typing import Any, Dict, Iterator, List, Optional, Tuple, Type
from typing import Any, Dict, FrozenSet, Iterator, List, Optional, Tuple, Type
from warnings import warn

from libcpp cimport bool as boolean, nullptr
from libcpp cimport bool as boolean, nullptr # noqa
from libcpp.memory cimport shared_ptr
from libcpp.string cimport string
from libcpp.utility cimport pair
from libcpp.vector cimport vector

from std cimport milliseconds
from bases cimport BaseMessageHandler
cimport alure
cimport alure # noqa

# Type aliases
Vector3 = Tuple[float, float, float]
Expand All @@ -74,30 +77,12 @@ device_name_default: Dict[str, str] = dict(
full=devmgr.default_device_name(alure.DefaultDeviceType.Full),
capture=devmgr.default_device_name(alure.DefaultDeviceType.Capture))


cdef vector[alure.AttributePair] mkattrs(vector[pair[int, int]] attrs):
"""Convert attribute pairs from Python object to alure format."""
cdef vector[alure.AttributePair] attributes
cdef alure.AttributePair pair
for attribute, value in attrs:
pair.attribute = attribute
pair.value = value
attributes.push_back(pair) # insert a copy
pair.attribute = pair.value = 0
attributes.push_back(pair) # insert a copy
return attributes


cdef vector[float] from_vector3(alure.Vector3 v):
"""Convert alure::Vector3 to std::vector of 3 floats."""
cdef vector[float] result
for i in range(3): result.push_back(v[i])
return result


cdef alure.Vector3 to_vector3(vector[float] v):
"""Convert std::vector of 3 floats to alure::Vector3."""
return alure.Vector3(v[0], v[1], v[2])
sample_types: FrozenSet[str] = frozenset({
'Unsigned 8-bit', 'Signed 16-bit', '32-bit float', 'Mulaw'})
channel_configs: FrozenSet[str] = frozenset({
'Mono', 'Stereo', 'Rear', 'Quadrophonic',
'5.1 Surround', '6.1 Surround', '7.1 Surround',
'B-Format 2D', 'B-Format 3D'})


def query_extension(name: str) -> bool:
Expand Down Expand Up @@ -430,6 +415,18 @@ cdef class Context:
"""
self.impl.destroy()

def is_supported(self, channel_config: str, sample_type: str) -> bool:
"""Return if the channel configuration and sample type
are supported by the context.

See Also
--------
sample_types : Set of sample types
channel_configs : Set of channel configurations
"""
return self.impl.is_supported(get_channel_config(channel_config),
get_sample_type(sample_type))

def update(self) -> None:
"""Update the context and all sources belonging to this context."""
self.impl.update()
Expand Down Expand Up @@ -549,17 +546,15 @@ cdef class Buffer:
"""Buffer's frequency in hertz."""
return self.impl.get_frequency()

# TODO: get channel config (enum class)
@property
def channel_config_name(self) -> str:
"""Buffer's sample configuration name."""
def channel_config(self) -> str:
"""Buffer's sample configuration."""
return alure.get_channel_config_name(
self.impl.get_channel_config())

# TODO: get sample type (enum class)
@property
def sample_type_name(self) -> str:
"""Buffer's sample type name."""
def sample_type(self) -> str:
"""Buffer's sample type."""
return alure.get_sample_type_name(
self.impl.get_sample_type())

Expand Down Expand Up @@ -1450,14 +1445,14 @@ cdef class Decoder:
return self.pimpl.get()[0].get_frequency()

@property
def channel_config_name(self) -> str:
"""Name of the channel configuration of the audio being decoded."""
def channel_config(self) -> str:
"""Channel configuration of the audio being decoded."""
return alure.get_channel_config_name(
self.pimpl.get()[0].get_channel_config())

@property
def sample_type_name(self) -> str:
"""Name of the sample type of the audio being decoded."""
def sample_type(self) -> str:
"""Sample type of the audio being decoded."""
return alure.get_sample_type_name(
self.pimpl.get()[0].get_sample_type())

Expand Down Expand Up @@ -1510,6 +1505,8 @@ cdef class MessageHandler:
Applications may derive from this and set an instance on a context
to receive messages. The base methods are no-ops, so subclasses
only need to implement methods for relevant messages.

Methods of MessageHandler must not raise any exception.
"""
def device_disconnected(self, device: Device) -> None:
"""Handle disconnected device messages.
Expand Down Expand Up @@ -1585,7 +1582,7 @@ cdef class MessageHandler:
return ''


cdef cppclass CppMessageHandler(BaseMessageHandler):
cdef cppclass CppMessageHandler(alure.BaseMessageHandler):
Context context

CppMessageHandler(Context ctx):
Expand Down Expand Up @@ -1613,3 +1610,65 @@ cdef cppclass CppMessageHandler(BaseMessageHandler):

string resource_not_found(string name):
return context.message_handler.resource_not_found(name)


# Helper cdef functions
cdef vector[alure.AttributePair] mkattrs(vector[pair[int, int]] attrs):
"""Convert attribute pairs from Python object to alure format."""
cdef vector[alure.AttributePair] attributes
cdef alure.AttributePair pair
for attribute, value in attrs:
pair.attribute = attribute
pair.value = value
attributes.push_back(pair) # insert a copy
pair.attribute = pair.value = 0
attributes.push_back(pair) # insert a copy
return attributes


cdef vector[float] from_vector3(alure.Vector3 v):
"""Convert alure::Vector3 to std::vector of 3 floats."""
cdef vector[float] result
for i in range(3): result.push_back(v[i])
return result


cdef alure.Vector3 to_vector3(vector[float] v):
"""Convert std::vector of 3 floats to alure::Vector3."""
return alure.Vector3(v[0], v[1], v[2])


cdef alure.SampleType get_sample_type(str name) except +:
"""Return the specified sample type enumeration."""
if name == 'Unsigned 8-bit':
return alure.SampleType.UInt8
elif name == 'Signed 16-bit':
return alure.SampleType.Int16
elif name == '32-bit float':
return alure.SampleType.Float32
elif name == 'Mulaw':
return alure.SampleType.Mulaw
raise ValueError(f'Invalid sample type name: {name}')


cdef alure.ChannelConfig get_channel_config(str name) except +:
"""Return the specified channel configuration enumeration."""
if name == 'Mono':
return alure.ChannelConfig.Mono
elif name == 'Stereo':
return alure.ChannelConfig.Stereo
elif name == 'Rear':
return alure.ChannelConfig.Rear
elif name == 'Quadrophonic':
return alure.ChannelConfig.Quad
elif name == '5.1 Surround':
return alure.ChannelConfig.X51
elif name == '6.1 Surround':
return alure.ChannelConfig.X61
elif name == '7.1 Surround':
return alure.ChannelConfig.X71
elif name == 'B-Format 2D':
return alure.ChannelConfig.BFormat2D
elif name == 'B-Format 3D':
return alure.ChannelConfig.BFormat3D
raise ValueError(f'Invalid channel configuration name: {name}')
4 changes: 1 addition & 3 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ commands =
filename = *.pxd, *.pyx, *.py
hang-closing = True
ignore = E225, E226, E227, E701
per-file-ignores =
*.pxd:E501,E999
*.pyx:E999
per-file-ignores = *.pxd:E501,E999
; See https://github.com/PyCQA/pycodestyle/issues/906
;max-doc-length = 72

Expand Down

0 comments on commit aac24f9

Please sign in to comment.