1 /* GStreamer
2 * Copyright (C) 2010 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
3 * Copyright (C) 2010 Nokia Corporation. All rights reserved.
4 * Contact: Stefan Kost <stefan.kost@nokia.com>
5 *
6 * Tremor modifications <2006>:
7 * Chris Lord, OpenedHand Ltd. <chris@openedhand.com>, http://www.o-hand.com/
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <string.h>
30 #include "gstvorbisdeclib.h"
31 #include "gstvorbiscommon.h"
32
33 #ifndef TREMOR
34 /* These samples can be outside of the float -1.0 -- 1.0 range, this
35 * is allowed, downstream elements are supposed to clip */
36 static void
copy_samples_m(vorbis_sample_t * out,vorbis_sample_t ** in,guint samples,gint channels)37 copy_samples_m (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
38 gint channels)
39 {
40 memcpy (out, in[0], samples * sizeof (float));
41 }
42
43 static void
copy_samples_s(vorbis_sample_t * out,vorbis_sample_t ** in,guint samples,gint channels)44 copy_samples_s (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
45 gint channels)
46 {
47 #ifdef GST_VORBIS_DEC_SEQUENTIAL
48 memcpy (out, in[0], samples * sizeof (float));
49 out += samples;
50 memcpy (out, in[1], samples * sizeof (float));
51 #else
52 gint j;
53
54 for (j = 0; j < samples; j++) {
55 *out++ = in[0][j];
56 *out++ = in[1][j];
57 }
58 #endif
59 }
60
61 static void
copy_samples(vorbis_sample_t * out,vorbis_sample_t ** in,guint samples,gint channels)62 copy_samples (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
63 gint channels)
64 {
65 #ifdef GST_VORBIS_DEC_SEQUENTIAL
66 gint i;
67
68 for (i = 0; i < channels; i++) {
69 memcpy (out, in[gst_vorbis_reorder_map[channels - 1][i]],
70 samples * sizeof (float));
71 out += samples;
72 }
73 #else
74 gint i, j;
75
76 for (j = 0; j < samples; j++) {
77 for (i = 0; i < channels; i++) {
78 *out++ = in[gst_vorbis_reorder_map[channels - 1][i]][j];
79 }
80 }
81 #endif
82 }
83
84 static void
copy_samples_no_reorder(vorbis_sample_t * out,vorbis_sample_t ** in,guint samples,gint channels)85 copy_samples_no_reorder (vorbis_sample_t * out, vorbis_sample_t ** in,
86 guint samples, gint channels)
87 {
88 #ifdef GST_VORBIS_DEC_SEQUENTIAL
89 gint i;
90
91 for (i = 0; i < channels; i++) {
92 memcpy (out, in[i], samples * sizeof (float));
93 out += samples;
94 }
95 #else
96 gint i, j;
97
98 for (j = 0; j < samples; j++) {
99 for (i = 0; i < channels; i++) {
100 *out++ = in[i][j];
101 }
102 }
103 #endif
104 }
105
106 CopySampleFunc
gst_vorbis_get_copy_sample_func(gint channels)107 gst_vorbis_get_copy_sample_func (gint channels)
108 {
109 CopySampleFunc f = NULL;
110
111 switch (channels) {
112 case 1:
113 f = copy_samples_m;
114 break;
115 case 2:
116 f = copy_samples_s;
117 break;
118 case 3:
119 case 4:
120 case 5:
121 case 6:
122 case 7:
123 case 8:
124 f = copy_samples;
125 break;
126 default:
127 f = copy_samples_no_reorder;
128 break;
129 }
130
131 return f;
132 }
133
134 #else
135
136 /* Taken from Tremor, misc.h */
137 #ifdef _ARM_ASSEM_
138 static inline ogg_int32_t
CLIP_TO_15(ogg_int32_t x)139 CLIP_TO_15 (ogg_int32_t x)
140 {
141 int tmp;
142 asm volatile ("subs %1, %0, #32768\n\t"
143 "movpl %0, #0x7f00\n\t"
144 "orrpl %0, %0, #0xff\n"
145 "adds %1, %0, #32768\n\t"
146 "movmi %0, #0x8000":"+r" (x), "=r" (tmp)
147 ::"cc");
148
149 return (x);
150 }
151 #else
152 static inline ogg_int32_t
CLIP_TO_15(ogg_int32_t x)153 CLIP_TO_15 (ogg_int32_t x)
154 {
155 int ret = x;
156
157 ret -= ((x <= 32767) - 1) & (x - 32767);
158 ret -= ((x >= -32768) - 1) & (x + 32768);
159 return (ret);
160 }
161 #endif
162
163 static void
copy_samples_16_m(vorbis_sample_t * _out,vorbis_sample_t ** _in,guint samples,gint channels)164 copy_samples_16_m (vorbis_sample_t * _out, vorbis_sample_t ** _in,
165 guint samples, gint channels)
166 {
167 gint16 *out = (gint16 *) _out;
168 ogg_int32_t **in = (ogg_int32_t **) _in;
169 gint j;
170
171 for (j = 0; j < samples; j++) {
172 *out++ = CLIP_TO_15 (in[0][j] >> 9);
173 }
174 }
175
176 static void
copy_samples_16_s(vorbis_sample_t * _out,vorbis_sample_t ** _in,guint samples,gint channels)177 copy_samples_16_s (vorbis_sample_t * _out, vorbis_sample_t ** _in,
178 guint samples, gint channels)
179 {
180 gint16 *out = (gint16 *) _out;
181 ogg_int32_t **in = (ogg_int32_t **) _in;
182 gint j;
183
184 for (j = 0; j < samples; j++) {
185 *out++ = CLIP_TO_15 (in[0][j] >> 9);
186 *out++ = CLIP_TO_15 (in[1][j] >> 9);
187 }
188 }
189
190 static void
copy_samples_16(vorbis_sample_t * _out,vorbis_sample_t ** _in,guint samples,gint channels)191 copy_samples_16 (vorbis_sample_t * _out, vorbis_sample_t ** _in, guint samples,
192 gint channels)
193 {
194 gint16 *out = (gint16 *) _out;
195 ogg_int32_t **in = (ogg_int32_t **) _in;
196 gint i, j;
197
198 for (j = 0; j < samples; j++) {
199 for (i = 0; i < channels; i++) {
200 *out++ = CLIP_TO_15 (in[gst_vorbis_reorder_map[channels - 1][i]][j] >> 9);
201 }
202 }
203 }
204
205 CopySampleFunc
gst_vorbis_get_copy_sample_func(gint channels)206 gst_vorbis_get_copy_sample_func (gint channels)
207 {
208 CopySampleFunc f = NULL;
209
210 switch (channels) {
211 case 1:
212 f = copy_samples_16_m;
213 break;
214 case 2:
215 f = copy_samples_16_s;
216 break;
217 default:
218 f = copy_samples_16;
219 break;
220 }
221 return f;
222 }
223
224 #endif
225