WarrenWeckesser / wavio

A Python module for reading and writing WAV files using numpy arrays.
133 stars 19 forks source link

_scale_to_sampwidth() produces DC offset when writing wav #13

Closed rviviano closed 1 year ago

rviviano commented 4 years ago

First off, thank you so much for writing this module! It saved me a lot of headache trying to work with 24-bit int wavs.

However, the scaling solution can translate the audio an appreciable amount when the waveform to be written has a zero mean but is asymmetric; that is, the magnitude of vmin and vmax are dissimilar. This is fairly common with complex real-world audio.

This dc offset can produce pops during the beginning and end of sample playback and can show up on spectrum analyzers as a peak << 1hz. Overall, I don't think this function should perform any translation.

I think a better option for 16bit+ would be to normalize the audio with something like:

normalization_ratio = outmax/np.max(np.abs(data)) 
data = normalization_ratio * data

Scaled 8bit audio should maintain a zero-crossing value of 127 or at least try to maintain the mean signal amplitude of the original data.

nj-vs-vh commented 3 years ago

+1 on this

Exitare commented 3 years ago

We encounter the same issue in our project. As this issue is old, are there any plans to fix this or is this library not supported anymore?

nj-vs-vh commented 3 years ago

Hey, I have just created PR for the issue, you can check it out and see if it resolves your problems!

Exitare commented 3 years ago

Hey, thanks for the PR!

WarrenWeckesser commented 2 years ago

A very belated "thanks!" for the feedback. I have rewritten--and simplified--the scaling behavior.

I don't think this function should perform any translation.

You're not the only one who has requested this, so wavio.write() no longer does any translation of the input. In the updated code, wavio.write() will always map the floating point value 0.0 to the midpoint of the integer output (i.e. 0 when the output is 16, 24 or 32 bit).

I haven't made a release yet, but I should get to that within a week.

Important! This is a backwards incompatible change! If you are still using wavio, once I have released 0.0.5, be sure to either update your code to use the new scaling behavior, or pin the dependency to version 0.0.4.

WarrenWeckesser commented 1 year ago

I have pushed a new version to PyPI, with the simplified API for writing. The latest release is 0.0.6 (the only difference between 0.0.5 and 0.0.6 is an update to README.rst). As noted in my previous comment, if anyone needs to use the old API for backwards compatibility, they should pin their dependency on wavio to version 0.0.4.