-
Notifications
You must be signed in to change notification settings - Fork 112
/
quantize.py
99 lines (87 loc) · 2.73 KB
/
quantize.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import numpy
np = numpy
#import scikits.audiolab
import random
import time
import os
import glob
### Basic utils ###
def __round_to(x, y):
"""round x up to the nearest y"""
return int(numpy.ceil(x / float(y))) * y
def __normalize(data):
"""To range [0., 1.]"""
data -= data.min(axis=1)[:, None]
data /= data.max(axis=1)[:, None]
return data
def __linear_quantize(data, q_levels):
"""
floats in (0, 1) to ints in [0, q_levels-1]
scales normalized across axis 1
"""
# Normalization is on mini-batch not whole file
#eps = numpy.float64(1e-5)
#data -= data.min(axis=1)[:, None]
#data *= ((q_levels - eps) / data.max(axis=1)[:, None])
#data += eps/2
#data = data.astype('int32')
eps = numpy.float64(1e-5)
data *= (q_levels - eps)
data += eps/2
data = data.astype('int32')
return data
def __a_law_quantize(data):
"""
:todo:
"""
raise NotImplementedError
def linear2mu(x, mu=255):
"""
From Joao
x should be normalized between -1 and 1
Converts an array according to mu-law and discretizes it
Note:
mu2linear(linear2mu(x)) != x
Because we are compressing to 8 bits here.
They will sound pretty much the same, though.
:usage:
>>> bitrate, samples = scipy.io.wavfile.read('orig.wav')
>>> norm = __normalize(samples)[None, :] # It takes 2D as inp
>>> mu_encoded = linear2mu(2.*norm-1.) # From [0, 1] to [-1, 1]
>>> print mu_encoded.min(), mu_encoded.max(), mu_encoded.dtype
0, 255, dtype('int16')
>>> mu_decoded = mu2linear(mu_encoded) # Back to linear
>>> print mu_decoded.min(), mu_decoded.max(), mu_decoded.dtype
-1, 0.9574371, dtype('float32')
"""
x_mu = np.sign(x) * np.log(1 + mu*np.abs(x))/np.log(1 + mu)
return ((x_mu + 1)/2 * mu).astype('int16')
def mu2linear(x, mu=255):
"""
From Joao with modifications
Converts an integer array from mu to linear
For important notes and usage see: linear2mu
"""
mu = float(mu)
x = x.astype('float32')
y = 2. * (x - (mu+1.)/2.) / (mu+1.)
return np.sign(y) * (1./mu) * ((1. + mu)**np.abs(y) - 1.)
def __mu_law_quantize(data):
return linear2mu(data)
def __batch_quantize(data, q_levels, q_type):
"""
One of 'linear', 'a-law', 'mu-law' for q_type.
"""
data = data.astype('float64')
data = __normalize(data)
if q_type == 'linear':
return __linear_quantize(data, q_levels)
if q_type == 'a-law':
return __a_law_quantize(data)
if q_type == 'mu-law':
# from [0, 1] to [-1, 1]
data = 2.*data-1.
# Automatically quantized to 256 bins.
data = __mu_law_quantize(data)
return data
raise NotImplementedError