/*-------------- Telecommunications & Signal Processing Lab --------------- McGill University Routine: void CPcopySamp (AFILE *AFp[], long int Nchan[], int Nfiles, long int Lim[2], double gain) Purpose: Copy and scale audio file samples Description: This copies input audio file(s) to an output audio file. The samples in the output file are scaled by a given gain. Parameters: -> AFILE *AFp[] Array of Nfiles audio file pointers -> long int Nchan[] Array of the number of channels for each file (Nfiles values) -> int Nfiles Number of files, Nfiles-1 input files and one output file -> long int Lim[2] Two element array of sample limits -> double gain Gain applied to the input samples Author / revision: P. Kabal Copyright (C) 1996 $Revision: 1.7 $ $Date: 1996/06/01 02:43:49 $ -------------------------------------------------------------------------*/ static char rcsid[] = "$Id: CPcopySamp.c 1.7 1996/06/01 AFsp-V2R1 $"; #include #include #include "CopyAudio.h" #define MINV(a, b) (((a) < (b)) ? (a) : (b)) #define MAXV(a, b) (((a) > (b)) ? (a) : (b)) #define BFSIZE 5120 void CPcopySamp (AFp, Nchan, Nfiles, Lim, gain) AFILE *AFp[]; long int Nchan[]; int Nfiles; long int Lim[2]; double gain; { int Nifiles; long int NchanMax, NchanO; int j; int Ns; AFILE *AFpO; float Fbuf[BFSIZE]; long int NchanI; /* Initialization */ Nifiles = Nfiles - 1; NchanO = Nchan[Nfiles-1]; AFpO = AFp[Nfiles-1]; /* Determine the total number of input channels and the maximum number of input channels to be read from any file */ NchanI = 0; NchanMax = 0; for (j = 0; j < Nifiles; ++j) { NchanMax = MAXV (NchanMax, Nchan[j]); NchanI += Nchan[j]; } if (NchanI != NchanO) UThalt ("CPcopySamp: No. of input channels not equal to no. output channels"); /* There are three cases: (1) single input file - the copying is a sample by sample copy without regard to channels (2) multiple input files - the input channels have to be interleaved in the output (a) The number of channels is such that more than one record from the file with the largest number of channels can fit into the buffer along with the output record. (b) The number of channels is large. The data from a single input file may have to be read in chunks. Each chunk is immediately sent to the output. */ if (Nifiles == 1) { long int offs, lasts; int Nsamp; /* Single input file, copy samples from the input file to the output file */ offs = Lim[0] * NchanI; lasts = Lim[1] * NchanI + (NchanI - 1); while (offs <= lasts) { Nsamp = (int) MINV (lasts - offs + 1, BFSIZE); AFreadData (AFp[0], offs, Fbuf, Nsamp); VRfScale (gain, Fbuf, Fbuf, Nsamp); AFwriteData (AFpO, Fbuf, Nsamp); offs = offs + Nsamp; } } /* Multiple input files */ else { /* Split the buffer space up for the input and output buffers */ Ns = (int) (BFSIZE / (NchanMax + NchanO)); if (Ns > 1) { long int offr; int nj, nO; int i, n; int Nframe; float *Fbufi, *Fbufo; /* The input and output buffers can coexist */ Fbufi = Fbuf; Fbufo = Fbuf + ((int) NchanMax) * Ns; nO = (int) NchanO; offr = Lim[0]; while (offr <= Lim[1]) { Nframe = (int) MINV (Lim[1] - offr + 1, Ns); n = 0; for (j = 0; j < Nifiles; ++j) { nj = (int) Nchan[j]; AFreadData (AFp[j], offr * nj, Fbufi, Nframe * nj); for (i = 0; i < Nframe; ++i) VRfScale (gain, &Fbufi[i*nj], &Fbufo[i*nO+n], nj); n = n + nj; } /* Write the samples to the output file */ AFwriteData (AFpO, Fbufo, Nframe * nO); offr = offr + Nframe; } } else { long int offr; int Nc; long int l; /* Large number of channels, handle at most one input file at a time */ for (offr = Lim[0]; offr <= Lim[1]; ++offr) { for (j = 0; j < Nifiles; ++j) { l = 0; while (l < Nchan[j]) { Nc = (int) MINV (Nchan[j] - l, BFSIZE); AFreadData (AFp[j], offr * Nchan[j] + l, Fbuf, Nc); VRfScale (gain, Fbuf, Fbuf, Nc); AFwriteData (AFpO, Fbuf, Nc); l = l + Nc; } } } } } return; }