ftp.nice.ch/pub/next/unix/audio/Cmix.N.s.tar.gz#/cmix/tape.backup/nsfrestore.c

This is nsfrestore.c in view mode; [Download] [Up]

#include "../H/sfheader.h"
#include "nlabel.h"
#include <stdio.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/mtio.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#define  BUFSIZE 65536

char tapename[16] = "/dev/rst1";
char *usefile;

	char buffer[BUFSIZE];

main(argc,argv)

int argc;
char *argv[];

{
	SFHEADER sfh1;
	struct stat sfst1;
	struct mtget mtget ;
	struct mtop mtop ;
	struct label label;

	char *cp,*sfout,*getsfcode();
/*	char buffer[BUFSIZE]; */
	int totalbytes,i,result,inbytes,sfile,tapeunit,tapefile,skipfile;
	int tapenumber;
	float duration;

	if(argc == 1) {
usage:		printf("Usage: -f [device] -l [tape number] -s [tape files to skip over] sf1 .. sfn\nDefaults: /dev/rsmt0, skip over label only\n");
		exit(1);
	}
	usefile = tapename;
	skipfile = tapenumber = 0;
	tapefile = 1;
	system("date");
	while((*++argv)[0] == '-') {
		argc -= 2; /* Take away two args */
		for(cp = argv[0]+1; *cp; cp++) {
			switch(*cp) { /* Grap options */
			case 'f': 
				usefile = *++argv;
				break;
			case 's':
				tapefile = atoi(*++argv);
				skipfile = tapefile ? 1 : 0;
				/* skip this number of files before writing*/
				break;
			case 'l':
				tapenumber = atoi(*++argv);
				break;
			default:
				printf("unknown option\n");
				goto usage;
			}
		}
	}
	if(!tapenumber) {
		printf("You didn't specify a tape number with -n flag\n");
		exit(-1);
	}
	if((tapeunit = open(usefile,0)) < 0) {
		printf("trouble opening tape unit\n");
		exit(tapeunit);
	}
	if(read(tapeunit,&label,SIZEOFLABEL) != SIZEOFLABEL) {
		printf("Can't seem to read the label on this tape\n");
		exit(tapeunit);
	}
	if(label.tapenumber != tapenumber) {
		printf
		("this is tape number %d, you are asking for tape number %d\n"
		,label.tapenumber,tapenumber);
		exit(tapeunit);
	}
	mtop.mt_op = MTFSF;
	mtop.mt_count = 1;
	if((ioctl(tapeunit,MTIOCTOP,&mtop)) == -1) {
		printf("error forward spacing tape past label eof\n");
		exit(-2);
	}
	printf("Comment on tape %d: %s\n",label.tapenumber,label.comment);

	for(i=0; i<argc-1; i++) {
		sfout = argv[i];
		if((sfile = open(sfout,O_CREAT | O_RDWR, 0644)) <= 0) {
			printf("Can't open file %s\n",sfout);
			exit(1);
		}
		totalbytes = 0;

		if(skipfile) {
			mtop.mt_op = MTFSF;
			mtop.mt_count = tapefile;
			if((ioctl(tapeunit,MTIOCTOP,&mtop)) == -1) {
				printf("error forward spacing tape\n");
				exit(-2);
			}
		}
		skipfile = 0;
		/* read first record to get header printed up*/
		if((inbytes = read(tapeunit,buffer,BUFSIZE)) != BUFSIZE) {
			printf("Bad read on tape unit %d %d\n",tapeunit,inbytes);
			exit(-1);
		}
		printf("-------------------------------------------------\n");
		/* this allows any type of header off of tape */
		if(parseHeader(buffer,&sfh1)) {
			printf("Bad sfheader on tape.\n");
			exit(-1);
		}
		printsf(&sfh1);

		if((write(sfile,buffer,BUFSIZE)) != BUFSIZE) {
			printf("Bad write on soundfile\n");
			exit(-1);
		}
		totalbytes = BUFSIZE;

		while(1) {
			if((inbytes=read(tapeunit,buffer,BUFSIZE)) <= 0) {
				printf("reached eof on input\n");
				close(sfile);
				break;
			}
			if(write(sfile,buffer,inbytes) != inbytes) {
				printf("Bad write on sound file\n");
				close(sfile);
				close(tapeunit);
				exit(0);
			}
			totalbytes += inbytes;
		}
		duration = 
			(float)totalbytes/(float)sfclass(&sfh1)/
				(float)sfchans(&sfh1)/sfsrate(&sfh1);
		tapefile++;
		printf
		     ("Bytes restored = %d, duration = %f, tapefile = %d\n\n\n",
			totalbytes,duration,tapefile);
		fflush(stdout);
		close(sfile);
	}
	close(tapeunit);
}

static SFCODE   ampcode = {
        SF_MAXAMP,
        sizeof(SFMAXAMP) + sizeof(SFCODE)
}; 

int
parseHeader(buff,header)
SFHEADER *header;
char *buff;
{
        int i;
	SFMAXAMP sfmnew;
        char *pointer;
        /* read in 1kb first, to see if hybrid header is present */
        bcopy(buff,(char *) header,SIZEOF_BSD_HEADER);
        /* if file has IRCAM-style header */
        if((header)->sfinfo.NeXTheader.magic == SF_MAGIC)
                return(parseIrcamHeader(header));
        /* if magic number is neither IRCAM nor local, we cant read it */
	/* in case it is byte-swapped, give a message saying so */
        if((header)->sfinfo.NeXTheader.magic == 1688404224) {
		fprintf(stderr, "This file must be byte-swapped before using!\n");
		return 1;
	}
        if((header)->sfinfo.NeXTheader.magic != SND_MAGIC)
                return 1;
        /* if hybrid header is there, we are done here */
        if((header)->sfinfo.sf_magic == SF_MAGIC) {
		fprintf(stderr, "This is a hybrid IRCAM/NeXT soundfile.\n");
                return 0;
	}

        /* else, if file being read is native NeXT soundfile... */

	fprintf(stderr, "This is a native NeXT soundfile.\n");
	/* zero out new header after NeXT portion */
	pointer = (char *)header;
	for(i=29; i<SIZEOF_BSD_HEADER; i++) *(pointer+i) = 0;
        /* load all values from native header into hybrid header */
        (header)->sfinfo.sf_magic = 0; /* so we know it is native NeXT file */
        (header)->sfinfo.sf_srate = (header)->sfinfo.NeXTheader.samplingRate;
        (header)->sfinfo.sf_chans = (header)->sfinfo.NeXTheader.channelCount;
        switch(header->sfinfo.NeXTheader.dataFormat) {
        case SND_FORMAT_FLOAT:
                (header)->sfinfo.sf_packmode = SF_FLOAT;
                break;
        case SND_FORMAT_LINEAR_16:
                (header)->sfinfo.sf_packmode = SF_SHORT;
                break;
        default:
                fprintf(stderr, "only float and short files can be used.\n");
                return 1;
        }
	for(i=0; i<2; i++) {
			sfmaxamp(&sfmnew,i)=0;
			sfmaxamploc(&sfmnew,i)=0;
		}
		sfmaxamptime(&sfmnew) = 0;
		putsfcode(header,&sfmnew,&ampcode);
        return 0;
}

int
parseIrcamHeader(hd)
        SFHEADER *hd;
{
        char *ptr = (char *) hd;
	int i;
	SFMAXAMP sfmnew;
	fprintf(stderr, "This is an IRCAM style soundfile.\n");
        /* copy everything in header (minus a small chunk) to the location
           in the header it needs to be in a hybrid header.  We loose 28 chars
           from the end of the comment, but who uses that much comment?  */
        bcopy(ptr, ptr + SIZEOF_NeXT_HEADER,
                sizeof(SFHEADER) - SIZEOF_NeXT_HEADER);
        /* and then zero out beginning and set the new magic number */
        bzero(ptr, SIZEOF_NeXT_HEADER);
	/* if no amp code in header, put one */
	if(getsfcode(hd, SF_MAXAMP) == NULL) {
		for(i=0; i<2; i++) {
			sfmaxamp(&sfmnew,i)=0;
			sfmaxamploc(&sfmnew,i)=0;
		}
		sfmaxamptime(&sfmnew) = 0;
		if(putsfcode(hd,&sfmnew,&ampcode) < 0) {
			fprintf(stderr, "Unable to add new amp sfcode.\n");
			return 1;
		}
	}
	/* set the magic number at the beginning to be the IRCAM magic number,
	   to signal that this should be written back out as such.	*/
        hd->sfinfo.NeXTheader.magic = SF_MAGIC;
        return 0;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.