예제 #1
0
    def __init__(self,
                 frame_length=160,
                 n_subframes=4,
                 lpc_order=10,
                 fixed_codebook_size=128,
                 adaptive_codebook_size=160,
                 frame_window="boxcar",
                 weigthing_coeff_1=0.9,
                 weigthing_coeff_2=0.6):

        self.frame_length = frame_length
        self.n_subframes = n_subframes
        self.lpc_order = lpc_order
        self.fc_size = fixed_codebook_size
        self.ac_size = adaptive_codebook_size

        self.subframe_length = self.frame_length / self.n_subframes
        self.zero_input = np.zeros(self.frame_length)
        self.delta = np.concatenate(([1.], np.zeros(self.subframe_length - 1)))

        self.frame_window = scipy.signal.get_window(frame_window, frame_length)

        self.weigthing_coeff_1, self.weigthing_coeff_2 = weigthing_coeff_1, weigthing_coeff_2

        self.fixed_codebook = FC

        self.adaptive_codebook = AdaptiveCodebook(
            vector_size=self.subframe_length,
            cb_size=adaptive_codebook_size,
            min_period=20)

        self._excitation = np.zeros(self.subframe_length)
예제 #2
0
    def test_add_vector(self):
        cb_size = 30
        vector_size = 10
        ac = AdaptiveCodebook(vector_size=vector_size,
                              cb_size=cb_size,
                              min_period=5)

        vector = [1] * vector_size
        ac.add_vector(vector)
        self.assertEqual(ac[0],
                         vector[-ac.min_period:] + vector[-ac.min_period:])
예제 #3
0
    def test_values(self):
        cb_size = 20
        vector_size = 10
        ac = AdaptiveCodebook(vector_size=vector_size,
                              cb_size=cb_size,
                              min_period=5)

        ac.samples = range(-ac.max_period, 0)

        self.assertEqual(ac[0], [-5, -4, -3, -2, -1, -5, -4, -3, -2, -1])
        self.assertEqual(ac[1], [-6, -5, -4, -3, -2, -1, -6, -5, -4, -3])
        self.assertEqual(ac[5], [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1])
        self.assertEqual(ac[19],
                         [-24, -23, -22, -21, -20, -19, -18, -17, -16, -15])
예제 #4
0
 def test_empty(self):
     cb_size = 20
     vector_size = 10
     ac = AdaptiveCodebook(vector_size=vector_size,
                           cb_size=cb_size,
                           min_period=5)
     self.assertEqual(len(ac), cb_size)
     for i in range(cb_size):
         self.assertEqual(len(ac[i]), vector_size)
예제 #5
0
class CELP(object):

    lpc_error_coefs_dtype = np.dtype(np.float16)
    amplifs_dtype = np.dtype(np.float16)
    index_dtype = np.dtype(np.uint8)

    def __init__(self,
                 frame_length=160,
                 n_subframes=4,
                 lpc_order=10,
                 fixed_codebook_size=128,
                 adaptive_codebook_size=160,
                 frame_window="boxcar",
                 weigthing_coeff_1=0.9,
                 weigthing_coeff_2=0.6):

        self.frame_length = frame_length
        self.n_subframes = n_subframes
        self.lpc_order = lpc_order
        self.fc_size = fixed_codebook_size
        self.ac_size = adaptive_codebook_size

        self.subframe_length = self.frame_length / self.n_subframes
        self.zero_input = np.zeros(self.frame_length)
        self.delta = np.concatenate(([1.], np.zeros(self.subframe_length - 1)))

        self.frame_window = scipy.signal.get_window(frame_window, frame_length)

        self.weigthing_coeff_1, self.weigthing_coeff_2 = weigthing_coeff_1, weigthing_coeff_2

        self.fixed_codebook = FC

        self.adaptive_codebook = AdaptiveCodebook(
            vector_size=self.subframe_length,
            cb_size=adaptive_codebook_size,
            min_period=20)

        self._excitation = np.zeros(self.subframe_length)

    def encode(self, frame):
        import lpc
        # Apply window
        frame *= self.frame_window

        # Generate LPC coefficients
        lpc_error_coeffs = lpc.lpc_ref(frame, self.lpc_order)

        out_fc_indexes, out_ac_indexes = [], []
        out_fc_amplifs, out_ac_amplifs = [], []

        # Buld the noise weigthing filter W matrix
        # W(z) = A(z/weigthing_coeff_1) / A(z/weigthing_coeff_2)
        weigthing_b = lpc_error_coeffs * np.power(
            self.weigthing_coeff_1, np.arange(self.lpc_order + 1))
        weigthing_a = lpc_error_coeffs * np.power(
            self.weigthing_coeff_2, np.arange(self.lpc_order + 1))
        w = lfilter(weigthing_b, weigthing_a, self.delta)
        W = scipy.linalg.toeplitz(
            w,
            np.concatenate(
                ([w[0]], self.zero_input[:self.subframe_length - 1])))

        # Buid the H matrix = 1 / A
        h = lfilter([1], lpc_error_coeffs, self.delta)
        H = scipy.linalg.toeplitz(
            h,
            np.concatenate(
                ([h[0]], self.zero_input[:self.subframe_length - 1])))

        for subframe in frame.reshape(
            (self.n_subframes, self.subframe_length)):
            lpc_filtered = lfilter([1], lpc_error_coeffs,
                                   np.concatenate(
                                       (self._excitation,
                                        np.zeros(self.subframe_length))))

            z0 = lpc_filtered[
                self.subframe_length:]  # Zero input response for the H filter
            z1 = lfilter(
                weigthing_b,
                weigthing_a,  # Zero input response for the W filter
                np.concatenate(
                    (lpc_filtered[:self.subframe_length],
                     np.zeros(self.subframe_length))))[self.subframe_length:]

            # Search the best adaptive signal
            M = np.dot(W, H)
            d = np.dot(W, subframe - z0) + z1
            ac_index, ac_amplif = search_codebook(M, d, self.adaptive_codebook)
            ac_excitation = self.adaptive_codebook[ac_index] * ac_amplif

            # Search the best fixed codebook signal
            d = np.dot(W, subframe - z0 - np.dot(H, ac_excitation) + z1)
            fc_index, fc_amplif = search_codebook(M, d, self.fixed_codebook)
            fc_excitation = fc_amplif * self.fixed_codebook[fc_index]

            # Build current excitation using adaptive and fixed codebooks
            self._excitation = ac_excitation + fc_excitation

            # Append current excitation to adaptive codebook
            self.adaptive_codebook.add_vector(self._excitation)

            # store output values for this frame
            out_fc_indexes.append(fc_index)
            out_fc_amplifs.append(fc_amplif)
            out_ac_indexes.append(ac_index)
            out_ac_amplifs.append(ac_amplif)

        # generate binary output string with all output values
        lpc = lpc_error_coeffs.astype(self.lpc_error_coefs_dtype).tostring()
        fc_indexes = np.array(out_fc_indexes,
                              dtype=self.index_dtype).tostring()
        fc_amplifs = np.array(out_fc_amplifs,
                              dtype=self.amplifs_dtype).tostring()
        ac_indexes = np.array(out_ac_indexes,
                              dtype=self.index_dtype).tostring()
        ac_amplifs = np.array(out_ac_amplifs,
                              dtype=self.amplifs_dtype).tostring()

        return lpc + fc_indexes + fc_amplifs + ac_indexes + ac_amplifs

    def bytes_per_frame(self):
        size = self.size_of_lpc(
        ) + self.size_of_indexes() * 2 + self.size_of_amplifs() * 2
        return size

    def size_of_lpc(self):
        return self.lpc_error_coefs_dtype.itemsize * (self.lpc_order + 1)

    def size_of_indexes(self):
        return self.index_dtype.itemsize * self.n_subframes

    def size_of_amplifs(self):
        return self.amplifs_dtype.itemsize * self.n_subframes

    def decode(self, frame_bits):
        frame_bits_it = iter(frame_bits)

        # read input values from input bits
        lpc_error_coeffs = np.fromstring("".join(
            islice(frame_bits_it, self.size_of_lpc())),
                                         dtype=self.lpc_error_coefs_dtype)
        fc_indexes = np.fromstring("".join(
            islice(frame_bits_it, self.size_of_indexes())),
                                   dtype=self.index_dtype)
        fc_amplifs = np.fromstring("".join(
            islice(frame_bits_it, self.size_of_amplifs())),
                                   dtype=self.amplifs_dtype)
        ac_indexes = np.fromstring("".join(
            islice(frame_bits_it, self.size_of_indexes())),
                                   dtype=self.index_dtype)
        ac_amplifs = np.fromstring("".join(
            islice(frame_bits_it, self.size_of_amplifs())),
                                   dtype=self.amplifs_dtype)
        out = np.array([])

        h = lfilter([1], lpc_error_coeffs, self.delta)
        H = scipy.linalg.toeplitz(
            h,
            np.concatenate(
                ([h[0]], self.zero_input[:self.subframe_length - 1])))

        for fc_index, fc_amplif, ac_index, ac_amplif in zip(
                fc_indexes, fc_amplifs, ac_indexes, ac_amplifs):
            z0 = lfilter(
                [1], lpc_error_coeffs,
                np.concatenate(
                    (self._excitation,
                     np.zeros(self.subframe_length))))[self.subframe_length:]
            self._excitation = fc_amplif * self.fixed_codebook[
                fc_index] + ac_amplif * self.adaptive_codebook[ac_index]

            subframe_out = np.dot(H, self._excitation) + z0
            out = np.concatenate((out, subframe_out))

            # Append current excitation to adaptive codebook
            self.adaptive_codebook.add_vector(self._excitation)

        return out