***[Possible UCE]*** [SciPy-user] Help with array functions
Travis Oliphant
oliphant at ee.byu.edu
Tue May 4 13:47:43 CDT 2004
Bob.Cowdery at CGI-Europe.com wrote:
> Hi all,
>
> Can anyone help me convert this loop to an array function. I can't
> have loops in my signal processing as they take far too much
> processing power. This is a fragment from a speech processor using
> Ferkins formula. Essentially the gain array (m_procGain) which is 2048
> long (m_sampl_sz) needs its nth element processing into it's (n-1)th
> element. This is eventually used to multiply the samples in
> m_complexout, the first 2048 elements of this are used. Attack is a
> scaler currently 0.4.
>
> peak =
> abs(self.m_complexout[argmax(abs(self.m_complexout[:self.m_sampl_sz]))])
> i = arange(1,self.m_sampl_sz)
> for x in i:
> if abs(self.m_complexout[x-1]) > 0:
> self.m_procGain[x] = ( (self.m_procGain[x-1] *
> (1 - attack)) + ((attack * peak) / abs(self.m_complexout[x-1])) )
> if self.m_procGain[x] > level:
> self.m_procGain[x] = level
> else:
> self.m_procGain[x] = 1
>
Bob,
You have here something similar to an IIR filter. The command
signal.lfilter is usually used in situations like this.
If I read this code correctly then define y[n] = self.m_procGain[n]
with a = (1-attack)
w[n] = (attack*peak) / abs(self.m_complexout[n])
and you want to basically compute
y[n] = a y[n-1] + w[n-1]
as long as w[n-1] is not infinite because of zero-valued
abs(self.m_complexout[n-1])
The problem with using signal.lfilter is you have a non-linear filter
due to the if statements. You could try to modify the algorithm a bit
to maintain a linear filter, or you will have to use weave (or f2py).
Just to expose you to the many ways to accomplish the problem. Here is
another test using f2py
******** Results *********************
weave results: [ 0. 0.8 0.96 0.992 0.9984 1. 1.
1. 1.
1. ]
python results: [ 0. 0.8 0.96 0.992 0.9984 1.
1. 1. 1.
1. ]
f2py results: [ 0. 0.8 0.96 0.992 0.9984 1. 1.
1. 1.
1. ]
C time: 0.08
Python time: 6.13
f2py time: 0.05
weave vs. Python speedup: 76.625
f2py vs. Python speedup: 122.6
********* Code below ***********
# test.py
fort_code = r"""
subroutine gain_compute(gain, abs_complexout, attack, peak,
$ level, samples)
integer samples
double precision attack, peak, level
double precision gain(samples), abs_complexout(samples)
double precision val
integer i
do i = 2, samples
if (abs_complexout(i-1).gt.0.0) then
val = gain(i-1)*(1.0-attack) +
$ (attack*peak) / abs_complexout(i-1)
if (val.gt.level) then
val = level
end if
else
val = 1.0
end if
gain(i) = val
end do
return
end subroutine gain_compute
"""
from scipy import zeros, ones, Float64, arange
from scipy import stats
import scipy_distutils
import weave
import f2py2e
try:
import forttest
except ImportError:
f2py2e.compile(fort_code, modulename='forttest')
import forttest
def python_algorithm(gain, abs_complexout, attack, peak, level, samples):
# gain is changed *inplace*
i = arange(1,samples)
for x in i:
if abs_complexout[x-1] > 0:
gain[x] = ( (gain[x-1] * (1.0 - attack)) + ((attack * peak) /
abs_complexout[x-1]) )
if gain[x] > level:
gain[x] = level
else:
gain[x] = 1
def weave_algorithm(gain, abs_complexout, attack, peak, level, samples):
# gain is changed *inplace*
code = """
for (int x=1; x < samples; x++)
{
if (abs_complexout[x-1] > 0.0)
{
gain[x] = ( (gain[x-1] * (1.0 - attack)) +
((attack * peak) / abs_complexout[x-1])
); if (gain[x] > level)
gain[x] = level;
}
else
gain[x] = 1;
}
"""
weave.inline(code,
['gain', 'abs_complexout', 'samples', 'attack', 'peak',
'level'],
compiler='gcc')
# some default parameters...
samples = 2048
gain = zeros(samples,typecode=Float64)
complexout = stats.choice([-1.0,0.0,1.0],size=samples)
attack = .8
peak = 1.0
level = 1.0
# equivalence tests
ac = abs(complexout)
weave_algorithm(gain, ac, attack, peak, level, samples)
print 'weave results:', gain[:10]
gain = zeros(samples,typecode=Float64)
python_algorithm(gain, ac, attack, peak, level, samples)
print 'python results:', gain[:10]
gain = zeros(samples,typecode=Float64)
forttest.gain_compute(gain, ac, attack, peak, level, samples)
print 'f2py results:', gain[:10]
# speed tests
import time
N = 1000
t1 = time.clock()
for it in range(N):
weave_algorithm(gain, complexout, attack, peak, level, samples)
t2 = time.clock()
ct = t2 - t1
print 'C time:', ct
t1 = time.clock()
for it in range(N):
python_algorithm(gain, complexout, attack, peak, level, samples)
t2 = time.clock()
pt = t2-t1
print 'Python time:', pt
f2py_algorithm = forttest.gain_compute
t1 = time.clock()
for it in range(N):
f2py_algorithm(gain, complexout, attack, peak, level, samples)
t2 = time.clock()
ft = t2-t1
print 'f2py time:', ft
ratio = pt/ct
ratio2 = pt/ft
print 'weave vs. Python speedup:', ratio
print 'f2py vs. Python speedup:', ratio2
> Thanks for any assistance.
>
> Bob
>
>
> Bob Cowdery
> CGI Senior Technical Architect
> +44(0)1438 791517
> Mobile: +44(0)7771 532138
> bob.cowdery at cgi-europe.com <mailto:bob.cowdery at cgi-europe.com>
>
>
>
>
> **** Confidentiality Notice **** Proprietary/Confidential
> Information belonging to CGI Group Inc. and its affiliates
> may be contained in this message. If you are not a recipient
> indicated or intended in this message (or responsible for
> delivery of this message to such person), or you think for
> any reason that this message may have been addressed to you
> in error, you may not use or copy or deliver this message
> to anyone else. In such case, you should destroy this
> message and are asked to notify the sender by reply email.
>
>------------------------------------------------------------------------
>
>_______________________________________________
>SciPy-user mailing list
>SciPy-user at scipy.net
>http://www.scipy.net/mailman/listinfo/scipy-user
>
>
More information about the SciPy-user
mailing list