📄 sound.c
字号:
Errorf("SoundRead : You should specify at least 1 signal"); if (start <= 0 && flagSample) start = 1; if (start <= 0 && !flagSample) start = 0; /* Does the file exist ? */ stream = FOpen(file,"r"); if (stream == NULL) Errorf("SoundRead : File '%s' does not exist",file); FClose(stream); f = ConvertFilename(file); /* This is the case the raw format has been forced and all the parameters specified */ if (sf1 != NULL) { if (sf1->nChannels == 0) { if (sig1 == NULL) sf1->nChannels = 1; else sf1->nChannels = 2; } if (sf1->nChannels <= 0) Errorf("SoundRead() : The number of channels should be strictly positive"); if (sf1->samplingRate == 0) sf1->samplingRate = 1; if (sf1->samplingRate <= 0) Errorf("SoundRead() : The samplingRate should be strictly positive"); sf.samplingRate = info.samplerate = sf1->samplingRate; sf.nChannels = info.channels = sf1->nChannels; info.pcmbitwidth = sf1->basicSoundFormat->bitWidth; info.format = sf1->basicSoundFormat->format; sf.basicSoundFormat = sf1->basicSoundFormat; if ((sndfile = sf_open_read(f,&info)) == NULL) Errorf("SoundRead() : Cannot read the file using the raw format you specified",file); sf_close(sndfile); size = info.samples; } /* Otherwise we first read the information to know if the file is readable (using the extension if necessary) */ else { if (SoundInfo(file, &sf, &size) == NO) Errorf1(""); info.samplerate = sf.samplingRate; info.format = sf.basicSoundFormat->format; info.pcmbitwidth = sf.basicSoundFormat->bitWidth; info.channels = sf.nChannels; } /* Convert the start and duration variables into number of samples */ if (flagSample == NO) { first = (int) (start*sf.samplingRate+1+.5); sizeAsked = (int) (duration*sf.samplingRate+.5); } else { first = (int) (start+.5); sizeAsked = (int) (duration+.5); } /* Compute the number of samples to read */ if (sizeAsked <= 0) sizeAsked = size; sizeAsked = MIN((sizeAsked+first-1),(size)); sizeAsked = sizeAsked-first+1; /* Some checkings */ if (sf.nChannels == 1 && sig1 != NULL) { Errorf("SoundRead() : Sorry, the sound file '%s' has just one channel",file); } if (first > size) { if (flagSample) Errorf("SoundRead() : Sorry, the sound file '%s' is too short for <start>=%d samples",file,first); else Errorf("SoundRead() : Sorry, the sound file '%s' is too short for <start>=%g seconds",file,start); } /* Set some variables */ samplingRate = sf.samplingRate; nChannels = sf.nChannels; /* Special case of the LastWave format */ if ((sf.basicSoundFormat->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_LW) { ReadSigFile(sig,file,first-1,sizeAsked,0,0); sig->x0 = 0; sig->dx = 1./samplingRate; if (flagNormalize) { xMin = 1; xMax = -1; MinMaxSig(sig,&xMin,&xMax,&yMin,&yMax,&iMin,&iMax,NO); yMax = MAX(fabs(yMax),fabs(yMin)); for (i=0;i<sig->size;i++) sig->Y[i] /= yMax; } return; } /* Look for the first sample */ if ((sndfile = sf_open_read(f,&info)) == NULL) Errorf("SoundRead() : Weird error"); if (sf_seek(sndfile,(first-1)*nChannels,SEEK_SET)==-1) { sf_close(sndfile); Errorf("SoundRead() : Weird error : Problem for seeking sample number '%d' of sound file %f",first,file); return; } /* Allocate a double array and read the sound in it */ sound = DoubleAlloc(sizeAsked*nChannels); sizeAsked = sf_read_double(sndfile,sound,sizeAsked*nChannels,flagNormalize)/nChannels; /* Close the file */ sf_close(sndfile); /* Error while reading ? */ if (sizeAsked == -1) { Free(sound); Errorf("SoundRead() : problem while reading sound file '%f'",file); } /* Fill up the signal(s) */ if (sig != NULL) { SizeSignal(sig,sizeAsked,YSIG); sig->x0 = 0; sig->dx = 1./samplingRate; } if (sig1 != NULL && nChannels == 2) { SizeSignal(sig1,sizeAsked,YSIG); sig1->x0 = 0; sig1->dx = 1./samplingRate; } /* Fill up the signal(s) Case of a mono sound file read in a signal */ if (nChannels == 1) { for (i=0;i<sizeAsked;i++) sig->Y[i] = sound[i]; } /* Case of a multichannel sound file read in a single signal : only the first channel is read */ else if (sig != NULL && sig1 == NULL) { for (i=0,j=0;i<sizeAsked;i++,j+=nChannels) sig->Y[i] = sound[j]; } /* or only the second channel is read ??????? */ else if (sig == NULL && sig1 != NULL) { for (i=0,j=0;i<sizeAsked;i++,j+=nChannels) sig1->Y[i] = sound[j+1]; } /* Case of a multichannel sound file read in two signals */ else { for (i=0,j=0;i<sizeAsked;i++,j+=nChannels) { sig->Y[i] = sound[j]; sig1->Y[i] = sound[j+1]; } } /* Free the double array */ Free(sound);} /* * Routine for writing a sound in a file * * file : the soundfile it will create * sig,sig1 : the signals to read (sig1 could be NULL). Only a sound file with 1 or 2 channels is supported. * flagNormalize : if YES then the signals will be normalized to the maximum amplitude before being written * if NO then 'maxNorm' is used as the maximum amplitude value. * maxNorm : specifies the maximum amplitude value in the case flagNormalize==NO. * If it is negative then the format maximum amplitude is used (e.g., [-32768,32767] for 16 bits integers). * sf : the sound format to be used (if it is NULL then the extension of the <file> should be used to determine it) */void SoundWrite(char *file,SIGNAL sig, SIGNAL sig1, char flagNormalize, LWFLOAT maxNorm, SoundFormat *sf){ char *f; SF_INFO info; int samplingRate; int size; int nChannels; SNDFILE *sndfile; double *sound,maxp,maxm,max; int i ,j; unsigned long l; SoundFormat *sf1; SoundFormat soundFormat; char *str; if (sig == NULL) Errorf("SoundWrite() : The first signal should be specified"); if (sig1 != NULL && sig->size != sig1->size) Errorf("SoundWrite() : The two signals should have the same size"); /* Set the sampling rate and the number of channels */ samplingRate = (int) (1/sig->dx+.5); if (sig1 == NULL) nChannels = 1; else nChannels = 2; /* Case we have to use the extension to understand the format */ sf1 = sf; if (sf1 == NULL) { sf1 = &soundFormat; str = strlen(file)+file; while (str != file && *str != '.') str--; if (*str != '.') Errorf("SoundWrite : Sorry, I cannot understand what the format you want me to use is"); if (Name2SoundFormat(str+1,sf1) == NO) Errorf("SoundWrite : Sorry, I cannot understand what the format you want me to use is"); /* Check the compatibility */ if (sf1->samplingRate != 0 && sf1->samplingRate != samplingRate) Errorf("SoundWrite : Sorry,incompatibility between the sampling rate the format requests (%d) and the sampling rate of the signal (%d)",sf1->samplingRate,samplingRate); if (sf1->nChannels != 0 && sf1->nChannels != nChannels) Errorf("SoundWrite : Sorry,incompatibility between the number of channels the format requests (%d) and the number of signals (%d)",sf1->nChannels,nChannels); } /* Special case of LastWave format (binary) */ if ((sf1->basicSoundFormat->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_LW) { if (nChannels == 2) Errorf("SoundWrite() : Sorry, only a single channel can be used in the LastWave format"); WriteSigFile(sig,file,YES,"y",YES,"",""); return; } /* Open the file */ f = ConvertFilename(file); info.samplerate = samplingRate; info.pcmbitwidth = sf1->basicSoundFormat->bitWidth; info.format = sf1->basicSoundFormat->format; info.channels = nChannels; if ((sndfile = sf_open_write(f,&info)) == NULL) Errorf("SoundWrite() : Cannot open sound file '%s'",file); /* Write in the case of a single signal */ if (sig1 == NULL) { sound = DoubleAlloc(sig->size); max = -1; for (i = 0;i<sig->size;i++) { sound[i] = sig->Y[i]; if (fabs(sound[i])>max) max = fabs(sound[i]); } if (flagNormalize || maxNorm > 0) { l = 1; if (flagNormalize) { maxm = max/(l<<(sf1->basicSoundFormat->bitWidth-1)); maxp = max/((l<<(sf1->basicSoundFormat->bitWidth-1))-1); } else { maxm = maxNorm/(l<<(sf1->basicSoundFormat->bitWidth-1)); maxp = maxNorm/((l<<(sf1->basicSoundFormat->bitWidth-1))-1); } for (i = 0;i<sig->size;i++) { if (sound[i]>=0) sound[i] /= maxp; else sound[i] /= maxm; } } size = sf_write_double(sndfile,sound,sig->size,0); Free(sound); sf_close(sndfile); if (size == -1) Errorf("SoundWrite() : Problem while writing sound file '%s'",file); return; } /* Write in the case of 2 signals */ sound = DoubleAlloc(sig->size*2); max = -1; for (i = 0,j=0;i<sig->size;i++,j+=2) { sound[j] = sig->Y[i]; sound[j+1] = sig1->Y[i]; if (fabs(sound[j])>max) max = fabs(sound[j]); if (fabs(sound[j+1])>max) max = fabs(sound[j+1]); } if (flagNormalize || maxNorm > 0) { l = 1; if (flagNormalize) { maxm = max/(l<<(sf1->basicSoundFormat->bitWidth-1)); maxp = max/((l<<(sf1->basicSoundFormat->bitWidth-1))-1); } else { maxm = maxNorm/(l<<(sf1->basicSoundFormat->bitWidth-1)); maxp = maxNorm/((l<<(sf1->basicSoundFormat->bitWidth-1))-1); } for (i = 0;i<2*sig->size;i++) { if (sound[i]>=0) sound[i] /= maxp; else sound[i] /= maxm; } } size = sf_write_double(sndfile,sound,sig->size*2,0); Free(sound); sf_close(sndfile); if (size == -1) Errorf("SoundWrite : Problem while writing sound file '%s'",file);} /* REMI : ANSI interface to the SoundWrite function */void SoundWriteSamples(char *file,short *samplesLeft, short *samplesRight,unsigned long nbSamples, LWFLOAT sampleFreq,SoundFormat *sf){ static SIGNAL sigLeft = NULL; static SIGNAL sigRight = NULL; unsigned long i; /* Allocates the signals, only once */ if(sigLeft == NULL) { sigLeft = NewSignal(); sigRight = NewSignal(); } /* Sets the size and copies the samplesLeft */ SizeSignal(sigLeft,nbSamples,YSIG); for(i = 0; i < nbSamples; i++) { sigLeft->Y[i] = samplesLeft[i]; } if(sampleFreq < 2000) { Warningf("SoundWriteSamples: Sampling rate %f Hz is below 2000 Hz, I changed it to 2000 Hz\n",sampleFreq); sigLeft->dx = 1/2000; } else { sigLeft->dx = 1/sampleFreq; } /* To play on one channel */ if(samplesRight == NULL) { SoundWrite(file,sigLeft,NULL,YES,0.0,sf); } else { SizeSignal(sigRight,nbSamples,YSIG); for(i = 0; i < nbSamples; i++) { sigRight->Y[i] = samplesRight[i]; } sigRight->dx = sigLeft->dx; SoundWrite(file,sigLeft,sigRight,YES,0.0,sf); }}/* * Play a sound which is represented by a 'signal'. * If 'sampleFreq' <= 0 then the dx of the signal is used * to compute the sample frequency otherwise 'sampleFreq' is used. * If 'flagMaxVolume' is YES then the signal is normalized to 1 before played * otherwise it is kept as it is (the values are supposed to be between -1 and 1). */void SoundPlay(SIGNAL sigLeft,SIGNAL sigRight,char flagMaxVolume, LWFLOAT sampleFreq){ LWFLOAT max; int i; short *samplesLeft,*samplesRight; LWFLOAT t; if(sigRight && (sigLeft->size!=sigRight->size)) Errorf("SoundPlay : the two channels have a different number of samples!"); /* Compute the max of the signal if normalization is needed */ if (flagMaxVolume) { max = 0; for(i=0;i<sigLeft->size;i++) { max = MAX(max,fabs(sigLeft->Y[i])); } /* REMI : normalization of stereo signal */ if (sigRight) { for(i=0;i<sigLeft->size;i++) { max = MAX(max,fabs(sigRight->Y[i])); } } } else max = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -