Created
October 11, 2019 15:21
-
-
Save HudsonHuang/fbdf8e9af7993fe2a91620d3fb86a182 to your computer and use it in GitHub Desktop.
Convert audio data of PCM16/float32 to byte, and vice versa.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Helper functions for working with audio files in NumPy.""" | |
"""some code borrowed from https://github.com/mgeier/python-audio/blob/master/audio-files/utility.py""" | |
import numpy as np | |
import contextlib | |
import librosa | |
import struct | |
import soundfile | |
def float_to_byte(sig): | |
# float32 -> int16(PCM_16) -> byte | |
return float2pcm(sig, dtype='int16').tobytes() | |
def byte_to_float(byte): | |
# byte -> int16(PCM_16) -> float32 | |
return pcm2float(np.frombuffer(byte,dtype=np.int16), dtype='float32') | |
def pcm2float(sig, dtype='float32'): | |
"""Convert PCM signal to floating point with a range from -1 to 1. | |
Use dtype='float32' for single precision. | |
Parameters | |
---------- | |
sig : array_like | |
Input array, must have integral type. | |
dtype : data type, optional | |
Desired (floating point) data type. | |
Returns | |
------- | |
numpy.ndarray | |
Normalized floating point data. | |
See Also | |
-------- | |
float2pcm, dtype | |
""" | |
sig = np.asarray(sig) | |
if sig.dtype.kind not in 'iu': | |
raise TypeError("'sig' must be an array of integers") | |
dtype = np.dtype(dtype) | |
if dtype.kind != 'f': | |
raise TypeError("'dtype' must be a floating point type") | |
i = np.iinfo(sig.dtype) | |
abs_max = 2 ** (i.bits - 1) | |
offset = i.min + abs_max | |
return (sig.astype(dtype) - offset) / abs_max | |
def float2pcm(sig, dtype='int16'): | |
"""Convert floating point signal with a range from -1 to 1 to PCM. | |
Any signal values outside the interval [-1.0, 1.0) are clipped. | |
No dithering is used. | |
Note that there are different possibilities for scaling floating | |
point numbers to PCM numbers, this function implements just one of | |
them. For an overview of alternatives see | |
http://blog.bjornroche.com/2009/12/int-float-int-its-jungle-out-there.html | |
Parameters | |
---------- | |
sig : array_like | |
Input array, must have floating point type. | |
dtype : data type, optional | |
Desired (integer) data type. | |
Returns | |
------- | |
numpy.ndarray | |
Integer data, scaled and clipped to the range of the given | |
*dtype*. | |
See Also | |
-------- | |
pcm2float, dtype | |
""" | |
sig = np.asarray(sig) | |
if sig.dtype.kind != 'f': | |
raise TypeError("'sig' must be a float array") | |
dtype = np.dtype(dtype) | |
if dtype.kind not in 'iu': | |
raise TypeError("'dtype' must be an integer type") | |
i = np.iinfo(dtype) | |
abs_max = 2 ** (i.bits - 1) | |
offset = i.min + abs_max | |
return (sig * abs_max + offset).clip(i.min, i.max).astype(dtype) | |
@contextlib.contextmanager | |
def printoptions(*args, **kwargs): | |
"""Context manager for temporarily setting NumPy print options. | |
See http://stackoverflow.com/a/2891805/500098 | |
""" | |
original = np.get_printoptions() | |
try: | |
np.set_printoptions(*args, **kwargs) | |
yield | |
finally: | |
np.set_printoptions(**original) | |
if __name__ == "__main__": | |
# load file to float32 | |
y,sr = librosa.load("1.wav",sr=None) | |
# convert to byte(PCM16) | |
byt = float_to_byte(y) | |
# save to pcm file | |
with open("1.pcm","wb") as f: | |
f.write(byt) | |
# read pcm file | |
with open("1.pcm","rb") as f: | |
byt = f.read() | |
# byte(PCM16) to float32 | |
f = byte_to_float(byt) | |
# save float32 to PCM16 with soundfile | |
soundfile.write("2.wav",f,sr,'PCM_16') |
Saved my day! <3
Very cool, saved us :)
THANK YOU!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you! Very nice