1 /*
2 * Siren Encoder/Decoder library
3 *
4 * @author: Youness Alaoui <kakaroto@kakaroto.homelinux.net>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22
23 #include "siren7.h"
24
25
26 static int rmlt_initialized = 0;
27 static float rmlt_window_640[640];
28 static float rmlt_window_320[320];
29
30 #define PI_2 1.57079632679489661923
31
32 void
siren_rmlt_init(void)33 siren_rmlt_init (void)
34 {
35 int i = 0;
36 float angle;
37
38 for (i = 0; i < 640; i++) {
39 angle = (float) (((i + 0.5) * PI_2) / 640);
40 rmlt_window_640[i] = (float) sin (angle);
41 }
42 for (i = 0; i < 320; i++) {
43 angle = (float) (((i + 0.5) * PI_2) / 320);
44 rmlt_window_320[i] = (float) sin (angle);
45 }
46
47 rmlt_initialized = 1;
48 }
49
50 int
siren_rmlt_encode_samples(float * samples,float * old_samples,int dct_length,float * rmlt_coefs)51 siren_rmlt_encode_samples (float *samples, float *old_samples, int dct_length,
52 float *rmlt_coefs)
53 {
54 int half_dct_length = dct_length / 2;
55 float *old_ptr = old_samples + half_dct_length;
56 float *coef_high = rmlt_coefs + half_dct_length;
57 float *coef_low = rmlt_coefs + half_dct_length;
58 float *samples_low = samples;
59 float *samples_high = samples + dct_length;
60 float *window_low = NULL;
61 float *window_high = NULL;
62 int i = 0;
63
64 if (rmlt_initialized == 0)
65 siren_rmlt_init ();
66
67 if (dct_length == 320)
68 window_low = rmlt_window_320;
69 else if (dct_length == 640)
70 window_low = rmlt_window_640;
71 else
72 return 4;
73
74 window_high = window_low + dct_length;
75
76
77 for (i = 0; i < half_dct_length; i++) {
78 *--coef_low = *--old_ptr;
79 *coef_high++ =
80 (*samples_low * *--window_high) - (*--samples_high * *window_low);
81 *old_ptr =
82 (*samples_high * *window_high) + (*samples_low++ * *window_low++);
83 }
84 siren_dct4 (rmlt_coefs, rmlt_coefs, dct_length);
85
86 return 0;
87 }
88
89
90
91 int
siren_rmlt_decode_samples(float * coefs,float * old_coefs,int dct_length,float * samples)92 siren_rmlt_decode_samples (float *coefs, float *old_coefs, int dct_length,
93 float *samples)
94 {
95 int half_dct_length = dct_length / 2;
96 float *old_low = old_coefs;
97 float *old_high = old_coefs + half_dct_length;
98 float *samples_low = samples;
99 float *samples_high = samples + dct_length;
100 float *samples_middle_low = samples + half_dct_length;
101 float *samples_middle_high = samples + half_dct_length;
102 float *window_low = NULL;
103 float *window_high = NULL;
104 float *window_middle_low = NULL;
105 float *window_middle_high = NULL;
106 float sample_low_val;
107 float sample_high_val;
108 float sample_middle_low_val;
109 float sample_middle_high_val;
110 int i = 0;
111
112 if (rmlt_initialized == 0)
113 siren_rmlt_init ();
114
115 if (dct_length == 320)
116 window_low = rmlt_window_320;
117 else if (dct_length == 640)
118 window_low = rmlt_window_640;
119 else
120 return 4;
121
122
123 window_high = window_low + dct_length;
124 window_middle_low = window_low + half_dct_length;
125 window_middle_high = window_low + half_dct_length;
126
127 siren_dct4 (coefs, samples, dct_length);
128
129 for (i = 0; i < half_dct_length; i += 2) {
130 sample_low_val = *samples_low;
131 sample_high_val = *--samples_high;
132 sample_middle_low_val = *--samples_middle_low;
133 sample_middle_high_val = *samples_middle_high;
134 *samples_low++ =
135 (*old_low * *--window_high) + (sample_middle_low_val * *window_low);
136 *samples_high =
137 (sample_middle_low_val * *window_high) - (*old_low * *window_low++);
138 *samples_middle_high++ =
139 (sample_low_val * *window_middle_high) -
140 (*--old_high * *--window_middle_low);
141 *samples_middle_low =
142 (*old_high * *window_middle_high++) +
143 (sample_low_val * *window_middle_low);
144 *old_low++ = sample_middle_high_val;
145 *old_high = sample_high_val;
146 }
147
148 return 0;
149 }
150