📄 wavfile.c
字号:
#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <unistd.h>#include <fcntl.h>#include <malloc.h>#include <string.h>#include <memory.h>#include <sys/types.h>#include <sys/ioctl.h>#include <assert.h>#include <linux/soundcard.h>#include "WAVfile.h"#include "WAVint.h"#include "def.h"/* * Internal routine to allocate WAVFILE structure: */static WAVFILE *wavfile_alloc(const char *Pathname) { WAVFILE *wfile = (WAVFILE *) malloc(sizeof (WAVFILE)); if ( wfile == NULL ) { printf("Allocating WAVFILE structure"); return NULL; } memset(wfile,0,sizeof *wfile); if ( (wfile->Pathname = strdup(Pathname)) == NULL ) { free(wfile); printf(" Allocating storage for WAVFILE.Pathname"); return NULL; } wfile->fd = -1; /* Initialize fd as not open */ wfile->Channels = Stereo; wfile->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) { WAVFILE *wfile = wavfile_alloc(Pathname); 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 */ int e; if ( wfile == NULL ) return NULL; /* Insufficient memory (class B msg) */ else printf("wfile not null"); /* * Open the file for reading: */ if ( (wfile->fd = open(wfile->Pathname,O_RDONLY)) < 0 ) { printf("nOpening WAV file "); goto errxit; } else printf("open WAV FILE OK! %s %d",wfile->Pathname,wfile->fd); if ( lseek(wfile->fd,0L,SEEK_SET) != 0L ) { printf("nRewinding WAV file"); goto errxit; /* Wav file must be seekable device */ } if ( (e = WaveReadHeader(wfile->fd,&channels,&samplerate,&sample_bits,&samples,&datastart)) != 0 ) { printf("nReading WAV header"); goto errxit; } /* * Copy WAV data over to WAVFILE struct: */ if ( channels == 2 ) wfile->Channels = Stereo; else wfile->Channels = Mono; wfile->SamplingRate = (UInt32) samplerate; wfile->Samples = (UInt32) samples; wfile->DataBits = (UInt16) sample_bits; wfile->DataStart = (UInt32) datastart; wfile->rw = 'R'; /* Read mode */ offset = wfile->DataStart - 4; /* * Seek to byte count and read dbytes: */ if ( lseek(wfile->fd,offset,SEEK_SET) != offset ) { printf("nSeeking to WAV data"); goto errxit; /* Seek failure */ } if ( read(wfile->fd,ubuf,4) != 4 ) { printf("nReading dbytes"); 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->DataBytes = dbytes; /* * Open succeeded: */ return wfile; /* Return open descriptor */ /* * Return error after failed open: */errxit: free(wfile->Pathname); /* Dispose of copied pathname */ free(wfile); /* Dispose of WAVFILE struct */ return NULL; /* Return error indication */}/* * Close a WAVFILE */intWavClose(WAVFILE *wfile) { 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 */ int e; if ( wfile == NULL ) { printf("WAVFILE pointer is NULL!"); 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)) != 0 ) printf("nReading WAV header"); else if ( lseek(wfile->fd,(long)(datastart-4),SEEK_SET) != (long)(datastart-4) ) printf("nSeeking in WAV header file"); else if ( write(wfile->fd,&wfile->Samples,sizeof wfile->Samples) != sizeof wfile->Samples ) printf("nWriting in WAV header file"); 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) ) printf("nTruncating file to correct size"); else if ( lseek(wfile->fd,4L,SEEK_SET) < 0L ) printf("nSeek 4 for RIFF block update"); else { fpos -= 8; /* Byte count for RIFF block */ if ( write(wfile->fd,&fpos,sizeof fpos) != sizeof fpos ) printf("nUpdate of RIFF block count failed"); } } } if ( close(wfile->fd) < 0 ) { printf("nClosing WAV file"); } wavfile_free(wfile); /* Release WAVFILE structure */ return 0; /* Successful exit */}/* * Open a WAV file for writing: */WAVFILE *WavOpenForWrite(const char *Pathname,Chan chmode,UInt32 sample_rate,UInt16 bits,UInt32 samples) { WAVFILE *wfile = wavfile_alloc(Pathname); int e; if ( wfile == NULL ) return NULL; /* ENOMEM (class_b msg) */ wfile->rw = 'W'; /* Mark as for writing */ wfile->SamplingRate = sample_rate; /* 8000Hz */ wfile->Channels = chmode; /* Mono / Stereo */ wfile->Samples = samples; /* 8000Hz*10s */ wfile->DataBits = bits; /* 16 */ /* * Open/create the file for writing: */ if ( (wfile->fd = open(wfile->Pathname,O_RDWR|O_TRUNC|O_CREAT,0666)) < 0 ) { printf("nOpening for WAV writing"); return NULL; /* Open error */ } /* * Write out a WAV file header: */ e = WaveWriteHeader(wfile->fd, wfile->Channels == Mono ? 1 : 2, wfile->SamplingRate, wfile->DataBits, wfile->Samples); /* Capture error messages to emsg[] */ if ( e != 0 ) { wavfile_free(wfile); printf("nWriting WAV header"); return NULL; } /* * Return successfuly opened file: */ return wfile;}/* $Source: /home/cvs/wavplay/file.c,v $ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -