Skip to content

Commit

Permalink
Merge pull request #63 from sp-nitech/alaw
Browse files Browse the repository at this point in the history
Add alaw
  • Loading branch information
takenori-y committed Jan 18, 2024
2 parents f4ec2ee + 4567ca0 commit 9e0aadf
Show file tree
Hide file tree
Showing 9 changed files with 250 additions and 6 deletions.
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])

0 comments on commit 9e0aadf

Please sign in to comment.