2 ** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
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.
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.
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.
26 #define INTERLEAVE_CHANNELS 6
29 { double buffer
[SF_BUFFER_LEN
/ sizeof (double)] ;
31 sf_count_t channel_len
;
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
) ;
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
) ;
47 static sf_count_t
interleave_seek (SF_PRIVATE
*, int mode
, sf_count_t samples_from_start
) ;
53 interleave_init (SF_PRIVATE
*psf
)
54 { INTERLEAVE_DATA
*pdata
;
56 if (psf
->file
.mode
!= SFM_READ
)
57 return SFE_INTERLEAVE_MODE
;
60 { psf_log_printf (psf
, "*** Weird, already have interleave.\n") ;
64 /* Free this in sf_close() function. */
65 if (! (pdata
= malloc (sizeof (INTERLEAVE_DATA
))))
66 return SFE_MALLOC_FAILED
;
68 puts ("interleave_init") ;
70 psf
->interleave
= pdata
;
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
;
78 pdata
->channel_len
= psf
->sf
.frames
* psf
->bytewidth
;
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
;
86 psf
->seek
= interleave_seek
;
89 } /* pcm_interleave_init */
91 /*------------------------------------------------------------------------------
95 interleave_read_short (SF_PRIVATE
*psf
, short *ptr
, sf_count_t len
)
96 { INTERLEAVE_DATA
*pdata
;
97 sf_count_t offset
, templen
;
99 short *inptr
, *outptr
;
101 if (! (pdata
= psf
->interleave
))
104 inptr
= (short*) pdata
->buffer
;
106 for (chan
= 0 ; chan
< psf
->sf
.channels
; chan
++)
107 { outptr
= ptr
+ chan
;
109 offset
= psf
->dataoffset
+ chan
* psf
->bytewidth
* psf
->read_current
;
111 if (psf_fseek (psf
, offset
, SEEK_SET
) != offset
)
112 { psf
->error
= SFE_INTERLEAVE_SEEK
;
116 templen
= len
/ psf
->sf
.channels
;
119 { if (templen
> SIGNED_SIZEOF (pdata
->buffer
) / SIGNED_SIZEOF (short))
120 count
= SIGNED_SIZEOF (pdata
->buffer
) / SIGNED_SIZEOF (short) ;
122 count
= (int) templen
;
124 if (pdata
->read_short (psf
, inptr
, count
) != count
)
125 { psf
->error
= SFE_INTERLEAVE_READ
;
129 for (k
= 0 ; k
< count
; k
++)
130 { *outptr
= inptr
[k
] ;
131 outptr
+= psf
->sf
.channels
;
139 } /* interleave_read_short */
142 interleave_read_int (SF_PRIVATE
*psf
, int *ptr
, sf_count_t len
)
143 { INTERLEAVE_DATA
*pdata
;
144 sf_count_t offset
, templen
;
146 int *inptr
, *outptr
;
148 if (! (pdata
= psf
->interleave
))
151 inptr
= (int*) pdata
->buffer
;
153 for (chan
= 0 ; chan
< psf
->sf
.channels
; chan
++)
154 { outptr
= ptr
+ chan
;
156 offset
= psf
->dataoffset
+ chan
* psf
->bytewidth
* psf
->read_current
;
158 if (psf_fseek (psf
, offset
, SEEK_SET
) != offset
)
159 { psf
->error
= SFE_INTERLEAVE_SEEK
;
163 templen
= len
/ psf
->sf
.channels
;
166 { if (templen
> SIGNED_SIZEOF (pdata
->buffer
) / SIGNED_SIZEOF (int))
167 count
= SIGNED_SIZEOF (pdata
->buffer
) / SIGNED_SIZEOF (int) ;
169 count
= (int) templen
;
171 if (pdata
->read_int (psf
, inptr
, count
) != count
)
172 { psf
->error
= SFE_INTERLEAVE_READ
;
176 for (k
= 0 ; k
< count
; k
++)
177 { *outptr
= inptr
[k
] ;
178 outptr
+= psf
->sf
.channels
;
186 } /* interleave_read_int */
189 interleave_read_float (SF_PRIVATE
*psf
, float *ptr
, sf_count_t len
)
190 { INTERLEAVE_DATA
*pdata
;
191 sf_count_t offset
, templen
;
193 float *inptr
, *outptr
;
195 if (! (pdata
= psf
->interleave
))
198 inptr
= (float*) pdata
->buffer
;
200 for (chan
= 0 ; chan
< psf
->sf
.channels
; chan
++)
201 { outptr
= ptr
+ chan
;
203 offset
= psf
->dataoffset
+ pdata
->channel_len
* chan
+ psf
->read_current
* psf
->bytewidth
;
205 /*-printf ("chan : %d read_current : %6lld offset : %6lld\n", chan, psf->read_current, offset) ;-*/
207 if (psf_fseek (psf
, offset
, SEEK_SET
) != offset
)
208 { psf
->error
= SFE_INTERLEAVE_SEEK
;
209 /*-puts ("interleave_seek error") ; exit (1) ;-*/
213 templen
= len
/ psf
->sf
.channels
;
216 { if (templen
> SIGNED_SIZEOF (pdata
->buffer
) / SIGNED_SIZEOF (float))
217 count
= SIGNED_SIZEOF (pdata
->buffer
) / SIGNED_SIZEOF (float) ;
219 count
= (int) templen
;
221 if (pdata
->read_float (psf
, inptr
, count
) != count
)
222 { psf
->error
= SFE_INTERLEAVE_READ
;
223 /*-puts ("interleave_read error") ; exit (1) ;-*/
227 for (k
= 0 ; k
< count
; k
++)
228 { *outptr
= inptr
[k
] ;
229 outptr
+= psf
->sf
.channels
;
237 } /* interleave_read_float */
240 interleave_read_double (SF_PRIVATE
*psf
, double *ptr
, sf_count_t len
)
241 { INTERLEAVE_DATA
*pdata
;
242 sf_count_t offset
, templen
;
244 double *inptr
, *outptr
;
246 if (! (pdata
= psf
->interleave
))
249 inptr
= (double*) pdata
->buffer
;
251 for (chan
= 0 ; chan
< psf
->sf
.channels
; chan
++)
252 { outptr
= ptr
+ chan
;
254 offset
= psf
->dataoffset
+ chan
* psf
->bytewidth
* psf
->read_current
;
256 if (psf_fseek (psf
, offset
, SEEK_SET
) != offset
)
257 { psf
->error
= SFE_INTERLEAVE_SEEK
;
261 templen
= len
/ psf
->sf
.channels
;
264 { if (templen
> SIGNED_SIZEOF (pdata
->buffer
) / SIGNED_SIZEOF (double))
265 count
= SIGNED_SIZEOF (pdata
->buffer
) / SIGNED_SIZEOF (double) ;
267 count
= (int) templen
;
269 if (pdata
->read_double (psf
, inptr
, count
) != count
)
270 { psf
->error
= SFE_INTERLEAVE_READ
;
274 for (k
= 0 ; k
< count
; k
++)
275 { *outptr
= inptr
[k
] ;
276 outptr
+= psf
->sf
.channels
;
284 } /* interleave_read_double */
286 /*------------------------------------------------------------------------------
290 interleave_seek (SF_PRIVATE
*psf
, int mode
, sf_count_t samples_from_start
)
291 { psf
= psf
; mode
= mode
;
294 ** Do nothing here. This is a place holder to prevent the default
295 ** seek function from being called.
298 return samples_from_start
;
299 } /* interleave_seek */