Tizen 2.1 base
[profile/ivi/gst-plugins-base0.10.git] / ext / vorbis / gstvorbisdeclib.c
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., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <string.h>
30 #include "gstvorbisdeclib.h"
31
32 #ifndef TREMOR
33 /* These samples can be outside of the float -1.0 -- 1.0 range, this
34  * is allowed, downstream elements are supposed to clip */
35 static void
36 copy_samples_m (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
37     gint channels, gint width)
38 {
39   memcpy (out, in[0], samples * sizeof (float));
40 }
41
42 static void
43 copy_samples_s (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
44     gint channels, gint width)
45 {
46 #ifdef GST_VORBIS_DEC_SEQUENTIAL
47   memcpy (out, in[0], samples * sizeof (float));
48   out += samples;
49   memcpy (out, in[1], samples * sizeof (float));
50 #else
51   gint j;
52
53   for (j = 0; j < samples; j++) {
54     *out++ = in[0][j];
55     *out++ = in[1][j];
56   }
57 #endif
58 }
59
60 static void
61 copy_samples (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples,
62     gint channels, gint width)
63 {
64 #ifdef GST_VORBIS_DEC_SEQUENTIAL
65   gint i;
66
67   for (i = 0; i < channels; i++) {
68     memcpy (out, in[i], samples * sizeof (float));
69     out += samples;
70   }
71 #else
72   gint i, j;
73
74   for (j = 0; j < samples; j++) {
75     for (i = 0; i < channels; i++) {
76       *out++ = in[i][j];
77     }
78   }
79 #endif
80 }
81
82 CopySampleFunc
83 get_copy_sample_func (gint channels, gint width)
84 {
85   CopySampleFunc f = NULL;
86
87   g_assert (width == 4);
88
89   switch (channels) {
90     case 1:
91       f = copy_samples_m;
92       break;
93     case 2:
94       f = copy_samples_s;
95       break;
96     default:
97       f = copy_samples;
98       break;
99   }
100
101   return f;
102 }
103
104 #else
105
106 /* Taken from Tremor, misc.h */
107 #ifdef _ARM_ASSEM_
108 static inline ogg_int32_t
109 CLIP_TO_15 (ogg_int32_t x)
110 {
111   int tmp;
112   asm volatile ("subs   %1, %0, #32768\n\t"
113       "movpl    %0, #0x7f00\n\t"
114       "orrpl    %0, %0, #0xff\n"
115       "adds     %1, %0, #32768\n\t"
116       "movmi    %0, #0x8000":"+r" (x), "=r" (tmp)
117       ::"cc");
118
119   return (x);
120 }
121 #else
122 static inline ogg_int32_t
123 CLIP_TO_15 (ogg_int32_t x)
124 {
125   int ret = x;
126
127   ret -= ((x <= 32767) - 1) & (x - 32767);
128   ret -= ((x >= -32768) - 1) & (x + 32768);
129   return (ret);
130 }
131 #endif
132
133 static void
134 copy_samples_32_m (vorbis_sample_t * _out, vorbis_sample_t ** _in,
135     guint samples, gint channels, gint width)
136 {
137   gint32 *out = (gint32 *) _out;
138   ogg_int32_t **in = (ogg_int32_t **) _in;
139   gint j;
140
141   for (j = 0; j < samples; j++) {
142     *out++ = CLIP_TO_15 (in[0][j] >> 9);
143   }
144 }
145
146 static void
147 copy_samples_32_s (vorbis_sample_t * _out, vorbis_sample_t ** _in,
148     guint samples, gint channels, gint width)
149 {
150   gint32 *out = (gint32 *) _out;
151   ogg_int32_t **in = (ogg_int32_t **) _in;
152   gint j;
153
154   for (j = 0; j < samples; j++) {
155     *out++ = CLIP_TO_15 (in[0][j] >> 9);
156     *out++ = CLIP_TO_15 (in[1][j] >> 9);
157   }
158 }
159
160 static void
161 copy_samples_32 (vorbis_sample_t * _out, vorbis_sample_t ** _in, guint samples,
162     gint channels, gint width)
163 {
164   gint32 *out = (gint32 *) _out;
165   ogg_int32_t **in = (ogg_int32_t **) _in;
166   gint i, j;
167
168   for (j = 0; j < samples; j++) {
169     for (i = 0; i < channels; i++) {
170       *out++ = CLIP_TO_15 (in[i][j] >> 9);
171     }
172   }
173 }
174
175 static void
176 copy_samples_16_m (vorbis_sample_t * _out, vorbis_sample_t ** _in,
177     guint samples, gint channels, gint width)
178 {
179   gint16 *out = (gint16 *) _out;
180   ogg_int32_t **in = (ogg_int32_t **) _in;
181   gint j;
182
183   for (j = 0; j < samples; j++) {
184     *out++ = CLIP_TO_15 (in[0][j] >> 9);
185   }
186 }
187
188 static void
189 copy_samples_16_s (vorbis_sample_t * _out, vorbis_sample_t ** _in,
190     guint samples, gint channels, gint width)
191 {
192   gint16 *out = (gint16 *) _out;
193   ogg_int32_t **in = (ogg_int32_t **) _in;
194   gint j;
195
196   for (j = 0; j < samples; j++) {
197     *out++ = CLIP_TO_15 (in[0][j] >> 9);
198     *out++ = CLIP_TO_15 (in[1][j] >> 9);
199   }
200 }
201
202 static void
203 copy_samples_16 (vorbis_sample_t * _out, vorbis_sample_t ** _in, guint samples,
204     gint channels, gint width)
205 {
206   gint16 *out = (gint16 *) _out;
207   ogg_int32_t **in = (ogg_int32_t **) _in;
208   gint i, j;
209
210   for (j = 0; j < samples; j++) {
211     for (i = 0; i < channels; i++) {
212       *out++ = CLIP_TO_15 (in[i][j] >> 9);
213     }
214   }
215 }
216
217 CopySampleFunc
218 get_copy_sample_func (gint channels, gint width)
219 {
220   CopySampleFunc f = NULL;
221
222   if (width == 4) {
223     switch (channels) {
224       case 1:
225         f = copy_samples_32_m;
226         break;
227       case 2:
228         f = copy_samples_32_s;
229         break;
230       default:
231         f = copy_samples_32;
232         break;
233     }
234   } else if (width == 2) {
235     switch (channels) {
236       case 1:
237         f = copy_samples_16_m;
238         break;
239       case 2:
240         f = copy_samples_16_s;
241         break;
242       default:
243         f = copy_samples_16;
244         break;
245     }
246   } else {
247     g_assert_not_reached ();
248   }
249   return f;
250 }
251
252 #endif