def log_weightingfilter(stop_freq=20000.0,
                        branches=5,
                        input=sumpf.Signal(),
                        amplify=True):
    ip_prp = sumpf.modules.ChannelDataProperties()
    ip_prp.SetSignal(input)
    frequencies = [
        stop_freq,
    ] * branches
    filter_spec = []
    for i, freq in enumerate(frequencies):
        alpha_filter = sumpf.modules.WeightingFilterGenerator(
            weighting=sumpf.modules.WeightingFilterGenerator.A,
            resolution=ip_prp.GetResolution(),
            length=ip_prp.GetSpectrumLength())
        alpha_filter.SetMaximumFrequency(frequency=freq)
        spec = alpha_filter.GetSpectrum()
        if amplify is True:
            amp = 1.0 / (i + 1)
            spec = sumpf.modules.AmplifySpectrum(input=spec,
                                                 factor=amp).GetOutput()
        kernel = sumpf.modules.InverseFourierTransform(spec).GetSignal()
        kernel = sumpf.Signal(channels=kernel.GetChannels(),
                              samplingrate=input.GetSamplingRate(),
                              labels=kernel.GetLabels())
        filter_spec.append(kernel)
    # filter_spec = [i for i in reversed(filter_spec)]
    return filter_spec
Example #2
0
def test_merge_signals_manually():
    """Tests the merging behavior with manually generated signals."""
    signal1 = sumpf.Signal(channels=numpy.array([(1.1, 1.2, 1.3)]),
                           sampling_rate=1.0,
                           offset=1,
                           labels=("s1c1",))
    signal2 = sumpf.Signal(channels=numpy.array([(2.1, 2.2, 2.3, 2.4), (3.1, 3.2, 3.3, 3.4)]),
                           sampling_rate=2.0,
                           offset=-4,
                           labels=("s2c1", "s2c2"))
    signal12 = sumpf.Signal(channels=numpy.array([(0.0, 0.0, 0.0, 0.0, 0.0, 1.1, 1.2, 1.3),
                                                  (2.1, 2.2, 2.3, 2.4, 0.0, 0.0, 0.0, 0.0),
                                                  (3.1, 3.2, 3.3, 3.4, 0.0, 0.0, 0.0, 0.0)]),
                            sampling_rate=1.0,
                            offset=-4,
                            labels=("s1c1", "s2c1", "s2c2"))
    signal21 = sumpf.Signal(channels=numpy.array([(2.1, 2.2, 2.3, 2.4, 0.0, 0.0, 0.0, 0.0),
                                                  (3.1, 3.2, 3.3, 3.4, 0.0, 0.0, 0.0, 0.0),
                                                  (0.0, 0.0, 0.0, 0.0, 0.0, 1.1, 1.2, 1.3)]),
                            sampling_rate=2.0,
                            offset=-4,
                            labels=("s2c1", "s2c2", "s1c1"))
    signal21c = sumpf.Signal(channels=numpy.array([(2.1, 2.2, 2.3, 2.4, 0.0, 0.0, 0.0, 0.0),
                                                   (0.0, 0.0, 0.0, 0.0, 0.0, 1.1, 1.2, 1.3),
                                                   (3.1, 3.2, 3.3, 3.4, 0.0, 0.0, 0.0, 0.0)]),
                             sampling_rate=2.0,
                             offset=-4,
                             labels=("s2c1", "s1c1", "s2c2"))
    FIRST_CHANNELS_FIRST = sumpf.Merge.modes.FIRST_CHANNELS_FIRST
    assert sumpf.Merge([signal1, signal2]).output() == signal12
    assert sumpf.Merge([signal2, signal1]).output() == signal21
    assert sumpf.Merge([signal1, signal2], mode=FIRST_CHANNELS_FIRST).output() == signal12
    assert sumpf.Merge([signal2, signal1], mode=FIRST_CHANNELS_FIRST).output() == signal21c
    def GetHarmonicImpulseResponse(self):
        """
        Get the harmonic impuse response.

        :return: the harmonic impulse response
        """
        # stable
        sweep_rate = self.__sweep_generator.GetSweepExcitationRate()
        harmonic_start_time = self.__sweep_duration - (math.log(self.__harmonic_order) * sweep_rate)

        harmonic_start_sample = sumpf.modules.DurationToLength(duration=harmonic_start_time,
                                                               samplingrate=self.__impulse_response.GetSamplingRate(),
                                                               even_length=False).GetLength()
        harmonic_stop_sample = len(self.__impulse_response)
        if self.__harmonic_order > 2:
            harmonic_stop_time = self.__sweep_duration - (math.log(self.__harmonic_order - 1) * sweep_rate)
            harmonic_stop_sample = sumpf.modules.DurationToLength(duration=harmonic_stop_time,
                                                                  samplingrate=self.__impulse_response.GetSamplingRate(),
                                                                  even_length=False).GetLength()
        # prepare the labels
        labels = []
        affix = " (%s harmonic)" % sumpf.helper.counting_number(self.__harmonic_order)
        for l in self.__impulse_response.GetLabels():
            if l is None:
                labels.append("Impulse Response" + affix)
            else:
                labels.append(l + affix)
        # crop to the impulse response of the wanted harmonic
        cropped = self.__impulse_response[harmonic_start_sample:harmonic_stop_sample]
        harmonic = sumpf.Signal(channels=cropped.GetChannels(),
                                samplingrate=cropped.GetSamplingRate(), labels=tuple(labels))
        if len(harmonic) % 2 != 0:
            harmonic = sumpf.Signal(channels=tuple([c + (0.0,) for c in harmonic.GetChannels()]),
                                    samplingrate=harmonic.GetSamplingRate(), labels=harmonic.GetLabels())
        return harmonic
Example #4
0
def _concatenate_signals(signals):
    """A simple but inefficient implementation, that concatenates signals by adding them."""
    # test for the corner cases of zero or one signal
    if not signals:
        raise RuntimeError("Nothing to concatenate")
    if len(signals) == 1:
        return signals[0]
    # add the signals
    sum_ = signals[0]
    index = signals[0].length() + signals[0].offset()
    for s in signals[1:]:
        # fill missing channels with zeros
        if len(s) < len(sum_):
            new_channels = numpy.zeros(shape=(len(sum_), s.length()))
            new_channels[0:len(s)] = s.channels()
            s = sumpf.Signal(channels=new_channels, offset=s.offset())
        elif len(sum_) < len(s):
            new_channels = numpy.zeros(shape=(len(s), sum_.length()))
            new_channels[0:len(sum_)] = sum_.channels()
            sum_ = sumpf.Signal(channels=new_channels, offset=sum_.offset())
        sum_ += s.shift(index)
        index += s.length() + s.offset()
    # return a signal with the correct labels
    return sumpf.Signal(channels=sum_.channels(),
                        sampling_rate=signals[0].sampling_rate(),
                        offset=sum_.offset(),
                        labels=tuple(
                            tuple(f"Concatenation {i}"
                                  for i in range(1,
                                                 len(sum_) + 1))))
Example #5
0
def test_manually_generated_signals():
    """Tests the concatenation behavior with manually generated signals."""
    signal1 = sumpf.Signal(channels=numpy.array([(1.1, 1.2, 1.3)]),
                           sampling_rate=1.0,
                           offset=1,
                           labels=("s1c1", ))
    signal2 = sumpf.Signal(channels=numpy.array([(2.1, 2.2, 2.3, 2.4),
                                                 (3.1, 3.2, 3.3, 3.4)]),
                           sampling_rate=2.0,
                           offset=-4,
                           labels=("s2c1", "s2c2"))
    signal12 = sumpf.Signal(channels=numpy.array([(2.1, 3.3, 3.5, 3.7),
                                                  (3.1, 3.2, 3.3, 3.4)]),
                            sampling_rate=1.0,
                            offset=0,
                            labels=("Concatenation 1", "Concatenation 2"))
    signal21 = sumpf.Signal(channels=numpy.array([
        (2.1, 2.2, 2.3, 2.4, 0.0, 1.1, 1.2, 1.3),
        (3.1, 3.2, 3.3, 3.4, 0.0, 0.0, 0.0, 0.0)
    ]),
                            sampling_rate=2.0,
                            offset=-4,
                            labels=("Concatenation 1", "Concatenation 2"))
    assert tests.compare_signals_approx(
        _concatenate_signals([signal1, signal2]), signal12)
    assert tests.compare_signals_approx(
        _concatenate_signals([signal2, signal1]), signal21)
    assert tests.compare_signals_approx(
        sumpf.Concatenate([signal1, signal2]).output(), signal12)
    assert tests.compare_signals_approx(
        sumpf.Concatenate([signal2, signal1]).output(), signal21)
Example #6
0
def from_rows(time_column, data_rows, labels):
    """Deserializes a signal from tabular data.

    :param time_column: a vector with time values, that correspond to the rows
                        in the data_rows matrix with the same index.
    :param data_rows: a matrix, where the rows contain a sample for each channel
                      of the signal.
    :param labels: the labels for the channels or an empty tuple.
    :returns: the deserialized signal
    """
    if len(data_rows) and len(data_rows[0]):    # pylint: disable=len-as-condition; data_rows can be a NumPy array
        sorted_time_row = sorted(time_column)
        minimum_time = sorted_time_row[0]
        maximum_time = sorted_time_row[-1]
        if len(sorted_time_row) <= 1:
            if minimum_time == 0.0:
                sampling_rate = 48000.0
            else:
                sampling_rate = 1.0 / abs(minimum_time)
        else:
            sampling_rate = (len(sorted_time_row) - 1) / (maximum_time - minimum_time)
        offset = int(round(minimum_time * sampling_rate))
        if numpy.array_equal(time_column, sorted_time_row):
            sorted_data_rows = data_rows
        else:
            sorted_data_rows = [[e for _, e in sorted(zip(time_column, data_row))] for data_row in data_rows]
        channels = allocate_array(shape=numpy.shape(sorted_data_rows))
        channels[:] = sorted_data_rows
        if len(labels) < len(channels):
            labels = tuple(labels) + ("",) * (len(channels) - len(labels))
        elif len(labels) > len(channels):
            labels = labels[0:len(channels)]
        return sumpf.Signal(channels=channels, sampling_rate=sampling_rate, offset=offset, labels=labels)
    else:
        return sumpf.Signal()
def dot_product(signal1=None, signal2=None):
    if signal1 is None:
        signal1 = sumpf.Signal()
    if signal2 is None:
        signal2 = sumpf.Signal()
    product = sumpf.modules.MultiplySignals(signal1=signal1,
                                            signal2=signal2).GetOutput()
    energy_allchannels = []
    for c in product.GetChannels():
        energy_singlechannel = []
        for s in c:
            energy_singlechannel.append(abs(s)**2)
        energy_allchannels.append(numpy.sum(energy_singlechannel))
    return energy_allchannels
Example #8
0
    def _GetFilterImpuleResponses(self):
        """
        Get the identified filter impulse responses.

        :return: the filter impulse responses
        """
        branches = max(self._select_branches)
        input_wgn = self.GetExcitation()
        output_wgn = self._system_response
        hermite_filterkernels = []
        decorrelated_inputs = self.__get_decorrelated_inputs(
            input_signal=input_wgn, branches=branches)
        for branch in range(branches):
            mode = sumpf.modules.CorrelateSignals.SPECTRUM
            input_decorrelated = decorrelated_inputs[branch]
            variance = sumpf.modules.SignalMean(
                input_decorrelated * input_decorrelated).GetMean()[0]
            cross_corr = sumpf.modules.CorrelateSignals(
                signal1=input_decorrelated, signal2=output_wgn,
                mode=mode).GetOutput()
            num = sumpf.modules.FourierTransform(cross_corr).GetSpectrum()
            den = sumpf.modules.FourierTransform(
                sumpf.modules.CorrelateSignals(
                    signal1=input_decorrelated,
                    signal2=input_decorrelated,
                    mode=mode).GetOutput()).GetSpectrum()
            linear = sumpf.modules.Divide(value1=num, value2=den).GetResult()
            kernel = sumpf.modules.InverseFourierTransform(linear).GetSignal()
            signal = sumpf.Signal(channels=kernel.GetChannels(),
                                  samplingrate=input_wgn.GetSamplingRate(),
                                  labels=kernel.GetLabels())
            hermite_filterkernels.append(signal)
        return hermite_filterkernels
Example #9
0
def test_channels_manual():
    """compares the result of an energy decay curve computation to a manually computed result."""
    signal = sumpf.Signal(channels=numpy.array([(1.0, 2.0, 3.0), (0.4, 0.5,
                                                                  0.6)]))
    edc = sumpf.EnergyDecayCurve(signal).channels()
    ref = numpy.array([(14.0, 13.0, 9.0), (0.77, 0.61, 0.36)])
    assert (edc == ref).all()
Example #10
0
def _compare_merge_signals_first_channel_first(signals, merged):
    """test if the merged signal's channels are ordered in a way that the first
    channels of all input signals come first"""
    sampling_rate = signals[0].sampling_rate()
    signals = list(signals)
    c = 0
    d = 0
    while signals:
        to_remove = []
        for s in signals:
            if d < len(s):
                signal = sumpf.Signal(channels=s[d].channels(),
                                      sampling_rate=sampling_rate,  # take the sampling rate from the first signal
                                      offset=s[d].offset(),
                                      labels=s[d].labels())         # the merged signal has a label for each channel, which could be empty
                start = signal.offset() - merged.offset()
                stop = start + signal.length()
                assert merged[c, start:stop] == signal
                c += 1
            else:
                to_remove.append(s)
        for s in to_remove:
            signals.remove(s)
        d += 1
    assert c == len(merged)
Example #11
0
def _sanitize_offsets(data):
    """makes sure, that the offsets of the signals and spectrograms are not so
    large, that the  merged signal requires excessive amounts of memory."""
    first_offset = data[0].offset()
    r = random.Random()
    r.seed(first_offset)
    # the first signal is returned with its original offset
    result = [data[0]]
    # the other signal's offset must not differ from the first signal's offset by more than their length
    for s in data[1:]:
        if abs(first_offset - s.offset()) < s.length():
            result.append(s)
        else:
            if isinstance(s, sumpf.Signal):
                result.append(sumpf.Signal(channels=s.channels(),
                                           sampling_rate=s.sampling_rate(),
                                           offset=random.randint(first_offset - s.length(),
                                                                 first_offset + s.length()),
                                           labels=s.labels()))
            else:  # s must be a spectrogram
                result.append(sumpf.Spectrogram(channels=s.channels(),
                                                resolution=s.resolution(),
                                                sampling_rate=s.sampling_rate(),
                                                offset=random.randint(first_offset - s.length(),
                                                                      first_offset + s.length()),
                                                labels=s.labels()))
    return result
def get_nl_harmonics_iden(sweep_generator, response, harmonics):
    sweep_length = sweep_generator.GetLength()
    rev = sweep_generator.GetReversedOutput()
    rev_spec = sumpf.modules.FourierTransform(rev).GetSpectrum()
    out_spec = sumpf.modules.FourierTransform(response).GetSpectrum()
    out_spec = out_spec / response.GetSamplingRate()
    tf = rev_spec * out_spec
    ir_sweep = sumpf.modules.InverseFourierTransform(tf).GetSignal()
    ir_sweep_direct = sumpf.modules.CutSignal(signal=ir_sweep,
                                              start=0,
                                              stop=int(sweep_length /
                                                       4)).GetOutput()
    ir_sweep_direct = nlsp.append_zeros(ir_sweep_direct)
    ir_sweep_direct = nlsp.relabel(ir_sweep_direct, "Identified Harmonics 1")
    ir_merger = sumpf.modules.MergeSignals(
        on_length_conflict=sumpf.modules.MergeSignals.FILL_WITH_ZEROS)
    ir_merger.AddInput(ir_sweep_direct)
    for i in range(harmonics - 1):
        split_harm = nlsp.FindHarmonicImpulseResponse_Novak(
            impulse_response=ir_sweep,
            harmonic_order=i + 2,
            sweep_generator=sweep_generator).GetHarmonicImpulseResponse()
        split_harm = sumpf.modules.CutSignal(
            signal=split_harm,
            stop=len(sweep_generator.GetOutput())).GetOutput()
        ir_merger.AddInput(
            sumpf.Signal(channels=split_harm.GetChannels(),
                         samplingrate=ir_sweep.GetSamplingRate(),
                         labels=("Identified Harmonics %r" % (i + 2), )))
    tf = sumpf.modules.FourierTransform(ir_merger.GetOutput()).GetSpectrum()
    return tf
def release_feature1(audio, threshold):
    thr = pow(10, -threshold / 20)
    signal = np.reshape(audio, [1, audio.size])
    signal = sumpf.Signal(signal, 44100.0)

    obj = SignalEnvelope(signal)
    a = obj.GetEnvelope()
    b = np.array(a.GetChannels())
    b = np.reshape(b, b.size)

    y_top = peakutils.indexes(b, thres=thr, min_dist=100)
    y_bottom = peakutils.indexes(thr - b, thres=0, min_dist=100)

    top_label = np.array([y_top, np.zeros(y_top.size)])
    bottom_label = np.array([y_bottom, np.ones(y_bottom.size)])

    labels = np.concatenate((top_label, bottom_label), axis=1)
    sorted_labels = np.array(sorted(np.transpose(labels), key=itemgetter(0)),
                             dtype='int')

    slop = []
    for i in range(sorted_labels.size / 4, sorted_labels.size / 2):
        j = i - 1
        if sorted_labels[i, 1] == 0 and sorted_labels[j, 1] == 1:
            k = sorted_labels[i, 0] - sorted_labels[j, 0]
            slop.append((b[sorted_labels[i, 0]] - b[sorted_labels[j, 0]]) / k)
        else:
            i += 1
            j += 1

    release_feature_AVR = np.mean(slop)
    release_feature_VAR = np.var(slop)

    return release_feature_AVR, release_feature_VAR
def getnl_ir(sweep_generator,output_sweep,branches=5):
    sweep_length = sweep_generator.GetLength()
    sweep_start_freq = sweep_generator.GetStartFrequency()
    sweep_stop_freq = sweep_generator.GetStopFrequency()
    ip_signal = sweep_generator.GetOutput()

    # output_sweep = nlsp.append_zeros(output_sweep)
    rev = sweep_generator.GetReversedOutput()
    rev_spec = sumpf.modules.FourierTransform(rev).GetSpectrum()
    out_spec = sumpf.modules.FourierTransform(output_sweep).GetSpectrum()
    out_spec = out_spec / output_sweep.GetSamplingRate()
    tf = rev_spec * out_spec
    ir_sweep = sumpf.modules.InverseFourierTransform(tf).GetSignal()
    # nlsp.common.plots.plot(ir_sweep)

    ir_sweep_direct = sumpf.modules.CutSignal(signal=ir_sweep,start=0,stop=int(sweep_length/4)).GetOutput()
    ir_sweep_direct = nlsp.append_zeros(ir_sweep_direct)
    ir_merger = sumpf.modules.MergeSignals(on_length_conflict=sumpf.modules.MergeSignals.FILL_WITH_ZEROS)
    ir_merger.AddInput(ir_sweep_direct)
    for i in range(branches-1):
        split_harm = nlsp.FindHarmonicImpulseResponse_Novak(impulse_response=ir_sweep,
                                                            harmonic_order=i+2,
                                                            sweep_generator=sweep_generator).GetHarmonicImpulseResponse()
        split_harm = sumpf.modules.CutSignal(signal=split_harm,stop=len(sweep_generator.GetOutput())).GetOutput()
        ir_merger.AddInput(sumpf.Signal(channels=split_harm.GetChannels(),
                                        samplingrate=ir_sweep.GetSamplingRate(), labels=split_harm.GetLabels()))
    ir_merger = ir_merger.GetOutput()

    # nlsp.common.plots.plot(ir_merger)
    return ir_sweep
Example #15
0
def _sanitize_offsets(data):
    """makes sure, that the offsets of the signals and spectrograms are not so
    large, that the concatenation requires excessive amounts of memory."""
    r = random.Random()
    r.seed(data[0].offset())
    # the first data set is returned with its original offset
    result = [data[0]]
    # the other data sets offset must not exceed their length, so the concatenation is at maximum twice as long as the original data sets combined
    for s in data[1:]:
        if abs(s.offset()) < s.length():
            result.append(s)
        else:
            if isinstance(s, sumpf.Signal):
                result.append(
                    sumpf.Signal(channels=s.channels(),
                                 sampling_rate=s.sampling_rate(),
                                 offset=random.randint(-s.length(),
                                                       s.length()),
                                 labels=s.labels()))
            else:
                result.append(
                    sumpf.Spectrogram(channels=s.channels(),
                                      resolution=s.resolution(),
                                      sampling_rate=s.sampling_rate(),
                                      offset=random.randint(
                                          -s.length(), s.length()),
                                      labels=s.labels()))
    return result
 def func(channel):
     signal = sumpf.Signal(channels=(channel, ),
                           samplingrate=48000,
                           labels=("nl", ))
     clipped = nlsp.sumpf.SoftClipSignal(signal=signal,
                                         thresholds=thresholds)
     return numpy.asarray(clipped.GetOutput().GetChannels()[0])
Example #17
0
def miso_identification(input_generator, output_wgn, branches):
    """
    MISO approach of system identification.
    :param input_generator: the input generator or the input signal
    :param output_wgn: the response of the nonlinear system
    :param branches: the number of branches
    :return: the filter kernels and the nonlinear function of a HGM
    """
    if hasattr(input_generator,"GetOutput"):
        input_wgn = input_generator.GetOutput()
    else:
        input_wgn = input_generator
    l = []
    L = []
    signal_matrix, k_matrix, mu_matrix = wgn_hgm_decorrelate(input_wgn,branches)
    for branch in range(1,branches+1):
        input_decorrelated = signal_matrix[branch-1]
        cross_corr = sumpf.modules.CorrelateSignals(signal1=input_decorrelated,signal2=output_wgn,mode=sumpf.modules.CorrelateSignals.SPECTRUM).GetOutput()
        num = sumpf.modules.FourierTransform(cross_corr).GetSpectrum()
        den = sumpf.modules.FourierTransform(sumpf.modules.CorrelateSignals(signal1=input_decorrelated,
                                                                            signal2=input_decorrelated,mode=sumpf.modules.CorrelateSignals.SPECTRUM).GetOutput()).GetSpectrum()
        linear = sumpf.modules.DivideSpectrums(spectrum1=num, spectrum2=den).GetOutput()
        kernel = sumpf.modules.InverseFourierTransform(linear).GetSignal()
        signal = sumpf.Signal(channels=kernel.GetChannels(),samplingrate=input_wgn.GetSamplingRate(),labels=kernel.GetLabels())
        l.append(signal)
        L.append(sumpf.modules.FourierTransform(signal).GetSpectrum())
    G = []
    for row in range(0,branches):
        A = sumpf.modules.ConstantSpectrumGenerator(value=0.0,resolution=L[0].GetResolution(),length=len(L[0])).GetSpectrum()
        for column in range(0,branches):
            temp = sumpf.modules.AmplifySpectrum(input=L[column],factor=k_matrix[row][column]).GetOutput()
            A = A + temp
        G.append(sumpf.modules.InverseFourierTransform(A + mu_matrix[row]).GetSignal())
    nl_func = nlsp.nl_branches(nlsp.function_factory.power_series,branches)
    return G,nl_func
Example #18
0
def test_output_ports():
    """Tests if the output ports of the :class:`~sumpf.Jack` instances are created
    from the labels of their input signal.
    """
    with _create_client() as client:
        xruns = _XRunHandler()
        jack = sumpf.Jack("CUT")  # Client Under Test
        jack.xruns.connect(xruns.xrun)
        # check the output port for the empty default input signal
        assert ["CUT:output_1"] == [
            p.name for p in client.get_ports(is_output=True)
            if p.name.startswith("CUT:")
        ]
        # check adding and renaming output ports
        jack.input(
            sumpf.MergeSignals([sumpf.BetaNoise(),
                                sumpf.SquareWave()]).output())
        assert ["CUT:Beta noise", "CUT:Square wave"] == [p.name for p in client.get_ports(is_output=True) if p.name.startswith("CUT:")]  # pylint: disable=line-too-long
        # check removing and renaming output ports
        jack.input(sumpf.ExponentialSweep())
        assert ["CUT:Sweep"] == [
            p.name for p in client.get_ports(is_output=True)
            if p.name.startswith("CUT:")
        ]
        # check generating port names from a signal with crooked labels
        jack.input(
            sumpf.Signal(channels=numpy.eye(3), labels=(None, "output_1"))
        )  # one label None, one label already exists as port name and one label is missing
        assert ["CUT:output_1", "CUT:output_2", "CUT:output_3"] == [p.name for p in client.get_ports(is_output=True) if p.name.startswith("CUT:")]  # pylint: disable=line-too-long
        assert xruns.xruns == []
    def GetReversedOutput(self, numberofsamples=None):
        """
        Get the reversed output sine sweep signal.

        :param numberofsamples: number of samples of the reversed sine sweep signal
        """
        numpy.seterr(all='ignore')
        if numberofsamples is None:
            length = self.GetLength()
        else:
            length = numberofsamples
        sampling_rate = self.GetOutput().GetSamplingRate()
        sweep_parameter = self.GetSweepExcitationRate()
        # fft_len = int(2**numpy.ceil(numpy.log2(length)))
        fft_len = int(length)
        interval = numpy.linspace(0,
                                  sampling_rate / 2.0,
                                  num=fft_len / 2 + 1.0)
        inverse_sweep = 2 * numpy.sqrt(interval / sweep_parameter) * numpy.exp(
            1j *
            (2 * numpy.pi * sweep_parameter * interval *
             (self.GetStartFrequency() / interval + numpy.log(
                 interval / self.GetStartFrequency()) - 1) + numpy.pi / 4))
        inverse_sweep[0] = 0j
        rev_sweep = numpy.fft.irfft(inverse_sweep)
        rev_sweep = sumpf.Signal(channels=(rev_sweep, ),
                                 samplingrate=sampling_rate,
                                 labels=("Reversed Sweep signal", ))
        rev_sweep = sumpf.modules.Multiply(
            value1=rev_sweep,
            value2=1.0 / self.GetAmplitudeRange()).GetResult()
        numpy.seterr(all='warn')
        return rev_sweep
    def GetOutput(self):
        """
        Get the output sine sweep signal.

        :return: the output sine sweep signal
        """
        t = numpy.arange(0,
                         self.GetLength() / self.__sampling_rate,
                         1 / self.__sampling_rate)
        s = numpy.sin(2 * numpy.pi * self.__start_frequency *
                      self.GetSweepExcitationRate() *
                      (numpy.exp(t / self.GetSweepExcitationRate()) - 1))
        if self.__fade_in > 0:
            s[0:self.__fade_in] = s[0:self.__fade_in] * ((-numpy.cos(
                numpy.arange(self.__fade_in) / self.__fade_in * numpy.pi) + 1)
                                                         / 2)
        if self.__fade_out > 0:
            s[-self.__fade_out:] = s[-self.__fade_out:] * ((numpy.cos(
                numpy.arange(self.__fade_out) / self.__fade_out * numpy.pi) +
                                                            1) / 2)
        ip_signal = sumpf.Signal(channels=(s, ),
                                 samplingrate=self.__sampling_rate,
                                 labels=("Sweep signal", ))
        if len(ip_signal) % 2 != 0:
            ip_signal = sumpf.modules.CutSignal(ip_signal, start=0,
                                                stop=-1).GetOutput()
        ip_signal = self.GetAmplitudeRange() * ip_signal
        return ip_signal
Example #21
0
def get_window(window, overlap, symmetric=True, sampling_rate=48000.0):
    """Convenience method for defining a window function

    * if window is an integer, a window function with that length will be generated.
       * if overlap is zero, the generated window will be a rectangular window.
       * otherwise, a Hann window will be generated.
    * if window is a :func:`numpy.array`, it will be wrapped in a :class:`~sumpf.Signal`.
    * if window is iterable, it will be converted to a :func:`numpy.array` and then wrapped in a :class:`~sumpf.Signal`.
    * otherwise, it will be returned as it is.

    :param window: an integer window length or a window signal
    :param overlap: the overlap in the application of the window function as an integer or a float
    :param symmetric: True, if the window's last sample shall be the same as its
                      first sample. False, if the window's last sample shall be
                      the same as its second sample. The latter is often beneficial
                      in segmentation applications, as it makes it easier to meet
                      the "constant overlap add"-constraint.
    :param sampling_rate: optional, specifies the sampling rate if a window is generated
    :returns: a :class:`~sumpf.Signal` instance
    """
    if isinstance(window, int):
        if overlap == 0:
            return sumpf.RectangularWindow(sampling_rate=sampling_rate,
                                           length=window,
                                           symmetric=symmetric)
        else:
            return sumpf.HannWindow(sampling_rate=sampling_rate,
                                    length=window,
                                    symmetric=symmetric)
    elif isinstance(window, numpy.ndarray):
        if len(window.shape) == 1:
            return sumpf.Signal(channels=numpy.array([window]),
                                sampling_rate=sampling_rate,
                                labels=("Window", ))
        elif len(window.shape) == 2:
            return sumpf.Signal(channels=window,
                                sampling_rate=sampling_rate,
                                labels=("Window", ) * len(window))
        else:
            raise ValueError(
                f"Array of shape {window.shape} cannot be wrapped in a Signal")
    elif isinstance(window, collections.abc.Iterable):
        return get_window(window=numpy.array(window),
                          overlap=overlap,
                          sampling_rate=sampling_rate)
    else:
        return window
 def GetOutput(self):
     new_channels = []
     for c in self.__signal.GetChannels():
         self.__dummy = c
         new_channels.append(tuple(self.__nonlin_func((c))))
     return sumpf.Signal(channels=new_channels,
                         samplingrate=self.__signal.GetSamplingRate(),
                         labels=self.__signal.GetLabels())
Example #23
0
    def _GetFilterImpuleResponses(self):
        """
        Get the identified filter impulse responses.

        :return: the filter impulse responses
        """
        branches = max(self._select_branches)
        sweep_length = self.__excitation_generator.GetLength()
        rev = self.__excitation_generator.GetReversedOutput()
        rev_spec = sumpf.modules.FourierTransform(rev).GetSpectrum()
        out_spec = sumpf.modules.FourierTransform(self._system_response).GetSpectrum()
        out_spec = out_spec / self._system_response.GetSamplingRate()
        tf = rev_spec * out_spec
        ir_sweep = sumpf.modules.InverseFourierTransform(tf).GetSignal()
        ir_sweep_direct = sumpf.modules.CutSignal(signal=ir_sweep, start=0, stop=int(sweep_length / 4)).GetOutput()
        ir_merger = sumpf.modules.MergeSignals(on_length_conflict=sumpf.modules.MergeSignals.FILL_WITH_ZEROS)
        ir_merger.AddInput(ir_sweep_direct)
        for i in range(branches - 1):
            split_harm = nlsp.common.FindHarmonicImpulseResponse_NovakSweep(impulse_response=ir_sweep,
                                                                            harmonic_order=i + 2,
                                                                            sweep_generator=self.__excitation_generator).GetHarmonicImpulseResponse()
            split_harm = sumpf.modules.CutSignal(signal=split_harm,
                                                 stop=len(self.__excitation_generator.GetOutput())).GetOutput()
            ir_merger.AddInput(sumpf.Signal(channels=split_harm.GetChannels(),
                                            samplingrate=ir_sweep.GetSamplingRate(),
                                            labels=split_harm.GetLabels()))
        ir_merger = ir_merger.GetOutput()
        n = len(ir_merger.GetChannels()) // branches
        items = range(len(ir_merger.GetChannels()))
        clubbed = [a for a in zip(*[iter(items)] * n)]
        ir_harmonics = []
        for clubb in clubbed:
            ir_harmonics.append(sumpf.modules.SplitSignal(data=ir_merger, channels=clubb).GetOutput())
        filter_kernels = []
        for branch in self._select_branches:
            if self._filter_length is not None:
                filter_kernels.append(
                    nlsp.common.helper_functions_private.change_length_signal(signal=ir_harmonics[branch - 1],
                                                                              length=self._filter_length))
            else:
                filter_kernels.append(ir_harmonics[branch - 1])
        filters = []
        for filt in filter_kernels:
            filters.append(sumpf.Signal(channels=filt.GetChannels(), samplingrate=ir_sweep.GetSamplingRate(),
                                        labels=filt.GetLabels()))
        return filter_kernels
def absolute(inputfreqspectrum):
    channels = []
    for c in inputfreqspectrum.GetChannels():
        channel = []
        for s in c:
            channel.append(abs(s))
        channels.append(tuple(channel))
    return sumpf.Signal(channels=tuple(channels),
                        labels=inputfreqspectrum.GetLabels())
    def __init__(self, input_signal=None, nonlinear_functions=(nlsp.function_factory.power_series(1),),
                 filter_irs=None, max_harmonics=None,
                 filterfunction=sumpf.modules.FilterGenerator.BUTTERWORTH(order=20),
                 attenuation=0.0001):
        """
        :param signal: the input signal
        :param nonlinear_functions: the tuple of nonlinear functions eg. (nlsp.function_factory.power_series(1),...)
        :param filter_irs: the tuple of filter impulse responses eg. (IR1,...)
        :param max_harmonics: the tuple of maximum harmonics eg. (1,...)
        :param filterfunction: the type of filter used for lowpass operation eg. sumpf.modules.FilterGenerator.BUTTERWORTH(order=20)
        :param attenuation: the attenuation required at the cutoff frequency eg. 0.001
        :return:
        """
        if input_signal is None:
            self.__signal = sumpf.Signal()
        else:
            self.__signal = input_signal
        self.inputstage = sumpf.modules.AmplifySignal(input=self.__signal)
        self.__nlfunctions = nonlinear_functions
        if filter_irs is None:
            self.__filter_irs = (sumpf.modules.ImpulseGenerator(length=len(input_signal)).GetSignal(),)
        else:
            self.__filter_irs = filter_irs
        self.__filterfunction = filterfunction
        self.__attenuation = attenuation
        if len(self.__nlfunctions) == len(self.__filter_irs):
            self.__branches = len(self.__nlfunctions)
        else:
            print "the given arguments dont have same length"
        if max_harmonics is None:
            self.__max_harmonics = range(1,self.__branches+1)
        else:
            self.__max_harmonics = max_harmonics
        self.hmodels = []
        self.__sums = [None] * self.__branches

        for nl,ir,mh in zip(self.__nlfunctions,self.__filter_irs,self.__max_harmonics):
            h = nlsp.AliasingCompensatedHM_lowpass(input_signal=self.inputstage.GetOutput(),
                                                              nonlin_func=nl, max_harm=mh,
                                                              filter_impulseresponse=ir,
                                                              filterfunction=self.__filterfunction,
                                                              attenuation=attenuation)
            self.hmodels.append(h)

        for i in reversed(range(len(self.hmodels)-1)):
            self.__a = sumpf.modules.AddSignals()
            # print "connecting hammerstein model %i to adder %i" % (i, i)
            sumpf.connect(self.hmodels[i].GetOutput, self.__a.SetInput1)
            if i == len(self.hmodels)-2:
                # print "connecting hammerstein model %i to adder %i" % (i+1, i)
                sumpf.connect(self.hmodels[i+1].GetOutput, self.__a.SetInput2)
            else:
                # print "connecting adder %i to adder %i" % (i+1, i)
                sumpf.connect(self.__sums[i+1].GetOutput, self.__a.SetInput2)
            self.__sums[i] = self.__a

        self.GetOutput = self.__sums[0].GetOutput
 def __init__(self, input_signal=None, desired_output=None, filter_length=None, initialcoefficients=None,
              step_size=None,
              leakage=None, iteration_cycle=None):
     """
     :param input_signal: the input signal
     :type input_signal: sumpf.Signal()
     :param desired_output: the desired output signal
     :type desired_output: sumpf.Signal()
     :param filter_length: the filter length
     :type filter_length: int
     :param initialcoefficients: the initial coefficients
     :type initialcoefficients: sumpf.Signal()
     :param step_size: the step size
     :type step_size: float
     :param leakage: the leakage value
     :type leakage: Eg, 0-no leakage, <1-leaky filter design, >2-error
     :param iteration_cycle: the iteration cycles, multiple iteration cycles results in over adaptation
     :type iteration_cycle: int
     """
     if input_signal is None:
         self._input_signal = sumpf.Signal()
     else:
         self._input_signal = input_signal
     if desired_output is None:
         self._desired_output = sumpf.Signal()
     else:
         self._desired_output = desired_output
     if filter_length is None:
         self._filter_length = 2 ** 10
     else:
         self._filter_length = filter_length
     self._initial_coeff = initialcoefficients
     if leakage is None:
         self._leakage = 0
     else:
         self._leakage = leakage
     if iteration_cycle is None:
         self._iteration_cycle = 1
     else:
         self._iteration_cycle = iteration_cycle
     if step_size is None:
         self._step_size = 0.1
     else:
         self._step_size = step_size
Example #27
0
    def __init__(self, input_signal1=None, input_signal2=None):
        """
        :param input_signal1: the first input signal
        :param input_signal2: the second input signal
        """
        # Get the input parameters
        if input_signal1 is None:
            self.__input_signal1 = sumpf.Signal()
        else:
            self.__input_signal1 = input_signal1

        if input_signal2 is None:
            self.__input_signal2 = sumpf.Signal()
        else:
            self.__input_signal2 = input_signal2

        self.__output_signal1 = self.__input_signal1
        self.__output_signal2 = self.__input_signal2
        self._changelength()
Example #28
0
    def inverse_fourier_transform(self):
        """Computes the channel-wise inverse Fourier transform of this spectrum.

        :returns: a :class:`~sumpf.Signal` instance
        """
        if self._length == 0:
            return sumpf.Signal(channels=numpy.empty(shape=(len(self), 0)),
                                sampling_rate=0.0,
                                offset=0,
                                labels=self._labels)
        length = max(1, (self._length - 1) * 2)
        sampling_rate = self.__resolution * length
        channels = sumpf_internal.allocate_array(shape=(len(self._channels),
                                                        length))
        channels[:, :] = numpy.fft.irfft(self._channels, n=length)
        return sumpf.Signal(channels=channels,
                            sampling_rate=sampling_rate,
                            offset=0,
                            labels=self._labels)
 def GetOutput(self):
     t = numpy.arange(0,self.GetLength()/self.__sampling_rate,1/self.__sampling_rate)
     s = numpy.sin(2*numpy.pi*self.__start_frequency*self.GetSweepParameter()*(numpy.exp(t/self.GetSweepParameter())-1))
     if self.__fade_in > 0:
         s[0:self.__fade_in] = s[0:self.__fade_in] * ((-numpy.cos(numpy.arange(self.__fade_in)/self.__fade_in*math.pi)+1) / 2)
     if self.__fade_out > 0:
         s[-self.__fade_out:] = s[-self.__fade_out:] *  ((numpy.cos(numpy.arange(self.__fade_out)/self.__fade_out*numpy.pi)+1) / 2)
     signal = sumpf.Signal(channels=(s,),samplingrate=self.__sampling_rate,labels=("Sweep signal",))
     if len(signal) % 2 != 0:
         signal = sumpf.modules.CutSignal(signal,start=0,stop=-1).GetOutput()
     return signal
Example #30
0
def from_dict(dictionary):
    """Deserializes a signal from a dictionary."""
    if "channels" in dictionary:
        channels = allocate_array(shape=numpy.shape(dictionary["channels"]))
        channels[:, :] = dictionary["channels"]
    else:
        channels = numpy.empty(shape=(1, 0))
    return sumpf.Signal(channels=channels,
                        sampling_rate=dictionary.get("sampling_rate", 48000.0),
                        offset=dictionary.get("offset", 0),
                        labels=dictionary.get("labels", ()))