1 /* Amiga 8SVX format handler: W V Neisius, February 1992 */
12 /* Private data used by writer */
17 sox_uint8_t buf
[4][BUFLEN
];
21 static void svxwriteheader(sox_format_t
*, size_t);
23 /*======================================================================*/
25 /*======================================================================*/
27 static int startread(sox_format_t
* ft
)
29 priv_t
* p
= (priv_t
* ) ft
->priv
;
42 lsx_fail_errno(ft
,SOX_EINVAL
,"8svx input file must be a file, not a pipe");
49 if (lsx_reads(ft
, buf
, (size_t)4) == SOX_EOF
|| strncmp(buf
, "FORM", (size_t)4) != 0)
51 lsx_fail_errno(ft
, SOX_EHDR
, "Header did not begin with magic word `FORM'");
54 lsx_readdw(ft
, &totalsize
);
55 if (lsx_reads(ft
, buf
, (size_t)4) == SOX_EOF
|| strncmp(buf
, "8SVX", (size_t)4) != 0)
57 lsx_fail_errno(ft
, SOX_EHDR
, "'FORM' chunk does not specify `8SVX' as type");
61 /* read chunks until 'BODY' (or end) */
62 while (lsx_reads(ft
, buf
, (size_t)4) == SOX_SUCCESS
&& strncmp(buf
,"BODY",(size_t)4) != 0) {
63 if (strncmp(buf
,"VHDR",(size_t)4) == 0) {
64 lsx_readdw(ft
, &chunksize
);
67 lsx_fail_errno(ft
, SOX_EHDR
, "VHDR chunk has bad size");
70 lsx_seeki(ft
,(off_t
)12,SEEK_CUR
);
72 lsx_seeki(ft
,(off_t
)1,SEEK_CUR
);
73 lsx_readbuf(ft
, buf
,(size_t)1);
76 lsx_fail_errno(ft
, SOX_EFMT
, "Unsupported data compression");
79 lsx_seeki(ft
,(off_t
)4,SEEK_CUR
);
83 if (strncmp(buf
,"ANNO",(size_t)4) == 0) {
84 lsx_readdw(ft
, &chunksize
);
87 chunk_buf
= lsx_malloc(chunksize
+ (size_t)2);
88 if (lsx_readbuf(ft
, chunk_buf
,(size_t)chunksize
)
91 lsx_fail_errno(ft
, SOX_EHDR
, "Couldn't read all of header");
94 chunk_buf
[chunksize
] = '\0';
95 lsx_debug("%s",chunk_buf
);
101 if (strncmp(buf
,"NAME",(size_t)4) == 0) {
102 lsx_readdw(ft
, &chunksize
);
105 chunk_buf
= lsx_malloc(chunksize
+ (size_t)1);
106 if (lsx_readbuf(ft
, chunk_buf
,(size_t)chunksize
)
109 lsx_fail_errno(ft
, SOX_EHDR
, "Couldn't read all of header");
112 chunk_buf
[chunksize
] = '\0';
113 lsx_debug("%s",chunk_buf
);
119 if (strncmp(buf
,"CHAN",(size_t)4) == 0) {
120 lsx_readdw(ft
, &chunksize
);
123 lsx_fail_errno(ft
, SOX_EHDR
, "Couldn't read all of header");
126 lsx_readdw(ft
, &channels
);
127 channels
= (channels
& 0x01) +
128 ((channels
& 0x02) >> 1) +
129 ((channels
& 0x04) >> 2) +
130 ((channels
& 0x08) >> 3);
135 /* some other kind of chunk */
136 lsx_readdw(ft
, &chunksize
);
139 lsx_seeki(ft
,(off_t
)chunksize
,SEEK_CUR
);
146 lsx_fail_errno(ft
, SOX_EHDR
, "Invalid sample rate");
149 if (strncmp(buf
,"BODY",(size_t)4) != 0)
151 lsx_fail_errno(ft
, SOX_EHDR
, "BODY chunk not found");
154 lsx_readdw(ft
, &(p
->nsamples
));
155 p
->left
= p
->nsamples
;
156 p
->ch0_pos
= lsx_tell(ft
);
158 ft
->signal
.length
= p
->nsamples
;
159 ft
->signal
.channels
= channels
;
160 ft
->signal
.rate
= rate
;
161 ft
->encoding
.encoding
= SOX_ENCODING_SIGN2
;
162 ft
->encoding
.bits_per_sample
= 8;
167 /*======================================================================*/
169 /*======================================================================*/
170 static size_t read_samples(sox_format_t
* ft
, sox_sample_t
*buf
, size_t nsamp
)
174 priv_t
* p
= (priv_t
* ) ft
->priv
;
175 size_t frames
= nsamp
/ ft
->signal
.channels
;
176 unsigned width
= p
->nsamples
/ ft
->signal
.channels
;
178 if (p
->left
< frames
)
181 while (done
!= frames
) {
182 size_t chunk
= frames
- done
;
189 for (ch
= 0; ch
!= ft
->signal
.channels
; ch
++) {
190 if (lsx_seeki(ft
, p
->ch0_pos
+ ch
* width
, SEEK_SET
) ||
191 chunk
!= lsx_readbuf(ft
, p
->buf
[ch
], chunk
))
192 return done
* ft
->signal
.channels
;
195 for (i
= 0; i
!= chunk
; i
++) {
196 for (ch
= 0; ch
!= ft
->signal
.channels
; ch
++) {
197 /* scale signed up to long's range */
198 *buf
++ = SOX_SIGNED_8BIT_TO_SAMPLE(p
->buf
[ch
][i
], dummy
);
203 p
->left
-= chunk
* ft
->signal
.channels
;
206 return done
* ft
->signal
.channels
;
209 /*======================================================================*/
211 /*======================================================================*/
212 static int startwrite(sox_format_t
* ft
)
214 priv_t
* p
= (priv_t
* ) ft
->priv
;
217 /* open channel output files */
218 for (i
= 0; i
< ft
->signal
.channels
; i
++) {
219 if ((p
->tmp
[i
] = lsx_tmpfile()) == NULL
)
221 lsx_fail_errno(ft
,errno
,"Can't open channel output file");
230 /*======================================================================*/
232 /*======================================================================*/
234 static size_t write_samples(sox_format_t
* ft
, const sox_sample_t
*buf
, size_t len
)
236 priv_t
* p
= (priv_t
* ) ft
->priv
;
245 for (i
= 0; i
< ft
->signal
.channels
; i
++) {
246 datum
= SOX_SAMPLE_TO_SIGNED_8BIT(*buf
++, ft
->clips
);
247 putc(datum
, p
->tmp
[i
]);
249 done
+= ft
->signal
.channels
;
254 /*======================================================================*/
256 /*======================================================================*/
258 static int stopwrite(sox_format_t
* ft
)
260 priv_t
* p
= (priv_t
* ) ft
->priv
;
265 svxwriteheader(ft
, (size_t) p
->nsamples
);
267 /* append all channel pieces to channel 0 */
268 /* close temp files */
269 for (i
= 0; i
< ft
->signal
.channels
; i
++) {
270 if (fseeko(p
->tmp
[i
], (off_t
)0, 0))
272 lsx_fail_errno (ft
,errno
,"Can't rewind channel output file %lu",(unsigned long)i
);
275 while (!feof(p
->tmp
[i
])) {
276 len
= fread(svxbuf
, (size_t) 1, (size_t) 512, p
->tmp
[i
]);
277 if (lsx_writebuf(ft
, svxbuf
, len
) != len
) {
278 lsx_fail_errno (ft
,errno
,"Can't write channel output file %lu",(unsigned long)i
);
285 /* add a pad byte if BODY size is odd */
286 if(p
->nsamples
% 2 != 0)
287 lsx_writeb(ft
, '\0');
292 /*======================================================================*/
293 /* 8SVXWRITEHEADER */
294 /*======================================================================*/
295 #define SVXHEADERSIZE 100
296 static void svxwriteheader(sox_format_t
* ft
, size_t nsamples
)
298 size_t formsize
= nsamples
+ SVXHEADERSIZE
- 8;
300 /* FORM size must be even */
301 if(formsize
% 2 != 0) formsize
++;
303 lsx_writes(ft
, "FORM");
304 lsx_writedw(ft
, (unsigned) formsize
); /* size of file */
305 lsx_writes(ft
, "8SVX"); /* File type */
307 lsx_writes(ft
, "VHDR");
308 lsx_writedw(ft
, 20); /* number of bytes to follow */
309 lsx_writedw(ft
, (unsigned) nsamples
/ft
->signal
.channels
); /* samples, 1-shot */
310 lsx_writedw(ft
, 0); /* samples, repeat */
311 lsx_writedw(ft
, 0); /* samples per repeat cycle */
312 lsx_writew(ft
, min(65535, (unsigned)(ft
->signal
.rate
+ .5)));
313 lsx_writeb(ft
,1); /* number of octabes */
314 lsx_writeb(ft
,0); /* data compression (none) */
315 lsx_writew(ft
,1); lsx_writew(ft
,0); /* volume */
317 lsx_writes(ft
, "ANNO");
318 lsx_writedw(ft
, 32); /* length of block */
319 lsx_writes(ft
, "File created by Sound Exchange ");
321 lsx_writes(ft
, "CHAN");
323 lsx_writedw(ft
, (ft
->signal
.channels
== 2) ? 6u :
324 (ft
->signal
.channels
== 4) ? 15u : 2u);
326 lsx_writes(ft
, "BODY");
327 lsx_writedw(ft
, (unsigned) nsamples
); /* samples in file */
330 LSX_FORMAT_HANDLER(svx
)
332 static char const * const names
[] = {"8svx", NULL
};
333 static unsigned const write_encodings
[] = {SOX_ENCODING_SIGN2
, 8, 0, 0};
334 static sox_format_handler_t
const handler
= {SOX_LIB_VERSION_CODE
,
335 "Amiga audio format (a subformat of the Interchange File Format)",
336 names
, SOX_FILE_BIG_END
|SOX_FILE_MONO
|SOX_FILE_STEREO
|SOX_FILE_QUAD
,
337 startread
, read_samples
, NULL
,
338 startwrite
, write_samples
, stopwrite
,
339 NULL
, write_encodings
, NULL
, sizeof(priv_t
)