Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Normalize multidimensional array

I have code to generate and export 12 stereo WAVs

Currently I'm just doing:

for i in range(0,12):
    filename = "out_%d.wav" % i
    L = ... some list of floats between -1.0 and +1.0 ...
    R = ... similarly ...

    exportWAV(filename,L,R)

but the volumes are too quiet.

What I need to do is find the maximum volume across all L & R, and divide all L & R by this volume. Then all of my values will be between -1 and 1.

It isn't a difficult task, and I can hack out some ugly code to get it done.

But how to do it cleanly?

I should be able to do it in just a few lines, something like:

all_LR = ''
all_file = ''

for i in range(0,12):
    filename = ...
    L, R = ...

    all_LR += (L,R)
    all_file += filename

maxVal = max( abs(all_LR) )
all_LR /= maxVal

for file,L,R in zip( all_file, all_LR ):
    exportWAV(filename L,R)

But I can't see how to turn this pseudocode into actual valid Python. abs and max don't operate over an array of tuples where each element in the tuple is itself an array of floats.

I feel like I'm making it more difficult than it needs to be just by trying to save a few lines of code.

EDIT: thanks to the below answer I now have the following working code:

all_LR = []

for i in range(0,12):
    print "Processing %d" % i

    hrtf_file = hrtf_path + "/%02d.wav" % (i+1)
    shep_file = shepard_path + "/shepard_%02d.WAV" % i

    L, R = import_WAV( hrtf_file )
    shep = import_WAV( shep_file )

    out_L = np.convolve(shep,L)
    out_R = np.convolve(shep,R)

    #out_LR = np.array( out_L, out_R )
    out_LR = (list(out_L), list(out_R))
    all_LR.append(out_LR)
    #np.append( all_LR, out_LR )

np_array = np.array(all_LR)

amp_max = np.amax( np.fabs(np_array) )
print( "AmpMAX: %f" % amp_max )

np_array /= amp_max

for i in range(0,12):
    out_file = out3d_path + "/s3D_%02d.WAV" % i
    print out_file

    L,R = np_array[i]

    export_WAV( out_file, L, R )
like image 339
P i Avatar asked Mar 14 '26 21:03

P i


1 Answers

If you can convert your data to numpy.arrays then you can use numpy.amax and numpy.fabs as below.

import numpy as np

a = np.array([(1, 2), (-3, 4), (-2, 2), (0, 1), (1, 3)])

a_abs = np.fabs(a)
print(a_abs)
# [[ 1.  2.]
#  [ 3.  4.]
#  [ 2.  2.]
#  [ 0.  1.]
#  [ 1.  3.]]

a_max = np.amax(a_abs)

print(a_max)
# 4.0

np.fabs will simply return an array of the same shape but with the absolute value for each element in a multidimensional array.

np.amax will return the maximum value of an array. If you select an axis using a keyword-argument (such as np.amax(a, axis=0)) then it will act along that axis. The default for the axis keyword however is None which will cause it to act along the flattened array.

like image 130
Ffisegydd Avatar answered Mar 18 '26 11:03

Ffisegydd



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!