xref: /third_party/libsnd/src/sds.c (revision b815c7f3)
1/*
2** Copyright (C) 2002-2017 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 "sfconfig.h"
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <fcntl.h>
24#include <string.h>
25#include <ctype.h>
26#include <math.h>
27
28#include "sndfile.h"
29#include "sfendian.h"
30#include "common.h"
31
32/*------------------------------------------------------------------------------
33*/
34
35#define	SDS_DATA_OFFSET				0x15
36#define SDS_BLOCK_SIZE				127
37
38#define SDS_AUDIO_BYTES_PER_BLOCK	120
39
40#define SDS_3BYTE_TO_INT_DECODE(x) (((x) & 0x7F) | (((x) & 0x7F00) >> 1) | (((x) & 0x7F0000) >> 2))
41#define SDS_INT_TO_3BYTE_ENCODE(x) (((x) & 0x7F) | (((x) << 1) & 0x7F00) | (((x) << 2) & 0x7F0000))
42
43/*------------------------------------------------------------------------------
44** Typedefs.
45*/
46
47typedef struct tag_SDS_PRIVATE
48{	int bitwidth, frames ;
49	int	samplesperblock, total_blocks ;
50
51	int (*reader) (SF_PRIVATE *psf, struct tag_SDS_PRIVATE *psds) ;
52	int (*writer) (SF_PRIVATE *psf, struct tag_SDS_PRIVATE *psds) ;
53
54	int read_block, read_count ;
55	unsigned char read_data [SDS_BLOCK_SIZE] ;
56	int	read_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */
57
58	int write_block, write_count ;
59	int total_written ;
60	unsigned char write_data [SDS_BLOCK_SIZE] ;
61	int	write_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */
62} SDS_PRIVATE ;
63
64/*------------------------------------------------------------------------------
65** Private static functions.
66*/
67
68static int	sds_close	(SF_PRIVATE *psf) ;
69
70static int	sds_write_header (SF_PRIVATE *psf, int calc_length) ;
71static int	sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
72
73static int	sds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
74
75static sf_count_t sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
76static sf_count_t sds_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
77static sf_count_t sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
78static sf_count_t sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
79
80static sf_count_t sds_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
81static sf_count_t sds_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
82static sf_count_t sds_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
83static sf_count_t sds_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
84
85static sf_count_t sds_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
86static int sds_byterate (SF_PRIVATE * psf) ;
87
88static int sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
89static int sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
90static int sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
91
92static int sds_read (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *iptr, int readcount) ;
93
94static int sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
95static int sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
96static int sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
97
98static int sds_write (SF_PRIVATE *psf, SDS_PRIVATE *psds, const int *iptr, int writecount) ;
99
100/*------------------------------------------------------------------------------
101** Public function.
102*/
103
104int
105sds_open	(SF_PRIVATE *psf)
106{	SDS_PRIVATE	*psds ;
107	int			error = 0 ;
108
109	/* Hmmmm, need this here to pass update_header_test. */
110	psf->sf.frames = 0 ;
111
112	if (! (psds = calloc (1, sizeof (SDS_PRIVATE))))
113		return SFE_MALLOC_FAILED ;
114	psf->codec_data = psds ;
115
116	if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
117	{	if ((error = sds_read_header (psf, psds)))
118			return error ;
119		} ;
120
121	if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_SDS)
122		return	SFE_BAD_OPEN_FORMAT ;
123
124	if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
125	{	if (sds_write_header (psf, SF_FALSE))
126			return psf->error ;
127
128		psf->write_header = sds_write_header ;
129
130		psf_fseek (psf, SDS_DATA_OFFSET, SEEK_SET) ;
131		} ;
132
133	if ((error = sds_init (psf, psds)) != 0)
134		return error ;
135
136	psf->container_close = sds_close ;
137	psf->seek = sds_seek ;
138	psf->byterate = sds_byterate ;
139
140	psf->blockwidth = 0 ;
141
142	return error ;
143} /* sds_open */
144
145/*------------------------------------------------------------------------------
146*/
147
148static int
149sds_close	(SF_PRIVATE *psf)
150{
151	if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
152	{	SDS_PRIVATE *psds ;
153
154		if ((psds = (SDS_PRIVATE *) psf->codec_data) == NULL)
155		{	psf_log_printf (psf, "*** Bad psf->codec_data ptr.\n") ;
156			return SFE_INTERNAL ;
157			} ;
158
159		if (psds->write_count > 0)
160		{	memset (&(psds->write_data [psds->write_count]), 0, (psds->samplesperblock - psds->write_count) * sizeof (int)) ;
161			psds->writer (psf, psds) ;
162			} ;
163
164		sds_write_header (psf, SF_TRUE) ;
165		} ;
166
167	return 0 ;
168} /* sds_close */
169
170static int
171sds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds)
172{
173	if (psds->bitwidth < 8 || psds->bitwidth > 28)
174		return (psf->error = SFE_SDS_BAD_BIT_WIDTH) ;
175
176	if (psds->bitwidth < 14)
177	{	psds->reader = sds_2byte_read ;
178		psds->writer = sds_2byte_write ;
179		psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 2 ;
180		}
181	else if (psds->bitwidth < 21)
182	{	psds->reader = sds_3byte_read ;
183		psds->writer = sds_3byte_write ;
184		psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 3 ;
185		}
186	else
187	{	psds->reader = sds_4byte_read ;
188		psds->writer = sds_4byte_write ;
189		psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 4 ;
190		} ;
191
192	if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR)
193	{	psf->read_short		= sds_read_s ;
194		psf->read_int		= sds_read_i ;
195		psf->read_float		= sds_read_f ;
196		psf->read_double	= sds_read_d ;
197
198		/* Read first block. */
199		psds->reader (psf, psds) ;
200		} ;
201
202	if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
203	{	psf->write_short	= sds_write_s ;
204		psf->write_int		= sds_write_i ;
205		psf->write_float	= sds_write_f ;
206		psf->write_double	= sds_write_d ;
207		} ;
208
209	return 0 ;
210} /* sds_init */
211
212static int
213sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds)
214{	unsigned char	channel, bitwidth, loop_type, byte ;
215	unsigned short	sample_no, marker ;
216	unsigned int	samp_period, data_length, sustain_loop_start, sustain_loop_end ;
217	int		bytesread, blockcount ;
218
219	/* Set position to start of file to begin reading header. */
220	bytesread = psf_binheader_readf (psf, "pE211", 0, &marker, &channel, &byte) ;
221
222	if (marker != 0xF07E || byte != 0x01)
223		return SFE_SDS_NOT_SDS ;
224
225	bytesread += psf_binheader_readf (psf, "e2", &sample_no) ;
226	sample_no = SDS_3BYTE_TO_INT_DECODE (sample_no) ;
227
228	psf_log_printf (psf, "Midi Sample Dump Standard (.sds)\nF07E\n"
229						" Midi Channel  : %d\n Sample Number : %d\n",
230						channel, sample_no) ;
231
232	bytesread += psf_binheader_readf (psf, "e13", &bitwidth, &samp_period) ;
233
234	samp_period = SDS_3BYTE_TO_INT_DECODE (samp_period) ;
235
236	psds->bitwidth = bitwidth ;
237
238	if (psds->bitwidth > 1)
239		psf_log_printf (psf, " Bit Width     : %d\n", psds->bitwidth) ;
240	else
241	{	psf_log_printf (psf, " Bit Width     : %d (should be > 1)\n", psds->bitwidth) ;
242		return SFE_SDS_BAD_BIT_WIDTH ;
243		} ;
244
245	if (samp_period > 0)
246	{	psf->sf.samplerate = 1000000000 / samp_period ;
247
248		psf_log_printf (psf, " Sample Period : %d\n"
249							" Sample Rate   : %d\n",
250							samp_period, psf->sf.samplerate) ;
251		}
252	else
253	{	psf->sf.samplerate = 16000 ;
254
255		psf_log_printf (psf, " Sample Period : %d (should be > 0)\n"
256							" Sample Rate   : %d (guessed)\n",
257							samp_period, psf->sf.samplerate) ;
258		} ;
259
260	bytesread += psf_binheader_readf (psf, "e3331", &data_length, &sustain_loop_start, &sustain_loop_end, &loop_type) ;
261
262	data_length = SDS_3BYTE_TO_INT_DECODE (data_length) ;
263
264	psf->sf.frames = psds->frames = data_length ;
265
266	sustain_loop_start = SDS_3BYTE_TO_INT_DECODE (sustain_loop_start) ;
267	sustain_loop_end = SDS_3BYTE_TO_INT_DECODE (sustain_loop_end) ;
268
269	psf_log_printf (psf, 	" Sustain Loop\n"
270							"     Start     : %d\n"
271							"     End       : %d\n"
272							"     Loop Type : %d\n",
273			sustain_loop_start, sustain_loop_end, loop_type) ;
274
275	psf->dataoffset = SDS_DATA_OFFSET ;
276	psf->datalength = psf->filelength - psf->dataoffset ;
277
278	bytesread += psf_binheader_readf (psf, "1", &byte) ;
279	if (byte != 0xF7)
280		psf_log_printf (psf, "bad end : %X\n", byte & 0xFF) ;
281
282	for (blockcount = 0 ; bytesread < psf->filelength ; blockcount++)
283	{
284		bytesread += (int) psf_fread (&marker, 1, 2, psf) ;
285
286		if (marker == 0)
287			break ;
288
289		psf_fseek (psf, SDS_BLOCK_SIZE - 2, SEEK_CUR) ;
290		bytesread += SDS_BLOCK_SIZE - 2 ;
291		} ;
292
293	psf_log_printf (psf, "\nBlocks         : %d\n", blockcount) ;
294	psds->total_blocks = blockcount ;
295
296	psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / ((psds->bitwidth + 6) / 7) ;
297	psf_log_printf (psf, "Samples/Block  : %d\n", psds->samplesperblock) ;
298
299	psf_log_printf (psf, "Frames         : %d\n", blockcount * psds->samplesperblock) ;
300
301	/* Always Mono */
302	psf->sf.channels = 1 ;
303	psf->sf.sections = 1 ;
304
305	/*
306	** Lie to the user about PCM bit width. Always round up to
307	** the next multiple of 8.
308	*/
309	switch ((psds->bitwidth + 7) / 8)
310	{	case 1 :
311			psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_S8 ;
312			break ;
313
314		case 2 :
315			psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_16 ;
316			break ;
317
318		case 3 :
319			psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_24 ;
320			break ;
321
322		case 4 :
323			psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_32 ;
324			break ;
325
326		default :
327			psf_log_printf (psf, "*** Weird byte width (%d)\n", (psds->bitwidth + 7) / 8) ;
328			return SFE_SDS_BAD_BIT_WIDTH ;
329		} ;
330
331	psf_fseek (psf, SDS_DATA_OFFSET, SEEK_SET) ;
332
333	return 0 ;
334} /* sds_read_header */
335
336static int
337sds_write_header (SF_PRIVATE *psf, int calc_length)
338{	SDS_PRIVATE *psds ;
339	sf_count_t	current ;
340	int samp_period, data_length, sustain_loop_start, sustain_loop_end ;
341	unsigned char loop_type = 0 ;
342
343	if ((psds = (SDS_PRIVATE *) psf->codec_data) == NULL)
344	{	psf_log_printf (psf, "*** Bad psf->codec_data ptr.\n") ;
345		return SFE_INTERNAL ;
346		} ;
347
348	if (psf->pipeoffset > 0)
349		return 0 ;
350
351	current = psf_ftell (psf) ;
352
353	if (calc_length)
354		psf->sf.frames = psds->total_written ;
355
356	if (psds->write_count > 0)
357	{	int current_count = psds->write_count ;
358		int current_block = psds->write_block ;
359
360		psds->writer (psf, psds) ;
361
362		psf_fseek (psf, -1 * SDS_BLOCK_SIZE, SEEK_CUR) ;
363
364		psds->write_count = current_count ;
365		psds->write_block = current_block ;
366		} ;
367
368	/* Reset the current header length to zero. */
369	psf->header.ptr [0] = 0 ;
370	psf->header.indx = 0 ;
371
372	if (psf->is_pipe == SF_FALSE)
373		psf_fseek (psf, 0, SEEK_SET) ;
374
375	psf_binheader_writef (psf, "E211", BHW2 (0xF07E), BHW1 (0), BHW1 (1)) ;
376
377	switch (SF_CODEC (psf->sf.format))
378	{	case SF_FORMAT_PCM_S8 :
379				psds->bitwidth = 8 ;
380				break ;
381		case SF_FORMAT_PCM_16 :
382				psds->bitwidth = 16 ;
383				break ;
384		case SF_FORMAT_PCM_24 :
385				psds->bitwidth = 24 ;
386				break ;
387		default:
388			return SFE_SDS_BAD_BIT_WIDTH ;
389		} ;
390
391	samp_period = SDS_INT_TO_3BYTE_ENCODE (1000000000 / psf->sf.samplerate) ;
392
393	psf_binheader_writef (psf, "e213", BHW2 (0), BHW1 (psds->bitwidth), BHW3 (samp_period)) ;
394
395	data_length			= SDS_INT_TO_3BYTE_ENCODE (psds->total_written) ;
396	sustain_loop_start	= SDS_INT_TO_3BYTE_ENCODE (0) ;
397	sustain_loop_end	= SDS_INT_TO_3BYTE_ENCODE (0) ;
398
399	psf_binheader_writef (psf, "e33311", BHW3 (data_length), BHW3 (sustain_loop_start), BHW3 (sustain_loop_end), BHW1 (loop_type), BHW1 (0xF7)) ;
400
401	/* Header construction complete so write it out. */
402	psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ;
403
404	if (psf->error)
405		return psf->error ;
406
407	psf->dataoffset = psf->header.indx ;
408	psf->datalength = psds->write_block * SDS_BLOCK_SIZE ;
409
410	if (current > 0)
411		psf_fseek (psf, current, SEEK_SET) ;
412
413	return psf->error ;
414} /* sds_write_header */
415
416
417/*------------------------------------------------------------------------------
418*/
419
420static int
421sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds)
422{	unsigned char *ucptr, checksum ;
423	unsigned int sample ;
424	int 	k ;
425
426	psds->read_block ++ ;
427	psds->read_count = 0 ;
428
429	if (psds->read_block * psds->samplesperblock > psds->frames)
430	{	memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ;
431		return 1 ;
432		} ;
433
434	if ((k = (int) psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
435		psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
436
437	if (psds->read_data [0] != 0xF0)
438	{	printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ;
439		} ;
440
441	checksum = psds->read_data [1] ;
442	if (checksum != 0x7E)
443	{	printf ("Error 1 : %02X\n", checksum & 0xFF) ;
444		}
445
446	for (k = 2 ; k <= SDS_BLOCK_SIZE - 3 ; k ++)
447		checksum ^= psds->read_data [k] ;
448
449	checksum &= 0x7F ;
450
451	if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2])
452	{	psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ;
453		} ;
454
455	ucptr = psds->read_data + 5 ;
456	for (k = 0 ; k < 120 ; k += 2)
457	{	sample = arith_shift_left (ucptr [k], 25) + arith_shift_left (ucptr [k + 1], 18) ;
458		psds->read_samples [k / 2] = (int) (sample - 0x80000000) ;
459		} ;
460
461	return 1 ;
462} /* sds_2byte_read */
463
464static int
465sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds)
466{	unsigned char *ucptr, checksum ;
467	unsigned int sample ;
468	int 	k ;
469
470	psds->read_block ++ ;
471	psds->read_count = 0 ;
472
473	if (psds->read_block * psds->samplesperblock > psds->frames)
474	{	memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ;
475		return 1 ;
476		} ;
477
478	if ((k = (int) psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
479		psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
480
481	if (psds->read_data [0] != 0xF0)
482	{	printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ;
483		} ;
484
485	checksum = psds->read_data [1] ;
486	if (checksum != 0x7E)
487	{	printf ("Error 1 : %02X\n", checksum & 0xFF) ;
488		}
489
490	for (k = 2 ; k <= SDS_BLOCK_SIZE - 3 ; k ++)
491		checksum ^= psds->read_data [k] ;
492
493	checksum &= 0x7F ;
494
495	if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2])
496	{	psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ;
497		} ;
498
499	ucptr = psds->read_data + 5 ;
500	for (k = 0 ; k < 120 ; k += 3)
501	{	sample = (((uint32_t) ucptr [k]) << 25) + (ucptr [k + 1] << 18) + (ucptr [k + 2] << 11) ;
502		psds->read_samples [k / 3] = (int) (sample - 0x80000000) ;
503		} ;
504
505	return 1 ;
506} /* sds_3byte_read */
507
508static int
509sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds)
510{	unsigned char *ucptr, checksum ;
511	uint32_t sample ;
512	int 	k ;
513
514	psds->read_block ++ ;
515	psds->read_count = 0 ;
516
517	if (psds->read_block * psds->samplesperblock > psds->frames)
518	{	memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ;
519		return 1 ;
520		} ;
521
522	if ((k = (int) psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
523		psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
524
525	if (psds->read_data [0] != 0xF0)
526	{	printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ;
527		} ;
528
529	checksum = psds->read_data [1] ;
530	if (checksum != 0x7E)
531	{	printf ("Error 1 : %02X\n", checksum & 0xFF) ;
532		}
533
534	for (k = 2 ; k <= SDS_BLOCK_SIZE - 3 ; k ++)
535		checksum ^= psds->read_data [k] ;
536
537	checksum &= 0x7F ;
538
539	if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2])
540	{	psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ;
541		} ;
542
543	ucptr = psds->read_data + 5 ;
544	for (k = 0 ; k < 120 ; k += 4)
545	{	sample = (((uint32_t) ucptr [k]) << 25) + (ucptr [k + 1] << 18) + (ucptr [k + 2] << 11) + (ucptr [k + 3] << 4) ;
546		psds->read_samples [k / 4] = (int) (sample - 0x80000000) ;
547		} ;
548
549	return 1 ;
550} /* sds_4byte_read */
551
552
553static sf_count_t
554sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
555{	BUF_UNION	ubuf ;
556	SDS_PRIVATE	*psds ;
557	int			*iptr ;
558	int			k, bufferlen, readcount, count ;
559	sf_count_t	total = 0 ;
560
561	if (psf->codec_data == NULL)
562		return 0 ;
563	psds = (SDS_PRIVATE*) psf->codec_data ;
564
565	iptr = ubuf.ibuf ;
566	bufferlen = ARRAY_LEN (ubuf.ibuf) ;
567	while (len > 0)
568	{	readcount = (len >= bufferlen) ? bufferlen : (int) len ;
569		count = sds_read (psf, psds, iptr, readcount) ;
570		for (k = 0 ; k < readcount ; k++)
571			ptr [total + k] = iptr [k] >> 16 ;
572		total += count ;
573		len -= readcount ;
574		} ;
575
576	return total ;
577} /* sds_read_s */
578
579static sf_count_t
580sds_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
581{	SDS_PRIVATE *psds ;
582	int			total ;
583
584	if (psf->codec_data == NULL)
585		return 0 ;
586	psds = (SDS_PRIVATE*) psf->codec_data ;
587
588	total = sds_read (psf, psds, ptr, len) ;
589
590	return total ;
591} /* sds_read_i */
592
593static sf_count_t
594sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
595{	BUF_UNION	ubuf ;
596	SDS_PRIVATE	*psds ;
597	int			*iptr ;
598	int			k, bufferlen, readcount, count ;
599	sf_count_t	total = 0 ;
600	float		normfact ;
601
602	if (psf->codec_data == NULL)
603		return 0 ;
604	psds = (SDS_PRIVATE*) psf->codec_data ;
605
606	if (psf->norm_float == SF_TRUE)
607		normfact = 1.0 / 0x80000000 ;
608	else
609		normfact = 1.0 / (1 << psds->bitwidth) ;
610
611	iptr = ubuf.ibuf ;
612	bufferlen = ARRAY_LEN (ubuf.ibuf) ;
613	while (len > 0)
614	{	readcount = (len >= bufferlen) ? bufferlen : (int) len ;
615		count = sds_read (psf, psds, iptr, readcount) ;
616		for (k = 0 ; k < readcount ; k++)
617			ptr [total + k] = normfact * iptr [k] ;
618		total += count ;
619		len -= readcount ;
620		} ;
621
622	return total ;
623} /* sds_read_f */
624
625static sf_count_t
626sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
627{	BUF_UNION	ubuf ;
628	SDS_PRIVATE	*psds ;
629	int			*iptr ;
630	int			k, bufferlen, readcount, count ;
631	sf_count_t	total = 0 ;
632	double		normfact ;
633
634	if (psf->codec_data == NULL)
635		return 0 ;
636	psds = (SDS_PRIVATE*) psf->codec_data ;
637
638	if (psf->norm_double == SF_TRUE)
639		normfact = 1.0 / 0x80000000 ;
640	else
641		normfact = 1.0 / (1 << psds->bitwidth) ;
642
643	iptr = ubuf.ibuf ;
644	bufferlen = ARRAY_LEN (ubuf.ibuf) ;
645	while (len > 0)
646	{	readcount = (len >= bufferlen) ? bufferlen : (int) len ;
647		count = sds_read (psf, psds, iptr, readcount) ;
648		for (k = 0 ; k < readcount ; k++)
649			ptr [total + k] = normfact * iptr [k] ;
650		total += count ;
651		len -= readcount ;
652		} ;
653
654	return total ;
655} /* sds_read_d */
656
657static int
658sds_read (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *ptr, int len)
659{	int	count, total = 0 ;
660
661	while (total < len)
662	{	if (psds->read_block * psds->samplesperblock >= psds->frames)
663		{	memset (&(ptr [total]), 0, (len - total) * sizeof (int)) ;
664			return total ;
665			} ;
666
667		if (psds->read_count >= psds->samplesperblock)
668			psds->reader (psf, psds) ;
669
670		count = (psds->samplesperblock - psds->read_count) ;
671		count = (len - total > count) ? count : len - total ;
672
673		memcpy (&(ptr [total]), &(psds->read_samples [psds->read_count]), count * sizeof (int)) ;
674		total += count ;
675		psds->read_count += count ;
676		} ;
677
678	return total ;
679} /* sds_read */
680
681/*==============================================================================
682*/
683
684static sf_count_t
685sds_seek (SF_PRIVATE *psf, int mode, sf_count_t seek_from_start)
686{	SDS_PRIVATE	*psds ;
687	sf_count_t	file_offset ;
688	int			newblock, newsample ;
689
690	if ((psds = psf->codec_data) == NULL)
691	{	psf->error = SFE_INTERNAL ;
692		return PSF_SEEK_ERROR ;
693		} ;
694
695	if (psf->datalength < 0 || psf->dataoffset < 0)
696	{	psf->error = SFE_BAD_SEEK ;
697		return PSF_SEEK_ERROR ;
698		} ;
699
700	if (seek_from_start < 0 || seek_from_start > psf->sf.frames)
701	{	psf->error = SFE_BAD_SEEK ;
702		return PSF_SEEK_ERROR ;
703		} ;
704
705	if (mode == SFM_READ && psds->write_count > 0)
706		psds->writer (psf, psds) ;
707
708	newblock = seek_from_start / psds->samplesperblock ;
709	newsample = seek_from_start % psds->samplesperblock ;
710
711	switch (mode)
712	{	case SFM_READ :
713			if (newblock > psds->total_blocks)
714			{	psf->error = SFE_BAD_SEEK ;
715				return PSF_SEEK_ERROR ;
716				} ;
717
718			file_offset = psf->dataoffset + newblock * SDS_BLOCK_SIZE ;
719
720			if (psf_fseek (psf, file_offset, SEEK_SET) != file_offset)
721			{	psf->error = SFE_SEEK_FAILED ;
722				return PSF_SEEK_ERROR ;
723				} ;
724
725			psds->read_block = newblock ;
726			psds->reader (psf, psds) ;
727			psds->read_count = newsample ;
728			break ;
729
730		case SFM_WRITE :
731			if (newblock > psds->total_blocks)
732			{	psf->error = SFE_BAD_SEEK ;
733				return PSF_SEEK_ERROR ;
734				} ;
735
736			file_offset = psf->dataoffset + newblock * SDS_BLOCK_SIZE ;
737
738			if (psf_fseek (psf, file_offset, SEEK_SET) != file_offset)
739			{	psf->error = SFE_SEEK_FAILED ;
740				return PSF_SEEK_ERROR ;
741				} ;
742
743			psds->write_block = newblock ;
744			psds->reader (psf, psds) ;
745			psds->write_count = newsample ;
746			break ;
747
748		default :
749			psf->error = SFE_BAD_SEEK ;
750			return PSF_SEEK_ERROR ;
751			break ;
752		} ;
753
754	return seek_from_start ;
755} /* sds_seek */
756
757static int
758sds_byterate (SF_PRIVATE * psf)
759{
760	if (psf->file.mode == SFM_READ)
761		return (psf->datalength * psf->sf.samplerate) / psf->sf.frames ;
762
763	return -1 ;
764} /* sds_byterate */
765
766/*==============================================================================
767*/
768
769static int
770sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
771{	unsigned char *ucptr, checksum ;
772	unsigned int sample ;
773	int 	k ;
774
775	psds->write_data [0] = 0xF0 ;
776	psds->write_data [1] = 0x7E ;
777	psds->write_data [2] = 0 ;							/* Channel number */
778	psds->write_data [3] = 2 ;
779	psds->write_data [4] = psds->write_block & 0x7F ;	/* Packet number */
780
781	ucptr = psds->write_data + 5 ;
782	for (k = 0 ; k < 120 ; k += 2)
783	{	sample = psds->write_samples [k / 2] ;
784		sample += 0x80000000 ;
785		ucptr [k] = (sample >> 25) & 0x7F ;
786		ucptr [k + 1] = (sample >> 18) & 0x7F ;
787		} ;
788
789	checksum = psds->write_data [1] ;
790	for (k = 2 ; k <= SDS_BLOCK_SIZE - 3 ; k ++)
791		checksum ^= psds->write_data [k] ;
792	checksum &= 0x7F ;
793
794	psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ;
795	psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ;
796
797	if ((k = (int) psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
798		psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
799
800	psds->write_block ++ ;
801	psds->write_count = 0 ;
802
803	if (psds->write_block > psds->total_blocks)
804		psds->total_blocks = psds->write_block ;
805	psds->frames = psds->total_blocks * psds->samplesperblock ;
806
807	return 1 ;
808} /* sds_2byte_write */
809
810static int
811sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
812{	unsigned char *ucptr, checksum ;
813	unsigned int sample ;
814	int 	k ;
815
816	psds->write_data [0] = 0xF0 ;
817	psds->write_data [1] = 0x7E ;
818	psds->write_data [2] = 0 ;							/* Channel number */
819	psds->write_data [3] = 2 ;
820	psds->write_data [4] = psds->write_block & 0x7F ;	/* Packet number */
821
822	ucptr = psds->write_data + 5 ;
823	for (k = 0 ; k < 120 ; k += 3)
824	{	sample = psds->write_samples [k / 3] ;
825		sample += 0x80000000 ;
826		ucptr [k] = (sample >> 25) & 0x7F ;
827		ucptr [k + 1] = (sample >> 18) & 0x7F ;
828		ucptr [k + 2] = (sample >> 11) & 0x7F ;
829		} ;
830
831	checksum = psds->write_data [1] ;
832	for (k = 2 ; k <= SDS_BLOCK_SIZE - 3 ; k ++)
833		checksum ^= psds->write_data [k] ;
834	checksum &= 0x7F ;
835
836	psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ;
837	psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ;
838
839	if ((k = (int) psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
840		psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
841
842	psds->write_block ++ ;
843	psds->write_count = 0 ;
844
845	if (psds->write_block > psds->total_blocks)
846		psds->total_blocks = psds->write_block ;
847	psds->frames = psds->total_blocks * psds->samplesperblock ;
848
849	return 1 ;
850} /* sds_3byte_write */
851
852static int
853sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
854{	unsigned char *ucptr, checksum ;
855	unsigned int sample ;
856	int 	k ;
857
858	psds->write_data [0] = 0xF0 ;
859	psds->write_data [1] = 0x7E ;
860	psds->write_data [2] = 0 ;							/* Channel number */
861	psds->write_data [3] = 2 ;
862	psds->write_data [4] = psds->write_block & 0x7F ;	/* Packet number */
863
864	ucptr = psds->write_data + 5 ;
865	for (k = 0 ; k < 120 ; k += 4)
866	{	sample = psds->write_samples [k / 4] ;
867		sample += 0x80000000 ;
868		ucptr [k] = (sample >> 25) & 0x7F ;
869		ucptr [k + 1] = (sample >> 18) & 0x7F ;
870		ucptr [k + 2] = (sample >> 11) & 0x7F ;
871		ucptr [k + 3] = (sample >> 4) & 0x7F ;
872		} ;
873
874	checksum = psds->write_data [1] ;
875	for (k = 2 ; k <= SDS_BLOCK_SIZE - 3 ; k ++)
876		checksum ^= psds->write_data [k] ;
877	checksum &= 0x7F ;
878
879	psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ;
880	psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ;
881
882	if ((k = (int) psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
883		psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
884
885	psds->write_block ++ ;
886	psds->write_count = 0 ;
887
888	if (psds->write_block > psds->total_blocks)
889		psds->total_blocks = psds->write_block ;
890	psds->frames = psds->total_blocks * psds->samplesperblock ;
891
892	return 1 ;
893} /* sds_4byte_write */
894
895static sf_count_t
896sds_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
897{	BUF_UNION	ubuf ;
898	SDS_PRIVATE	*psds ;
899	int			*iptr ;
900	int			k, bufferlen, writecount, count ;
901	sf_count_t	total = 0 ;
902
903	if (psf->codec_data == NULL)
904		return 0 ;
905	psds = (SDS_PRIVATE*) psf->codec_data ;
906	psds->total_written += len ;
907
908	iptr = ubuf.ibuf ;
909	bufferlen = ARRAY_LEN (ubuf.ibuf) ;
910	while (len > 0)
911	{	writecount = (len >= bufferlen) ? bufferlen : (int) len ;
912		for (k = 0 ; k < writecount ; k++)
913			iptr [k] = arith_shift_left (ptr [total + k], 16) ;
914		count = sds_write (psf, psds, iptr, writecount) ;
915		total += count ;
916		len -= writecount ;
917		} ;
918
919	return total ;
920} /* sds_write_s */
921
922static sf_count_t
923sds_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
924{	SDS_PRIVATE *psds ;
925	int			total ;
926
927	if (psf->codec_data == NULL)
928		return 0 ;
929	psds = (SDS_PRIVATE*) psf->codec_data ;
930	psds->total_written += len ;
931
932	total = sds_write (psf, psds, ptr, len) ;
933
934	return total ;
935} /* sds_write_i */
936
937static sf_count_t
938sds_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
939{	BUF_UNION	ubuf ;
940	SDS_PRIVATE	*psds ;
941	int			*iptr ;
942	int			k, bufferlen, writecount, count ;
943	sf_count_t	total = 0 ;
944	float		normfact ;
945
946	if (psf->codec_data == NULL)
947		return 0 ;
948	psds = (SDS_PRIVATE*) psf->codec_data ;
949	psds->total_written += len ;
950
951	if (psf->norm_float == SF_TRUE)
952		normfact = 1.0 * 0x80000000 ;
953	else
954		normfact = 1.0 * (1 << psds->bitwidth) ;
955
956	iptr = ubuf.ibuf ;
957	bufferlen = ARRAY_LEN (ubuf.ibuf) ;
958	while (len > 0)
959	{	writecount = (len >= bufferlen) ? bufferlen : (int) len ;
960		for (k = 0 ; k < writecount ; k++)
961			iptr [k] = normfact * ptr [total + k] ;
962		count = sds_write (psf, psds, iptr, writecount) ;
963		total += count ;
964		len -= writecount ;
965		} ;
966
967	return total ;
968} /* sds_write_f */
969
970static sf_count_t
971sds_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
972{	BUF_UNION	ubuf ;
973	SDS_PRIVATE	*psds ;
974	int			*iptr ;
975	int			k, bufferlen, writecount, count ;
976	sf_count_t	total = 0 ;
977	double		normfact ;
978
979	if (psf->codec_data == NULL)
980		return 0 ;
981	psds = (SDS_PRIVATE*) psf->codec_data ;
982	psds->total_written += len ;
983
984	if (psf->norm_double == SF_TRUE)
985		normfact = 1.0 * 0x80000000 ;
986	else
987		normfact = 1.0 * (1 << psds->bitwidth) ;
988
989	iptr = ubuf.ibuf ;
990	bufferlen = ARRAY_LEN (ubuf.ibuf) ;
991	while (len > 0)
992	{	writecount = (len >= bufferlen) ? bufferlen : (int) len ;
993		for (k = 0 ; k < writecount ; k++)
994			iptr [k] = normfact * ptr [total + k] ;
995		count = sds_write (psf, psds, iptr, writecount) ;
996		total += count ;
997		len -= writecount ;
998		} ;
999
1000	return total ;
1001} /* sds_write_d */
1002
1003static int
1004sds_write (SF_PRIVATE *psf, SDS_PRIVATE *psds, const int *ptr, int len)
1005{	int	count, total = 0 ;
1006
1007	while (total < len)
1008	{	count = psds->samplesperblock - psds->write_count ;
1009		if (count > len - total)
1010			count = len - total ;
1011
1012		memcpy (&(psds->write_samples [psds->write_count]), &(ptr [total]), count * sizeof (int)) ;
1013		total += count ;
1014		psds->write_count += count ;
1015
1016		if (psds->write_count >= psds->samplesperblock)
1017			psds->writer (psf, psds) ;
1018		} ;
1019
1020	return total ;
1021} /* sds_write */
1022
1023