📄 file.c
字号:
/* $Header: /home/cvs/wavplay/file.c,v 1.2 1999/12/04 00:01:20 wwg Exp $ * Warren W. Gay VE3WWG Sun Feb 16 20:43:59 1997 * * WAV FILE OPERATIONS: * * X LessTif WAV Play : * * Copyright (C) 1997 Warren W. Gay VE3WWG * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details (see enclosed file COPYING). * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. * * Send correspondance to: * * Warren W. Gay VE3WWG * * Email: * ve3wwg@yahoo.com * wgay@mackenziefinancial.com * * $Log: file.c,v $ * Revision 1.2 1999/12/04 00:01:20 wwg * Implement wavplay-1.4 release changes * * Revision 1.1.1.1 1999/11/21 19:50:56 wwg * Import wavplay-1.3 into CVS * * Revision 1.3 1997/04/22 00:37:56 wwg * Patched to update the RIFF block size, after patching * the data block size, when the xltwavplay client * terminates the recording session. This is a temp. fix * until a real RIFF block module is added to this suite. * * Revision 1.2 1997/04/14 00:49:07 wwg * Added ioctl(fd,SNDCTL_DSP_SYNC) calls * * Revision 1.1 1997/04/14 00:12:15 wwg * Initial revision * */static const char rcsid[] = "@(#)file.c $Revision: 1.2 $";#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <malloc.h>#include <string.h>#include <memory.h>#include <signal.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/ioctl.h>#include <assert.h>#include <linux/soundcard.h>#include "wavplay.h"extern int clntIPC; /* Needed for message passing in PlayDSP *//* Number of updates sent to the client per second during playback and *//* record. For high sample rates in stereo, too many per second floods the *//* client. 3 is a compromise between update speed and smoothness; 4 tends *//* to cause "jumpy" updates. (The cause of the jumps probably lie in *//* LessTif and/or X since the IPC messages are sent regularly). */#define RECPLAY_UPDATES_PER_SEC 3static ErrFunc v_erf; /* This module's error reporting function */static char emsg[2048];/* * Error reporting function for this source module: */static voiderr(const char *format,...) { va_list ap; if ( v_erf == NULL ) return; /* Only report error if we have function */ va_start(ap,format); v_erf(format,ap); /* Use caller's supplied function */ va_end(ap);}static void_v_erf(const char *format,va_list ap) { vsprintf(emsg,format,ap); /* Capture message into emsg[] */}/* * Internal routine to allocate WAVFILE structure: */static WAVFILE *wavfile_alloc(const char *Pathname) { WAVFILE *wfile = (WAVFILE *) malloc(sizeof (WAVFILE)); if ( wfile == NULL ) { err("%s: Allocating WAVFILE structure",sys_errlist[ENOMEM]); return NULL; } memset(wfile,0,sizeof *wfile); if ( (wfile->Pathname = strdup(Pathname)) == NULL ) { free(wfile); err("%s: Allocating storage for WAVFILE.Pathname",sys_errlist[ENOMEM]); return NULL; } wfile->fd = -1; /* Initialize fd as not open */ wfile->wavinfo.Channels = Mono; wfile->wavinfo.DataBits = 8; return wfile;}/* * Internal routine to release WAVFILE structure: * No errors reported. */static voidwavfile_free(WAVFILE *wfile) { if ( wfile->Pathname != NULL ) free(wfile->Pathname); free(wfile);}/* * Open a WAV file for reading: returns (WAVFILE *) * * The opened file is positioned at the first byte of WAV file data, or * NULL is returned if the open is unsuccessful. */WAVFILE *WavOpenForRead(const char *Pathname,ErrFunc erf) { WAVFILE *wfile = wavfile_alloc(Pathname); int e; /* Saved errno value */ UInt32 offset; /* File offset */ Byte ubuf[4]; /* 4 byte buffer */ UInt32 dbytes; /* Data byte count */ /* wavfile.c values : */ int channels; /* Channels recorded in this wav file */ u_long samplerate; /* Sampling rate */ int sample_bits; /* data bit size (8/12/16) */ u_long samples; /* The number of samples in this file */ u_long datastart; /* The offset to the wav data */ v_erf = erf; /* Set error reporting function */ if ( wfile == NULL ) return NULL; /* Insufficient memory (class B msg) */ /* * Open the file for reading: */ if ( (wfile->fd = open(wfile->Pathname,O_RDONLY)) < 0 ) { err("%s:\nOpening WAV file %s", sys_errlist[errno], wfile->Pathname); goto errxit; } if ( lseek(wfile->fd,0L,SEEK_SET) != 0L ) { err("%s:\nRewinding WAV file %s", sys_errlist[errno], wfile->Pathname); goto errxit; /* Wav file must be seekable device */ } if ( (e = WaveReadHeader(wfile->fd,&channels,&samplerate,&sample_bits,&samples,&datastart,_v_erf)) != 0 ) { err("%s:\nReading WAV header from %s", emsg, wfile->Pathname); goto errxit; } /* * Copy WAV data over to WAVFILE struct: */ if ( channels == 2 ) wfile->wavinfo.Channels = Stereo; else wfile->wavinfo.Channels = Mono; wfile->wavinfo.SamplingRate = (UInt32) samplerate; wfile->wavinfo.Samples = (UInt32) samples; wfile->wavinfo.DataBits = (UInt16) sample_bits; wfile->wavinfo.DataStart = (UInt32) datastart; wfile->num_samples = wfile->wavinfo.Samples; wfile->rw = 'R'; /* Read mode */ offset = wfile->wavinfo.DataStart - 4; /* * Seek to byte count and read dbytes: */ if ( lseek(wfile->fd,offset,SEEK_SET) != offset ) { err("%s:\nSeeking to WAV data in %s",sys_errlist[errno],wfile->Pathname); goto errxit; /* Seek failure */ } if ( read(wfile->fd,ubuf,4) != 4 ) { err("%s:\nReading dbytes from %s",sys_errlist[errno],wfile->Pathname); goto errxit; } /* * Put little endian value into 32 bit value: */ dbytes = ubuf[3]; dbytes = (dbytes << 8) | ubuf[2]; dbytes = (dbytes << 8) | ubuf[1]; dbytes = (dbytes << 8) | ubuf[0]; wfile->wavinfo.DataBytes = dbytes; /* * Open succeeded: */ return wfile; /* Return open descriptor */ /* * Return error after failed open: */errxit: e = errno; /* Save errno */ free(wfile->Pathname); /* Dispose of copied pathname */ free(wfile); /* Dispose of WAVFILE struct */ errno = e; /* Restore error number */ return NULL; /* Return error indication */}/* * Apply command line option overrides to the interpretation of the input * wav file: * */voidWavReadOverrides(WAVFILE *wfile,WavPlayOpts *wavopts) { UInt32 num_samples; /* * Override sampling rate: -s sampling_rate */ if ( wavopts->SamplingRate.optChar != 0 ) { wfile->wavinfo.SamplingRate = wavopts->SamplingRate.optValue; wfile->wavinfo.bOvrSampling = 1; } /* * Override mono/stereo mode: -S / -M */ if ( wavopts->Channels.optChar != 0 ) { wfile->wavinfo.Channels = wavopts->Channels.optValue; wfile->wavinfo.bOvrMode = 1; } /* * Override the sample size in bits: -b bits */ if ( wavopts->DataBits.optChar != 0 ) { wfile->wavinfo.DataBits = wavopts->DataBits.optValue; wfile->wavinfo.bOvrBits = 1; } /* * Set the first sample: */ wfile->StartSample = 0; num_samples = wfile->wavinfo.Samples = wfile->num_samples; if ( wavopts->StartSample != 0 ) { wfile->StartSample = wavopts->StartSample; wfile->wavinfo.Samples -= wfile->StartSample; } /* * Override # of samples if -t seconds option given: */ if ( wavopts->Seconds != 0 ) { wfile->wavinfo.Samples = wavopts->Seconds * wfile->wavinfo.SamplingRate; if (wfile->StartSample+wfile->wavinfo.Samples > num_samples) wfile->wavinfo.Samples = num_samples-1; }}/* * Close a WAVFILE */intWavClose(WAVFILE *wfile,ErrFunc erf) { int e = 0; /* Returned error code */ int channels; /* Channels recorded in this wav file */ u_long samplerate; /* Sampling rate */ int sample_bits; /* data bit size (8/12/16) */ u_long samples; /* The number of samples in this file */ u_long datastart; /* The offset to the wav data */ long fpos; /* File position in bytes */ v_erf = erf; /* Set error reporting function */ if ( wfile == NULL ) { err("%s: WAVFILE pointer is NULL!",sys_errlist[EINVAL]); errno = EINVAL; return -1; } /* * If the wav file was open for write, update the actual number * of samples written to the file: */ if ( wfile->rw == 'W' ) { fpos = lseek(wfile->fd,0L,SEEK_CUR); /* Get out file position */ if ( (e = WaveReadHeader(wfile->fd,&channels,&samplerate,&sample_bits,&samples,&datastart,_v_erf)) != 0 ) err("%s:\nReading WAV header from %s",emsg,wfile->Pathname); else if ( lseek(wfile->fd,(long)(datastart-4),SEEK_SET) != (long)(datastart-4) ) err("%s:\nSeeking in WAV header file %s",sys_errlist[errno],wfile->Pathname); else if ( write(wfile->fd,&wfile->wavinfo.Samples,sizeof wfile->wavinfo.Samples) != sizeof wfile->wavinfo.Samples ) err("%s:\nWriting in WAV header file %s",sys_errlist[errno],wfile->Pathname); else { /* * 'data' chunk was updated OK: Now we have to update the RIFF block * count. Someday very soon, a real RIFF module is going to replace * this fudging. */ if ( ftruncate(wfile->fd,(size_t)fpos) ) err("%s:\nTruncating file %s to correct size", sys_errlist[errno], wfile->Pathname); else if ( lseek(wfile->fd,4L,SEEK_SET) < 0L ) err("%s:\nSeek 4 for RIFF block update of %s", sys_errlist[errno], wfile->Pathname); else { fpos -= 8; /* Byte count for RIFF block */ if ( write(wfile->fd,&fpos,sizeof fpos) != sizeof fpos ) err("%s:\nUpdate of RIFF block count in %s failed", sys_errlist[errno], wfile->Pathname); } } } if ( close(wfile->fd) < 0 ) { err("%s:\nClosing WAV file",sys_errlist[errno]); e = errno; /* Save errno value to return */ } wavfile_free(wfile); /* Release WAVFILE structure */ if ( (errno = e) != 0 ) return -1; /* Failed exit */ return 0; /* Successful exit */}/* * Open a WAV file for writing: */WAVFILE *WavOpenForWrite(const char *Pathname,Chan chmode,UInt32 sample_rate,UInt16 bits,UInt32 samples,ErrFunc erf) { WAVFILE *wfile = wavfile_alloc(Pathname); int e; /* Saved errno value */ v_erf = erf; /* Set error reporting function */ if ( wfile == NULL ) return NULL; /* ENOMEM (class_b msg) */ wfile->rw = 'W'; /* Mark as for writing */ wfile->wavinfo.SamplingRate = sample_rate; wfile->wavinfo.Channels = chmode; /* Mono / Stereo */ wfile->wavinfo.Samples = samples; wfile->wavinfo.DataBits = bits; /* * Open/create the file for writing: */ if ( (wfile->fd = open(wfile->Pathname,O_RDWR|O_TRUNC|O_CREAT,0666)) < 0 ) { err("%s:\nOpening %s for WAV writing", sys_errlist[errno], wfile->Pathname); return NULL; /* Open error */ } /* * Write out a WAV file header: */ e = WaveWriteHeader(wfile->fd, wfile->wavinfo.Channels == Mono ? 1 : 2, wfile->wavinfo.SamplingRate, wfile->wavinfo.DataBits, wfile->wavinfo.Samples, _v_erf); /* Capture error messages to emsg[] */ if ( e != 0 ) { wavfile_free(wfile); err("%s:\nWriting WAV header to %s", emsg, wfile->Pathname); return NULL; } /* * Return successfuly opened file:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -