Commit f5121821 authored by Vladimir Malenovsky's avatar Vladimir Malenovsky
Browse files

complement reverb tool with HOA3 format, corrections and fixes

parent ade4f928
Loading
Loading
Loading
Loading
+87 −18
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ from typing import Optional
import numpy as np
from scipy.fft import fft

from ivas_processing_scripts.audiotools import audio
from ivas_processing_scripts.audiotools.audio import Audio
from ivas_processing_scripts.audiotools.audiofile import read, write
from ivas_processing_scripts.audiotools.wrappers.filter import resample_itu
@@ -128,7 +129,9 @@ def reverb(
        output = copy(tmp_input)
        output.audio, _ = read(tmp_output_file, nchannels=1, fs=tmp_input.fs)

        # reverse the resampling
        # remove trailing part (to ensure that the length of the output is the same as the input)
        output.audio = output.audio[:-(IR.audio.shape[0]-1), :]

        if old_fs:
            output.audio = resample_itu(output, old_fs)
            output.fs = old_fs
@@ -183,9 +186,8 @@ def reverb_stereo(
    y_right = reverb(input, IR_right, align=align)

    # combine into stereo output
    y = copy(input)
    y.name = "STEREO"
    y.num_channels = 2
    y = audio.fromtype('STEREO')
    y.fs = input.fs
    y.audio = np.column_stack([y_left.audio, y_right.audio])

    return y
@@ -197,14 +199,14 @@ def reverb_foa(
    align: Optional[float] = None,
) -> Audio:
    """
    Wrapper for the ITU-T reverb binary to convolve mono audio signal with an FOA impulse response
    Convolve mono audio signal with an FOA impulse response

    Parameters
    ----------
    input: Audio
        Input audio signal
    IR: Audio
        Impulse response
    foa_IR: Audio
        FOA impulse response
    align: float
         multiplicative factor to apply to the reverberated sound in order to align its energy level with the second file

@@ -249,10 +251,9 @@ def reverb_foa(
    y_y = reverb(input, IR_y, align=align)
    y_z = reverb(input, IR_z, align=align)

    # combine into foa output
    y = copy(input)
    y.name = "FOA"
    y.num_channels = 4
    # combine into FOA output
    y = audio.fromtype('FOA')
    y.fs = input.fs
    y.audio = np.column_stack([y_w.audio, y_x.audio, y_y.audio, y_z.audio])

    return y
@@ -264,14 +265,14 @@ def reverb_hoa2(
    align: Optional[float] = None,
) -> Audio:
    """
    Wrapper for the ITU-T reverb binary to convolve mono audio signal with an HOA2 impulse response
    Convolve mono audio signal with an HOA2 impulse response

    Parameters
    ----------
    input: Audio
        Input audio signal
    IR: Audio
        Impulse response
    hoa2_IR: Audio
        HOA2 impulse response
    align: float
         multiplicative factor to apply to the reverberated sound in order to align its energy level with the second file

@@ -301,10 +302,71 @@ def reverb_hoa2(
        # convolve mono input with channel IR
        ych.append(reverb(input, IR, align=align))

    # combine into hoa2 output
    y = copy(input)
    y.name = "HOA2"
    y.num_channels = numchannels
    # combine into HOA2 output
    y = audio.fromtype('HOA2')
    y.fs = input.fs
    y.audio = np.column_stack(
        [
            ych[0].audio,
            ych[1].audio,
            ych[2].audio,
            ych[3].audio,
            ych[4].audio,
            ych[5].audio,
            ych[6].audio,
            ych[7].audio,
            ych[8].audio,
        ]
    )

    return y

def reverb_hoa3(
    input: Audio,
    hoa3_IR: Audio,
    align: Optional[float] = None,
) -> Audio:
    """
    Convolve mono audio signal with an HOA3 impulse response

    Parameters
    ----------
    input: Audio
        Input audio signal
    hoa3_IR: Audio
        HOA3 impulse response
    align: float
         multiplicative factor to apply to the reverberated sound in order to align its energy level with the second file

    Returns
    -------
    output: Audio
        Convolved audio signal with HOA3 IR
    """

    # convert to float32
    hoa3_IR.audio = np.float32(hoa3_IR.audio)

    numchannels = 16  # HOA3 by definition

    # calculate the scaling (multiplicative) factor such that the maximum gain of the IR filter across all frequencies is 0dB
    if align is None:
        H = fft(hoa3_IR.audio, axis=0)
        align = 1.0 / np.max(np.abs(H))

    IR = copy(hoa3_IR)
    IR.name = "MONO"
    IR.num_channels = 1
    ych = []
    for i in range(numchannels):
        # separate IR into each channel
        IR.audio = np.reshape(hoa3_IR.audio[:, i], (-1, 1))
        # convolve mono input with channel IR
        ych.append(reverb(input, IR, align=align))

    # combine into HOA3 output
    y = audio.fromtype('HOA3')
    y.fs = input.fs
    y.audio = np.column_stack(
        [
            ych[0].audio,
@@ -316,6 +378,13 @@ def reverb_hoa2(
            ych[6].audio,
            ych[7].audio,
            ych[8].audio,
            ych[9].audio,
            ych[10].audio,
            ych[11].audio,
            ych[12].audio,
            ych[13].audio,
            ych[14].audio,
            ych[15].audio,
        ]
    )