📄 sound.c
字号:
/*..........................................................................*//* *//* L a s t W a v e P a c k a g e 'sound' 2.1 *//* *//* For the 'sndfile' library *//* Copyright (C) 1999 Erik de Castro Lopo <erikd@zip.com.au> *//* *//* For everything else *//* Copyright (C) 1999-2002 Emmanuel Bacry. *//* Copyright (C) 2002 Remi Gribonval. *//* email : lastwave@cmap.polytechnique.fr *//* *//*..........................................................................*//* *//* This program is a 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; either version 2 of the *//* License, or (at your option) any later version *//* *//* 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. *//* *//* You should have received a copy of the GNU General Public License *//* along with this program (in a file named COPYRIGHT); *//* if not, write to the Free Software Foundation, Inc., *//* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* *//*..........................................................................*/#include "lastwave.h"#include "xx_audio.h"#include "sndfile.h"#include "signals.h"#include "soundlw.h"/* * * The sound formats are referred to by names such as 'aiff8' for coding AIFF using 8 bits. * This name is used as the default extension (if none is specified) for the sound filename. * Thus for instance a filename named 'sound.aiff8' will refer to a soundfile coded using AIFF 8 bits format. * There is a predefined list of 'BasicSoundFormat' corresponding to formats LastWave knows about. * The user does not access directly this structure but rather the 'soundFormat' structure. * Every 'BasicSoundFormat' can be seen as a 'SoundFormat'. However, * in order to be able to associate a given extension (such a '.wav') to a given basic format (such as 'waw16') * the user can define a new 'SoundFormat' that points to a 'BasicSoundFormat' and give it the name he wants. * In the case of 'raw' data (for which there is no header), one must specify (when reading a file) the sampling * rate and the number of channels. This is done by using the corresponding 'raw' basic format name (such as raw16_le) * and add after it the string '_<samplingRate>_<nChannels>'. If not specified, the sampling rate is 1 * and the number of channels is 1. Thus 'raw16_le_44100_1' is a valid sound format. * The 'BasicSoundFormat' structure is used to store everything but the sampling rate and the number of channels. * These two parameters will be coded (for raw format only) in the 'SoundFormat' structure. * *//* * The different basic sound formats available */static BasicSoundFormat theBasicSoundFormats[] ={ "lw",SF_FORMAT_LW,0,"LastWave read/write file format : This is the format managed by the 'write' and 'read' LastWave commands (without the '-r' option). It uses float values. When writing, it uses '-b' option (i.e., binary coded values).", "aiff8",SF_FORMAT_AIFF+SF_FORMAT_PCM,8,"AIFF format on 8 bits", "aiff16",SF_FORMAT_AIFF+SF_FORMAT_PCM,16,"AIFF format on 16 bits (little endian)", "aiff24",SF_FORMAT_AIFF+SF_FORMAT_PCM,24,"AIFF format on 24 bits (little endian)", "aiff32",SF_FORMAT_AIFF+SF_FORMAT_PCM,32,"AIFF format on 32 bits (little endian)", "au8",SF_FORMAT_AU+SF_FORMAT_PCM,8,"AU format on 8 bits", "au16",SF_FORMAT_AU+SF_FORMAT_PCM,16,"AU format on 16 bits (big endian)", "au24",SF_FORMAT_AU+SF_FORMAT_PCM,24,"AU format on 24 bits (big endian)", "au32",SF_FORMAT_AU+SF_FORMAT_PCM,32,"AU format on 32 bits (big endian)", "au16_ulaw",SF_FORMAT_AU+SF_FORMAT_ULAW,16,"AU format on 8 bits (obtained by ulaw coding 16 bits)", "au16_alaw",SF_FORMAT_AU+SF_FORMAT_ALAW,16,"AU format on 8 bits (obtained by alaw coding 16 bits)", "raw8_s",SF_FORMAT_RAW+SF_FORMAT_PCM_S8,8,"RAW format on 8 bits (as char)", "raw8_u",SF_FORMAT_RAW+SF_FORMAT_PCM_U8,8,"RAW format on 8 bits (as unsigned char)", "raw16_le",SF_FORMAT_RAW+SF_FORMAT_PCM_LE,16,"RAW format on 16 bits (little endian)", "raw24_le",SF_FORMAT_RAW+SF_FORMAT_PCM_LE,24,"RAW format on 24 bits (little endian)", "raw32_le",SF_FORMAT_RAW+SF_FORMAT_PCM_LE,32,"RAW format on 32 bits (little endian)", "raw16_be",SF_FORMAT_RAW+SF_FORMAT_PCM_BE,16,"RAW format on 16 bits (big endian)", "raw24_be",SF_FORMAT_RAW+SF_FORMAT_PCM_BE,24,"RAW format on 24 bits (big endian)", "raw32_be",SF_FORMAT_RAW+SF_FORMAT_PCM_BE,32,"RAW format on 32 bits (big endian)", "wave8",SF_FORMAT_WAV+SF_FORMAT_PCM,8,"WAVE format on 8 bits", "wave16",SF_FORMAT_WAV+SF_FORMAT_PCM,16,"WAVE format on 16 bits (big endian)", "wave24",SF_FORMAT_WAV+SF_FORMAT_PCM,24,"WAVE format on 24 bits (big endian)", "wave32",SF_FORMAT_WAV+SF_FORMAT_PCM,32,"WAVE format on 32 bits (big endian)", "wave16_ulaw",SF_FORMAT_WAV+SF_FORMAT_ULAW,16,"WAVE format on 8 bits (obtained by ulaw coding 16 bits)", "wave16_alaw",SF_FORMAT_WAV+SF_FORMAT_ALAW,16,"WAVE format on 8 bits (obtained by alaw coding 16 bits)", /* "wave_float",SF_FORMAT_WAV+SF_FORMAT_FLOAT,32,"", "wave_ms_adpcm",SF_FORMAT_WAV+SF_FORMAT_MS_ADPCM,8,"", "wave_ima_adpcm",SF_FORMAT_WAV+SF_FORMAT_IMA_ADPCM,8,"", */ "paf16_le",SF_FORMAT_PAF+SF_FORMAT_PCM_LE,16,"ENSONIQ PARIS format on 16 bits (little endian)", "paf24_le",SF_FORMAT_PAF+SF_FORMAT_PCM_LE,24,"ENSONIQ PARIS format on 24 bits (little endian)", "paf16_be",SF_FORMAT_PAF+SF_FORMAT_PCM_BE,16,"ENSONIQ PARIS format on 16 bits (big endian)", "paf24_be",SF_FORMAT_PAF+SF_FORMAT_PCM_BE,24,"ENSONIQ PARIS format on 24 bits (big endian)", /* "svx8",SF_FORMAT_SVX+SF_FORMAT_PCM,8,"SVX (amiga) format on 8 bits", "svx16",SF_FORMAT_SVX+SF_FORMAT_PCM,16,"SVX (amiga) format on 16 bits", does not work */ NULL,0,0,NULL};#define NMAXSF 100 /* The maximum number of sound formats */static SoundFormat theSoundFormats[NMAXSF]; /* The array which holds all the sound format */static nSoundFormats = 0; /* the number of sound formats in the array 'theSoundFormats' *//* * This routine allows to get the sound format associated to a name */char Name2SoundFormat(char *str, SoundFormat *sf){ int i,l; char *str1,*str2; char c; int samplingRate,nChannels; sf->name = NULL; sf->samplingRate = 0; sf->nChannels = 0; sf->basicSoundFormat = NULL; /* We look in the basic sound formats array first */ for (i=0;theBasicSoundFormats[i].name !=NULL;i++) { if (!strcmp(str,theBasicSoundFormats[i].name)) { sf->basicSoundFormat = theBasicSoundFormats+i; return(YES); } } /* Then in the sound formats array */ for (i=0;i<nSoundFormats;i++) { if (!strcmp(str,theSoundFormats[i].name)) { *sf = theSoundFormats[i]; return(YES); } } /* * Then we check the raw format with a possible sampling rate and number of channels specified */ if (strncmp(str,"raw",3)) return(NO); /* We first look for te corresponding basic format */ for (i=0;theBasicSoundFormats[i].name !=NULL;i++) { if (strncmp(theBasicSoundFormats[i].name,"raw",3)) continue; l = strlen(theBasicSoundFormats[i].name); if (strncmp(theBasicSoundFormats[i].name,str,l)) continue; /* Now that we found it, we look for the sampling rate */ str1 = str+l; if (*str1 != '_') continue; str1++; str2 = str1; while(isdigit(*str2)) str2++; c = *str2; *str2 = '\0'; if (ParseInt_(str1,1,&samplingRate)==NO || samplingRate <= 0) { *str2 = c; continue; } *str2 = c; if (*str2 == '\0') { sf->basicSoundFormat = theBasicSoundFormats+i; sf->samplingRate = samplingRate; return(YES); } if (*str2 != '_') continue; /* Then an eventual number of channels */ str2++; str1 = str2; while(isdigit(*str2)) str2++; c = *str2; *str2 = '\0'; if (ParseInt_(str1,1,&nChannels)==NO || nChannels <= 0) { *str2 = c; continue; } *str2 = c; if (*str2 == '\0') { sf->basicSoundFormat = theBasicSoundFormats+i; sf->samplingRate = samplingRate; sf->nChannels = nChannels; return(YES); } continue; } return(NO);}/* * Get the Basic sound format associated to a format code of the sndfile library */BasicSoundFormat *Code2BasicSoundFormat(int formatCode, int bitWidth){ int i; for (i=0;theBasicSoundFormats[i].name !=NULL;i++) { if (theBasicSoundFormats[i].format == formatCode && theBasicSoundFormats[i].bitWidth == bitWidth) return(theBasicSoundFormats+i); } return(NULL);}/* * Get the sound format of a file and the size of the sound in it. * In the case of a raw file it uses the extension to understand the format. * returns YES if succeeded. */char SoundInfo(char *file, SoundFormat *sf, int *size){ char *f,*str; SF_INFO info; SNDFILE *sndfile; BasicSoundFormat *bsf; FILE * stream; struct signal siginfo; char header,binaryMode,binaryCoding; int nCols,nsize; /* Does the file exist ? */ stream = FOpen(file,"r"); if (stream == NULL) { SetErrorf("SoundInfo() : File '%s' does not exist",file); return(NO); } FClose(stream); /* Is it a LastWave file ? */ if (ReadInfoSigFile(file, &siginfo, &header,&binaryMode, &binaryCoding, &nCols,&nsize)==YES) { if (header == YES) { if (siginfo.type == XYSIG) return(NO); sf->basicSoundFormat = Code2BasicSoundFormat(SF_FORMAT_LW,0); sf->samplingRate = (int) (1/siginfo.dx+.5); sf->nChannels = 1; *size = siginfo.size; return(YES); } } f = ConvertFilename(file); if ((sndfile = sf_open_read(f,&info)) == NULL) { /* We try to use the extension */ str = file+strlen(file); while (str != file && *str != '.') str--; if (*str != '.') { SetErrorf("SoundInfo() : Cannot understand which format the sound file '%s' is in",file); return(NO); } str++; if (Name2SoundFormat(str,sf) == NO) { SetErrorf("SoundInfo() : Cannot understand which format the sound file '%s' is in",file); return(NO); } if (sf->samplingRate == 0) { SetErrorf("SoundInfo() : Cannot understand what the sampling rate of the sound file '%s' is",file); return(NO); } if (sf->nChannels == 0) sf->nChannels = 1; info.samplerate = sf->samplingRate; info.format = sf->basicSoundFormat->format; info.pcmbitwidth = sf->basicSoundFormat->bitWidth; info.channels = sf->nChannels; if ((sndfile = sf_open_read(f,&info)) == NULL) { SetErrorf("SoundInfo() : Cannot understand which format the sound file '%s' is in (even when using the extension)",file); return(NO); } } sf_close(sndfile); sf->samplingRate = info.samplerate; *size = info.samples; sf->nChannels = info.channels; bsf = Code2BasicSoundFormat(info.format,info.pcmbitwidth); if (bsf == NULL) Errorf("SoundInfo() : Sorry, sound format unknown by LastWave"); sf->basicSoundFormat = bsf; sf->name = NULL; return(YES);}/* * Reading a sound file * * file : the name of the sound file. * sig,sig1 : the signals to read (sig1 could be NULL). * Only a reading of the first 2 channels is supported. * flagSample : if YES then both 'start' and 'duration' are expressed * in samples, otherwise they are expressed in seconds. * start : first sample to read. * duration : number of samples to read. * flagNormalize : if YES then the maximum format value will be * renormalized to [-1,1] otherwise the orginal values * (e.g., 16 bits integers) are used. * flagRaw : if YES then the file is a raw file and the following * parameters indicate hown to read it : * flagLittleEndian : if YES then raw little endian * (used only if bitWidth >= 16). * flagUnsigned : if YES then raw unsigned char * (only used if bitwidth is 8). * bitWidth : number of bits per sample. * sRate : the sampling rate. * nc : the number of channels. */void SoundRead(char *file,SIGNAL sig, SIGNAL sig1, char flagSample, LWFLOAT start, LWFLOAT duration, char flagNormalize,SoundFormat *sf1){ char *f; SF_INFO info; int samplingRate; int size,first,sizeAsked; int nChannels; SNDFILE *sndfile; double *sound; int i ,j; SoundFormat sf; FILE * stream; LWFLOAT xMin,yMin,xMax,yMax; int iMin,iMax; if (sig == NULL && sig1 == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -