Skip to content

Commit

Permalink
Consolidate decimate functions in a single file
Browse files Browse the repository at this point in the history
  • Loading branch information
tlecomte committed Mar 25, 2018
1 parent b8cc8ac commit f6825eb
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 61 deletions.
43 changes: 5 additions & 38 deletions friture/delay_estimator.py
Expand Up @@ -21,47 +21,14 @@
from numpy import argmax
import numpy
from numpy.fft import rfft, irfft
from .filter import decimate
from .signal.decimate import decimate_multiple, decimate_multiple_filtic
from friture import generated_filters
from .ringbuffer import RingBuffer

from friture.audiobackend import SAMPLING_RATE

DEFAULT_DELAYRANGE = 1 # default delay range is 1 second


def subsampler(Ndec, bdec, adec, x, zis):
x_dec = x

# FIXME problems when x is smaller than filter coeff

# do not run on empty arrays, otherwise bad artefacts on the output !!
if x.size == 0:
return x, zis

if zis is None:
for i in range(Ndec):
x_dec, zf = decimate(bdec, adec, x_dec)
return x_dec, None
else:
zfs = []
for i, zi in zip(list(range(Ndec)), zis):
x_dec, zf = decimate(bdec, adec, x_dec, zi=zi)
# zf can be reused to restart the filter
zfs += [zf]
return x_dec, zfs

# build a proper array of zero initial conditions to start the subsampler


def subsampler_filtic(Ndec, bdec, adec):
zfs = []
for i in range(Ndec):
l = max(len(bdec), len(adec)) - 1
zfs += [numpy.zeros(l)]
return zfs


def generalized_cross_correlation(d0, d1):
# substract the means
# (in order to get a normalized cross-correlation at the end)
Expand Down Expand Up @@ -160,8 +127,8 @@ def __init__(self, parent=None):
[self.bdec, self.adec] = generated_filters.PARAMS['dec']
self.bdec = numpy.array(self.bdec)
self.adec = numpy.array(self.adec)
self.zfs0 = subsampler_filtic(self.Ndec, self.bdec, self.adec)
self.zfs1 = subsampler_filtic(self.Ndec, self.bdec, self.adec)
self.zfs0 = decimate_multiple_filtic(self.Ndec, self.bdec, self.adec)
self.zfs1 = decimate_multiple_filtic(self.Ndec, self.bdec, self.adec)

# ringbuffers for the subsampled data
self.ringbuffer0 = RingBuffer()
Expand Down Expand Up @@ -193,8 +160,8 @@ def handle_new_data(self, floatdata):
x0 = floatdata[0, :]
x1 = floatdata[1, :]
# subsample them
x0_dec, self.zfs0 = subsampler(self.Ndec, self.bdec, self.adec, x0, self.zfs0)
x1_dec, self.zfs1 = subsampler(self.Ndec, self.bdec, self.adec, x1, self.zfs1)
x0_dec, self.zfs0 = decimate_multiple(self.Ndec, self.bdec, self.adec, x0, self.zfs0)
x1_dec, self.zfs1 = decimate_multiple(self.Ndec, self.bdec, self.adec, x1, self.zfs1)
# push to a 1-second ring buffer
x0_dec.shape = (1, x0_dec.size)
x1_dec.shape = (1, x1_dec.size)
Expand Down
14 changes: 1 addition & 13 deletions friture/filter.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from numpy import arange, sqrt, zeros, array
from .lfilter import pyx_lfilter_float64_1D
from .signal.decimate import decimate

NOCTAVE = 9

Expand Down Expand Up @@ -114,20 +115,7 @@ def octave_filter_bank_decimation(blow, alow, forward, feedback, x, zis):

return y, dec, zfs


def decimate(bdec, adec, x, zi):
if len(x) == 0:
raise Exception("Filter input is too small")

# could use a polyphase decimator here
x_dec, zf = pyx_lfilter_float64_1D(bdec, adec, x, zi)

x_dec = x_dec[::2]
return x_dec, zf

# build a proper array of zero initial conditions to start the filters


def octave_filter_bank_decimation_filtic(blow, alow, forward, feedback):
bands_per_octave = len(forward)
zfs = []
Expand Down
4 changes: 1 addition & 3 deletions friture/longlevels.py
Expand Up @@ -26,9 +26,7 @@
DEFAULT_LEVEL_MAX)
from friture.audioproc import audioproc
from friture.timeplot import TimePlot
from .filter import decimate
from friture import generated_filters
from friture.exp_smoothing_conv import pyx_exp_smoothed_value
from .signal.decimate import decimate
from .ringbuffer import RingBuffer
from .lfilter import pyx_lfilter_float64_1D

Expand Down
61 changes: 61 additions & 0 deletions friture/signal/decimate.py
@@ -0,0 +1,61 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (C) 2018 Timothée Lecomte

# This file is part of Friture.
#
# Friture is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as published by
# the Free Software Foundation.
#
# Friture is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Friture. If not, see <http://www.gnu.org/licenses/>.

import numpy
from ..lfilter import pyx_lfilter_float64_1D

def decimate(bdec, adec, x, zi):
if len(x) == 0:
raise Exception("Filter input is too small")

# could use a polyphase decimator here
x_dec, zf = pyx_lfilter_float64_1D(bdec, adec, x, zi)

x_dec = x_dec[::2]
return x_dec, zf

# decimate 'Ndec' times
def decimate_multiple(Ndec, bdec, adec, x, zis):
x_dec = x

# FIXME problems when x is smaller than filter coeff

# do not run on empty arrays, otherwise output contains artifacts
if x.size == 0:
return x, zis

if zis is None:
for i in range(Ndec):
x_dec, zf = decimate(bdec, adec, x_dec)
return x_dec, None
else:
zfs = []
for i, zi in zip(list(range(Ndec)), zis):
x_dec, zf = decimate(bdec, adec, x_dec, zi=zi)
# zf can be reused to restart the filter
zfs += [zf]
return x_dec, zfs

# build a proper array of zero initial conditions to start the subsampler
def decimate_multiple_filtic(Ndec, bdec, adec):
zfs = []
for i in range(Ndec):
l = max(len(bdec), len(adec)) - 1
zfs += [numpy.zeros(l)]
return zfs
13 changes: 6 additions & 7 deletions sandbox/delay.py
Expand Up @@ -21,10 +21,9 @@
import numpy
import numpy as np
from numpy.fft import rfft, irfft, fft, ifft
from friture.filter import decimate
from friture import generated_filters
from friture.ringbuffer import RingBuffer
from friture.delay_estimator import subsampler, subsampler_filtic, DEFAULT_DELAYRANGE
from friture.delay_estimator import DEFAULT_DELAYRANGE
from friture.signal.decimate import decimate_multiple, decimate_multiple_filtic
from scipy.io import wavfile
import matplotlib.pyplot as plt

Expand Down Expand Up @@ -106,8 +105,8 @@ def main():
Ndec = 2
subsampled_sampling_rate = SAMPLING_RATE/2**(Ndec)
[bdec, adec] = generated_filters.PARAMS['dec']
zfs0 = subsampler_filtic(Ndec, bdec, adec)
zfs1 = subsampler_filtic(Ndec, bdec, adec)
zfs0 = decimate_multiple_filtic(Ndec, bdec, adec)
zfs1 = decimate_multiple_filtic(Ndec, bdec, adec)

delayrange_s = DEFAULT_DELAYRANGE # confidence range

Expand All @@ -116,9 +115,9 @@ def main():
x1 = m
#subsample them
print("subsampling x0")
x0_dec, zfs0 = subsampler(Ndec, bdec, adec, x0, zfs0)
x0_dec, zfs0 = decimate_multiple(Ndec, bdec, adec, x0, zfs0)
print("subsampling x1")
x1_dec, zfs1 = subsampler(Ndec, bdec, adec, x1, zfs1)
x1_dec, zfs1 = decimate_multiple(Ndec, bdec, adec, x1, zfs1)

time = 2*delayrange_s
length = time*subsampled_sampling_rate
Expand Down

0 comments on commit f6825eb

Please sign in to comment.