⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aiff.c

📁 linux下录音程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * September 25, 1991 * Copyright 1991 Guido van Rossum And Sundry Contributors * This source code is freely redistributable and may be used for * any purpose.  This copyright notice must be maintained.  * Guido van Rossum And Sundry Contributors are not responsible for  * the consequences of using this software. *//* * Sound Tools SGI/Amiga AIFF format. * Used by SGI on 4D/35 and Indigo. * This is a subformat of the EA-IFF-85 format. * This is related to the IFF format used by the Amiga. * But, apparently, not the same. * * Jan 93: new version from Guido Van Rossum that  * correctly skips unwanted sections. * * Jan 94: add loop & marker support * Jul 97: added comments I/O by Leigh Smith * Nov 97: added verbose chunk comments * * June 1, 1998 - Chris Bagwell (cbagwell@sprynet.com) *   Fixed compile warnings reported by Kjetil Torgrim Homme *   <kjetilho@ifi.uio.no> * * Sept 9, 1998 - fixed loop markers. * */#include <math.h>#include <stdlib.h>#include <string.h>#include "st.h"#ifndef SEEK_SET#define SEEK_SET 0		/* nasty nasty */#endif#ifndef SEEK_CUR#define SEEK_CUR 1		/* nasty nasty */#endif /* SEEK_CUR *//* Private data used by writer */struct aiffpriv {	ULONG nsamples;	/* number of 1-channel samples read or written */};double read_ieee_extended();LONG rawread(P3(ft_t, LONG *, LONG));void aiffwriteheader(P2(ft_t, LONG));void rawwrite(P3(ft_t, LONG *, LONG));void write_ieee_extended(P2(ft_t, double));double ConvertFromIeeeExtended();void ConvertToIeeeExtended(P2(double, char *));void textChunk(P3(char **text, char *chunkDescription, ft_t ft));void reportInstrument(P1(ft_t ft));void aiffstartread(ft) ft_t ft;{	struct aiffpriv *p = (struct aiffpriv *) ft->priv;	char buf[5];	ULONG totalsize;	LONG chunksize;	int channels = 0;	ULONG frames;	int bits = 0;	double rate = 0.0;	ULONG offset = 0;	ULONG blocksize = 0;	int littlendian = 0;	char *endptr;	int foundcomm = 0, foundmark = 0, foundinstr = 0;	struct mark {		int id, position;		char name[40]; 	} marks[32];	int i, j;	LONG nmarks = 0;	LONG sustainLoopBegin = 0, sustainLoopEnd = 0,	     releaseLoopBegin = 0, releaseLoopEnd = 0;	LONG seekto = 0L, ssndsize = 0L;	char *author;	char *copyright;	char *nametext;	/* FORM chunk */	if (fread(buf, 1, 4, ft->fp) != 4 || strncmp(buf, "FORM", 4) != 0)		fail("AIFF header does not begin with magic word 'FORM'");	totalsize = rblong(ft);	if (fread(buf, 1, 4, ft->fp) != 4 || strncmp(buf, "AIFF", 4) != 0)		fail("AIFF 'FORM' chunk does not specify 'AIFF' as type");		/* Skip everything but the COMM chunk and the SSND chunk */	/* The SSND chunk must be the last in the file */	while (1) {		if (fread(buf, 1, 4, ft->fp) != 4)			if (ssndsize > 0)				break;			else				fail("Missing SSND chunk in AIFF file");		if (strncmp(buf, "COMM", 4) == 0) {			/* COMM chunk */			chunksize = rblong(ft);			if (chunksize != 18)				fail("AIFF COMM chunk has bad size");			channels = rbshort(ft);			frames = rblong(ft);			bits = rbshort(ft);			rate = read_ieee_extended(ft);			foundcomm = 1;		}		else if (strncmp(buf, "SSND", 4) == 0) {			/* SSND chunk */			chunksize = rblong(ft);			offset = rblong(ft);			blocksize = rblong(ft);			chunksize -= 8;			ssndsize = chunksize;			/* if can't seek, just do sound now */			if (!ft->seekable)				break;			/* else, seek to end of sound and hunt for more */			seekto = ftell(ft->fp);			fseek(ft->fp, chunksize, SEEK_CUR); 		}		else if (strncmp(buf, "MARK", 4) == 0) {			/* MARK chunk */			chunksize = rblong(ft);			nmarks = rbshort(ft);			chunksize -= 2;			for(i = 0; i < nmarks; i++) {				int len;				marks[i].id = rbshort(ft);				marks[i].position = rblong(ft);				chunksize -= 6;				len = getc(ft->fp);				chunksize -= len + 1;				for(j = 0; j < len ; j++) 					marks[i].name[j] = getc(ft->fp);				marks[i].name[j] = 0;				if ((len & 1) == 0) {					chunksize--;					getc(ft->fp);				}			}			/* HA HA!  Sound Designer (and others) makes */			/* bogus files. It spits out bogus chunksize */			/* for MARK field */			while(chunksize-- > 0)				getc(ft->fp);			foundmark = 1;		}		else if (strncmp(buf, "INST", 4) == 0) {			/* INST chunk */			chunksize = rblong(ft);			ft->instr.MIDInote = getc(ft->fp);			getc(ft->fp);				/* detune */			ft->instr.MIDIlow = getc(ft->fp);			ft->instr.MIDIhi = getc(ft->fp);			getc(ft->fp);			/* low velocity */			getc(ft->fp);			/* hi  velocity */			rbshort(ft);				/* gain */			ft->loops[0].type = rbshort(ft); /* sustain loop */			sustainLoopBegin = rbshort(ft);	 /* begin marker */			sustainLoopEnd = rbshort(ft);    /* end marker */			ft->loops[1].type = rbshort(ft); /* release loop */			releaseLoopBegin = rbshort(ft);  /* begin marker */			releaseLoopEnd = rbshort(ft);    /* end marker */			foundinstr = 1;		}		else if (strncmp(buf, "APPL", 4) == 0) {			chunksize = rblong(ft);			while(chunksize-- > 0)				getc(ft->fp);		}		else if (strncmp(buf, "ALCH", 4) == 0) {			/* I think this is bogus and gets grabbed by APPL */			/* INST chunk */			rblong(ft);		/* ENVS - jeez! */			chunksize = rblong(ft);			while(chunksize-- > 0)				getc(ft->fp);		}		else if (strncmp(buf, "ANNO", 4) == 0) {			/* Old form of comment chunk */			chunksize = rblong(ft);			/* allocate enough memory to hold the comment */			ft->comment = (char *) malloc((size_t) chunksize);			if (ft->comment == NULL)			  fail("AIFF: Couldn't allocate ANNO header");			if (fread(ft->comment, 1, chunksize, ft->fp) != chunksize)			  fail("AIFF: Unexpected EOF in ANNO header");		}		else if (strncmp(buf, "AUTH", 4) == 0) {		  /* Author chunk */		  textChunk(&author, "Author:", ft);		  free(author);		}		else if (strncmp(buf, "NAME", 4) == 0) {		  /* Name chunk */		  textChunk(&nametext, "Name:", ft);		  free(nametext);		}		else if (strncmp(buf, "(c) ", 4) == 0) {		  /* Copyright chunk */		  textChunk(&copyright, "Copyright:", ft);		  free(copyright);		}		else {			buf[4] = 0;			/* bogus file, probably from the Mac */			if ((buf[0] < 'A' || buf[0] > 'Z') ||			    (buf[1] < 'A' || buf[1] > 'Z') ||			    (buf[2] < 'A' || buf[2] > 'Z') ||			    (buf[3] < 'A' || buf[3] > 'Z'))				break;			if (feof(ft->fp))				break;			report("AIFFstartread: ignoring '%s' chunk\n", buf);			chunksize = rblong(ft);			if (feof(ft->fp))				break;			/* Skip the chunk using getc() so we may read			   from a pipe */			while (chunksize-- > 0) {				if (getc(ft->fp) == EOF)					break;			}		}		if (feof(ft->fp))			break;	}	/* 	 * if a pipe, we lose all chunks after sound.  	 * Like, say, instrument loops. 	 */	if (ft->seekable)		if (seekto > 0)			fseek(ft->fp, seekto, SEEK_SET);		else			fail("AIFF: no sound data on input file");	/* SSND chunk just read */	if (blocksize != 0)		fail("AIFF header specifies nonzero blocksize?!?!");	while ((LONG) (--offset) >= 0) {		if (getc(ft->fp) == EOF)			fail("unexpected EOF while skipping AIFF offset");	}	if (foundcomm) {		ft->info.channels = channels;		ft->info.rate = rate;		ft->info.style = SIGN2;		switch (bits) {		case 8:			ft->info.size = BYTE;			break;		case 16:			ft->info.size = WORD;			break;		default:			fail("unsupported sample size in AIFF header: %d", bits);			/*NOTREACHED*/		}	} else  {		if ((ft->info.channels == -1)			|| (ft->info.rate == -1)			|| (ft->info.style == -1)			|| (ft->info.size == -1)) {		  report("You must specify # channels, sample rate, signed/unsigned,\n");		  report("and 8/16 on the command line.");		  fail("Bogus AIFF file: no COMM section.");		}	}	p->nsamples = ssndsize / ft->info.size;	/* leave out channels */	/* process instrument and marker notations. */	if (foundmark && !foundinstr)		fail("Bogus AIFF file: MARKers but no INSTrument.");	if (!foundmark && foundinstr)		fail("Bogus AIFF file: INSTrument but no MARKers.");	if (foundmark && foundinstr) {		int i;		int slbIndex = 0, sleIndex = 0;		int rlbIndex = 0, rleIndex = 0;		/* find our loop markers and save their marker indexes */		for(i = 0; i < nmarks; i++) { 		  if(marks[i].id == sustainLoopBegin)		    slbIndex = i;		  if(marks[i].id == sustainLoopEnd)		    sleIndex = i;		  if(marks[i].id == releaseLoopBegin)		    rlbIndex = i;		  if(marks[i].id == releaseLoopEnd)		    rleIndex = i;		}		ft->instr.nloops = 0;		if (ft->loops[0].type != 0) {			ft->loops[0].start = marks[slbIndex].position;			ft->loops[0].length = 			    marks[sleIndex].position - marks[slbIndex].position;			/* really the loop count should be infinite */			ft->loops[0].count = 1;				ft->instr.loopmode = LOOP_SUSTAIN_DECAY | ft->loops[0].type;			ft->instr.nloops++;		}		if (ft->loops[1].type != 0) {			ft->loops[1].start = marks[rlbIndex].position;			ft->loops[1].length = 			    marks[rleIndex].position - marks[rlbIndex].position;			/* really the loop count should be infinite */			ft->loops[1].count = 1;			ft->instr.loopmode = LOOP_SUSTAIN_DECAY | ft->loops[1].type;			ft->instr.nloops++;		} 	}	if (verbose)	  reportInstrument(ft);	endptr = (char *) &littlendian;	*endptr = 1;	if (littlendian == 1)		ft->swap = 1;}/* print out the MIDI key allocations, loop points, directions etc */void reportInstrument(ft)ft_t ft;{  int loopNum;  if(ft->instr.nloops > 0)    fprintf(stderr, "AIFF Loop markers:\n");  for(loopNum  = 0; loopNum < ft->instr.nloops; loopNum++) {    if (ft->loops[loopNum].count) {      fprintf(stderr, "Loop %d: start: %6d", loopNum, ft->loops[loopNum].start);      fprintf(stderr, " end:   %6d", 	      ft->loops[loopNum].start + ft->loops[loopNum].length);      fprintf(stderr, " count: %6d", ft->loops[loopNum].count);      fprintf(stderr, " type:  ");      switch(ft->loops[loopNum].type & ~LOOP_SUSTAIN_DECAY) {      case 0: fprintf(stderr, "off\n"); break;      case 1: fprintf(stderr, "forward\n"); break;      case 2: fprintf(stderr, "forward/backward\n"); break;      }    }  }  fprintf(stderr, "Unity MIDI Note: %d\n", ft->instr.MIDInote);  fprintf(stderr, "Low   MIDI Note: %d\n", ft->instr.MIDIlow);  fprintf(stderr, "High  MIDI Note: %d\n", ft->instr.MIDIhi);}/* Process a text chunk, allocate memory, display it if verbose and return */void textChunk(text, chunkDescription, ft) char **text;char *chunkDescription;ft_t ft;{  LONG chunksize = rblong(ft);  /* allocate enough memory to hold the text including a terminating \0 */  *text = (char *) malloc((size_t) chunksize + 1);  if (*text == NULL)    fail("AIFF: Couldn't allocate %s header", chunkDescription);  if (fread(*text, 1, chunksize, ft->fp) != chunksize)    fail("AIFF: Unexpected EOF in %s header", chunkDescription);  *(*text + chunksize) = '\0';  if(verbose) {    printf("%-10s   \"%s\"\n", chunkDescription, *text);  }}LONG aiffread(ft, buf, len)ft_t ft;LONG *buf, len;{	struct aiffpriv *p = (struct aiffpriv *) ft->priv;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -