"""
Ambisonics
==========

"""

import numpy as np
from scipy.misc import factorial


def acn(order=1):
    """Spherical harmonic degree `n` and order `m` for ambisonics order `order`.

    :param order: Ambisonics order.

    Yields tuples `(n, m)` where `n` is the degree and `m` the order.

    Follows ACN.

    === == == ======
    ACN n  m  letter
    === == == ======
    0   0  0  W
    --- -- -- ------
    1   1  -1 Y
    --- -- -- ------
    2   1  0  Z
    --- -- -- ------
    3   1  +1 X
    === == == ======

    """
    for n in range(order + 1):
        for m in range(-n, n + 1):
            yield (n, m)


def sn3d(m, n):
    """SN3D or Schmidt semi-normalisation

    :param m: order `n`
    :param n: degree `m`

    http://en.wikipedia.org/wiki/Ambisonic_data_exchange_formats#SN3D

    """
    m = np.atleast_1d(m)
    n = np.atleast_1d(n)

    d = np.logical_not(m.astype(bool))
    out = np.sqrt((2.0 - d) / (4.0 * np.pi) * factorial(n - np.abs(m)) / factorial(n + np.abs(m)))
    return out


def n3d(m, n):
    """N3D or full three-D normalisation

    :param m: order `n`
    :param n: degree `m`

    http://en.wikipedia.org/wiki/Ambisonic_data_exchange_formats#N3D

    """
    n = np.atleast_1d(n)
    return sn3d(m, n) * np.sqrt(2 * n + 1)


__all__ = ['acn', 'sn3d', 'n3d']

"""
Ambisonics
==========

"""

import numpy as np
try:
    from scipy import math
    factorial = math.factorial
except AttributeError:
    from scipy.misc import factorial


def acn(order=1):
    """Spherical harmonic degree `n` and order `m` for ambisonics order `order`.

    :param order: Ambisonics order.

    Yields tuples `(n, m)` where `n` is the degree and `m` the order.

    Follows ACN.

    === == == ======
    ACN n  m  letter
    === == == ======
    0   0  0  W
    --- -- -- ------
    1   1  -1 Y
    --- -- -- ------
    2   1  0  Z
    --- -- -- ------
    3   1  +1 X
    === == == ======

    """
    for n in range(order + 1):
        for m in range(-n, n + 1):
            yield (n, m)


def sn3d(m, n):
    """SN3D or Schmidt semi-normalisation

    :param m: order `n`
    :param n: degree `m`

    http://en.wikipedia.org/wiki/Ambisonic_data_exchange_formats#SN3D

    """
    m = np.atleast_1d(m)
    n = np.atleast_1d(n)

    d = np.logical_not(m.astype(bool))
    out = np.sqrt((2.0 - d) / (4.0 * np.pi) * factorial(n - np.abs(m)) / factorial(n + np.abs(m)))
    return out


def n3d(m, n):
    """N3D or full three-D normalisation

    :param m: order `n`
    :param n: degree `m`

    http://en.wikipedia.org/wiki/Ambisonic_data_exchange_formats#N3D

    """
    n = np.atleast_1d(n)
    return sn3d(m, n) * np.sqrt(2 * n + 1)


__all__ = ['acn', 'sn3d', 'n3d']

Fix factorial import with scipy 1.3