ref: c4a08032074cdf097cfb13683efb4cfad74b96c6
dir: /src/sndrtool.c/
/* * Sounder/Sndtool format handler: W V Neisius, February 1992 * * June 28, 93: force output to mono. * * March 3, 1999 - cbagwell@sprynet.com * Forced extra comment fields to zero. */ #include "st_i.h" #include <math.h> #include <string.h> #include <stdio.h> #ifdef HAVE_ERRNO_H #include <errno.h> #endif #ifdef HAVE_UNISTD_H #include <unistd.h> /* For SEEK_* defines if not found in stdio */ #endif /* Private data used by writer */ typedef struct sndpriv { st_size_t nsamples; st_size_t dataStart; } *snd_t; #ifndef SEEK_CUR #define SEEK_CUR 1 #endif static void sndtwriteheader(ft_t ft, st_size_t nsamples); int st_sndseek(ft_t ft, st_size_t offset) { snd_t snd = (snd_t ) ft->priv; return st_seek(ft,offset*ft->info.size + snd->dataStart,SEEK_SET); } /*======================================================================*/ /* SNDSTARTREAD */ /*======================================================================*/ int st_sndtstartread(ft_t ft) { snd_t snd = (snd_t ) ft->priv; char buf[97]; unsigned short rate; int rc; /* Needed for rawread() */ rc = st_rawstartread(ft); if (rc) return rc; /* sndt is in little endian format so * swap bytes on big endian machines. */ if (ST_IS_BIGENDIAN) { ft->swap = ft->swap ? 0 : 1; } rate = 0; /* determine file type */ /* if first 5 bytes == SOUND then this is probably a sndtool sound */ /* if first word (16 bits) == 0 and second word is between 4000 & 25000 then this is sounder sound */ /* otherwise, its probably raw, not handled here */ if (fread(buf, 1, 2, ft->fp) != 2) { st_fail_errno(ft,errno,"SND: unexpected EOF"); return(ST_EOF); } if (strncmp(buf,"\0\0",2) == 0) { /* sounder */ st_readw(ft, &rate); if (rate < 4000 || rate > 25000 ) { st_fail_errno(ft,ST_EFMT,"SND: sample rate out of range"); return(ST_EOF); } fseek(ft->fp,4,SEEK_CUR); } else { /* sndtool ? */ fread(&buf[2], 1, 6, ft->fp); if (strncmp(buf,"SOUND",5)) { st_fail_errno(ft,ST_EFMT,"SND: unrecognized SND format"); return(ST_EOF); } fseek(ft->fp,12,SEEK_CUR); st_readw(ft, &rate); fseek(ft->fp,6,SEEK_CUR); if (st_reads(ft, buf, 96) == ST_EOF) { st_fail_errno(ft,ST_EHDR,"SND: unexpected EOF in SND header"); return(ST_EOF); } st_report("%s",buf); } ft->info.channels = 1; ft->info.rate = rate; ft->info.encoding = ST_ENCODING_UNSIGNED; ft->info.size = ST_SIZE_BYTE; snd->dataStart = ftell(ft->fp); ft->length = st_filelength(ft) - snd->dataStart; return (ST_SUCCESS); } /*======================================================================*/ /* SNDTSTARTWRITE */ /*======================================================================*/ int st_sndtstartwrite(ft_t ft) { snd_t p = (snd_t ) ft->priv; int rc; /* Needed for rawwrite() */ rc = st_rawstartwrite(ft); if (rc) return rc; /* sndt is in little endian format so * swap bytes on big endian machines */ if (ST_IS_BIGENDIAN) { ft->swap = ft->swap ? 0 : 1; } /* write header */ ft->info.channels = 1; ft->info.encoding = ST_ENCODING_UNSIGNED; ft->info.size = ST_SIZE_BYTE; p->nsamples = 0; sndtwriteheader(ft, 0); return(ST_SUCCESS); } /*======================================================================*/ /* SNDRSTARTWRITE */ /*======================================================================*/ int st_sndrstartwrite(ft_t ft) { int rc; /* Needed for rawread() */ rc = st_rawstartread(ft); if (rc) return rc; /* sndr is in little endian format so * swap bytes on big endian machines */ if (ST_IS_BIGENDIAN) { ft->swap = ft->swap ? 0 : 1; } /* write header */ ft->info.channels = 1; ft->info.encoding = ST_ENCODING_UNSIGNED; ft->info.size = ST_SIZE_BYTE; /* sounder header */ st_writew (ft,0); /* sample size code */ st_writew (ft,(int) ft->info.rate); /* sample rate */ st_writew (ft,10); /* volume */ st_writew (ft,4); /* shift */ return(ST_SUCCESS); } /*======================================================================*/ /* SNDTWRITE */ /*======================================================================*/ st_ssize_t st_sndtwrite(ft_t ft, st_sample_t *buf, st_ssize_t len) { snd_t p = (snd_t ) ft->priv; p->nsamples += len; return st_rawwrite(ft, buf, len); } /*======================================================================*/ /* SNDTSTOPWRITE */ /*======================================================================*/ int st_sndtstopwrite(ft_t ft) { snd_t p = (snd_t ) ft->priv; int rc; /* Flush remaining buffer out */ rc = st_rawstopwrite(ft); if (rc) return rc; /* fixup file sizes in header */ if (fseek(ft->fp, 0L, 0) != 0){ st_fail_errno(ft,errno,"can't rewind output file to rewrite SND header"); return ST_EOF; } sndtwriteheader(ft, p->nsamples); return(ST_SUCCESS); } /*======================================================================*/ /* SNDTWRITEHEADER */ /*======================================================================*/ static void sndtwriteheader(ft_t ft, st_size_t nsamples) { char name_buf[97]; /* sndtool header */ st_writes(ft, "SOUND"); /* magic */ st_writeb(ft, 0x1a); st_writew (ft,0); /* hGSound */ st_writedw (ft,nsamples); st_writedw (ft,0); st_writedw (ft,nsamples); st_writew (ft,(int) ft->info.rate); st_writew (ft,0); st_writew (ft,10); st_writew (ft,4); memset (name_buf, 0, 96); sprintf (name_buf,"%.62s - File created by Sound Exchange",ft->filename); fwrite (name_buf, 1, 96, ft->fp); }