AudiooPy 0.1

Module audioopy

Class sppasChannelMixer

Description

A channel utility class to mix several channels in one.

Constructor

Create a ChannelMixer instance.

def __init__(self):
    """Create a ChannelMixer instance."""
    self._channels = []
    self._factors = []

Public functions

get_channel

Return the channel of a given index.

Parameters

  • idx: (int) the index of the channel to return

Returns

  • (sppasChannel)
def get_channel(self, idx):
    """Return the channel of a given index.

        :param idx: (int) the index of the channel to return
        :returns: (sppasChannel)

        """
    return self._channels[idx]
append_channel

Append a channel and the corresponding factor for a mix.

Parameters

  • channel: (Channel object) the channel to append
  • factor: (float) the factor associated to the channel
def append_channel(self, channel, factor=1):
    """Append a channel and the corresponding factor for a mix.

        :param channel: (Channel object) the channel to append
        :param factor: (float) the factor associated to the channel

        """
    self._channels.append(channel)
    self._factors.append(factor)
check_channels

Checking the conformity of the channels.

def check_channels(self):
    """Checking the conformity of the channels."""
    if len(self._channels) == 0:
        raise MixChannelError
    sampwidth = self._channels[0].get_sampwidth()
    framerate = self._channels[0].get_framerate()
    nframes = self._channels[0].get_nframes()
    for i in range(1, len(self._channels)):
        if self._channels[i].get_sampwidth() != sampwidth:
            raise MixChannelError(1)
        if self._channels[i].get_framerate() != framerate:
            raise MixChannelError(2)
        if self._channels[i].get_nframes() != nframes:
            raise MixChannelError(3)
mix

Mix the channels of the list in one.

Parameters

  • attenuator: (float) the factor to apply to each sample calculated

Returns

  • the result Channel
def mix(self, attenuator=1):
    """Mix the channels of the list in one.

        :param attenuator: (float) the factor to apply to each sample calculated
        :return: the result Channel

        """
    self.check_channels()
    sampwidth = self._channels[0].get_sampwidth()
    framerate = self._channels[0].get_framerate()
    frames = b''
    if sampwidth == 4:
        for s in range(0, len(self._channels[0].get_frames()), sampwidth):
            value = sppasChannelMixer._sample_calculator(self._channels, s, sampwidth, self._factors, attenuator)
            try:
                frames += struct.pack('<l', long(value))
            except:
                frames += struct.pack('<l', int(value))
    elif sampwidth == 2:
        for s in range(0, len(self._channels[0].get_frames()), sampwidth):
            value = sppasChannelMixer._sample_calculator(self._channels, s, sampwidth, self._factors, attenuator)
            frames += struct.pack('<h', int(value))
    else:
        for s in range(0, len(self._channels[0].get_frames()), sampwidth):
            value = sppasChannelMixer._sample_calculator(self._channels, s, sampwidth, self._factors, attenuator)
            frames += struct.pack('<b', int(value))
    return sppasChannel(framerate, sampwidth, frames)
get_minmax

Return a tuple with the minimum and the maximum samples values.

Returns

  • the tuple(minvalue, maxvalue)
def get_minmax(self):
    """Return a tuple with the minimum and the maximum samples values.

        :return: the tuple (minvalue, maxvalue)

        """
    self.check_channels()
    sampwidth = self._channels[0].get_sampwidth()
    minval = 0
    maxval = 0
    sampsum = 0
    for s in range(0, len(self._channels[0].get_frames()), sampwidth):
        value = sppasChannelMixer._sample_calculator(self._channels, s, sampwidth, self._factors, 1)
        try:
            sampsum = long(value)
        except:
            sampsum = int(value)
        maxval = max(sampsum, maxval)
        minval = min(sampsum, minval)
    return (minval, maxval)
norm_length

Normalize the number of frames of all the channels,

by appending silence at the end.

def norm_length(self):
    """Normalize the number of frames of all the channels,
        by appending silence at the end.

        """
    nframes = 0
    for i in range(len(self._channels)):
        nframes = max(nframes, self._channels[i].get_nframes())
    for i in range(len(self._channels)):
        if self._channels[i].get_nframes() < nframes:
            fragment = sppasChannelFrames(self._channels[i].get_frames())
            fragment.append_silence(nframes - self._channels[i].get_nframes())
            self._channels[i] = sppasChannel(self._channels[i].get_framerate(), self._channels[i].get_sampwidth(), fragment.get_frames())

Private functions

_sample_calculator

Return the sample value, applying a factor and an attenuator.

Parameters

  • channels: (Channel[]) the list of channels
  • pos: (int) the position of the sample to calculate
  • sampwidth: (int) the sample width
  • factors: (float[]) the list of factors to apply to each sample of a channel (1 channel = 1 factor)
  • attenuator: (float) a factor to apply to each sum of samples

Returns

  • (float) the value of the sample calculated
@staticmethod
def _sample_calculator(channels, pos, sampwidth, factors, attenuator):
    """Return the sample value, applying a factor and an attenuator.

        :param channels: (Channel[]) the list of channels
        :param pos: (int) the position of the sample to calculate
        :param sampwidth: (int) the sample width
        :param factors: (float[]) the list of factors to apply to each sample of a channel (1 channel = 1 factor)
        :param attenuator: (float) a factor to apply to each sum of samples

        :return: (float) the value of the sample calculated

        """
    minval = float(sppasChannelFrames().get_minval(sampwidth))
    maxval = float(sppasChannelFrames().get_maxval(sampwidth))
    sampsum = 0
    for factor, channel in zip(factors, channels):
        data = channel.get_frames()[pos:pos + sampwidth]
        data = sppasAudioConverter().unpack_data(data, sampwidth, 1)
        data = data[0]
        sampsum += data[0] * factor * attenuator
    if sampsum < 0:
        return max(sampsum, minval)
    elif sampsum > 0:
        return min(sampsum, maxval)
    return 0.0