/*-------------- Telecommunications & Signal Processing Lab --------------- McGill University Routine: void CPcombSamp (AFILE *AFp[], long int Nchan[], int Nfiles, long int Lim[2], float Chgain[][]) Purpose: Combine audio file samples (linear combinations of values) Description: This copies input audio file(s) to an output audio file. The samples in the output file are linear combinations of the input channels. 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 -> float [][] Chgain Array of channel gains Author / revision: P. Kabal Copyright (C) 1996 $Revision: 1.13 $ $Date: 1996/06/01 02:43:32 $ -------------------------------------------------------------------------*/ static char rcsid[] = "$Id: CPcombSamp.c 1.13 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 /* At least MAXCHANI + MAXCHANO */ void CPcombSamp (AFp, Nchan, Nfiles, Lim, Chgain) AFILE *AFp[]; long int Nchan[]; int Nfiles; long int Lim[2]; float Chgain[MAXCHANO][MAXCHANI]; { int Nifiles; int NchanMax, NchanO; long int offr; int Nframe; int i, j, k, l, n, p; AFILE *AFpO; float Fbuf[BFSIZE]; float *Fbufi, *Fbufo; float gain; long int Nt, Nj; int nt, NI; int Ns, Nc; /* Initialization */ Nifiles = Nfiles - 1; NchanO = (int) Nchan[Nfiles-1]; AFpO = AFp[Nfiles-1]; /* Determine the maximum number of channels that will be read from a file; the end channels may not be needed */ Nt = 0; for (j = 0; j < Nifiles; ++j) Nt += Nchan[j]; NI = (int) MINV (Nt, MAXCHANI); /* Max number of channels to be read */ nt = 0; NchanMax = 0; for (j = 0; j < Nifiles; ++j) { Nc = (int) MINV (NI - nt, Nchan[j]); nt = nt + Nc; NchanMax = MAXV (NchanMax, Nc); } /* The copying operation takes scaled samples from the input si(n,i) (channel n, sample i) and sums them to form so(k,i) (channel k, sample i) so(k,i) = SUM g(k,n) * si(n,i) n However, samples from different channels are interleaved. Thus so(k,i) is really so(i * No + k), where No is the number of output channels. For the input data, the channels appear in different files. The copying operation loops over the input channels n, the output channels k and the samples i. The inner loop is chosen to be over the samples, so that this loop can be skipped if the gain for an input/output channel combination is zero. The looping over input channels is actually two loops; one over files and the other for channels within a file. The loop over files is outermost, so that the data from the input files need only be read once. */ /* Split the buffer space up for the input and output buffers */ Ns = BFSIZE / (NchanMax + NchanO); Fbufi = Fbuf; Fbufo = Fbuf + NchanMax * Ns; /* Main loop */ offr = Lim[0]; while (offr <= Lim[1]) { Nframe = (int) MINV (Lim[1] - offr + 1, Ns); VRfZero (Fbufo, Nframe * NchanO); n = 0; nt = 0; for (j = 0; j < Nifiles; ++j) { Nj = Nchan[j]; Nc = (int) MINV (NI - nt, Nj); /* Read Nc channels (out of Nj) channels from file j */ if (Nc == Nj) AFreadData (AFp[j], offr * Nc, Fbufi, Nframe * Nc); else if (Nc > 0 ) { for (p = 0; p < Nframe; ++p) AFreadData (AFp[j], (offr+p) * Nj, &Fbufi[p*Nc], Nc); } nt = nt + Nc; /* Add the contribution from file j to the output */ for (l = 0; l < Nc; ++l, ++n) { for (k = 0; k < NchanO; ++k) { gain = Chgain[k][n]; if (gain != 0.0) { for (i = 0; i < Nframe; ++i) Fbufo[i*NchanO+k] += gain * Fbufi[i*Nc+l]; } } } } /* Write the samples to the output file */ AFwriteData (AFpO, Fbufo, Nframe * NchanO); offr = offr + Nframe; } return; }