• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** Copyright (C) 2002-2013 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
interleave_init(SF_PRIVATE * psf)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
interleave_read_short(SF_PRIVATE * psf,short * ptr,sf_count_t len)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
interleave_read_int(SF_PRIVATE * psf,int * ptr,sf_count_t len)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
interleave_read_float(SF_PRIVATE * psf,float * ptr,sf_count_t len)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
interleave_read_double(SF_PRIVATE * psf,double * ptr,sf_count_t len)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
interleave_seek(SF_PRIVATE * UNUSED (psf),int UNUSED (mode),sf_count_t samples_from_start)290 interleave_seek	(SF_PRIVATE * UNUSED (psf), int UNUSED (mode), sf_count_t samples_from_start)
291 {
292 	/*
293 	** Do nothing here. This is a place holder to prevent the default
294 	** seek function from being called.
295 	*/
296 
297 	return samples_from_start ;
298 } /* interleave_seek */
299 
300