Bugfix in exportAsWave, with normalize

This commit is contained in:
Anne de Jong 2021-04-29 20:48:21 +02:00
parent 5e32b6264d
commit 99b8553235

View File

@ -96,6 +96,9 @@ class IterRawData:
Args:
f: Audio dataset in the h5 file, accessed as f['audio']
channels: list of channel indices to use
istart: index of first sample
istop: index of last sample (not including istop)
"""
assert isinstance(channels, list)
@ -173,22 +176,6 @@ class IterData(IterRawData):
return scaleBlockSens(nextraw, self.sens)
def exportAsWave(fn, fs, data, force=False):
if '.wav' not in fn[-4:]:
fn += '.wav'
nchannels = data.shape[1]
sampwidth = getSampWidth(data.dtype)
if os.path.exists(fn) and not force:
raise RuntimeError('File already exists: %s', fn)
with wave.open(fn, 'w') as wf:
wf.setparams((nchannels, sampwidth, fs, 0, 'NONE', 'NONE'))
wf.writeframes(np.asfortranarray(data).tobytes())
class Measurement:
"""Provides access to measurement data stored in the h5 measurement file
format."""
@ -594,7 +581,7 @@ class Measurement:
def exportAsWave(self, fn=None, force=False, newsampwidth=None,
normalize=True, channels=None):
normalize=True, **kwargs):
"""Export measurement file as wave. In case the measurement data is
stored as floats, the values are scaled to the proper integer (PCM)
data format.
@ -626,20 +613,21 @@ class Measurement:
if not np.isclose(self.samplerate%1,0):
raise RuntimeError(f'Sample rates should be approximately integer for exporting to Wave to work')
# TODO: With VERY large files, this is not possible!
data = self.rawData()
if np.issubdtype(data.dtype, np.floating):
if newsampwidth is None:
# TODO: With VERY large measurment files, this is not possible! Is this
# a theoretical case?
data = self.rawData(**kwargs)
if np.issubdtype(data.dtype, np.floating) and newsampwidth is None:
raise ValueError('Newsampwidth parameter should be given for floating point raw data')
if normalize:
maxabs = np.max(np.abs(data), axis=0)
data /= maxabs[np.newaxis, :]
# Scale back to maximum of absolute value
maxabs = np.max(np.abs(data))
data /= maxabs
if newsampwidth is not None:
# Convert to floats, then to new sample width
data = scaleBlockSens(data, self.sensitivity**0)
sensone = np.ones_like(self.sensitivity)
data = scaleBlockSens(data, sensone)
if newsampwidth == 2:
newtype = np.int16
@ -648,11 +636,11 @@ class Measurement:
else:
raise ValueError('Invalid sample width, should be 2 or 4')
scalefac = 2**(8*(newsampwidth-1))-1
scalefac = 2**(8*newsampwidth-1)-1
# Scale data to integer range, and then convert to integers
data = (data*scalefac).astype(newtype)
wavfile.write(fn, int(self.samplerate), data)
@staticmethod