Git init
[external/libsndfile.git] / src / interleave.c
1 /*
2 ** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
3 **
4 ** This program is free software; you can redistribute it and/or modify
5 ** it under the terms of the GNU Lesser General Public License as published by
6 ** the Free Software Foundation; either version 2.1 of the License, or
7 ** (at your option) any later version.
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 ** GNU Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public License
15 ** along with this program; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include        "sfendian.h"
20
21 #include        <stdlib.h>
22
23 #include        "sndfile.h"
24 #include        "common.h"
25
26 #define         INTERLEAVE_CHANNELS             6
27
28 typedef struct
29 {       double  buffer [SF_BUFFER_LEN / sizeof (double)] ;
30
31         sf_count_t              channel_len ;
32
33         sf_count_t              (*read_short)   (SF_PRIVATE*, short *ptr, sf_count_t len) ;
34         sf_count_t              (*read_int)     (SF_PRIVATE*, int *ptr, sf_count_t len) ;
35         sf_count_t              (*read_float)   (SF_PRIVATE*, float *ptr, sf_count_t len) ;
36         sf_count_t              (*read_double)  (SF_PRIVATE*, double *ptr, sf_count_t len) ;
37
38 } INTERLEAVE_DATA ;
39
40
41
42 static sf_count_t       interleave_read_short   (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
43 static sf_count_t       interleave_read_int     (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
44 static sf_count_t       interleave_read_float   (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
45 static sf_count_t       interleave_read_double  (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
46
47 static sf_count_t       interleave_seek (SF_PRIVATE*, int mode, sf_count_t samples_from_start) ;
48
49
50
51
52 int
53 interleave_init (SF_PRIVATE *psf)
54 {       INTERLEAVE_DATA *pdata ;
55
56         if (psf->file.mode != SFM_READ)
57                 return SFE_INTERLEAVE_MODE ;
58
59         if (psf->interleave)
60         {       psf_log_printf (psf, "*** Weird, already have interleave.\n") ;
61                 return 666 ;
62                 } ;
63
64         /* Free this in sf_close() function. */
65         if (! (pdata = malloc (sizeof (INTERLEAVE_DATA))))
66                 return SFE_MALLOC_FAILED ;
67
68 puts ("interleave_init") ;
69
70         psf->interleave = pdata ;
71
72         /* Save the existing methods. */
73         pdata->read_short       = psf->read_short ;
74         pdata->read_int         = psf->read_int ;
75         pdata->read_float       = psf->read_float ;
76         pdata->read_double      = psf->read_double ;
77
78         pdata->channel_len = psf->sf.frames * psf->bytewidth ;
79
80         /* Insert our new methods. */
81         psf->read_short         = interleave_read_short ;
82         psf->read_int           = interleave_read_int ;
83         psf->read_float         = interleave_read_float ;
84         psf->read_double        = interleave_read_double ;
85
86         psf->seek = interleave_seek ;
87
88         return 0 ;
89 } /* pcm_interleave_init */
90
91 /*------------------------------------------------------------------------------
92 */
93
94 static sf_count_t
95 interleave_read_short   (SF_PRIVATE *psf, short *ptr, sf_count_t len)
96 {       INTERLEAVE_DATA *pdata ;
97         sf_count_t      offset, templen ;
98         int                     chan, count, k ;
99         short           *inptr, *outptr ;
100
101         if (! (pdata = psf->interleave))
102                 return 0 ;
103
104         inptr = (short*) pdata->buffer ;
105
106         for (chan = 0 ; chan < psf->sf.channels ; chan++)
107         {       outptr = ptr + chan ;
108
109                 offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ;
110
111                 if (psf_fseek (psf, offset, SEEK_SET) != offset)
112                 {       psf->error = SFE_INTERLEAVE_SEEK ;
113                         return 0 ;
114                         } ;
115
116                 templen = len / psf->sf.channels ;
117
118                 while (templen > 0)
119                 {       if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (short))
120                                 count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (short) ;
121                         else
122                                 count = (int) templen ;
123
124                         if (pdata->read_short (psf, inptr, count) != count)
125                         {       psf->error = SFE_INTERLEAVE_READ ;
126                                 return 0 ;
127                                 } ;
128
129                         for (k = 0 ; k < count ; k++)
130                         {       *outptr = inptr [k] ;
131                                 outptr += psf->sf.channels ;
132                                 } ;
133
134                         templen -= count ;
135                         } ;
136                 } ;
137
138         return len ;
139 } /* interleave_read_short */
140
141 static sf_count_t
142 interleave_read_int     (SF_PRIVATE *psf, int *ptr, sf_count_t len)
143 {       INTERLEAVE_DATA *pdata ;
144         sf_count_t      offset, templen ;
145         int                     chan, count, k ;
146         int             *inptr, *outptr ;
147
148         if (! (pdata = psf->interleave))
149                 return 0 ;
150
151         inptr = (int*) pdata->buffer ;
152
153         for (chan = 0 ; chan < psf->sf.channels ; chan++)
154         {       outptr = ptr + chan ;
155
156                 offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ;
157
158                 if (psf_fseek (psf, offset, SEEK_SET) != offset)
159                 {       psf->error = SFE_INTERLEAVE_SEEK ;
160                         return 0 ;
161                         } ;
162
163                 templen = len / psf->sf.channels ;
164
165                 while (templen > 0)
166                 {       if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (int))
167                                 count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (int) ;
168                         else
169                                 count = (int) templen ;
170
171                         if (pdata->read_int (psf, inptr, count) != count)
172                         {       psf->error = SFE_INTERLEAVE_READ ;
173                                 return 0 ;
174                                 } ;
175
176                         for (k = 0 ; k < count ; k++)
177                         {       *outptr = inptr [k] ;
178                                 outptr += psf->sf.channels ;
179                                 } ;
180
181                         templen -= count ;
182                         } ;
183                 } ;
184
185         return len ;
186 } /* interleave_read_int */
187
188 static sf_count_t
189 interleave_read_float   (SF_PRIVATE *psf, float *ptr, sf_count_t len)
190 {       INTERLEAVE_DATA *pdata ;
191         sf_count_t      offset, templen ;
192         int                     chan, count, k ;
193         float           *inptr, *outptr ;
194
195         if (! (pdata = psf->interleave))
196                 return 0 ;
197
198         inptr = (float*) pdata->buffer ;
199
200         for (chan = 0 ; chan < psf->sf.channels ; chan++)
201         {       outptr = ptr + chan ;
202
203                 offset = psf->dataoffset + pdata->channel_len * chan + psf->read_current * psf->bytewidth ;
204
205 /*-printf ("chan : %d     read_current : %6lld    offset : %6lld\n", chan, psf->read_current, offset) ;-*/
206
207                 if (psf_fseek (psf, offset, SEEK_SET) != offset)
208                 {       psf->error = SFE_INTERLEAVE_SEEK ;
209 /*-puts ("interleave_seek error") ; exit (1) ;-*/
210                         return 0 ;
211                         } ;
212
213                 templen = len / psf->sf.channels ;
214
215                 while (templen > 0)
216                 {       if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (float))
217                                 count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (float) ;
218                         else
219                                 count = (int) templen ;
220
221                         if (pdata->read_float (psf, inptr, count) != count)
222                         {       psf->error = SFE_INTERLEAVE_READ ;
223 /*-puts ("interleave_read error") ; exit (1) ;-*/
224                                 return 0 ;
225                                 } ;
226
227                         for (k = 0 ; k < count ; k++)
228                         {       *outptr = inptr [k] ;
229                                 outptr += psf->sf.channels ;
230                                 } ;
231
232                         templen -= count ;
233                         } ;
234                 } ;
235
236         return len ;
237 } /* interleave_read_float */
238
239 static sf_count_t
240 interleave_read_double  (SF_PRIVATE *psf, double *ptr, sf_count_t len)
241 {       INTERLEAVE_DATA *pdata ;
242         sf_count_t      offset, templen ;
243         int                     chan, count, k ;
244         double          *inptr, *outptr ;
245
246         if (! (pdata = psf->interleave))
247                 return 0 ;
248
249         inptr = (double*) pdata->buffer ;
250
251         for (chan = 0 ; chan < psf->sf.channels ; chan++)
252         {       outptr = ptr + chan ;
253
254                 offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ;
255
256                 if (psf_fseek (psf, offset, SEEK_SET) != offset)
257                 {       psf->error = SFE_INTERLEAVE_SEEK ;
258                         return 0 ;
259                         } ;
260
261                 templen = len / psf->sf.channels ;
262
263                 while (templen > 0)
264                 {       if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (double))
265                                 count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (double) ;
266                         else
267                                 count = (int) templen ;
268
269                         if (pdata->read_double (psf, inptr, count) != count)
270                         {       psf->error = SFE_INTERLEAVE_READ ;
271                                 return 0 ;
272                                 } ;
273
274                         for (k = 0 ; k < count ; k++)
275                         {       *outptr = inptr [k] ;
276                                 outptr += psf->sf.channels ;
277                                 } ;
278
279                         templen -= count ;
280                         } ;
281                 } ;
282
283         return len ;
284 } /* interleave_read_double */
285
286 /*------------------------------------------------------------------------------
287 */
288
289 static sf_count_t
290 interleave_seek (SF_PRIVATE *psf, int mode, sf_count_t samples_from_start)
291 {       psf = psf ;     mode = mode ;
292
293         /*
294         ** Do nothing here. This is a place holder to prevent the default
295         ** seek function from being called.
296         */
297
298         return samples_from_start ;
299 } /* interleave_seek */
300