Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add alaw #63

Merged
merged 1 commit into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions diffsptk/core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .acorr import AutocorrelationAnalysis
from .alaw import ALawCompression
from .ap import Aperiodicity
from .b2mc import MLSADigitalFilterCoefficientsToMelCepstrum
from .c2acr import CepstrumToAutocorrelation
Expand Down Expand Up @@ -27,6 +28,7 @@
from .gmm import GaussianMixtureModeling as GMM
from .gnorm import GeneralizedCepstrumGainNormalization
from .grpdelay import GroupDelay
from .ialaw import ALawExpansion
from .idct import InverseDiscreteCosineTransform
from .idct import InverseDiscreteCosineTransform as IDCT
from .ifreqt2 import SecondOrderAllPassInverseFrequencyTransform
Expand Down
75 changes: 75 additions & 0 deletions diffsptk/core/alaw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# ------------------------------------------------------------------------ #
# Copyright 2022 SPTK Working Group #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ------------------------------------------------------------------------ #

import math

import torch
import torch.nn as nn


class ALawCompression(nn.Module):
"""See `this page <https://sp-nitech.github.io/sptk/latest/main/alaw.html>`_
for details.

Parameters
----------
abs_max : float > 0 [scalar]
Absolute maximum value of input.

a : float >= 1 [scalar]
Compression factor, :math:`A`.

"""

def __init__(self, abs_max=1, a=87.6):
super(ALawCompression, self).__init__()

self.abs_max = abs_max
self.a = a

assert 0 < self.abs_max
assert 1 <= self.a

self.const = self.abs_max / (1 + math.log(self.a))

def forward(self, x):
"""Compress waveform by A-law algorithm.

Parameters
----------
x : Tensor [shape=(...,)]
Waveform.

Returns
-------
y : Tensor [shape=(...,)]
Compressed waveform.

Examples
--------
>>> x = diffsptk.ramp(4)
>>> alaw = diffsptk.ALawCompression(4)
>>> y = alaw(x)
>>> y
tensor([0.0000, 2.9868, 3.4934, 3.7897, 4.0000])

"""
x_abs = x.abs() / self.abs_max
x1 = self.a * x_abs
x2 = 1 + torch.log(x1)
condition = x_abs < (1 / self.a)
y = self.const * torch.sign(x) * torch.where(condition, x1, x2)
return y
77 changes: 77 additions & 0 deletions diffsptk/core/ialaw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# ------------------------------------------------------------------------ #
# Copyright 2022 SPTK Working Group #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ------------------------------------------------------------------------ #

import math

import torch
import torch.nn as nn


class ALawExpansion(nn.Module):
"""See `this page <https://sp-nitech.github.io/sptk/latest/main/ialaw.html>`_
for details.

Parameters
----------
abs_max : float > 0 [scalar]
Absolute maximum value of input.

a : float >= 1 [scalar]
Compression factor, :math:`A`.

"""

def __init__(self, abs_max=1, a=87.6):
super(ALawExpansion, self).__init__()

self.abs_max = abs_max
self.a = a

assert 0 < self.abs_max
assert 1 <= self.a

self.const = self.abs_max / self.a
self.z = 1 + math.log(self.a)

def forward(self, y):
"""Expand waveform by A-law algorithm.

Parameters
----------
y : Tensor [shape=(...,)]
Compressed waveform.

Returns
-------
x : Tensor [shape=(...,)]
Waveform.

Examples
--------
>>> x = diffsptk.ramp(4)
>>> alaw = diffsptk.ALawCompression(4)
>>> ialaw = diffsptk.ALawExpansion(4)
>>> x2 = ialaw(alaw(x))
>>> x2
tensor([0.0000, 1.0000, 2.0000, 3.0000, 4.0000])

"""
y_abs = y.abs() / self.abs_max
y1 = self.z * y_abs
y2 = torch.exp(y1 - 1)
condition = y_abs < (1 / self.z)
x = self.const * torch.sign(y) * torch.where(condition, y1, y2)
return x
6 changes: 3 additions & 3 deletions diffsptk/core/iulaw.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def __init__(self, abs_max=1, mu=255):
self.mu = mu

assert 0 < self.abs_max
assert 0 < self.mu
assert 1 <= self.mu

self.const = self.abs_max / self.mu

Expand All @@ -66,6 +66,6 @@ def forward(self, y):
tensor([0.0000, 1.0000, 2.0000, 3.0000, 4.0000])

"""
y2 = y.abs() / self.abs_max
x = self.const * torch.sign(y) * (torch.pow(1 + self.mu, y2) - 1)
y_abs = y.abs() / self.abs_max
x = self.const * torch.sign(y) * (torch.pow(1 + self.mu, y_abs) - 1)
return x
6 changes: 3 additions & 3 deletions diffsptk/core/ulaw.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def __init__(self, abs_max=1, mu=255):
self.mu = mu

assert 0 < self.abs_max
assert 0 < self.mu
assert 1 <= self.mu

self.const = self.abs_max / math.log1p(self.mu)

Expand All @@ -67,6 +67,6 @@ def forward(self, x):
tensor([0.0000, 3.0084, 3.5028, 3.7934, 4.0000])

"""
x2 = x.abs() / self.abs_max
y = self.const * torch.sign(x) * torch.log1p(self.mu * x2)
x_abs = x.abs() / self.abs_max
y = self.const * torch.sign(x) * torch.log1p(self.mu * x_abs)
return y
9 changes: 9 additions & 0 deletions docs/core/alaw.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.. _alaw:

alaw
----

.. autoclass:: diffsptk.ALawCompression
:members:

.. seealso:: :ref:`ialaw` :ref:`ulaw`
9 changes: 9 additions & 0 deletions docs/core/ialaw.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.. _ialaw:

ialaw
-----

.. autoclass:: diffsptk.ALawExpansion
:members:

.. seealso:: :ref:`alaw` :ref:`iulaw`
36 changes: 36 additions & 0 deletions tests/test_alaw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# ------------------------------------------------------------------------ #
# Copyright 2022 SPTK Working Group #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ------------------------------------------------------------------------ #

import pytest

import diffsptk
import tests.utils as U


@pytest.mark.parametrize("device", ["cpu", "cuda"])
def test_compatibility(device, v=10, a=80, L=10):
alaw = diffsptk.ALawCompression(v, a)

U.check_compatibility(
device,
alaw,
[],
f"ramp -l {L}",
f"alaw -v {v} -a {a}",
[],
)

U.check_differentiable(device, alaw, [L])
36 changes: 36 additions & 0 deletions tests/test_ialaw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# ------------------------------------------------------------------------ #
# Copyright 2022 SPTK Working Group #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ------------------------------------------------------------------------ #

import pytest

import diffsptk
import tests.utils as U


@pytest.mark.parametrize("device", ["cpu", "cuda"])
def test_compatibility(device, v=10, a=80, L=10):
ialaw = diffsptk.ALawExpansion(v, a)

U.check_compatibility(
device,
ialaw,
[],
f"ramp -l {L}",
f"ialaw -v {v} -a {a}",
[],
)

U.check_differentiable(device, ialaw, [L])