A DIRECTIONAL ACOUSTIC SIGNAL PROCESSOR AND METHOD THEREFOR

Abstract: Two or more microphones (10, 12) are mounted in an environment that contains an equal or lesser number of distinct sound sources. Acoustic energy from each source, with its attendant echoes and reverberation, impinges on each microphone. Using direction-of-arrival information (20), a first module (30) attempts to extract the original source signals as if the acoustic environment were anechoic. Any residual crosstalk between the channels, which may be caused by echoes and reverberation, is removed by a second module (50). The first and second modules may be implemented using existing technology.

Description: A Directional Acoustic Signal Processor and Method Therefor This application is submitted with a microfiche appendix, containing copyrighted material Copyright 1994, Interval Research Corporation The Appendix consists of one ( 1 ) microfiche with forty- six (46) frames The copyright owner has no objection to the facsimile reproduction by anyone of the patent document or the patent disclosure, as it appears in the Patent and Trademark Office patent file or records, but otherwise reserves all copyright rights whatsoever in the appendices Technical Field This invention relates to the field of microphone-array signal processing, and more particularly to a two stage processor for extracting one substantially pure sound signal from a mixture of such signals even in the presence of echoes and reverberations Background of the invention It is well known that a human being can focus attention on a single source of sound even in an environment that contains many such sources This phenomenon is often called the "cocktail-party effect " Considerable effort has been devoted in the prior art to solve the cocktail-party effect, both in physical devices and in computational simulations of such devices One prior technique is to separate sound based on auditory scene analysis In this analysis, vigorous use is made of assumptions regarding the nature of the sources present It is assumed that a sound can be decomposed into small elements such as tones and bursts, which in turn can be grouped according to attributes such as harmonicity and continuity in time Auditory scene analysis can be performed using information from a single microphone or from several microphones For an early example of auditory scene analysis, see Weintraub ( 1984, 1985, 1986) Other prior art work related to sound separation by auditory scene analysis are due to Parsons ( 1976), von der Malsburg and Schneider ( 1986), Nay lor and Porter ( 1991 ). and Mellinger ( 1991 ) Techniques involving auditory scene analysis, although interesting from a scientific point of view as models of human auditory processing, are currently far too computationally demanding and specialized to be considered practical techniques for sound separation until fundamental progress is made Other techniques for separating sounds operate by exploiting the spatial separation of their sources Devices based on this principle vary in complexity The simplest such devices are microphones that have highly selective, but fixed patterns of sensitivity A directional microphone, for example, is designed to have maximum sensitivity to sounds emanating from a particular direction, and can therefore be used to enhance one audio source relative to others (see Olson, 1967) Similarly, a close-talking microphone mounted near a speaker's mouth rejects distant sources (see, for example, the knowles CF 2949 data sheet) Microphone-array processing techniques related to separating sources by exploiting spatial separation of their sources are also well known and have been of interest for several decades In one early class of microphone-array techniques nonlinear processing is employed In each output stream some source direction of arrival, a "look direction " is assumed The microphone signals are delay ed to remove differences in time of flight from the look direction Signals from any direction other than tht look direction are thus misaligned in time The signal in the output stream is formed, in essence, by "gating" sound fragments from the microphones At any given instant, the output is chosen to be equal to one of the microphone signals These techniques, exemplified by Kaiser and David ( I 960), b Mitchell et al (1971 ), and by Lyon (1983), perform best when the undesired sources consist predominantly of impulse trains, as is the case with human speech While these nonlinear techniques can be very computationally efficient and are of scientific interest as models of human cocktail-part) processing, they do not have practical or commercial significance because of their inherent inability to bring about full suppression of unwanted sources This inability originates from the incorrect assumption that at every instant in time, at least one microphone contains only the desired signal One widely known class of techniques in the prior art for linear microphone-array processing is often referred to as "classical beamforming" (Flanagan et al , 1985) As with the nonlinear techniques mentioned above, processing begins with the removal of time-of-flight differences among the microphone signals with respect to the look direction In place of the "gating" scheme, the delayed microphone signals are simply averaged together Thus, any signal from the look direction is represented in the output with its original power, whereas signals from other directions are relatively attenuated Classical beamforming was employed in a patented directional hearing aid invented by Widrow and Brearley ( 1988) The degree to which a classical beamformer is able to attenuate undesired sources relative to the desired source is limited by (1 ) the number of microphones in the array, and (2) the spatial extent of the array relative to the longest wavelength of interest present in the undesired sources ln particular, a classical beamformer cannot provide relative attenuation of frequency components whose wavelengths are larger than the array For example, an array one foot wide cannot greatly attenuate frequency components below approximately 1 kHz Also known from the prior art is a class of active-cancellation algorithms, which is related to sound separation However, it needs a "reference signal," i e , a signal derived from only of one of the sources For example, active noise-cancellation techniques (see data sheets for Bose® Aviation Headset, NCT proACTIVE® Series, and Sennheiser HDC451 Noiseguard® Mobile Headphone) reduce the contribution of noise to a mixture by filtering a known signal that contains only the noise, and subtracting it from the mixture Similarly, echo-cancellation techniques such as those employed in full- duplex modems (Kelly and Logan, 1970, Gπtton and Lin, 1984) improve the signal-to-noise ratio of an outgoing signal by removing noise due to echoes from the known incoming signal Techniques for active cancellation that do not require a reference signal are called "blind " The\ are now classified, based on the degree of realism of the underlying assumptions regarding the acoustic processes by which the unwanted signals reach the microphones To understand the practical significance of this classification, recall a feature common to the principles by which active-cancellation techniques operate the extent to which a given undesired source can be canceled by subtracting processed microphone signals depends ultimately on the exactness with which copies of the undesired source in the different microphones can be made to match one another This depends, in turn, on how accurately the signal processing models the acoustic processes by which the unwanted signals reach the microphones One class of blind active-cancellation techniques may be called "gain-based" it is presumed that the waveform produced by each source is received by the microphones simultaneously, but with varying relative gams (Directional microphones must be employed to produce the required differences in gain ) Thus a gain-based system attempts to cancel copies of an undesired source in different microphone signals by applying relative gains to the microphone signals and subtracting, but never applying time delays or otherwise filtering Numerous gain-based methods for blind active cancellation have been proposed, see Herault and Jutten ( 1986) Bhatti and Bibyk ( 1991 ) Cohen ( 1991 ), Tong et al ( 1991 ), and Molgedey and Schuster ( 1994) The assumption of simultaneity is violated when microphones are separated in space A class of blind active-cancellation techniques that can cope w ith non-simultaneous mixtures mav be called - based" it is assumed that the waveform produced by each source is received by the various microphones with relative time delays, but without any other filtering (See Morita. 1991 and Bar-Ness, 1993 ) Under anechoic conditions, this assumption holds true for a microphone array that consists of omnidirectional microphones However, this simple model of acoustic propagation from the sources to the microphones is violated when echoes and reverberation are present When the signals involved are narrowband, some gain-based techniques for blind active cancellation can be extended to employ complex gain coefficients (see Strube ( 1981 ), Cardoso ( 1989,1991 ), Lacoume and Ruiz (1992), Comon et al ( 1994)) and can therefore accommodate, to a limited degree, time delays due to microphone separation as well as echoes and reverberation These techniques can be adapted for use with audio signals, which are broadband, if the microphone signals are divided into narrowband components by means of a filter bank The frequency bands produced by the filter bank can be processed independently, and the results summed (for example, see Strube ( 1981 ) or the patent of Comon (1994)) However, they are computationally intensive relative to the present invention because of the duplication of structures across frequency bands, are slow to adapt in changing situations, are prone to statistical error and are extremely limited in their ability to accommodate echoes and reverberation The most realistic active-cancellation techniques currently known are "convolutive" the effect of acoustic propagation from each source to each microphone is modeled as a convolutive filter These techniques are more realistic than gain-based and delay-based techniques because they explicitly accommodate the effects of inter-microphone separation, echoes and reverberation They are also more general since, in principle, gains and delays are special cases of convolutive filtering Convolutive active-cancellation techniques have recently been described by Jutten et al ( 1992), by Van Compemolle and Van Gerven (1992), by Platt and Faggin (1992), and by D c and Bar-Ness ( 1994) While these techniques have been used to separate mixtures constructed by simulation using oversimplified models of room acoustics, to the best of our knowledge none of them has been applied successfully to signals mixed in a real acoustic environment The simulated mixtures used by Jutten et al , by Platt and Faggin, and by Dine and Bar-Ness differ from those that would arise in a real room in two respects First, the convolutive filters used in the simulations are much shorter than those appropriate for modeling room acoustics, they allowed for significant indirect propagation of sound over only one or two feet, compared with tens of feet typical of echoes and reverberation in an office Second, the mixtures used in the simulations were partially separated to begin with, i e , the crosstalk between the channels was weak ln practice, the microphone signals must be assumed to contain strong crosstalk unless the microphones are highly directional and the geometry of the sources is constrained To overcome some of the limitations of the convolutive active-cancellation techniques named above, the present invention employs a two-stage architecture Its two-stage architecture is substantially different from other two-stage architectures found in pπor art A two-stage signal processing architecture is employed in a Griffiths-Jim beamformer (Griffiths and Jim, 1982) The first stage of a Griffiths-Jim beamformer is delay-based two microphone signals are delayed to remove time-of-flight differences with respect to a given look direction, and in contrast with classical beamforming, these delayed microphone signals are subtracted to create a reference noise signal ln a separate channel, the delayed microphone signals are added, as in classical beamforming, to create a signal in which the desired source is enhanced relative to the noise Thus, the first stage of a Griffiths-Jim beamformer produces a reference noise signal and a signal that is predominantly desired source The noise reference is then employed in the second stage, using standard active noise- cancellation techniques, to improve the signal-to-noise ratio in the output The Griffiths-Jim beamformer suffers from the flaw that under reverberant conditions, the delay - based first stage cannot construct a reference noise signal devoid of the desired signal, whereas the second stage relies on the purity of that noise reference If the noise reference is sufficiently contaminated with the desired source, the second stage suppresses the desired source, not the noise (Van Compemolle 1990) Thus, the Griffiths-Jim beamformer incorrectly suppresses the desired signal under conditions that are normally considered favorable when the signal-to-noise ratio in the microphones is high Another two-stage architecture is described by Najar et al ( 1994) Its second stage employs blind convolutive active cancellation However, its first stage differs significantly from the first stage of the Griffiths-Jim beamformer It attempts to produce separated outputs by adaptively filtering each microphone signal in its own channel When the sources are spectrally similar, filters that produce partially separated outputs after the first stage are unlikely to exist Thus, it is desirable to provide an architecture for separation of sources that avoids the difficulties exhibited by existing techniques Summary of The Invention An audio signal processing system for processing acoustic waves from a plurality of sources, comprising a plurality of spaced apart transducer means for receiving acoustic waves from the plurality of sources, including echoes and reverberations thereof The transducer means generates a plurality of acoustic signals in response thereto Each of the plurality of transducer means receives acoustic waves from the plurality of sources including echoes and reverberations thereof, and generates one of the plurality of acoustic signals A first processing means receives the plurality of acoustic signals and generates a plurality of first processed acoustic signals in response thereto In the absence of echoes and reverberations of the acoustic waves from the plurality of sources, each of the first processed acoustic signals represent acoustic waves from only one different source A second processing means receives the plurality of first processed acoustic signals and generates a plurality of second processed acoustic signals in response thereto ln the presence of echoes and reverberations of the acoustic waves from the plurality of sources, each of the second processed acoustic signals represent acoustic waves from only one different source Brief Description of The Drawings Figure 1 is a schematic block diagram of an embodiment of an acoustic signal processor of the present invention, using two microphones Figure 2 is a schematic block diagram of an embodiment of the direct-signal separator portion, I e the first stage of the processor shown in Figure 1 Figure 3 is a schematic block diagram of an embodiment of the crosstalk remover portion, i e . the second stage of the processor shown in Figure 1 Figure 4 is an overview of the delay in the acoustic waves arriving at the direct signal separator portion of the signal processor of Figure 1 , and showing the separation of the signals Figure 5 is an overview of a portion of the crosstalk remover of the signal processor of Figure I showing the removal of the crosstalk from one of the signal channels Figure 6 is a detailed schematic block diagram of an embodiment of a direct-signal separator using three microphones Figure 7 is a detailed schematic block diagram of an embodiment of a crosstalk remover suitable using three microphones Detailed Description of The Invention The present invention is a device that mimics the cocktail-party effect using a plurality of microphones with as many output audio channels, and a signal-processing module When situated in a complicated acoustic environment that contains multiple audio sources with arbitrary spectral characteristics, it supplies output audio signals, each of which contains sound from at most one of the original sources These separated audio signals can be used in a variety of applications, such as hearing aids or voice-activated devices Figure 1 is a schematic diagram of a signal separator processor of one embodiment of the present invention As previously discussed, the signal separator processor of the present invention can be used with any number of microphones In the embodiment shown in Figure 1, the signal separator processor receives signals from a first microphone 10 and a second microphone 12, spaced apart by about two centimeters As used herein, the microphones 10 and 12 include transducers (not shown), their associated pre-amplifiers (not shown), and A/D converters 22 and 24 (shown in Figure 2) The microphones 10 and 12 in the preferred embodiment are omnidirectional microphones, each of which is capable of receiving acoustic wave signals from the environment and for generating a first and a second acoustic electrical signal 14 and 16 respectively The microphones 10 and 12 are either selected or calibrated to have matching sensitivity The use of matched omnidirectional microphones 10 and 12, instead of directional or other microphones leads to simplicity in the direct-signal separator 30, described below In the preferred embodiment, two Knowles EM-3046 omnidirectional microphones were used, with a separation of 2 centimeters The pair was mounted at least 25 centimeters from any large surface in order to preserve the omnidirectional nature of the microphones Matching was achieved by connecting the two microphone outputs to a stereo microphone preamplifier and adjusting the individual channel gains so that the preamplifier outputs were closely matched The preamplifier outputs were each digitally sampled at 22,050 samples per second, simultaneously These sampled electrical signals 14 and 16 are supplied to the direct signal separator 30 and to a Direction of Arrival (DOA) estimator 20 The direct-signal separator 30 employs information from a DOA estimator 20 which derives its estimate from the microphone signals In a different embodiment of the invention, DOA information could come from an source other than the microphone signals, such as direct input from a user via an input device The direct signal separator 30 generates a plurality of output signals 40 and 42 The direct signal separator 30 generates as many output signals 40 and 42 as there are microphones 10 and 12 generating as many input signals 14 and 16 as are supplied to the direct signal separator 30 Assuming that there are two sources, A and B, generating acoustic wave signals in the environment in which the signal processor 8 is located, then each of the microphones 10 and 12 would detect acoustic waves from both sources Hence, each of the electrical signals 14 and 16, generated by the microphones 10 and 12 respectively, contains components of sound from sources A and B The direct-signal separator 30 processes the signals 14 and 16 to generate the signals 40 and 42 respectively, such that in anechoic conditions (i e , the absence of echoes and reverberations), each of the signals 40 and 42 would be of an electrical signal representation of sound from only one source ln the absence of echoes and reverberations, the electrical signal 40 would be of sound only from source A, with electrical signal 42 being of sound only from source B, or vice versa Thus under anechoic conditions the direct-signal separator 30 can bring about full separation of the sounds represented in signals 14 and 16 However, when echoes and reverberation are present, the separation is only partial The output signals 40 and 42 of the direct signal separator 30 are supplied to the crosstalk remover 50 The crosstalk remover 50 removes the crosstalk between the signals 40 and 42 to bring about fully separated signals 60 and 62 respectively Thus the direct-signal separator 30 and the crosstalk remover 50 play complementary roles in the system 8 The direct-signal separator 30 is able to bring about full separation of signals mixed in the absence of echoes and reverberation, but produces only partial separation when echoes and reverberation are present The crosstalk remover 50 when used alone is often able to bring about full separation of sources mixed in the presence of echoes and reverberation, but is most effective when given inputs 40 and 42 that are partially separated After some adaptation time, each output 60 and 62 of the crosstalk remover 50 contains the signal from only one sound source A or B Optionally, these outputs 60 and 62 can be connected individually to post filters 70 and 72, respectively, to remove known frequency coloration produced by the direct signal separator 30 or the crosstalk remover 50 Practitioners skilled in the art will recognize that there are many ways to remove this known frequency coloration, these vary in terms of their cost and effectiveness An inexpensive post filtering method, for example, consists of reducing the treble and boosting the base The filters 70 and 72 generate output signals 80 and 82, respectively, which can be used in a variety of applications For example, they may be connected to a switch box and then to a hearing aid Referring to Figure 2 there is shown one embodiment of the direct signal separator 30 portion of the signal processor 8 of the present invention The microphone transducers generate input signals 1 1 and 13, which are sampled and digitized, by clocked sample-and-hold circuits followed by analog-to- digital converters 22 and 24, respectively, to produce sampled digital signals 14 and 16 respectively The digital signal 14 is supplied to a first delay line 32 In the preferred embodiment, the delay line 32 delays the digitally sampled signal 14 by a non-integral multiple of the sampling interval T, which was 45 35 microseconds given the sampling rate of 22,050 samples per second The integral portion of the delay was implemented using a digital delay line, while the remaining subsample delay of less than one sample interval was implemented using a non-causal, truncated sine filter with 41 coefficients Specifically, to implement a subsample delay of t, given that t<T, the following filter is used 20 y(n) = Σ w(k) x(n-k) k=-20 where x(n) is the signal to be delayed, y(n) is the delayed signal, and w(k) {k=-20,-19, 19,20} are the 41 filter coefficients The filter coefficients are determined from the subsample delay t as follows w(k) = ( 1/S) sιnc{ π [(t/T) - k] } where sιnc(a) = sιn(a) / a if a not equal to 0 = 1 otherwise, and S is a normalization factor given by 20 S = Σ sιnc{ π [(t/T) - k] } k = -20 The output of the first delay line 32 is supplied to the negative input of a second combiner 38 The first digital signal 14 is also supplied to the positive input of a first combiner 36 Similarly, for the other channel, the second digital signal 16 is supplied to a second delay line 34, which generates a signal which is supplied to the negative input of the first combiner 36 In the preferred embodiment, the sample-and-hold and A/D operations were implemented by the audio input circuits of a Silicon Graphics Indy workstation, and the delay lines and combiners were implemented in software running on the same machine However, other delay lines such as analog delay lines, surface acoustic wave delays, digital low - pass filters, or digital delay lines with higher sampling rates, may be used in place of the digital delay line 32, and 34 Similarly, other combiners, such as analog voltage subtractors using operational amplifiers, or special purpose digital hardware, may be used in place of the combiners 36 and 38 Schematically, the function of the direct signal separator 30 may be seen by referring to Figure 4 Assuming that there are no echoes or reverberations, the acoustic wave signal received by the microphone 12 is the sum of source B and a delayed copy of source A (For clarity in presentation here and in the forthcoming theory section, time relationship between the sources A and B and the microphones 10 and 12 are described as if the electrical signal 14 generated by the microphone 10 were simultaneous with source A and the electrical signal 16 generated by the microphone 12 were simultaneous with source B This determines the two-arbitrary additive time constants that one is free to choose in each channel ) Thus, the electrical signal 16 generated by the microphone 12 is an electrical representation of the sound source B plus a delayed copy of source A Similarly, the electrical signal 14 generated by the microphone 10 is an electrical representation of the sound source A and a delayed copy of sound source B By delaying the electrical signal 14 an appropriate amount, the electrical signal supplied to the negative input of the combiner 38 would represent a delayed copy of source A plus a further delayed copy of source B The subtraction of the signal from the delay line 32 and digital signal 16 would remove the signal component representing the delayed copy of sound source A, leaving only the pure sound B (along with the further delayed copy of B) The amount of delay to be set for each of the digital delay lines 32 and 34 can be supplied from the DOA estimator 20 Numerous methods for estimating the relative time delays have been described in the prior art (for example, Schmidt, 1981 , Roy et al . 1988, Morita, 1991. Allen, 1991 ) Thus the DOA estimator 20 is well known in the art In a different embodiment, omni-directional microphones 10 and 12 could be replaced by directional microphones placed very close together Then all delays would be replaced by multipliers, in particular, digital delay lines 32 and 34 would be replaced by multipliers Each multiplier would receive the signal from its respective A/D converter and generate a scaled signal, which can be either positive or negative, in response A preferred embodiment of the crosstalk remover 50 is shown in greater detail in Figure 3 The crosstalk remover 50 comprises a third combiner 56 for receiving the first output signal 40 from the direct signal separator 30 The third combiner 56 also receives, at its negative input, the output of a second adaptive filter 54 The output of the third combiner 56 is supplied to a first adaptive filter 52 The output of the first adaptive filter 52 is supplied to the negative input of the fourth combiner 58, to which the second output signal 42 from the direct signal separator 30 is also supplied The outputs of the third and fourth combiners 56 and 58 respectively, are the output signals 60 and 62, respectively of the crosstalk remover 50 Schematically, the function of the crosstalk remover 50 may be seen by referring to Figure 5 The inputs 40 and 42 to the crosstalk remover 50 are the outputs of the direct-signal separator 30 Let us assume that the direct-signal separator 30 has become fully adapted, i e , (a) that the electrical signal 40 represents the acoustic wave signals of source B and its echoes and reverberation, plus echoes and reverberation of source A, and similarly (b) that the electrical signal 42 represents the acoustic wave signals of source A and its echoes and reverberation, plus echoes and reverberation of source B Because the crosstalk remover 50 is a feedback network, it is easiest to analyze subject to the assumption that adaptive filters 52 and 54 are fully adapted, so that the electrical signals 62 and 60 already correspond to colored versions of B and A, respectively The processing of the electrical signal 60 by the adaptive filter 52 will generate an electrical signal equal to the echoes and reverberation of source B present in the electrical signal 42, hence subtraction of the output of adaptive filter 52 from the electrical signal 42 leaves output signal 62 with signal components only from source A Similarly, the processing of the electrical signal 62 by the adaptive filter 54 will generate an electrical signal equal to the echoes and reverberation of source A present in the electrical signal 40, hence subtraction of the output of adaptive filter 54 from the electrical signal 40 leaves output signal 60 with signal components only from source B Theory It is assumed, solely for the purpose of designing the direct-signal separator 30. that the microphones 10 and 12 are omnidirectional and matched in sensitivity Under anechoic conditions, the signals λ j (t) and λ->(t), which correspond to the input signals, received by microphones 10 and 12, respectively, may be modeled as x,(t) = w,(t) + w 2 (t-τ 2 ) x 2 (t) = w 2 (t) + ,(t-τ,), where W j (t) and w 9 (t) are the original source signals, as they reach microphones 10 and 12. respectively and ti and τ 2 are unknown relative time delays, each of which may be positive or negative Practitioners experienced in the art will recognize that bounded "negative" time delays can be achieved by adding a net time delay to the entire system The relative time delays τi and τ-> are used to form outputs y , (t) and y- > (t). which correspond to signals 40 and 42 y,(t) = x,(t) - x 2 (t-τ 2 ) = w,(t) - w,(t-(τ,+τ 2 )) y 2 (t) = x 2 (t) - x,(t-τ,) = w 2 (t) - w 2 (t-(τ,+τ 2 )) As depicted in Figure 2, these operations are accomplished by time-delay units 32 and 34, and combiners 36 and 38 Under anechoic conditions, these outputs 40 and 42, would be fully separated, i e , each output 40 or 42 would contain contributions from one source alone However under echoic conditions these outputs 40 and 42 are not fully separated Under echoic and reverberant conditions, the microphone signals X j (t) and x 7 (t), which correspond to input signals received by the microphones 10 and 12, respectively, may be modeled as x,(t) = w^O+w^t-τ^+k, ,'(t)*w,(t)+ , 2 '(t)* 2 (t) x 2 (t) = w 2 (t)+w,(t-τ ] )+k 2] '(t)*w 1 (t)+k 22 '(t)*w 2 (t), where the symbol "*" denotes the operation of convolution, and the impulse responses ki ,'(t), kp'(t), k ] '(t), and k 77 '(t) incorporate the effects of echoes and reverberation Specifically, k, ] '(t)*w,(t) represents the echoes and reverberations of source 1 (wι(t)) as received at input 1 (microphone 10), kp'(t)*w 2 (t) represents the echoes and reverberations of source 2 (w-,(t)) as received at input 1 (microphone 10), k 2j '(t)*W ] (t) represents the echoes and reverberations of source 1 (w j (f)) as received at input 2 (microphone 12), and k 2 '(t)*w-,(t) represents the echoes and reverberations of source 2 (w 7 (t)) as received at input 2 (microphone 12) In consequence of the presence of echoes and reverberation, the outputs 40 and 42 from the direct- signal separator 30 are not fully separated, but instead take the form y,(t) = x,(t)-x 2 (t-τ 2 ) = w | (t)-w 1 (t-(τ,+τ 2 ))+k 1 j (t) * w,(t)+k 12 (t) * w 2 (t) = w 2 (t)-w 2 (t-(τ 1 +τ 2 ))+k 2] (t) * w,(t)+k 22 (t) * w 2 (t) where the filters k ]| (t), kp(t), k 7] (t), and k ->(t) are related to k || '(t), kp'(t). k 71 '(t). and k ? V(t) by time shifts and linear combinations Specifically, k π (t) = k π '(t)-k 2] '(t-τ 2 ), k, 2 (t) = k 12 '(t)-k 22 '(t-τ 2 ), k 21 (t) = k 2] '(f)- k n '(t-T | ), and k 22 (t) = k 22 '(t) - k ]2 '(t-τ,) Note that y j (t) is contaminated by the term kp(t) * w-,(t), and that y-,(t) is contaminated by the term k 2 ,(t)* W j (t) Several possible forms of the crosstalk remover have been described as part of the background of this invention, under the heading of convolutive blind source separation ln the present embodiment, the crosstalk remover forms discrete time sampled outputs 60 and 62 thus 1000 z^n) = y 2 (n) - h, (k)z, (n-k) L k = l where the discrete time filters h j and h correspond to elements 52 and 54 in Figure 3 and are estimated adaptively The filters h j and h 2 are strictly causal, I e , they operate only on past samples of z, and z-, This structure was described independently by Jutten et al ( 1992) and by Platt and Faggin ( 1992) The adaptation rule used for the filter coefficients in the preferred embodiment is a variant of the LMS rule ("Adaptive Signal Processing," Bernard Widrow and Samuel D Steams, Prentice-Hall, Englewood Cliffs, N , 1985, p 99) The filter coefficients are updated at every time-step n. after the new values of the outputs Zι (n) and z 2 (n) have been calculated Specifically, using these new values of the outputs, the filter coefficients are updated as follows h , (k) [new] = h , (k) [old] + m z^n) z,(n-k) k=l ,2, ,1000 h 2 (k) [new] = h 2 (k) [old] + m z, (n) z^n-k) k=l ,2, , 1000 where m is a constant that determines the rate of adaptation of the filter coefficients, e g 0 15 if the input signals 10 and 12 were normalized to lie in the range -1 < x(t) < +1 One skilled in the art will recognize that the filters h j and h can be implemented in a variety of ways, including FIRs and lattice IIRs As described, the direct-signal separator 30 and crosstalk remover 50 adaptively bring about full separation of two sound sources mixed in an echoic, reverberant acoustic environment However, the output signals Z j (t) and z^(t) may be unsatisfactory in practical applications because they are colored versions of the original sources w, (t) and w 2 (t), l e , z, = ζ, (t)*w ,(t) where ζ j (t) and ζ->(t) represent the combined effects of the echoes and reverberations and of the various known signal transformations performed by the direct-signal separator 30 and crosstalk remover 50 As an optional cosmetic improvement for certain commercial applications, it may be desirable to append filters 70 and 72 to the network The purpose of these filters is to undo the effects of filters ζι (t) and ζ 2 (t) As those familiar with the art will realize, a large body of techniques for performing this inversion to varying and predictable degrees of accuracy currently exist The embodiment of the signal processor 8 has been described in Figures 1 -5 as being useful with two microphones 10 and 12 for separating two sound sources, A and B Clearly, the invention is not so limited The forthcoming section describes how more than two microphones and sound sources can be accomodated General case with M microphones and M sources The invention is able to separate an arbitrary number M of simultaneous sources as long as they are statistically independent if there are at least M microphones Let v (t) be the j'th source signal and x,(t) be the l'th microphone (mic) signal Let t be the time required for sound to propagate from source j to mic l, and let d(t ) be the impulse response of a filter that delays a signal by t Mathematically d(t ) is the unit impulse delayed by t that is whe *„> δ(f- re V δ(t) is the unit impulse function ("Circuits, Signals and Systems", by William McC Siebert The MIT Press. McGraw Hill Book Company, 1986, p 319) In the absence of echoes and reverberation, the i'th mic signal x^t) can be expressed as a sum of the appropriately delayed j source signals repr esentation allows a compact representation of this equation for all M mic signals X(t) = D(t) * Wit) whe re X(t) is an V -element column vector whose i'th element is the i'th mic signal x (t), D(t) is an MxM element square matrix whose ij'th element (ie , the element in the i'th row and j'th column) is d(t ) and W(t) is an M-element column vector whose j'th element is the j'th source signal w (t) Specifically , For each source w (t), if the delays t- for ι=l ,2,. M to the M mics are known (up to an arbitrary constant additive factor that can be different for each source), then M signals y (t), j=l ,2, ,Λ/, that each contain energy from a single but different source w (t), can be constructed from the mic signals x (t) as follows Y(t) = adjDit) * X(ή , where is the /W-element column vector whose j'th element is the separated signal y (t), and adjD(t) is the adjugate matrix of the matrix D(t) The adjugate matrix of a square matrix is the matrix obtained by replacing each element of the original matrix by its cofactor, and then transposing the result ("Linear Systems", by Thomas Kailath, Prentice Hall. Inc , 1980, p 649) The product of the adjugate matrix and the original matrix is a diagonal matrix, with each element along the diagonal being equal to the determinant of the original matrix Thus Y(t) = ad]D(t) * X(t) = adjD(t) * D(t) * W(t) where 'D(t) is the determinant of D(t) Thus, y (t) is a "colored" or filtered version of w (t) because of the convolution by the filter impulse response |D(t)' If desired, this coloration can be undone by post filtering the outputs by a filter that is the inverse of |D(t)' Under certain circumstances determined by the highest frequency of interest in the source signals and the separation between the mics, the filter 'D(t) may have zeroes at certain frequencies, these make it impossible to exactly realize the inverse of the filter |D(t)| Under these circumstances any one of the numerous techniques available for approximating filter inverses (see, for example, "Digital Filters and Signal Processing", by Leland B Jackson, Kluwer Academic Publishers, 1986, p 146) may be used to derive an approximate filter with which to do the post filtering The delays t can be estimated from the statistical properties of the mic signals, up to a constant additive factor that can be different for each source This is the subject of a co- pending patent application by the same inventors, filed even date herewith Alternatively, if the position of each microphone and each source is known, then the delays t can be calculated exactly For any source that is distant, i e , many times farther than the greatest separation between the mics, only the direction of the source is needed to calculate its delays to each mic, up to an arbitrary additive constant The first stage of the processor 8, namely the direct signal separator 30, uses the estimated delays to construct the adjugate matrix adjD(t), which it applies to the microphone signals X(t) to obtain the outputs Y(t) of the first stage, given by Y(t) = adjD(t) * X(t) In the absence of echoes and reverberations, each output y (t) contains energy from a single but different source w (t) When echoes and reverberation are present, each mic receives the direct signals from the sources as well as echoes and reverberations from each source Thus M M *,(,) = ∑ d( tιj ) *wp) +∑ ep) *wp) for ι = 1,2, ,M j- l l- l where e (t) is the impulse response of the echo and reverberation path from the j 'th source to the i'th mic All M of these equations can be represented in compact matrix notation by λ(t) = D(t) *W(t)+E(t)*W(t) where E(t) is the MxM matrix whose ljth element is the filter e (t) If the mic signals are now convolved with the adjugate matrix of D(t). instead of obtaining separated signals we obtain partially separated signals Y(t)= adjD(t) *X(t) = \D(t) \ * W(t) +adjD(t) *E(t) * W(t) Notice that each y (t) contains a colored direct signal from a single source, as in the case with no echoes, and differently colored components from the echoes and reverberations of every source, including the direct one The echoes and reverberations of the other sources are removed by the second stage of the network, namely the crosstalk remover 50, which generates each output as follows zp) = yp) - ∑ h t) *zp) for j = \ ,2,. ,M k.j where the entities h ^(t) are causal adaptive filters (The term "causal" means that . (t)=0 for t<0 ) In matrix form these equations are written as Z(t) = Y(t)-H(t)*Z(t) where Z(t) is the /V/-element column vector whose j'th element is z (t), and H(t) is an MxM element matrix whose diagonal elements are zero and whose off diagonal elements are the causal, adaptive filters h-^(t) These filters are adapted according to a rule that is similar to the Least Mean Square update rule of adaptive filter theory ("Adaptive Signal Processing," Bernard Widrow and Samuel D Steams, Prentice-Hall, Englewood Cliffs, NJ, 1985, p 99) This is most easily illustrated in the case of a discrete time system Illustrative weight update methodology for use with a discrete time representation First, we replace the time parameter t by a discrete time index n Second, we use the notation H(n)[new] to indicate the value of H(n) in effect just before computing new outputs at time n At each time step n, the outputs Z(n) are computed according to Z(n) = Y(n)-H(n)[new]*Z(n) Note that the convolution on the right hand side involves only past values of Z, ie Z(n- l ),Z(n-2), , Z(n-N), because the filters that are the elements of H are causal (N is defined to be the order of the filters in H) Now new values are computed for the coefficients of the filters that are the elements of H These will be used at the next time step Specifically , for each j and each k, with j ≠ k, perform the following h ]k (u)[old] = h jk (u)[new] u = l,2,...,M h jk (u)[new] = h jk (u)[old]- μ jk zp)z k (n-u) u = l,2,...,M The easiest way to understand the operation of the second stage is to observe that the off-diagonal elements of H(t) have zero net change per unit time when the products like z (t)zι (t-u) are zero on average Because the sources in W are taken to be statistically independent of each other, those products are zero on average when each output z (t) has become a colored version of a different source, say w (t) (The correspondence between sources and outputs might be permuted so that the numbering of the sources does not match the numbering of the outputs.) More specifically, let Z(t)=Ψ(t)*W(t). From the preceding paragraph, equilibrium is achieved when Ψ(t) is diagonal, ln addition, it is required that: Z(t) =Y(t)-H(t) * (t) * W(t) = \D(t) I * W(t) +adjD(t) *E(t) * W(t)-H(t) * Ψ(t) * W(t) =( | (r) \I+adjD(t) *E(t) -H(t) * Ψ(f)) * W(i) so that Ψ(f)= \D(t) \I+adjD(t) *E(t) -H(t) *Ψ(t) V(tM H(t)Y l [ \D(t) \I+adjD(t) *E(ή] This relation determines the coloration produced by the two stages of the system, taken together. An optional third stage can use any one of numerous techniques available to reduce the amount of coloration on any individual output. Example of general case with M = 3, i.e. with 3 mics and 3 sources In the case where there are 3 mics and 3 sources, the general matrix equation X = D*IV becomes If the delays t- are known, then the adjugate matrix of D(t) is given by d(t u + r 33 ) - d(r 23 + 1 32 ) d(t n + t n ) - d(t n * f 33 ) d(t + 23 ) -d(t n * t 13 ) adjD = <f(r 23 +r 3I ) -d(t 21 *t n ) d{t +r 33 ) -d(t n + r 31 ) d(t 2l *t n ) -d(t u +t 23 ) d(t 2l + t 32 ) -d(t 22 + t 3l ) d(t +t 3l ) -d(t i2 ) dd +t^ -d^ +tu) Note that adding a constant delay to the delays associated with any column of D(t) leaves the adjugate matrix unchanged. This is why the delays from a source to the three mics need only be estimated up to an arbitrary additive constant. The output of the first stage, namely the direct signal separator 30, is formed by convolving the mic signals with the adjugate matrix. The network that accomplishes this is shown in Figure 6 In the absence of echoes and reverberations, the outputs of the first stage are the individual sources, each colored by the determinant of the delay matrix In the general case when echoes and reverberation are present, each output of the first stage also contains echoes and reverberations from each source The second stage, namely the cross talk remover 50, consisting of a feedback network of adaptive filters, removes the effects of these unwanted echoes and reverberations to produce outputs that each contain energy only one different source, respectively The matrix equation of the second stage Z = Y-H*Z becomes where each h is a causal adaptive filter The network that accomplishes this is shown in Figure 7 CONCLUSION It should be noted that the number of microphones and associated channels of signal processing need not be as large as the total number of sources present, as long as the number of sources emitting a significant amount of sound at any given instant in time does not exceed the number of microphones For example, if during one interval of time only sources A and B emit sound, and in another interval of time only sources B and C emit sound, then during the first interval the output channels will correspond to A and B respectively, and during the second interval the output channels will correspond to B and C respectively As previously discussed, in the preferred embodiment of the present invention, the invention has been implemented in software, as set forth in the microfiche appendix The software code is written in the C++ language for execution on a workstation from Silicon Graphics However, as previously discussed, hardware implementation of the present invention is also contemplated to be within the scope of the present invention Thus, for example, the direct signal separator 30 and the crosstalk remover 50 can be a part of a digital signal processor, or can be a part of a general purpose computer, or can be a part of analog signal processing circuitry In addition, the present invention is not limited to the processing of acoustic waves It can be used to process signals, having a delay with the problem of separation of the signals from the sources There are many advantages and differences of the present invention from the prior art 1 Although the present invention is similar in objective to sound separation based on auditory scene analysis, it differs from them in principle and in technique 2 In contrast with approaches based on auditory scene analysis, this invention separates sounds by exploiting the separation of their sources in space and their statistical independence 3 The present invention differs from directional microphones in that few presuppositions are made with regard to the locations of sound sources relative to the device The present device need not be pointed at or mounted close to a source of interest The necessary selectivity is brought about by processing of signals captured by a microphone array, I e , a collection of microphones Moreover, the selectivity attained is much greater a directional microphone cannot completely suppress any source of sound 4 While the pπor art nonlinear techniques can be very computationally efficient and are of scientific interest as models of human cocktail -party processing, they are of less practical or commercial significance than the present invention because of their inherent inability to bring about full suppression of unwanted sources This inability originates from the incorrect assumption that at every instant in time, at least one microphone contains only the desired signal The present invention differs from these nonlinear techniques in that linear operations (addition, subtraction, and filtering) are employed to cancel unwanted sources 5 The present invention is an example of "active cancellation " In contrast with classical beamforming, which aligns copies of a desired source in time and adds them together, active cancellation matches copies of undesired sources and subtracts them to bring about cancellation ("Matching" the copies of the undesired sources generally entails more than simply re-aligning them in time, usually, it involves re-shaping them by filtering ) Bearing this simplified explanation in mind, it may be seen that the degree of selectivity achieved by active cancellation is determined by factors rather different from those important in classical beamforming In active cancellation, the degree of selectivity is determined by the exactness with which identical copies of unwanted sources can be created from different microphones for subsequent cancellation In contrast with a classical beamformer, a sound- separation device that employs active cancellation can in principle remove one undesired source completely using just two microphones 6 The present invention also does not need a reference sound 7 In contrast with active-cancellation algorithms that require a reference signal, the present invention operates "blindly" it accommodates the more difficult case in which all of the signals directly available for processing, I e , the microphone signals, are assumed to be mixtures of sources The present invention is a method for bringing about blind separation of sources, given the direction of arrival (DOA) of each source This DOA information may be obtained in a variety of ways, for example by direct specification from a human user or by statistical estimation from the microphone signals Precisely how DOA information is obtained is immaterial in the context of the present invention, what is important is how DOA information is used to bring about source separation 8 The present invention differs from gain-based active cancellation in that it requires no assumption of simultaneity of signal reception at all of the microphones 9 In contrast with purely delay-based active cancellation and variants that introduce simple gains in addition to delays (e g , Platt & Faggin, 1992), the present invention is based on an acoustic model that includes the effects of echoes and reverberation 10 Single-stage techniques for blind, convolutive active cancellation are usually unable to separate mixtures that are not already partially separated 1 1 Two pπor art techniques for blind, convolutive active cancellation are like the present invention based on a two-stage architecture Of these the technique of Najar et al ( 1994) differs from the present invention in that each output channel of its first stage is a filtered version of only one input channel Therefore, the first stage of the system described by Najar et al (1994) cannot bring about full separation even in the absence of echoes and reverberation, unless the original sources have no overlapping spectral components 12 The other prior art technique based on a two-stage architecture is the Griffiths-Jim beamformer (Griffiths and Jim, 1982) The Griffiths-Jim beamformer employs active cancellation in its second stage that requires a reference signal The necessary reference noise signal is produced by the first stage, using known DOA information If this reference noise signal contains a significant amount of the desired signal, then the second stage will erroneously enhance the noise and suppress the desired signal (Van Compemolle, 1989) In the present invention, the second stage is blind, it employs its own outputs as reference signals Unlike the Griffiths-Jim reference signal, these become progressively purer with time as the network adapts -// Cro»ββcho2 -•-<:♦♦-*- SRβviaion: 12.2 $ SDatβ: 1994/08/05 23:37:57 $ // Second atage of our two-stage algorithm. lifndβf _Croββecho2_h ♦define _Cro«ββcho2_h claaa Croaaac o2 { // Conatructor, destructor public: Croaaacho2( int ntap, f oat mu ) ; -Croaaecho2 {) ; // Settinga private: float mu; int ntap; // State private: float * a, « wb; float *za, 'lb; int ino ; int fire _timβ_ hrough; // Interface to deacendanta public: void Proceaa ( loat* za_no , float* zb_no , float ya. float yb ); void dump_to_cout() ; ); tendif // _Croβaβcho2_h // Croaaacho2 -'-c*»-*- SReviaion: 12.2 $ $Date: 1994/08/05 23:37:57 $ tinclude *Croeaecho2.h* ♦include 'myatream.h' Croaaecho2: :Croaaacho2 ( int ntap_, float mu_ ) ( mu ■ mu_; ntap • ntap_; wa • new float (ntap) ; b « new float (ntap) ; za • new float [ntap] ; zb « new float [ntap); for( int i « 0; i < ntap; i++ ) wa[i] » wb[i] > 0; inow * 0; firat_ti e_through « 1; ) Croasecho2: :-Cro»»βcho2 () ( delete wa; delete wb; delete za; delete zb; ) void Croeaβcho.i : roceaa( float* za_now_, float* zb_now_, float ya, float yb ) 1 // Initialize output valuea with (ya.yb) regiater float za_now « ya; regiater float zb_now • yb; ift lfirβt_time_through ) ( // Update output valuea with feedback int ilag « inow; for) int i « 0; i < ntap; i+* ) { za_now ♦» wa(i] * zblilagj; zb_now ♦» wb(i) * za(ilag); if f ♦♦ilag >* ntap 1 ilag ■ 0 ; ) // Update the weighta regiater float mu_za * mu * za_now; regiater float mu_zb « mu * zb_now; for ( i « 0; i < ntap; i** ) [ wa [i] -« mu_za * zbdlag] ; wb[i) -« mu_zb * za(ilag) ; if( ♦♦ilag >« ntap ) ilag • 0; ) ) // Update the circular buffer za(inow) « za_jnow_ « za_jιow; zb(inow) « zb_now_ » zb_now; if( '♦♦inow >= ntap ) ( firβt_time_through « 0; inow » 0; ) void Croaaecho2: :dump_to_cout() ( cout.width(10); / / cout .aetf (ioe : latielcywidth) ; for( int i « 0; i < ntap; L++ ) cout « wa[i] TB « wb(i] « endl; // // Teat main // •ifdef TEST ♦include 'Signal.h* tinclude 'myatream.h* ιin() cout.aetf(ioa: :uni but) ; // Read in aignala cout « "Reading in aignala\n*; Signal ya, yb; ya.read_ai c(*Croaaecho2-a.in") ; yb.read aifc('Croaaecho2-b.in*) i // ya.truncate(SOOOO) ; // yb.truncate(SOOOO) ; long aampa ■ ya.get_aamplea() ; float freq « ya.get_aampling_frequency() ; // Prepare output aignala cout « 'Preparing out aignala\n*; Signal za(aampa, freq) , zb(aampa,freq) ; // Procβaβ the aignala, sample by βamplβ cout « "Spawning gizmoVn"; Croaaecho2 gizmo) 2000, 0.15 / (32768. * 32768.) ) ; float za_max ■ 1, zb_max • 1; cout « "Looping over for( long i « 0; i < aa pa; i+* ) ( float za_, zb_; gizmo.Process) za_, zb_, ya[i), yb[i) ),- za(i] > za_; zb(i) • zb_; if( i % 1000 « 0 ) cout « i TB « za_ TB « zb_ NL; // cout « za_ TB « zb_ TB « yall] TB « yb[l) NL; ) cout « 'Writing output Croaaecho2-a.out\n"; za.writβ_aifc("Croaa«cho2-a.out*) ; cout « "Writing output Croaaecho2-b.out\n"; zb.write_aifc("Croaaecho2-b.out") ; // cout « "Playing output a\n"; za.playO; // cout « "Playing output b\n"; zb.playl); return 0; ) tendif (define MAXKICS 10 ♦include ■ Signal.h" ♦include "SrchSStourn.h" ♦include 'SrchSSpop.h' ♦include 'SrchSShc.h' ♦include 'RepnSS.h' ♦include *Croaaecho2.h" ♦include "myatream.h* ♦include • SS2.h- ♦include <atdlib.h> ♦include <atring.h> claaa SoSenaor; atatic SrchSSpop* arch ■ 0; char* filename (KAX 1CS); int nmica; int main( int argc, char** argv ) ( cout.aetfl ioattunitbuf ); cerr.aetft ioa::unitbuf ); // Parae coαnand-line arga char *filal > 0, *file2 « 0; int delaya « 0; int croaaacho « 0; ; 0; hi « 0; 0; SS2i:Setup! argc, argv, aa, repn, ya, yb, filel, file2, lo, hi, aamps, freq, delaya, croaaacho, nrβp ); SS2* ss2 « (SS2*) aa; // Figure out aampling frequency and window aize ♦define WINDOW_TIME 0.01 conat long window_aampa « long( freq * WINDOW_TIME ♦ 0.5 ); // Form outputs Signal za( samps, freq ) , zb( aamps, req ) ; // Start up a new searcher RβpnSS* suggest ■= (RepnSS*) rβpn->Clonβ() ; ♦define NPOP 30 SrchSShc* auggeater « new SrchSShc(sugges ) ; arch • new SrchSSpop( repn, NPOP, auggeater ); if( dalaya < 2 ) auggaater->pop > arch; auggeater->maxrank > NPOP-1; auggeater->rank_factor « 0.8; RepnSS* follower « (RepnSS*) arch->gβt_follower0 ; // Set some parameters switch! delaya ) ( caae 0: arch->min iterations to_max_aaaets = 50; arch->max_incoBia_dif _per_lteration ■ 10; arch->iterationa_par_auggeation = 10; arch->auggestiona_per_aample > 10; break; caaa It arch->min_itarationa_to_max_aaaeta • 10; srch->max_incomβ_dif _pβr_itβration » 10; srch->itβrations_pβr_βuggeation • 3; arch->auggestionβ_per_aample > 3; break; caaa 2: arch->min_iterationa_to_max_aaaeta * 50; arch->max_income_di f_per_iteration « 10; srch->itβrations_pβr_βuggββtion « 5; βrch->βuggβstions_pβr_βamplβ « 5; break; ) βrch->replacβment_thrβahold « 0; // Do the loop over samples long it • 0; int irep ■ 0; followβr->Install() ; Croaβecho2 atage2( 225, 0.15 / (32768. • 32768.) ) ; while (1) { as2->Sample2 (ya lit) ,yb[it) ) ; if ( irep « 0 ) ( float za_, zb_; βa2->FoπnOut2 ( za_, zb_ ) ; if ( croaaacho ) atagβ2. Process ( za(it) , zbllt] , za_, zb_ ) ; elae za[it] « za_; zbtit) « zb_; ) if( it % window_aampa »« 0 ) ( arch->Iterate() ; // cout « follower->Evaluate() NL; cout « follower->to_βtrin () NL; ) if( ++it >» aamps ) { it * 0; if ( ♦♦irep «» 1 ) ( char *infilel « 0, *infile2 » 0; char Outfilel, *outfile2; out e « new char [strlen( ilel)*51 i outfile2 • new char (strlen(file2)+5) i atrcpy( outfilel, *aa2-' ) ; βtrcpyl outfile2, strca ( outfilel, street* outfilβ2, ) alae ( outfilel ■ new char [βtrlβn(filβl)♦β] , outfile2 > new char [βtrlenffilel)+8] ; βtrcpy( outfilel, *aa2-za-' ); βtrcp l outfile2, • sβ2-zb-" ); atrcat( outfilel. filel ); atreat( outfilβ2. filel ); infilal « new char [βtrlenlfilel) +8) ; infil«2 = new char [strlen!filel) +8) a rcpy( lnfilel, "aa2-ya-" I; atrcpy( infile2, ■ aβ2-yb-" ); atrcat ( infilel, filel ),- atrcat ( infile2. filel ) ; cerr << 'Writing outputa: ' « outfilal SP « outfile2 NL; double adev « 0x7fff • 0.02; double var • adav * adev; za.normalize.variance! var ); zb.normalize.variance( var ); za.write_aifc( outfilel ); zb.write_aifc( outfile2 ); ift infilel ** infile2 ) ( cerr « 'Writing inputs: " « infilel SP « infile2 NL; ya.write_aifc( infilel ); yb.write_aifc( infila2 ); ) ) if ( irep >« nrep ) break; return 0; ) ♦ifndef _myatream_h ♦define _myatream_h ♦Include <atream.h> ♦include <fstream. > ♦dafine SP « ' ' ♦dafine NL « ' \n' ♦de'ine TB « ' \ ' ♦endif // _mystream_h // Signal module -*-c*«—*- // Handles monophonic sound aignala // Ia able to do arithmetic like superpose signals with scaling and // time delay: compute running correlation ♦define DBFAULT_SAMPLING_FREQϋENCY 44100 ♦include <audio.h> claaa Signal { // Constructor and destructor public: Signa ( long βamplββ_ «0, float βampllng_frequency_ « DEFAULT_SAMPLING_FREQOENCY ) ; -SignaK); // Sampling frequency private: float eampling_frequency; float dt; publici void •et_aampling_frequency( float ); float get_aampling_frequency() ( return aampling_frequency; ) // Size and atorage public: void truncate( long aam lβa_new ) ; private! long βamplββ: float* value; void reaize( long aamplea_new ) ; void reaize( float approx_βaπtplβs_new ) ; // Acceaa publici float* operator (] ( long i ) ( return valued) ι ); const long get_aamplea() ( return samples; ) // Read or create a signal publici void create_zero( long βamplββ »0 ) j void create_random( long βamplββ «0 ) ,• void create_alne( float sinfreq, long βamplββ «0 ) ; // Arithmetic public: void operator *« ( float ); void add( Signal* that, float acale = 1.0, float delay « 0.0 )r void add_product( Signal* a, Signal* b ); // void damp! float elife ); void wlndow_avβrage( long iwindow ) ; friend Signal* window_averagβ( Signal* arc, long elife ) ; void exponentlal.average( Signal*, arc, long elife ); void forcβ_zero_mβan( ) ; void normalize,varlancet float dβairβd_variance '1.0 ),- void normalize_to_max( float deaired_max ); // void correlate) Signal* a, Signal* b. float alife ) ; // Convolution public: void add_timedelay( Signal* arc, double tau, double deβired_sum =1 ); // void timedelayf Signal* arc, double tau, double deaired_aum =1 ),- p ivate: atatic double* convolution; atatic int nconvolution, nconv2; // Transformed aignala public: Signal* operator « ( Signal* that ) ; // void AGC( Signal*, float elife ); // Audio I/O public: void playl float apeedup *1.0 ); void record) float duration ); void play_aaync( float apeedup «1.0 ); atatic long play_aβync_morβ() ; // ret cur aample or -1 private: typβdβf short aoundsample; atatic ALport alport; atatic aoundaa plβ* alport_buf; // 0 when buffer empty atatic void alport_buf_rβaizβ( long ); atatic long alpor Jsuf_aize; atatic long alport_buf_curaor; // -1 when port not in use // File I/O public: void write( conat char* filename ); void rβad( conat char* filename ) ; void wrltβ_aifc( conat char* filename ) ; void read_aifc( conat char* filaname, int rightchannel =0 ); void wri β_human( conat char* filename ); void rβad_human( conat char* filename ) ; ); // -*-e**-«- ♦include "Signal.h' ♦include "myatrea .h" ♦include <atdlib.h> ♦include <atring.h> ♦include <audio ile.h> ♦include <aath.h> ♦dafine TWO_PI 2 * M_PI extern *C" ( extern int aginapdong ticks); ) atatic double βinc! double x ) ( if( x «« 0 ) return 1; return ain(x) / x; ) // // Static buffer / / ALport Signal: ialport; Signal::aoundaample* Signal: :alport_buf « 0; void Signal: ιalport_buf_rββizβ( long newaiza ) ( ift alport_buf_βizβ ■« newaize ) return; ift alport_buf ) delete alport_bufι alport_buf • new aoundsample (alport_buf_aize « newaize); ) long Signal: :alport_buf_aize « 0; long Signal: :alport_buf_curβor « -1; double* Signal: :convolution • 0; int Signal: tnconvolution * 0; int Signal: :nconv2 • 0; // // Constructor and destructor / / Signal: :Signal ( long aamplea_, float sampling_frequency_ ) : βamplββ(0) , value(0) ( βet_aampling_frequency( aampling_frequency_ ) ; reaize( βamplβs_ ) ; fort long i * 0; i < samples; i*t ) valued) • 0.0; ift (convolution ) ( nconv2 » 10; nconvolution « nconv2 " 2 ♦ 1; convolution « new double [nconvolution) ; ) ) Signal: :-Signal() ( ift βamplββ > 0 ) delete value; ) void Signal: :aet_βampling_frequency( float x ) ( aampling_frequency » x; dt « 1.0 / x; ) void Signal: :reaize( long aamplea_new ) ( if! aamplea_new l« βampleβ ) ( if( βa plea > 0 ) delete value; samples ■ eamplea_new; value s (samples > 0) 7 new float [samples = samples_new) : 0; ) ) void Signal: :reaize( float approx_βamplβs ) ( long βampleβ_new • (long) floor(approχ_aamplea ♦ 0.5); resize! eamplea_new ); ) // // Truncate // void Signal: :truncate( long aamplea_new ) { if( βamplββ_nβw «« aampleβ ) return; float* value_new > new float taamplea.new] ; fort long i • 0; i < βamplea_new; l*+ ) valuβ_new[i] • (i < samples) 7 valued) : 0; delete value; value « valuβ_nβw; βamplββ « βampleβ_nβw; ) //— // Read or create a aignal // void Signal: :create_sine( float alnfreq, long samples. ) ( iff βamplββ_ > 0 ) reaize( aamplea_ ); for( long i = 0; i < βampleai i*» ) ( float t = i * dt; valued) « βin( TWO_PI * t * alnfreq ); ) ) void Signal: :creatβ_random) long βamplββ_ ) ( ift samplea_ > 0 ) reaize! aamplea_ ); float mean > 0; fort long i * 0; i < samples: i+* ) mean ♦= valued) - ( (random!) % 10000) / 5000.0) - 1.0; mean /» βampleβ; for) i * 0; i < βamplea; 1** ) valued) -= mean; ) void Signal: :create_zero( long βamplββ_ ) ( if! aamplea_ > 0 ) reaize( samples. ); fort long i « 0; 1 < βampleβ; i++ ) valued) = 0.0; ) // - - — // Arithmetic // — void Signal: iad ( Signal* that, float acala, float delay ) ( if! thia->aampling_frequency I* that.aampling.frequency ) cerr « "Warning: Signal: :add() encountered unequal aampling freqa\n"; // Compute delay in terms of number of time samples long idelay > long(delay * sampling_frequency ♦ 0.5); if! idelay > thie->aampleβ ) idalay « thia->aamplea; // Copy signal long ithia • idelay, ithat * 0; while! (ithia < thia->aamplea) ** (ithat < that.βamplββ) ) thiβ->valueϋthia**) ♦- that.value[ithat♦♦) • βcale; ) void Signal: :add_product( Signal* a. Signal* b ) ( if( aampling_frequency I* a.aampling_fraquency ) cerr « 'Warning: Signal: :add() encountered unequal aampling ift sampling_frequency l« b.aampling_frequency ) cerr « 'Warning: Signal: :add() encountered unequal aampling if( βamplββ l» a.βamplββ ) cerr « 'Warning: Signal: :add() encountered unequal signal lengthsVn*; if( aamplea I* b.βamplββ ) cerr « 'Warning: Signal: :add() encountered unequal aignal lengtha\n',- // Copy signal for! long i « 0; i < aamplea; i . ) valued) ♦» a.valued] • b.valued],- ) void Signal: ιwindow_average( long iwindow ) ( float iwin_inv * 1.0 / iwindow; float aura » 0; float* valuβ_nβv « new float (βamplββ); for! long i » 0; i < aamplea; i+* ) ( sum ♦* valued] i ift 1 >« iwindow ) sum -• value[i-iwindow) ; value_new[i] * au * lwln_inv; ) delete value; value « valuβ_nβ ι ) Signal* window_average( Signal* arc, long iwindow ) ( long aamplββ « arc.ge _βamplβa() ; Signal* dat • new Signal! aamplea ); float iwin_inv « 1.0 / iwindow; float aum « 0; for! long i « 0; i < aamplea; i** ) ( aum ♦« arc. valued] ; lf( i >« iwindow ) sum -• arc.value[i-iwindow]; dβt->valuβ[i) « aum * iwin_inv; > return *dat; ) Signal* βxponβntlal_avβragβ( Signal* arc, long alife ) ( long βamplββ • βrc.get_aamplea( ) ; Signal* dst • new Signal ( aamplea ) ; dβt->exponential_average( arc, elife ); return *dat; ) void Signal: :exponen ial_avβrage( Signal* arc, long elife ) ( float frac « -expml ( -1.0 / elife ); float avg « 0; for ( long i • 0; i < aamplea; !♦♦ ) ( avg » frac * arc. valued) ♦ (1-frac) * avg; valued] • avg; ) ) void Signal : : f orce_zero_mean ( ) ( float mean ■ 0; fort long i * 0; 1 < aamplaa; i+* ) mean ♦« valued) ; mean /• aamplaa; fort 1 ■ 0; i < aamplea; i*+ ) valued) -■= mean; ) void Signal: :normalize_variance( float desired_variance ) ( orcβ_τβro_mβan() ; float aumsq « 0.0; fort long i » 0; i < samplea; i+* ) aumaq ♦- valued) * valued); float acala « (aumaq «« 0.0) 7 1.0 : β<jrt(dβaired_variance*(aamplea/aumaq) ) ; fort i « 0; i < aamplea; !♦♦ ) valued] *= acale; ) void Signal: :noπnalizβ_to_max( float deaired_max ) ( forcβ_zero_mβan() ; float actual_max » 0; for( long i -> 0; i < aamplea; i+* ) if! faba(valued) ) > actual_max ) actual_max = fabs(valued) ) ,- float acale • (actual_max «» 0.0) 7 1.0 : dββirβd_max / actual_max; for! i ■ 0; i < aamplea; i+* ) valued] *= acale; ) void Signal::operator *= ( float scale ) ( for( long i « 0; 1 < aamplea; i+ ) valued) *« acale; ) / / _- // Time delay // // void Signal: :timedelay( Signal* arc, double tau, // double deaired_aum ) // // Tau should be number of time aamplea, not neceaaarily integer // I // // aet convolution // double aum « 0; // for( int d * 0; d < nconvolution; d++ ) // aum ♦» (convolution[d] « βinc( M_PI * (d - nconv2 - tau) ) ) ; // double acale • deaired_aum / aum; // for( d « 0; d < nconvolution; ++ ) convolution(d) *■ acale; // Compute thia by convolving arc with convolution for( long t « 0; t < aamplea; *+ ) ( value! ] * 0; for! d « 0; d < nconvolution; d^+ ) { long ts - t ♦ d - nconv2; if( ts >« 0 ** ts < src.aamplea ) value! t ) ♦• convolutlon(d) * src.value! ts ) ; ) ) ) void Signal: :add_timedelay( Signal* arc, double tau, double deaired_aum ) // Tau ahould be number of time aamplea, not naceaaarily integer t // set convolution double aum ■ 0; for( int d » 0; d < nconvolution; d++ ) aum ♦■ (convolution(d) = ainc( M_PI * !d nconv2 - tau) ) ) ; double acale » deaired_aum / aum; for! d « 0; d < nconvolution; ύ** ) convolution[dl *« acale; // Compute thia by convolving arc with convolution for! long t ■ 0; t < aamplea; t*» ) ( for( d ■ 0; d < nconvolution; ά** ) ( long ta • t ♦ nconv2 - d; if( ta >* 0 ** ta < arc.aamplaa ) value! t ) ♦» convolution(d) * βrc.value[ ta ]; ) ) // // Tranβformed aignala // Signal* Signal: :operator * ( Signal* that ) ( reaize! that.aamplaa ); aampling.frequency * that.aampling_frequency; dt m that.dt; for! long 1 « 0; i < aamplea; i** ) value!i) » that.valued) ; return "thia; ♦define DEFAUL GAIN 1.0 // // Audio I/O // ♦define VOLOMB 20000 void Signal: :play_aaync ( float apeedup ) ( // Cloaa port if neceaaary if! alport_buf_curaor >« 0 ) ALcloaaport(alport) ; // Creata buffer into which sound will be copied alport_buf_resize( aamplea ) ; // Find maximum abaolute value of algnal, and from that, acaling float value_maxaba « 0.0; for( long i * 0; i < alport_buf_aizβ; !♦♦ ) ( regiater float valuβ_aba • fabaf(valued] ) ; if! value_aba > value_maxaba ) value_maxabs » value_abs; ) float acale » (value_maxaba «= 0) ? 0.0 : (VOLUME / value_maxabs) ; // Copy to buffer for( i * 0; i < alport_buf_aize; i+* ) alport_buf[i] « (βoundsa plβ) (valued] * scale ♦ 0.5); // Set correct aampling rate atatic long PVbuffer[2); PVbufferlO] » AL_OOTPUT_RATE; PVbufferd] ■ long! aampling_frequency * speedup ♦ 0.5 ),- ALaetparama(AL_DEFAULT_DEVICE, PVbuffer, 2); // Set other parametera: monophonic, 16-bit values ALconfig config ■ ALnewcon l () ; ALaetchannela(config,ALJ10NO) ; ALaβtwidt (config,AL_SAKPLE_16) ; // Open the port, write the buffer, play it alport * ALopenportl'sound', "w" .config) ; alport_buf_curaor « 0; long Signal: ιplay_aβync_morβ() ( // Return if not currently playing a sound if! alport_buf_curaor < 0 ) return -1; // Decide how much to write long chunk « ΛLgβtfillablβ(alport) ; if! chunk «« 0 ) // port can't take anything return alport_buf_c raor - ALgetfilled(alport) ; if! chunk > alport_buf_βizβ - alport_buf_curβor ) chunk » alport_buf_βizβ - alpor _buf_curβor; // If there ia more to be written, do it if! chunk > 0 ) { ALwritβaamps(alport,alport_buf+alport_buf_curaor.chunk) ; alport_buf_curaor ♦■ chunk; return alport_buf_curaor - ALgetfilled(alport) ,- ) // Muat be done writing long atillplaying ■ ALgetfilled(alport) ,- if( atillplaying > 0 ) return alport_buf_curaor - stillplaying; // Done playing too ALcloaeport(alport) ; return alport_buf_curβor « -1; ) void Signal: :play( float apeedup ) ( play_aaync( apeedup ) ; while( play_asyπc_morβ() » 0 ) aginap(l); ) void Signal: :record! float duration ) ! reaize(duration * aampling_frequency) ; alport_buf_reaize( aamplea ) ; // Set correct aampling rate atatic long PVbuffβr(2]) PVbuffβr'O] « AL_INPOT_RATE; PVbufferd) ' (long) aampling.frequency; ALeβtparama(AL_DEFAϋLT_DEVICE, PVbuffer, 2); // Set other parametera: monophonic, 16-bit valuea ALconflg config ■ ALnewconfig() ; ALβetchannβlβ(config,ALJiONO) ; ALaetwidth(config,AL_SAHPLE_16) ; // Record the signal ALport p = ALopenportl"sound", "r",config) ; cout « "Starting to record signal " « duration « ' aeconds long\n* long recorded » 0; while) recorded < aamplea ) ( long chunk • ALgetfille (p) ; if( chunk > aamplea - recorded ) chunk • aamplea - recorded; ALreβdaampβ(p,alport_buf♦recorded.chunk) ; recorded +• chunk; while! ΛLgβtfilled(p) «« 0 ) aginap(l); ) cout « 'Donβ n'; ALcloaeport(p) ; // Find maximum abaolute value of buffer, and from that, acaling long maxabβ « 0; for( alport_buf_curaor • 0; alport_buf_curβor < aamplea; alport_buf_curaor*» ) ( regiater long x • label (long)alport_bufIalport_buf_curaor] ) ; if! x > maxabβ ) axaba • x; ) float acale » (maxaba •■ 0) 7 0.0 : (1.0 / maxaba); // Copy to buffer fort alport_buf_curaor ■ 0; alport_buf_curβor < aamplea; alport_buf_curaor»* ) value(alport_buf_curaor) « (float) alport_buf[alport_buf_curaor) • acale; alport_buf_curaor « -1; ) // — // File I/O // void Signal: :write( conat char* filename ) ( ofatream out; out.opβnffilβnamβ) ; out « 'Signal' NL; out « aamplea NL; out « aampling_frequency NL; out.write! (char'lvalue, int(aizeof(float) 'βamplea) ) NL; out « 'End' NL; ) ♦dafine BUFLEN 1000 void Signal: :read( const char* filename ) ( char buf[BUFLEN+2]; ifatream in; in.openlfilename) ; // Check that firat line aaya "Signal" in.getlinetbuf.BDFLEN) ; if! βtrneznplbuf, "Signal",6) ) cerr « "Warning: Not a Signal filβVn"; // Read in number of aamplea, aampling frequency long βamplea_new; ln » aamples_new; resize(aamplea_new) ,- in » eastpling_frequ«ncy; set_*ampling_frequency(sampling_frequency) ; // Read in the algnal in.ignored) ; in.read((char*lvalue,int(aizao (float) "aamplea) ) ; // Check that laat line aaya "End* in.ignored) ; in.getlinetbuf,BDFLEN) ; if! atrnαnplbuf, "End',3) ) cerr « "Warning: End of file corruptvn*; ) ♦undef BUFLEN ♦define OOTBITS 16 void Signal: :write_aifc( conat char* filename ) ( alport_buf_reaize( aamplea ); // Configure the output file AFfilesetup outaetup ■ AFnβwfilββetup() ; AFinitfilefm ( outaetup, AF_FILE_AIFFC ) ; APinitcompreaaion! outaetup, AF_DEFAOLT_TRACK, // AF_CCMPRESSION_AWARE_DEFAULT_LOSSLESS ) ; AF_COKPRESSION_NONE ) ; AFinitrate( outaetup, AF_DSFAϋLT_TRΛCK, aampling_frequency ) ; AFinitaampfmt! outaetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOHP, aizeof(aoundaample) *β ) ; AFinitchannela( outaetup, AF_DEFAOLT_TRACK, 1 ) ; // Write the data to the output file AFfllehandle outhandla « AFopenfilβ) filename, "V, outaetup ) ; for! long i ■ 0; i < βamplββ; i*+ ) alport sufd] « βoundβamplβ! valued] ♦ 0.5 ) ,- long framaswritten « AFwritβframes( outhandle, AF_DEFAULT_TRACK, alport_buf, aamplea ); lf( frameawritten Is eamplea ) cerr « "Warning: frameawritten * * « frameawritten « "; aamplea « • « aamplea NL; AFcloβafile( outhandle ); // Free βetup AFfreβfilβββtu ( outaetup ); ) void Signal: :read_aifc( conat char* filaname, int rightchannel ) ( // Open the input file and find out everything about it AFfilesetup insβtup * AFnewfilesetupO ; AFfilehsndle inhandle • AFopenfilβ) filename, "r", inββtup ); long inframecnt = AFgetframecnt ( inhandle, AF_DEFAULT_TRACK ) ,- long inchannela « AFgetchannels ( inhandle, AF_DEFAϋLT_TRACK ) ; long inaampcnt » inframecnt * inchannelβ; long inaampf t, insampwidth; AFgβtaampfmt( inhandle, AF_DEFAULT_TRACK, iinaampfmt, *inaaσpwidth) ; long inaampbytewidth > (inβampwidth ♦ 7) / 8; long inbytea • inaa pcnt * inaampbytewidth; int inrate = int(AFgetratβ( inhandle, AF_DEFADLT_TRACK ) ♦ .5); iff inchannela l« 2 ) rightchannel « 0; // Read the data into a buffer βigned char* inbuf * new βignβd char (inbytea); long framββrβad • AFreadfra ea( inhandle, AF_DEFAOLT_TRACK, inbuf, inframecnt ); if( framββrβad Is inframecnt ) cerr « "Warning: framββrβad « ■ « framearead « *; inframecnt « ■ « inframecnt NL; // Copy the data to our own member variablea reaize! inframecnt ) ; βignβd char *p * inbuf ♦ rightchannel * inβampbytewidth; for( long i « 0; i < inframecnt; i*+ ) ( if! inaampbytewidth « 1 ) ! valued) « *p; ) elae if! inaampbytewidth <• 2 ) ( ahort* q * (short *) p; valued) = *q; ) elae if! inaampbytewidth <» 4 ) ( long* q * (long *) p; valued] « *q; ) elae cerr « 'Warning: inaampbytewith > 4Vn"; p ♦» inaampbytewidth * inchannela; ) aet_aampling_ requency( inrate ) ; // Free atuff delete inbuf; AFcloββfilβ! inhandle ); AFfreeflleaatupl insetup ); void Signal: :write_human( const char* filename ) ( ofstream out; out.open(filename) ; out « 'Signal* NL; out « aamplea NL; out « aampling.f equency NL; for( long i « 0; i < aamplea; im* ) out « valued) NL; out « 'End' NL; out « 'End 2' NL; ) ♦define BDFLEN 1000 void Signal: :read humβn( conat char* filaname ) t char buf[BDFLEN^2] ; ifβtream in; in.open(filena e) ,- // Check that first line aaya 'Signal" in.gβtlinβ(buf.BUFLEN) ; if( atrncmpfbuf, -Signal*, 6) ) cerr « "Warning: Not a Signal filβVn* // Read in number of samples, sampling frequency long samples_new; in » aamplea_new; rββizβ(βamplββ_nβw) i in » aampling_frequency; ββt_sampling_fraquency(aampling_frequency) ; // Read in the signal for! long i - 0; i < aamplea; i++ ) in » valued] ; // Check that laat line aaya 'End* in.ignore(l) ; in.getlinβ(buf.BUFLEN) ; if( atmcmplbuf, 'End",3) ) cerr « 'Warning: End of file corruptvn' ) tundef BDFLEN // // Teat main // ♦ifdef TEST int main! int argc, char** argv ) t cout.setf(ioa: lunitbu ); Signal arc; arc.reac_aifc(argv[l] ) ; Signal mix(src.get_aamplea() ) ; // mix.timedelaylarc O .S) ; arc. play! ) ; mix.play!); // mixl.add(srcl,0.95); // mixl.add(arc2); // Signal sinl, sin2; // sinl.create_eine(10, 40); // βin2.crβatβ_βine(8,660) ; // mix.crβatβ_zero(10) ; // mix.add(sinl); // mix.add(βin2,0.7,1); // x.record!20) ; // mixl.writeCmix-cohβn-intβrval.sig*) ; // ainl.playO; // x.read(*volce-123.aig*) ; // mix.play() ; // Teat of AGC // Signal aini; // ainl.create_alnβ<1.440) ; // ainl *= 100; // Signal ain2; // ain2.AGC(*ainl,0.1); // // ainl.write_human(*fool.sig*) ; // ain2.write_human('foo2.aig*) ; // Teat of read_aifc // Signal aig; // βig.rβad_aifc!argv[l] ) ; // βig.play! (argc >* 3) 7 atof(argv(2) ) : 1 ) ; // βig.wrlte_aifc(*foo.aifc'); return 0; ) ♦endif // Hodint -•-C++-'- SReviaion: 1.1 $ SDatei 1994/08/04 17:15:16 $ // Integera modulo baae ♦ifndef _Modint_h ♦define _ odint_h claaβ Modint ( privste: int 1; public: Hodin () t i • 0; ) Hodint(int J) ( i « J; ) Hodint(Hodint* J) ( i = J.i; ) -Hodint() () static int baae; public: friend Hodint* min(Hodint,Hodint) ; operator into ( return i; ) void operator ♦♦ () ( i f *+i >= baae ) i ■= 0; ) void operator -- ( ) ( if( --i < 0 ) i « baae-1; ) int operator - (Int); int operator - (Hodint); ); inline Hodint* min(Hodint 1, Hodint J) ( return! i.i < J.i ? i : J ); ) inline int Hodint::operator - (int J) ( J ' i - it while( j < 0 ) j — baae; return j; ) inline int Hodin ::operator - (Hodint j) ( int k « i - J.i; if( k < 0 ) k ♦- baae; return k; ) ♦endif // _Hodint_h // Hodint -'-C++-'- SReviaion: 1.1 $ SDate: 1994/08/04 17:15:16 $ ♦include 'Hodint. * int Hodint::baae * 1; // - - // Teat main // - ♦ifdef TEST ♦include 'myatream.h* main! int argc, char** argv ) ! cout « 'Hodint has no test ainVn" return 0; ) ♦endif // SS -'-C++-*- SReviaion: 12.1 $ SDate: 1994/08/04 17:16:01 $ // Abstract base class for accumulation of βtatistica for // sound-separation problems. ♦ifndaf _SS_h ♦define _SS_h claaa Signal; claaa RepnSS; claaa SS ( // Constructor, destructor public: SSI); -SS()ι virtual RepnSS* new_repn() «0; // Leaky integration public: void SetLeakl double ββampleβ » -1 ); protected: double nearly_one; double nearly_zero; ♦define ACCUM_LEAKILY(βx,x> ( \ ex *« nearly_one; V ex ♦« nearly_zero * (x) ; \ ) ♦define ADD_LEA ILY(ex,exold,x) ( \ ex ■ (βxold) • nearly_one ♦ (x) * nearly_zβro; V ) // Maintain running averagea public: virtual void ClearStataO "0; virtual void Sample! double* y ) «0; virtual void Sa pleNoStata( double* y ) «0; // Evaluate candidate aeparation parametera public: virtual double Evaluate! double** ) >0; // Step down gradient public: virtual void GoDownhill) double** aepcoeff. double amount ) *0; // Apply aeparation parametera public: virtual void Install! double** ) «0; virtual void FormOutput! float* ) «0; // // Otilltles comnon to many SS applicationa // public: // atatic void Setup! int argc, char** argv, // SS** SS, // Signal* ya. Signal* yb, // char** filel, char** file2, // double* lo. double* hi, // long* samps, double* freq, // int* delaya, int* nrβp ); ); ♦endif // _SS_h // SS -«-c*»-*- SReviaion: 12.1 S SDate: 1994/08/04 17:16:01 S ♦include *Signal.h* ♦include 'SS.h* ♦include * epnSS.h* ♦include <math.h> ♦include <stdlib.h> SS::SS!) ( Se eak))j ) SS:.-SS() () void SS: :Set eak) double eaamplea ) ( if! eeamplaa > 0 ) ( nearly.zero « -expml! -1.0 / eeamplaa ); nearly_one ■ 1.0 - nearly_zβro; ) elae ( // no leak desired nβarly_zero « 1; nearly_one * 1; ) ) // void SS::Setup) int argc, char** argv, // SS** SS, // Signal* ya, Signal* yb, // char** filel, char** filβ2, // double* lo, double* hi, // long* aamps, double* freq, // int* delaya, int* nrep ) // ( // for! int iarg « 1; iarg < argc; iarg** ) ( // if! argv[iarg][0) ■- '-' ) awitch! argv[iarg] [1] ) ( // caaa 'g' : delaya * 0; break; // caaa 'd'ι delaya * 1; break; // caaa 'f: delaya « 2; breek; // caaa 'r' : nrβp ■ atoϋargvdarg] ) ; break; // ) elae ( // iff I ilel ) filel = argv[iar ] ; // elaa if( I filβ2 ) file2 « argv(iarg1 ; // ) // ) // // // Read in aignala // ya.read_aifc( filel ); // if( file2 ) yb.rβad_aifc( filβ2 ); // elae yb.read_aifc( filel, 1 ) ; // aa pa • ya.gat_βamplae() ; // iff yb.gβt_aamplββ() < aampa ) aampa • yb.get_aamplea() ,- // freq « ya.get_aampling_frequency() ; // // // Figure out aampling frequency and window aize // tdefinβ WINDOW_TIME 0.01 // const long window_aampa * long! freq * WINDOW_TIME + 0.5 ); // // // Do SS-dependent stuff // switch! delaya ) { // SS * new SSGaina; // lo « 0; // hi « 1; // break; // caae 1: // SS = new SSDelays! 10 ); // lo = -2; hi > 2; RepnSS: i orce_upper_triangle • 1; RepnSS: :mutation_atyle « RepnSS: :MUTATE_ONE_DIMENSION; ((SSDelaya *)SS)->SβtAlpha! .9 ); break; caae 2: SS • new SSfir2Dβlaya( 10 ) ; lo » -2; hi ■ 2; RepnSS: :force_upper_triangle « 1; RepnSS: :mutation_atyle ■ RepnSS: :HUTATE_ONE_DIHENSION; ((SSDelaya )SS)->Set lpha) O.S ) ; break; ) SS->SetLeak( window.aampa ) ; RepnSS: :ββt_SS( SS ) ; RepnSS: :aat_bounda( lo, hi, lo, hi ); // SS2 -*-c**-*- SReviaion: 12.2 $ SDate: 1994/08/05 23:37:57 S // Abatract baae claas for accumulation of statistics for 2x2 // sound-separation problems. ♦ifndef _SS2_h ♦define _SS2_h claaa Signal; claaa RepnSS; ♦ii.clude *SS.h" claaa SS2 : public SS ( // Constructor, destructor public: SS2(); -SS2(); // Utilities common to many SS2 applications public: static void Setup( int argc, char** argv, SS** aa, RepnSS** repn, Signal* ya, Signal* yb, char** filel, char** file2, double* lo, double* hi, long* aampa, double* freq, int* delaya, int* croaaecho, int* nrep ) ; // Interface to deacendants public: virtual void Sample! double* y ); virtual void Sample2( double ya, double yb ) «0; virtual void Sa plβNoStata( double* y ); virtual void Sample2NoStats ( double ya, double yb ) «0; virtual double evaluate< double** ); virtual double Bval2( double a, double b ) «0; virtual void CoDownhill! double** aepcoeff, double amount ) ; virtual void GoDownhill ( double* a, double* b, double amount ) «0; virtual void Inβtall) double** aepcoeff ); virtual void Inatall ( double a, double b) «0; virtual void FormOutput! float* z ); virtual void FormOut2 ( float* za, float* zb) *0; ); ♦endif // _SS2_h // SS2 - « -c**- « - SReviaion: 12.2 S SDate: 1994/08/05 23:37:57 S ♦include "Signal. * ♦include *SS2.h* ♦include *SS2FIR.h* ♦include 'SS2Delβyβ.h* ♦include *SS2Gaina.h* // ♦include "SS2DβlGainβ.h* ♦include "RepnSS2.li" ♦include "RepnSSFIR2.h* // ♦include *RepnSS2DelGains.h* ♦include math.h> ♦include <βtdlib.h> SS2::SS2() () SS2::-SS2() () void SS2 iiSam le) double* y ) Sample2( y[0], yd) ) ; void SS2::SampleNoStata( double* y ) Sample2NoStata( y(0], yd) ); double SS2: :Evaluate( double** aepcoeff ) return Eval2( aepcoeff[0] [1] . aepcoeff[l] [0] ); void SS2: iGoDownhill ( double** aepcoeff, double amount ) GoDownhill2( aepcoeff(0] [1] , aepcoef [1] (0) , amount ); void SS2: :Inatall( double** aepcoeff ) Install2( sepcoeff[0] d) , ββpcoβ f(1) [0] ); void SS2: :For Output ( float* z ) Form0ut2( z[0], zd) ) ; void SS2::Setup( int argc, char** argv, SS** aa, RepnSS** repn. Signal* ya. Signal* yb, char** filel, char** filβ2, double* lo, double* hi, long* aampa, double* freq, int* delaya, int* croaaacho, int* nrep ) ( croaaacho « 0; for! int iarg > 1; iarg < argc; iarg** ) ( if( argv[iarg)[0) ■« • -' ) switch! argv[iarg] [1] ) ( caae 'x' : croaaacho * 1; break; caae 'g'ι delaya « 0; break; caae 'd': delaya = 1; break; caaa ' f : delaya * 2; break; // caae '4': delaya ■= 3; break; caaa 'r': nrep = atoϋargvdarg]); break; ) elaa ( iff Ifilel ) filel • argv[iarg] ; elae if! I file2 ) file2 « argvdarg); 1 // Read in aignala ya.read_aifc( filel ); if! filβ2 ) yb.rβad_aifc( file2 ) ; elae yb.read_aifc( filel, 1 ); samps * ya.get_samplea() ; if( yb.get_βamplβa() < aamps ) samps * yb.ge _samples() ; freq > ya.get_aampling_frequency() ; // Figure out aampling frequency and window aize ♦define WINDOW.TIKB 0.01 conat long window_aampa « long( freq * WINDOW_TIME + 0.5 ) ; // Do SS2-dependent stuff switch( delaya ) ( caae 0: aa * new SS2Galna; lo β 0; hi « 1; RepnSS2: :Initialize( aa, lo, hi ); Rβpn≤SΣ: :mutation_βtyle » RepnSS2 : :MUTATE_GRADIENT_RESTARTS; // RepnSS2: :mutation_atyle - RepnSS2: :MUTΛTE_CDBIC; break; caae 1: aa ■ new SS2Delaya ( 10, 10 ); lo » -2; hi « 2; RepnSS2::Initialize! ss, lo, hi ); RepnSS : :force_uppβr_trianglβ « 1; RepnSS2ιιmutation_atyle « RepnSS2: :HDTATE_ONE_DIHENSION; break; caae 2: aa « new SS2FIR! 0, 0 ); lo « -2; hi « 2; RepnSSFIR2::Initialize! 2, (SS2FIR*)aa, lo, hi ); RβpnSSFIR2::mutation_βtylβ > RepnSSFIR2: :HUTATE_GRADIENT_RESTARTS; break; // caae 3: // aa - new SS2DelGaina( 10, 10 ) ; // lo ■ hi ■ 0; // RepnSS2DelGaina::Initialize! !SS2DelGaina')aa, 0, -2, 1, 2 ); // break; ) repn « aa->new_repn() ; aa->SetLeak( window_sampa ); // SS2FIR -*-c**-*- SReviaion: 12.3 S SDate: 1994/08/05 23:37:00 S // Claaa for accumulation of atatiatica for aound aeparation baaed // on differential FIRs (aeparated omni mica plua echoea and reverb) ♦ifndef _SS2FIR_h ♦define _SS2FIR_h ♦include "SS2.h* ♦include "Hodint.h" class SS2FIR : public SS2 ( friend class Rβpn≤SFXR2; // Constructor, destructor publici SS2FIR! int T_head. int T_tail ) ; -SS2FIRO; virtual RepnSS* new_repn(); protected: int T_hβad, T_tail, T_tot; // int T2, T2_l; // precomputed quantitiea // Running averages public: virtual void ClearStata() ; virtual void Samplβ2 ( double, double ) ; virtual void Sample2NoStata( double, double ); private: Hodint tree; double *xbuf, *ybuf; // Signals in recent past double 'ex, *ey; // Decayed aignala [tine] double **exx, **eyy; // Autocorrelation [time] [relative offaatl double **exy, **eyx; // Croββ-corrβlation [time] [relative offaat) // Evaluate candidate aeparation parametera public: virtual double Eval2FIR( double*, double* ); private: double eu, ev; double nu er, f; int f_aign; double norm2_c; double* c; double denom; // Go down gradient a little bit public: void GoDownhillFIR2( double* fir_a, double* fir_b, double maxamount, double minamount. int maxcount ) ; privatel double *grad_a, *grad_b; // Apply aeparation parametera public: virtual void Inβtall2FIR( double*, double* ) ; virtual void FormOut2 ( float*, float* ); private: double *inatalled_a, *inatalled_b; // Naive aolution of binding problem private: double correlatβ_different_aolutionβ( double* al, double* bl, double* a2, double* b2, int u_vs_v_l, int u_vs_v_2 ) ; ); ♦ endif // _SS2FIIU> // SS2FIR -*- c **-*- SReviaion: 12.3 S SDate: 1994/08/05 23:37:00 S // Mica x, y // Outputa u « x - b y, v « y - a x // where a and b are convolving functions // F ■ <u v - <u> <v> ♦Include *SS2FIR.h' ♦Include *RβpnSSFIR2.h* ♦include <math.h> ♦include <atdlib.h> ♦include 'myatream.h' // db // - // ϋtilitiea // - — inline int min! int a, int b ) ( return (a < b) 7 a : b; ) inline int max! int a, int b ) ( return (a > b) 7 a : b; ) // // Conatructor, destructor // - - - — SS2FIR::SS2FIR( int T_hβad_, int T_tail_ ) ( Hodint: :baae = T_tot = (T_head = T_head_) ♦ (T_tail = T_tall_) ♦ 1; xbuf s new double (T_tot) ; ybuf * new double (T_totl; ex ■ new double [T_tot); ey « new double (T_tot) ; exx « new double* (T_tot); βyy m new double* [T_tot] ; exy « new double* [T_tot] ; βyx « new double* [T_tot] ; for( int t » 0; t < T_tot; t** ) ( exx(t) * new double [T_tot] ; eyy(t) « new double (T_tot) ; exy[t] * new double [T_tot)ι eyx[t) = new double (T_tot); ) inatalled_a • new double [T_tot]; inatalled_b • new double [T_tot]; grad_a « new double [T_tot] ; grad_b * new double (T_tot) ,- c » new double [T_tot « 2 - 1] ; ClearStata() ; ) SS2FIR: 1-SS2FIR!) ( delete ex; delete ey; for( int t « 0; t < T_tot; t++ ) ( delete exx[t] delete eyy[t) . delete βxy(t) , delete eyx[t] . ) delete βxx; delete eyy; delete exy; delete eyx; delete xbuf; delete ybuf; delete inatalled.a; delete installed_b; delete grad_a; delete grad_b; delete c; ) RepnSS* SS2FIR: :new_repn() ( return new RepnSSFIR2; ) // - // Running averages of signal products // // ♦define HODT(t) ( ( (t)+T_tot)%T_to ) void SS2FIR: :ClearStata() ( void SS2FIR::Sample2NoStata( double ya, double yb ) ( Hodint tprev ■ tree; ♦♦tree; // tree » HODT( tree ♦ 1 ) ; // Update x, y xbuf[tree] ■ ya; ybuf[tree] * yb; ) void SS2FIR: :Sample2( double ya, double yb ) ( Hodint tprev = tree; // tree « HODTI tree + 1 ); ♦♦tree; double* χ_ * ya; double* y_ • yb; // Update x, y xbuf(tree) ■ x_; ybuf (tree) * y_; // Dpdata ex, ey ADD_LEAKILY(ex[trec] ,ex[tprev] ,x_) ; ADD_LEAKILY(ey(trec] ,ey[tprev] ,y_) ; // A minor optimization... double* exxnow < exx(trec]; double* eyynow « eyy(trec); double* exynow « exy(tree]; double* eyxnow = eyx[tree]; double* exxprev « exx(tprev) ; double* eyyprev ■ βy ltprev); double* exyprev « exy[tprev] ; double* eyxprev « eyx[tprev] ; // Update exx, eyy, exy, eyx Hodint td * tree; fort int d « 0; d < T_tot; d** ) ! ΛDD_LEΛXILY<βxxnow[d] , exxprev (d) , χ_*xbuf (td) ) ; ADD_LEAKILY(eyynow(d] , eyyprβvtd] , _*ybuf [td] ) ; ADD_LEAI ILY(exynow(d] , exyprev[d] , χ_*ybuf [td] ) ; ADC_LEAKILY(eyxnow[d] . eyxprev [d] ,y_*xbuf [td] ) ; --td; // lf ( — d < 0 ) td = T_tot - 1 ; ) // // Evaluate candidate aeparation parametera // - - double SS2FIR: :Eval2FIR( double* eval_a, double* βval_b ) ( // Compute eu, ev Hodint tplay » tree - T_hβad; // int tplay ■ HODT(trec-T_hβad) ; eu • e [tplay]; βv » βy[tplay); Hodint t » trac; for! int d * 0; d < T T__ttoott;; dd**** ) { // Compute euv regiater double euv • exy[tplay) [0] ; for! d « 0; d < T_tot; d** ) ( Hodint td • tree - min(T_head,d) ; int dd > aba(T_head - d) ; euv ♦■ eval_a[d) * exxltd] [dd] ; euv ♦» eval_b[d] * eyy[td] [dd] ; ) ♦if 0 for! d « 0; d < T_tot; d** ) for! int d2 « 0; d2 < T_tot; d2+* ) * exy[HODT(tree-d))[d2-d]; • βyx[H0DT(trβc-d2)] [d-d2] j exy(trec-d) [d2-d] ; eyx[trβc-d2][d-d2); // Compute c = convolve(a,b) 0; ic <» 2 * T_tot - 2; ic** ) ( max! 0. ic-(T_tot-l) ) ; int J_hi « mini T_tot-l, ic ); for! int J = J_lo; J <« J_hi; J*+ ) ( c[ic] ♦• βval_a[J] * βval_b[ic-j) ; // cout « J TB « eval_a[J] TB « eval_b[J) NL; ) c[2*T_head) -« 1; norm2_c ♦« c[ic] * c(ic); ) // // Compute deno // norm2_a « 0; // norm2_b x 0; // for( d * 0; d < T_tot; d+* ) ( // norm2_a ♦■ βval_a[d] * eval_a(d); // norm2_b ♦» eval_b[d] • βval_b[d); // // cout « d TB « eval_a[d] TB « eval_b[d] NL; // ) // Return a function of euv double invdenom * (norm2_c « 0) 7 0 : l./βqrt (norm2_c) ; double f « numer * invdenom; // cout « numer TB « norm2_c TB « invdenom TB « F NL; ♦define KIN_F le-20 if! F < HIN_F ) F « HIN_F; return log(F) ; ) // - // Go downhill along gradient // Reference: Lab notebook, 7/13/94 and 8/3/94 // void SS2FIR: :GoDownhillFIR2 ( dovible* fir_a, double* fir_b, double maxamount, double minamount, int axcount ) ( double before « Eval2FIR( fir_a, fir_b ) ; // precompute aome quantitiea double norm2 ■ 0; for! int i « 0; i < T_tot; i*+ ) 1 // (da.db) will become the gradient of f' Hodint tl « tree - i; Hodint tm • tree - min(T_hβad, i) ; int dd » aba(T_head - i) ; regiater double da • exx(tm) [dd] ; register double db • eyy(tm) [dd] ; for( int d > 0; d < i; d+* ) ( Hodint td ■ tree - d; da ♦« fir_b[d] * eyx[td][i-d); db ♦« fir_a(d] « βxyltd] [i-d] ; ) for! d • i; d < T_tot; d+* ) 1 da ♦« fir_b[d] * exytti)[d-i]; db ♦« fir_a[d) * eyx(ti] [d-ij ; ) // (da.db) ia now dteuv) /dtai.bi) da -* eu « ex(tl); db -» ev * ey[ti] ; // (da.db) ia now d(f)/dtai.bi) da ** norm2_c; db *« norm2_c; regiater double aumca -> 0, sumcb • 0; for( int iaum • 0; iβu < T_tot; isum** ) t aumca ♦« cdaum * d] * fir_adaum] ; βumcb ♦ * cdaum * d) * fir_b[iaum) ; ) da -> numer * aumcb; db -a numer * aumca; // da *■ denom « a * b; // db *« denom • a * b; // da -« norm2_b * fir_a[d] * numer; // db -« norm2_a * fir_b[d) * numer; // (da.db) is now d(f')/d(ai,bl) // (da.db) ia now proportional to f_βign(f'J * d(f (/dtai.bi) grad_a[i] « da; grad_ d) * db; norm2 ♦« da * da ♦ db * db; ) if( noπa2 «« 0 ) return; double acale » 1.0 / aqrt(norm2); for! i « 0; i < T_tot; i** ) 1 grad_ad) ** acale; grad_b[i] •= acale; ) double after ■ before; for! double amount « maxamount; faba)amount) > minamount; amount *= 0.1) ( for! int aign * -1; aign <• 1; aign += 2 ) ( while (1) ( if! maxcoun — <* 0 ) break; for! i * 0; i < T_tot; i** ) ( fir_a(i) ♦« amount • sign * grad_.a[i]; fir_bd) ♦« amount * aign * grβd_bd); ) // cout « amount * sign TB « after NL; double eval2 > Eval2FIR( fir.a, fir_b ); ift eval2 > after ) ( for! i * 0; i < T_tot; i** 1 ( fir_a[i] — amount * aign * grad_a[i]; fir_b[i) -« amount * aign * grad_b(i); ) break; ) elae after » eval2; ) if) maxcount <= 0 ) break; ) if! maxcount <■= 0 ) break; ) // cout << after - before TB « before TB << after NL; ) //- - - — // Apply aaparation parametera // - void SS2FIR: :Install2FIR( double* a, double* b for! int d = 0 ; d < T_tot; ) ( inatalled_a [d] = a [d] ; installed_b[d] - b[d) ; ) void SS2FIR: :FormOut2( float* za, float* zb ) ( // Compute (za, zb) i.e., colored outputs Hodint tplay = tree T_head; za s xbuf( tplay ] ; zb = ybu [ tplay ] ; tplay « tree; for( int d * 0; d < T_tot; d** ) ( za += installed_b[d] * * ybuf[tplay]; zb += installed_a[d] • * xbuf(tplay); —tplay; // if( —tplay < 0 ) tplay « T_tot - ) // // Naive solution of binding problem // double SS2FIR: :correlate_different_solutiona( double* al, double* bl, double* a2, double* b2, int u_vβ_v_l, int u_vβ_v 2 ) ! // // prototypically doing <D V> - <U> <V> // double* X = u_vs_v_l 7 ex i ey; // double* Y = u_vβ_v_2 7 ey : ex; // double* A « u_vβ_v_l 7 al * al; a2 » a2; return 0; ) // // Test main // - ♦ifdef TEST ♦include "m stream.h' main! int argc, char** argv ) ( cout « 'SS2FIR haa no teat main\n* return 0,- ) ♦endif // SS2Delaya -*-c**-*- SReviaion: 12.1 S SDate: 1994/08/04 17:16:01 $ // Claaa for accumulation of atatiatica for 2x2 aound aeparation baaed // on differential delaya (aeparated omni mica) ♦include -SS2FIR.h" claaa SS2Delaya : public SS2FIR [ // Constructor, destructor public: SS2Dβlays( int T.head. int T.tail ); -SS2Delaya() ; virtual RepnSS* nβw_repn() ; // Evaluate candidate aeparation parametera public: virtual double Bval2 ( double tau_a, double tau_b ); private: void costpute_delay_convolution( double*, double tau, double deaired_aum *1 ) ; double *βinc_a, *βinc_b; // Sine functions // Apply separation parametera public: virtual void Inatall2 ( double, double ) ; ); // SS2Delaya -*- c **-*- SReviaion: 12.1 S SDate: 1994/08/04 17:16:01 $ ♦include *SS2Delaya.h' ♦Include *RepnSS2.h* ♦include <math.h> ♦include <stdlib.h> // ♦include 'mystream.h* // db // - — - // Utilitiea // - - atatic double sine! double x ] ( lf( x >• 0 ) return 1; return sin(x) / x; ) // — // Constructor, destructor // SS2Delaya::SS2Delaya( int T_hβad, int T.tail ) : SS2FIR) T.head. T_tail ) ( ainc_a • new double (T_tot); βinc_b M new double [T_tot],- ) SS2Delaya: :-SS2Delays() ( delete ainc_a; delete βinc_b; ) RepnSS* SS2Delays::new_repn() ( return new RepnSS2; ) / - // Evaluate candidate aeparation parametera // - double SS2Delaya: :Eval ( double tau_a, double tau_b ) ( // Compute ainc functions compute_delay_convolution( ainc_a, tau_a, -1 ); cσmputβ_dβlay_convolution( ainc_b, tau_b, -1 ); return Eval2FIR( ainc_a, ainc_b ); ) void SS2Delaya: :compute_delay_convolution( double* a, double tau, double deaired_aum ) ( double sum « 0; for( int d « 0; d < T_tot> d+* ) aum ♦• (a[d) « βinc( H_PI * (d - T_tail - tau) )); double acale * deaired_aum / aum; for! d » 0; d < T_tot; d+* ) a[d] *■ acale; ) // // Apply aeparation parametera // void SS2Delayβ: :Install2 I double tau_a, double tau_b ) t compute_delay_convolution( ainc_a, tau_a, -1 ) ; compute_delay_convolution( slnc_b, tau_b, -1 ); SS2FIR::Install2FIR( βinc_a, ainc.b ); ) // // Test main //— ♦ifdef TEST ♦include "myatream.h* main( int argc, char" argv ) ( cout « *SS2Delays has no test main\n*; return 0; ) ♦endif // Representation -*-c**-*- SReviaion: 12.2 $ SDate: 1994/10/25 17:05:04 $ // Abatract baae class for a solution-space representation to be used // with stochastic optimization. It ia expected that problem-instance // variables will be static, whereaa aolution-instance variables will // not be. ♦ifndef _Representation_h ♦define _Repreaentation_h ♦include *Hath.h* claaa Repreaentatlon : public Hath I // Cone true tor, dee true tor public: Repreaentatlon!) ; -Repreaentatlon() ; // Virtual methods public: virtual void Randomized «0; virtual void Hutate) int exploit =0 ) =0; virtual void UndoHutation() «0; virtual double Evaluate!) =0; virtual Repreaentatlon* Clone!) «0; // Juat alloca; doesn't copy contenta virtual void Copy! conat Representation* ) »0; // Just copies; doesn't new virtual const char* to_βtring() «0; virtual void froπv_atring( char* ) «0; ); ♦endif // _Reprβββntation_h // Repreeenta ion -*-c**- « - SReviaion: 12.2 S SDate: 1994/10/25 17:05:04 S ♦include "Repreaentation.h* // - - // Repreaentatlon itaelf // - - - - Repreaentatlon: Representation() ! ) Representation: :-Repreaentatlon! ) ! ) // RepnSS -*-c**-*- SRβviβion: 12.2 S SDate: 1994/10/25 17:04:54 $ // Abatract baae claaa for representations of 2x2 aound aeparation. ♦ifndef _RepnSS_h ♦define _RβpnSS_h ♦include 'Repreβentation.h* claaa SS; claaa RepnSS : public Representation ( // Constructor, destructor public: RepnSS() ; -RepnSS() ; etatic void Initialize! int nmic, SS*, double lo, double hi ); protected: etatic SS •••; static double lo, hi; atatic double range; atatic int nmic; atatic char* b t; // Candidate aeparation parametera public: double** aepcoeff; private: double** aepcoeff_old; // Kutation styles (which affect expectation) public: βnum ( HUTATE_CUBIC, HOTATE_ONE_DIHENSION, MOTATE.GRADIENT, KUTATE_GRADIENT_RESTARTS ) ; atatic int mutatlon_atyle; // Virtual methods public: virtual void Randomize() ; virtual void Hutate( int exploit «0 ) ; virtual void SaveForUndo() ; virtual void Undo)); virtual double Evaluate!); virtual Repreaentatlon* Clone!); // Juat alloca; doesn't copy contents virtual void Copy! const Representation* ); // Juat copiea; doean't new virtual conat char* to_etring!); virtual void fro _βtring( char* ); virtual void Follow) RepnSS*, double leak ) ; // Form outputa given current aeparation parametera public: virtual void Install)); // virtual void PormOutputl float* ) ; ); ♦endif // _RepnSS_h // RepnSS -*-c*—*- SReviaion: 12.2 $ SDate: 1994/10/25 17:04:46 $ ♦include 'RepnSS. " ♦include *SS.h- ♦include 'myatream.h* ♦include <math.h> ♦include <βtdlib.h> ♦include <string.h> ♦define BUFLEN 1000 SS 'RepnSSι:sβ • 0; int RepnSS: :nmic • 0; double RepnSS: :lo « 0; double RepnSS: :hi • 0; double RepnSS: :range « 0,- char* RepnSS: :buf » 0; int RepnSS: :mutation_βtyle * HUTATE_CDBIC; ♦define ALL.IMIC for! int i ic « 0; imic < nmic; irnic** ) ♦define ALL_IMIC_PAIRS \ ALL_IMIC for( int imic2 « 0; imic2 < nmic; imic2*+ ) \ lf( imic2 I* imic ) ♦define SEPCOEFF βepcoe f(imic) (imic2) ♦define SEPCOEFF_OLD βepcoeff_old[imic] dmic2) RepnSS: :RepnSS() ( sepcoeff « new double* [nmic]; βepcoβff_old » new double* [nmic]; ALL_MIC t sepcoeff(imic) = new double [nmic]; sepcoeff_olddmic] = new double [nmic] ; ) ) RepnSS: i-RepnSS() ( ALL_DUC [ delete sepcoeff[imic] ; delete sepcoeff_old[imic] ; ) delete sepcoeff; delete βepcoeff_old; ) void RepnSS: :Initialize! int nmic_, SS* as_, double lo_, double hi_ I ( if! nmic l> 0 ) exit(l); nmic « nmic_; ββ ■ ss_; lo » lo_; hi ' hi_; range • hi - lo; buf « new char [BDFLEN*2]; ) void RepnSS: :Randomize() ( ALL_IHIC_PAIRS SEPCOEFF = random_double( lo, hi ) ; ) void RepnS : :Hutate(int) // perturb switch! mutation_style ) ( case HDTATE_CUBIC: ( ALL_IKIC_PAIRS ( register double r - random_double)-l, 1) ; SEPCOEFF ♦= r*r*r * range; ) ) break; case HUTATE_ONE_DIMENSIONι ( int imic ■ random_int(0,nmic-l) ; int imic2 - random_int(l,nmic-l) ; if! imic2 *• imic ) imic2 « 0; ift random_char(0,l) ) ( regiater double r « rando _double(-l, 1) ; SEPCOEFF ♦= r*r*r * range; ) elae SEPCOEFF * random_double(lo.hi) ; ) break; case HUTATE_GRADIEN : ( double amount « 0.1 * range * exp(random_double(-3,0) ) ; // random_doublβ(0, (hi-lo)*0.01) ; ββ->GoDownhill ( aepcoeff, amount ) ; ) break; case MUTATE_GRADIENT_RESTARTS: if( random_int(0,9) < 1 ) ( ALL_IMIC_PAIRS ( regiater double r ■ random_double(-l, 1) ,- SEPCOEFF ♦« r*r*r * range; ) ) elae ( double amount = 0.1 * range * exp(random_double (-3, 0) ) ; // random_doublβ(0, (hi-lo) *0.01) ; βa->GoDownhill ( sepcoeff, amount ) ; ) break; ALL_IMIC_PAIRS ( // wrap once if( SEPCOEFF < lo ) SEPCOEFF ♦= range; iff SEPCOEFF > hi ) SEPCOEFF -= range; // confine ift SEPCOEFF < lo ) SEPCOEFF * lo; ift SEPCOEFF > hi ) SEPCOEFF - hi; void RepnSS: iSaveForUndo() ( ALL_IMIC_PAIRS SEPCOEFF_OLD = SEPCOEFF; ) void RepnSS: :Undo() i ALL_IHIC_PAIRS SEPCOEFF = SEPCOEFF.OLD; i double RepnSS: :Evaluate() ( return aa->Evaluate(aepcoeff) ; ) // void RepnSS::FormOutput ( float* z ) // ( // ss->FormOutput(z) ; // ) Representation* RepnSS: :Cloned ( return new RepnSS; ) void RepnSS::Copy( const Representation* that. ) ( RepnSS* that * (RepnSS*) that.; ALL_IMIC_PAIRS SEPCOEFF « that->SEPCOEFF; 1 const char* RepnSS: :to.strin () ! •buf « '\0'; ALL_IMIC_PAIRS atrcat! buf, form(*%lf *, SEPCOEFF) ) ; buf(strlen(buf)-l] - '\0'; return buf; ) void RepnSS: :from_string( char* ) ( ) void RepnSS: :Follow! RepnSS* target, double leak ) ( ALL_IMIC_PAIRS SEPCOEFF « SEPCOEFF * (1-lβak) ♦ targβt->SEPCOEFF * leak; ) void RepnSS: linetall() I sβ->Install(aepcoeff) ; ) // RβpnSS2 -*-c**-*- SReviaion: 12.1 S SDate: 1994/08/04 18:47:36 S // Abatract baae class for repreaentations of 2x2 sound separation. ♦ifndef _RepnSS2_h ♦define _RepnSS2_h ♦include • epnSS.h" claaa SS2; claaa RβpnSS2 : public RepnSS ( // Constructor, destructor public: RβpnSS2() ; -RepnSS2 !) ; atatic void Initialize! SS*, double lo, double hi ); // atatic void aet_SS2 ( SS2* ); // atatic void sat_bounds( double alo, double ahi, // double bio, double bhi ) ; atatic int force.upper.triangle; private: // atatic SS2 *aa2; // atatic double alo, ahi, bio, bhi; // atatic double arange, brange; // Candidate aeparation parametera // public: // double a, b; // private: // double a.old, b.old; // // Mutation atylea (which affect expectation) // public: // enum ( HDTATE.CDBIC, HUTATE.ONE.DIKENSION ); // atatic int mutation_atyle; // Virtual methoda public: // virtual void Randomized; // virtual void Mutate!) ; // virtual void SavePorUndo() ; // virtual void Undo!); // virtual double Evaluate!); // virtual Repreaentatlon* Clone!); // Just alloca; doesn't copy contents // virtual void Copy! const Representation* ) ; // Just copies; doesn't new virtual const char* to_βtring( ) ; // virtual void from_βtring( char* ); // virtual void Follow) RepnSS*, double leak ); // Interface to RepnSS private: // atatic double** acoeff; atatic float fval[2); public: // double Eva12 ( double a, double b ); void FormOut2( float* za, float* zb ); // Form outputa given current eeparation parameters // private: // float fval[21; // public: // void Install!); // void FormOut2( float*, float* ) ; ); ♦endif // _RepnSS2_h // RepnSS2 -•- c **-*- SReviaion: 12.1 S SDate: 1994/0B/04 18:47:36 S ♦include *RepnSS2.h" ♦include *SS2.h* ♦include "myβtream.h* int RepnSS : :forcβ.upper.triangle « 0; ♦define FORCE.DPPER ^ TRIANGLE \ if! force.upper.triangle ** a+b < 0 ) \ ( double awap > -a; a > -b; b « awap; ) // SS2 *RepnSS2::as2 « 0; // double RepnSS2::alo « 0; // double RepnSS2::ahi ■ 0; // double ReρnSS2::blo « 0; // double RβpnSS2ι:bhi ■ 0; // double RepnSS : :arange; // double RepnSS2: ibrangβ; // int RepnSS2: imutation.atyle « MUTATE.CDBIC; RepnSS2: :RepnSS () ( ) RepnSS2: :-RepnSS () ( ) // double** RepnSS2: :acoeff ■ 0; float RepnSS2::fval[2); void RepnSS2: :Initialize! SS* ss., double lo_, double hi. ) ( RepnSS: initialize! 2, βs_, lo_, hi. ) ; // scoeff ' new double* (2); // scoeff[0] « new double [2]; // scoeff[1] = new double [2]; ) // void RepnSS2: :βet_SS2 ( SS2* aβ2_ ) ( ss2 r. ss2_; ) // void RepnSS2: :ββt_boundβ( double alo_, double ahi_, double blo_, double bhi_ ) // void RepnSS2: :Randomize() // ( // a » random.double( alo, ahi ); // b « random.double( bio, bhi ); // FORCE_UPPER_TRIANGLE; // ) // void RepnSS2: :Mutate(int) // t // // perturb // switch) utation.Btyle ) ( // caae HUTATE.CDBIC: // regiater double ra • random_double(-l,l) ; // regiater double rb = random.double(-1, 1) ; // double RepnSS2: :Evaluate!) // ( // return ss2->Evaluate(a,b) ; // ) // // void RepnSS2::InstallI) // ( // ss2->Install( a, b ); // ) // // double RepnSS2: :Eval2 ( double a, double b ) // ( // scoeff[0] [1] • a; // βcoeffdHO] ■ b; // return RepnSS: :Evaluate(acoeff) ; // ) // void RepnSS2: :FormOut2( float* za, float* b ) // ( // RepnSS: :FormOutput(fva1) ; // za * fval[0] ; // zb « fvaldl; // ) // Representation* RepnSS2 :;Clone() // ( // return new RepnSS2; void RepnSS2: :Copy( const Representation* that. ) ( RepnSS2* that = (RepnSS2>) that.; a » that->a; b = that->b; conat char* RepnSS2: :to_atring() ( return form! *%lf %lf, sepcoeff[0] [1] , sepcoeff[1] [0] ); ) // void RepnSS2: :from_string( char* I // ( // ) // void RepnSS2: :Follow! RepnSS* target., double leak ) // ( // RepnSS2* target = (RepnSS2*) target.; // a » a * (1-leak) + targe ->a * leak; // b « b * (1-leak) ♦ target->b * leak; // ) // Searcher -*-c**-*- SReviaion: 12.1 S SDate: 1994/10/25 17:05:37 $ // Abatract baae class for a stochastic search engine. ♦ifndef .Sβarcher.h ♦define .Searchβr.h ♦include 'Repreaentatlon.h* claaa Searcher : public Hath ( // Constructor, destructor public: Searcher() ; -Searchar() ; // Virtual methods public: virtual void Initialized »0; virtual void Iterate! ahort niter =1 ) =0; virtual Repreaentatlon* get.best!) *0; virtual double get.best.βcorβ( ) «0; ); ♦endif // .Searcher.h // Searcher -*-c**-*- SReviaion: 12.1 S SDate: 1994/10/25 17:05:37 S ♦include *Searcher.h" Searcher: :Searcher0 ! ) Searcher: :-Searcher() ( ) void Searcher::Initialize!) {) void Searcher: :Iterate! short ) () Repreeentation* Searcher: : et_beβt ( ) ( return 0; ) double Searcher: :gβt_beβt_βcorβ() ( return 0; ) // SrchSS -*-c**-*- SReviaion: 12.0 S SDate: 1994/08/04 00:23:25 S // Abetract baae claas for an adaptive atochaatic aearch engine for // aound aeparation ♦ifndβf _SrchSS_h ♦define _SrchSS_h ♦include 'Searcher.h* claaa SrchSS : public Saarcher ( // Constructor, destructor public: SrchSS!) ; -SrchSS() ; // Virtual methods public: virtual void Initialized >0; virtual void Iterate! ahort niter >1 ) *0; virtual Repreaentatlon* get.beat!) =0; virtual double gβt.best.βcore( ) *0; // Some popular random-number generatora protected: atatic ahort random_βhort( ahort lo, ahort hi ) ; atatic double random.fraction() ; ); ♦endif // .SrchSS.h // SrchSS -*-c**-*- SRevision: 12.0 $ SDate: 1994/08/04 00:23:25 $ ♦include ■ SrchSS. " SrchSS::SrchSS() () SrchSS: :-SrchSS() ( ) -70- // SrchSShc - • - e **-*- SRβviβion: 12.1 S SDate: 1994/10/25 18:02:25 S // Hill climber for aound aeparation ♦lfndef .SrchSShc.h ♦define .SrchSShc.h ♦include 'SrchSS. * claaa RepnSSi claaa SrchSSpop; claas SrchSShc : public SrchSS ( // Conatructor. destructor public: SrchSShc! RepnSS* repn ); -SrchSShc() ; // State private: RepnSS* he; double lateat.hc.acore; // Attached population (optionally used for getting parenta) public; SrchSSpop* pop; int maxrank; double rank_factor; // Virtual methods public: virtual void Initialized; virtual void Iterate! ahort niter *1 ) ; virtual Repreeentation* get.bβatd; virtual double get.best.acora() ; ); ♦endif // .SrchSShc.h // SrchSShc -*-c**-*- SRevision: 12.1 $ SDate: 1994/10/25 18:02:25 $ ♦include 'SrchSShc.h* ♦include • SrchSSpop.h" ♦include *RepnSS.h* ♦include 'myatrea .h' // db SrchSShc: :SrchSShc( RepnSS* repn ) t he « repn; pop ■ 0; maxrank « 0; rank_factor « 0.8; Initialized; ) SrchSShc: :-SrchSShc{) ( delete he; ) void SrchSShc: tlnitialize!) ( hc->Randomize() ; lateat.hc.acore « hc->Evaluate() ; ) void SrchSShc: :Iterate( ahort niter ) ( int exploit ■ 0; while) niter-- > 0 ) f double oldLacore » hc->Evaluatβ() ; hc->SaveForUndo() ; if! pop ) hc->Copy( pop->get_aomeon6_good( maxrank, rank.factor ) ); hoHutate( exploit ) ; exploit > 1; double new.acore * hc->Evaluate() ; if! new.acore > old_acore ) ( hc->Undo() ; latββt.hc.βcore = old_acore; ) alae { latββt.hc.βcore « new.acore; ) ) Repreeentation* SrchSShc: iget.beat( ) return he; double SrchSShc: :gβt_best_βcore( ) return lateat.hc.acore; // // Teet main // ♦ifdef TEST ♦define DELAYS 0 ♦if DELAYS ♦include *SS2Delaya.h* ♦else ♦include 'SS2Gaina.h* ♦endif ♦include 'myatream.h* ♦Include *InventorSS .h* ♦include "InventorWindow.h" ♦include *RepnSS2.h* ♦include 'Signal.h' atatic JrchSShc* arch • 0; void aearcher( long ) ! arch->Itβrate() ; ) main! int argc, char** argv ) ( cout.aetff ioβiiunitbuf ); if) argc l« 3 ) ( cerr « *Usage: ■ « argv(O) « " sigl sig2\n*; return 1; ) Signal ya, yb; ya.rβad_aifc( argv[l] ); yb.rβad_aifc( argv(2] ); // Do SS2-dependent atuff ♦if DELAYS SS2Dβlayβ βs2(10); double lo « -2; double hi * 2; ♦elae SS2Gaina as2; double lo * 0; double hi ■= 1; ♦endif // Start up a new aearcher ♦define WINDOW.TIME 0.05 «s2.SetLeak) ya.get_aampling_frequency() * WINDOW.TIME ); RepnSS2: :aet_SS2( *as2 ); RepnSS2 : :βet_bounds( lo, hi, lo, hi ) ; RepnSS2* he « new RepnSS2 () ; βrch * new SrchSShc( he ) ; // Start tha graphics ♦define MARJCER.DIM 0.01 ♦define MARXER^ALT 0.001 InventorSS2 invaa2( *aa2, lo, hi, 10, lo, hi, 20 ) ,- invaa2.allocatβ_squareaeta( 1 ); invsa2.regiater_squareaet ( 0, 1, the. HARKER.DIM. HARKER.ALT, 0.1. 1, 0.1, SoKeyboardEvent: :H ) ; // Runl ♦if DELAYS invaa2.max_catehup • 100; ♦endif invaa2.Run! *ya, *yb, aearcher, 100, new InventorWindow('SS2') ), return 0; ) ♦endif // SrchSSpop -*-c**-*- SReviaion: 12.1 S SDate: 1994/08/05 23:40:37 $ // Hypotheβiβ population for sound aeparation ♦lfndaf .SrchSSpop.h ♦define .SrchSSpop.h ♦include 'SrchSS.h' claaa RepnSS; claaa SrchSSpop : public SrchSS ( // Constructor, destructor public: SrchSSpop( RepnSS* repn, int npop, SrchSS* suggeβter ) ; -SrchSSpop() ; private: SrchSS* auggeater; // Parametera public: double min_iterations_to_maχ_aaaetβ; double maχ_income_diff.per.itera ion; int iterations_per_suggestion; int auggeationa_per_sample; double replacemen .threshold; // State private: RepnSS* follower; int npop; int ipop_median_incαme; int ipop_median_aaβetβ; double inv.npop; RepnSS** pop; double* eval; double* income; double* aaeeta; ahort* income.invrank; ahort* aaseta.invrank; double* eolorfrac; public: RepnSS** get_pop<) ( return pop; ) double* get.colorfracd ( return eolorfrac; ) // Hoatly virtual... public: virtual void Initialized; virtual void Iterate! ahort niter *1 ); virtual Repreaentatlon* get.best( ) ; virtual double get.beat.acore( ) ; virtual Repreeentation* get.aomeone.good! int maxrank, double rank.factor ) ; RepnSS* get.follower() ( return follower; ) private: int richeat; double richeat.acore; // Qβort aupport private: atatic int invrank_decreaaing( conat void*, const void* ) ; static ahort* qaort.invrank; static double* qsort.valua; ); ♦endif / / .SrchSSpop.h -76- // SrchSSpop -*-c**-*- SReviaion: 12.1 S SDate: 1994/08/05 23:40:37 S ♦include 'SrchSSpop.h* ♦include 'RepnSS2.h* ♦Include <Inventor/Xt/viβwβrβ/SoXtExa inerViewer.h> ♦include <math.h> ♦include <atdlib.h> ♦include 'myβtream.h' // db SrchSSpop: :SrchSSpop( RepnSS* repn, int npop., SrchSS* a. ) ( βuggester « e_; follower * repn; npop ■ npop.; lpop_median_income « 5; ipop_mβdian_aβββtβ > npop / 2; inv.npop • 1. / npop; pop • new RepnSS* (npop); pop[0] « repn; fort βhort i « 0; i < npop; i** ) popd) * (RepnSS*) rβpn->Clone() ; eval * new double [npop] ; income ■ new double [npop]; aaaatβ » new double [npop] ; inco e.invrank * new ahort (npop) ; aaaeta.invrank ■ new ahort [npop] ; eolorfrac • new double [npop) ; forf i * 0; i < npop; i** ) income.invrank[1] • aaaeta.invrank!i] « i; // default valuea min_iterationa_to_m*x_aaaeta « 10; max_incσmβ_dif _pβr_itβration a 10; lteratione_per_βuggaation ■ 10; auggestiona_per_βample • 1; replacement.threahold * -1; Initialized; SrchSSpop: :-SrchSSpop() ( for! int i * 0; i < npop; i** ) delete pop(i); delete pop; delete eval; delete income; delete aaaeta; delete income.invrank; delete aaaeta.invrank; delete eolorfrac; ) void SrchSSpop: initialized ( rlcheat • -1; double rlcheat.aeaetβ • 0; for! int i » 0; i < npop; i** ) ( pop(i) ->Randomize( ) ,- ♦if 0 aaseted) = -pop[i)->Evβluate( ) ; 3 -77- if! richest < 0 || aasetsd) > richest.asaeta ) [ richest • i; richeat.aaaets » aβaeta d) ; ♦ elβe aasets d] « 0; richest * 0; richest.aaaeta * 0; ♦endi ) f ollower->Randomize ( ) ; ) ♦define MAX_ΛSSETS (min.iterationβ.to.max.asβets * max.income.dif f_ er_iteration) ♦define INVJΪAX kSSETS (1. / MAX VSSETS) ahort* SrchSSpop : ; aort.invrank * 0; double* S chSSpop : : sort.value * 0; int SrchSSpop: :invrank_dβcreasing( const void* one., const void* two.) ( short one ■ * (short* ) one.; short two « * (short*)two.; if! qsort.valuelone) > qsort.value[two] ) return -1; if( qsort.value[one) < qsort.value(two) ) return 1; return 0; void SrchSSpop: :Iterate! βhort ) ( // Evaluate population and compute gross income for! int ip = 0; ip < npop; ip** ) ( evaldp] • pop(ip) ->Evaluatβ() ; incomedp] * -evaldp]; ) // // Find median income // qaort.invrank » income.invrank; // qsort.value « income; // qsort! qsort.invrank, npop, sizeof(short) , SrchSSpop::invrank.decreasing ),- // double median. ncome « income(income.invran [lpop.median.inco e]] ; // // Compute income and mean income // double mean_income • 0; // for( int ip « 0; ip < npop; ip** ) ( // eval dp) s popdp] ->Evaluate( ) ; // income [ip] « -eval dp J ; // mean.income *« income dp) ; // ) // mean.income •« inv.npop; // Pay income for( ip » 0; ip < npop; ip** ) { // income [ip] -> median. income i // lf ( income dp) < -maχ_incαme_diff_per_iteration ) // income (ip) * -maχ_income_di f .per.itβration; // if ( income dp) > max_income_dif f jper.iteration ) // income p] « maχ_income_dif f .per.iteration; aaaetadp] ♦» income (ip) ι ) // Rank asseta qsort.invrank « aaaeta.invrank; qsort.value « aaaetβ; qsort ( qsort.invrank, npop, sizeof (ahort) , SrchSSpop: :invrank.decreasing ),- // double median.asaeta * as ββ tβ(a β βets_ιnvrank(ipop_median_assβts) 1 ; // for) int idb = 0; idb < npop; idb** ) // cout « idb TB // « income[income.invrank[idb) ) TB // « aaaete[aaβata_invrank(idb)] TB // « eval(aaaeta.invrank!idb] ] NL; // cout NL; // // Compute mean aaβetβ // double mean.aaseta * 0; // for) ip * 0; ip < npop; ip** ) mean.aasets ♦* assetsdp); // mβan.aaββtβ *« inv.npop; // Hake richest have MAX.ASSETS richest = assets_invrank[ 0 ]; double richeat.aaaets ■= aaaeta[ richest ] ; for( ip « 0; ip < npop; ip** ) ( aaaetadp) *« MAX_^SSETS - richeat.aβsets; ) richest.aasetβ « MAX^SSETS; // Hake aβsets have zero median, and apply limit; find richest and poorest richest.assets * 0 ; richeβt * -1 ; for! lp * 0; ip < npop; ip** ) ( aaaeta dp) -» median.aaaeta ; if ! aaβetβ dp] > HAX_ΛSSETS ) aaaeta (ip) e MAX.ASSETS; if ! aaaeta dp] < -MAX.ASSETS ) aaaets (ip) = -MAX kSSETS; if ( richest < 0 | | aβββtβdp) > richeat.assets ) [ richest.assets ■ assets dp) ; richest - ip; ) // Solicit suggeβtione double old.βug.score • 0; for! int is i 0; is < suggestions.per.βample; is** ) ( // Update auggeater auggββter->Iterate( iterationa_per_auggestion ); double sug.βcore « suggester->get_best_score( ) ; // If this suggestion is same aa last, ignore it if! is > 0 ** sug.score *= old_sug_βcore ) continue,- old.sug.βcore = sug.βcore; // If βuggester not much better than best, ignore it if! sug.score - eval(riches ) > replacement.threβhold ) continue; // Replace poorest int poorest » -1; double poorest.a ount = 0; for( ip » 0; ip < npop; ip** ) ( if! pooreβt < 0 | | assets[ip] < poorest.amount ) ( poorest.amount « aaaetadp); pooreat s ip; ) ) int poorest.rank ■ npop - 1 - ia; if( poorest.rank < 0 ) poorest.rank « 0; int pooreβt • aaββtβ_invrank( poorest.rank ] : pop(poores ] ->Copy( βuggeβter->get_bes ( ) ); aββets[poorest] ε 0; ) // Update eolorfrac for) ip • 0; ip < npop; ip** ) colorfracdp] = (aββeta dp] / HAX.ASSETS) * 0. 5 + 0.5 ; // for ! ip = 0; ip < npop; ip** ) cout « colorfrac p) NL; // cout NL; // Follower ♦define FOLLOWER.LEAK 0.1 // cout « richest TB « asβets.invrankt O) TB // « pop(richest) ->to_string ( ) NL; follower->Follow( pop(richest) , FOLLOWER.LEAX ) ; f ollower->Inatall ( ) ; ) Representation* SrchSSpop: :get_best() ( return pop[richest] ; ) ♦define GRAN 100000 Representation* SrchSSpop: :get_someone_good( int maxrank, double rank.factor ) ( iff maxrank =■= 0 ) return pop[ income.invrank[0] J; double prob.unif » rank_factor / (1 + maxrank * (1 - rank_factor) ) ; long rank ■= random!) % (maxrank * 1); if! (rank > random() % maxrank) ** (random!) % GRAN >« prob.unif * GRAN) ) rank = maxrank - rank; return pop[ income.invrank[rank) ] ; ) ♦undef GRAN double SrchSSpop: :get_best_score( ) ( return eval[riches ) ; ) // — - // Test main // - ♦ifdef TEST ♦include *SS2Delayβ.h' ♦include 'SS2Gaina.h* ♦include "InventorSS .h" ♦include 'InventorWindow.h* ♦include 'RepnSS.h* ♦include "SrchSShc.h* ♦include "SrchSStourn.h* ♦include "Signal. " ♦include 'myatream.h* static SrchSSpop* arch * 0; void aearcher( long ) ( arch->Iterate() ; ) main! int argc, char** argv ) ( cout.aβtf) loa::unitbuf ); // Parae coπnand-lina arga and aet up aoundaep problem ch« *filβl ■ 0, *file2 = 0; int delaya « 0; int nrep a 1; Signal ya, yb; long aampa * 0; double freq « 0; double lo * 0, hi = 0; SS* as • 0; SS2itSetup) argc, argv, aa, ya, yb, filel, file2, lo. hi. samps, freq, delays, nrep ) ; RepnSS2* repn « new RepnSS2; // Read in aignala and deal with lengtha, frequencies freq « 8000; if! delaya ) ( ya.aat.aampling.frequency! freq ) ; yb.aat.eampling.frequency! freq ); ya.normalize.varianca() ; yb.normalize.variancβ() ; ) Signal zaf aampa, freq ), zb) aamps, freq ); if) yb.get.βaπplβa( ) < aamps ) aampa « yb.get.βamplead ; ♦define HINDOW.TIHE 0.01 conat long window.aampa ■= long) freq * WINDOW.TIME * 0.5 ); // Start up a new aearcher RepnSS2* auggaat = (RepnSS2*) repn->Clone() ; ♦define NPOP 30 SrchSShc* auggeater ■ new SrchSShc(auggaat) ; arch • new SrchSSpop! repn, NPOP, auggeater ) ; auggeater->pop « arch; auggester->maxrank * NPOP-1; suggββtβr->rank_factor « 0.8; RepnSS2* follower « (RepnSS2>) arch->get_followerd ; // Start the graphica ♦define HARKER.DIM 0.01 ♦define MARKERJUT 0.001 InvβntorWindow* invwin • new InventorWindow('SS') ; InvβntorSS2 invss2 ( ss2, lo, hi, 20, lo, hi, 10. Inventor: :CGPea ) ,- invββ .allocatβ.βquarββetβ( 3 ); invsa2.regiater_a<juareaet ( 0, 1, *suggest, HARKEfU3IM*3 , MARKERJU-T * 0 .98 , SoKeyboardEvent : : H , 0 , .4, .4 , .4 ) ; invββ2 . register.βquareβe ( 1 , NPOP, (Rβpn≤S2**) arch->get.pop() , HARKER.DIM, KARKER.ALT. SoKeyboardEven : :P, 1, βrch->get_colorfrac () , Inventor: :BMRY ) ; invβs .regie er.βquarββet ( 2, 1, *follower, MARKER_DIM*2, MAR ER.ALT * 0.99, SoKeyboardEvent: :F, 1, 0, 0, 0 ); // Set some parameters iff delays ) ( arch->min_iterationa_to_max_aB8ets = 10; βrch->max_income_diff_p6r_itβrβtion = 10; arch->iterationa_per_βuggeation * 3; srch->βuggeationa.pβr.βamplβ « 3; invss2.maχ_catchup • 100; ) else ( srch->min_iterations_to.max_aββeta = 50; βrch->max_income_diff_per_iteration = 10; βrch->iterations.per.suggestion « 5; srch->βuggestionsj>er_βample = 5; ) srch->replacement_threshold « 0; // Runl invwin->get_viewβr()->βetViewing( FALSE ); invss2.Run( *ya, *yb, searcher, wlndow.βamps, invwin ) ; return 0; ) ♦endif // SrchSStoum -* -c*+-*- SReviaion: 12 .0 S SDate: 1994/08/04 00 : 23 :30 $ // Tournaments for sound separation ♦ifndef .SrchSStoum.h ♦define .SrchSStoum.h ♦include *SrchSS.h * class RepnSS; claaa SrchSStoum : public SrchSS { // Conatructor, deβtructor public: SrchSStoum( RepnSS* repn ) ; -SrchSStou () ; // State private: RepnSS* beat; double beat.acore; // Virtual methods public: virtual void Initialized; virtual void Iterate( short niter -1 ) ; virtual Repreaentatlon* get.beatd; virtual double get.best.score( ) ; ); ♦endif // .SrchSStou .h // SrchSStoum -*-c**-'- SReviaion: 12.0 S SDate: 1994/08/04 00:23:30 S ♦include 'SrchSStoum.h* ♦include "RepnSS.h* // ♦include " yβtream.h" // db SrchSStou : :SrchSStou ! RepnSS* repn ) beat « repn; Initialized; SrchSStou : :-SrchSStoum( ) delete beat; void SrchSStou : :Initialized Iterated) ; void SrchSStoum: :Iterate( short niter ) best->Randomize( ) ; beet.βcore ■ beat->Evaluate() ; for( int itβr « 1; iter < niter; iter** ) ( beβt->SaveForUndo!) ; beat->Randomize() ; double new.acore « beat->Evaluata() ; if! new.acore > beat.acore ) best->Undo() ; elae best.score = new.score; Representation* SrchSStou : :get_beat() ( return beet; ) double SrchSStoum: :get.best.acore() I return best.score,- ) // // Test main // ♦ifdef TEST ♦define DELAYS 0 ♦if DELAYS ♦include "SS2Delaya. " ♦else ♦include *SS2Gaina.h* ♦endif ♦include 'myetream.h' ♦include " Invent orSS2.h* ♦include " InventorWindow.h" ♦include *RβpnSS2.h* ♦include 'Signal.h* atatic SrchSStoum* arch • 0; void aearcher! long ) ( arch->Iterate() ; ) main) int argc, char** argv ) ( cout.βetf! ioa::unitbuf ); if! argc 1= 3 ) ( cerr « 'Ueaga: * « argv(0] « ' sigl sig2\n*; rβturn 1; ) Signal ya, yb; ya.rβad.aifc) argv(l) ); yb.read.aifcl argv(2] ); // Do SS2-dependent atuff ♦if DELAYS SS2Delaya ss2(10); double lo « -2; double hi « 2; ♦elae SS2Gaina ββ2; double lo • 0; double hi » 1; ♦endif // Start up a new aearchar ♦define WINDOW.TIHE 0.05 ββ2.SetLeak) ya. et.aampling.frequencyI) * WINDOW.TIME ); RβpnSS2: :ββt_SS2 ( *aa2 ); RepnSS2: :aet_bounds( lo, hi, lo, hi ); RepnSS2* best « new RepnSS2 ( ) ; βrch * new SrchSStou ( best ) ; // Start the graphics ♦dafine MARKER.DIM 0.01 ♦define MARKER.ALT 0.001 InventorSS2 invββ2 ( *βs2. lo, hi, 10. lo, hi, 20 ),- invBs2.allocate.aquareaeta( 1 ); invaa2.rβgiater.aquareaet( 0, 1, *beat. MARKER.DIM. MARKER.ALT, 0.1, 1, 0.1. SoKeyboardEvent: :H ); // Run! ♦if DELAYS invas2.max_catchup » 100; ♦endif invss2.Run( *ya, *yb, searcher, 100, new InventorWindow(*SS2*) ),- return 0; ) ♦endif

Claims: What Is Claimed Is 1 A signal processing system for processing waves from a plurality of sources, said system comprising a plurality of transducer means for receiving waves from said plurality of sources, including echoes and reverberation thereof and for generating a plurality of signals in response thereto, wherein each of said plurality of transducer means receives waves from said plurality of sources including echoes and reverberations thereof, and for generating one of said plurality of signals, first processing means for receiving said plurality of signals and for generating a plurality of first processed signals in response thereto, wherein each of said first processed signals represents waves from one source, and a reduced amount of waves from other sources, and second processing means for receiving said plurality of first processed signals and for generating a plurality of second processed signals in response thereto, wherein each of said second processed signals represents waves from only one source, said second processing means including feedback means for supplying said plurality of second processed signals to said second processing means for combining said plurality of second processed signals with said plurality of first processed signals to generate said plurality of second processed signals 2 The system of claim 1 , further comprising means for generating a direction of arrival signal for said waves, and wherein said first processing means generates said plurality of first processed signals, in response to said direction of arrival signal 3 The system of claim 1 , wherein the number of transducer means is two, the number of first processed signals is two, and the number of second processed signals is two 4 The system of claim 1 , wherein said transducer means are spaced apart omnidirectional microphones 5 The system of claim 4, wherein said first processing means comprises a plurality of delay means, each for receiving one of said plurality of signals and for generating a delayed signal in response thereto, and a plurality of combining means, each for receiving at least one delayed signal and one of said plurality of signals and for combining said received delayed signal and said signal to produce one of said first processed signals 6 The system of claim 1 wherein said microphones are co-located directional microphones 7 The system of claim 6, wherein said first processing means comprises a plurality of multiplying means, each for receiving different ones of said plurality of signals and for generating a scaled signal in response thereto, and a plurality of combining means, each for receiving at least one scaled signal and one of said plurality of signals and for combining said received scaled signal and said signal to produce one of said first processed signals 8 The system of claim 1, 2, 3, 4, 5, 6, and 7 wherein said second processing means comprises a plurality of combining means, each combining means having a first input, at least one other input, and an output, each of said combining means for receiving one of said first processed signals at said first input, an input signal at said other input, and for generating an output signal, at said output, said output signal being one of said plurality of second processed signals and is a difference between said first processed signal received at said first input and the sum of said input signal received at said other input, a plurality of adaptive filter means for generating a plurality of adaptive signals, each of said adaptive filter means for receiving said output signal from one of said plurality of combining means and for generating an adaptive signal in response thereto, and means for supplying each of said plurality of adaptive signals to one of said other input of said plurality of combining means other than the associated one combining means 9 The system of claim 8 further comprising means for filtering each of said second processed signals to generate a plurality of third processed signals 10 The system of claim 9 wherein said second processed signals are characterized by having a low frequency component and a high frequency component, and wherein said filtering means boosts the low frequency component relative to the high frequency component of said second processed signals 1 1 A signal processing system for processing waves from a plurality of sources, said system comprising a plurality of transducer means for receiving waves from said plurality of sources, including echoes and reverberations thereof and for generating a plurality of signals in response thereto, wherein each of said plurality of transducer means receives waves from said plurality of sources including echoes and reverberations thereof, and for generating one of said plurality of signals, first processing means for receiving said plurality of signals and for generating a plurality of first processed signals in response thereto, wherein in the absence of echoes and reverberations of said waves from said plurality of sources, each of said first processed signals represents waves from only one different source, and second processing means for receiving said plurality of first processed signals and for generating a plurality of second processed signals in response thereto, wherein in the presence of echoes and reverberations of said waves from said plurality of sources, each of said second processed signals represents waves from only one source, said second processing means including feedback means for supplying said plurality of second processed signals to said second processing means for combining said plurality of second processed signals with said plurality of first processed signals to generate said plurality of second processed signals 12 The system of claim 1 1 wherein said waves are acoustic waves, and said transducer means are microphones 13. The system of claim 12 further comprising means for filtering each of said second processed signals to generate a plurality of third processed signals. 14. The system of claim 13 wherein said second processed signals are characterized by having a low frequency component and a high frequency component, and wherein said filtering means boosts the low frequency component relative to the high frequency component of said second processed signals. 15. The system of claim 1 1, wherein the number of transducer means is two, the number of first processed signals is two, and the number of second processed signals is two. 16. The system of claim 1 1 , wherein said transducer means are spaced apart omnidirectional microphones. 17. The system of claim 16, wherein said first processing means comprises: a plurality of delay means, each for receiving one of said plurality of signals and for generating a delayed signal in response thereto; and a plurality of combining means, each for receiving at least one delayed signal and one of said plurality of signals and for combining said received delayed signal and said signal to produce one of said first processed signals. 18. The system of claim 1 1 wherein said microphones are co-located directional microphones. 19. The system of claim 18, wherein said first processing means comprises: a plurality of multiplying means, each for receiving different ones of said plurality of signals and for generating a scaled signal in response thereto; and a plurality of combining means, each for receiving at least one scaled signal and one of said plurality of signals and for combining said received scaled signal and said signal to produce one of said first processed signals. 20. The system of claim 1 1, 12, 13, 14, 15, 16, 17, 18 and 19 wherein said second processing means comprises: a plurality of combining means, each combining means having a first input, at least one other input, and an output; each of said combining means for receiving one of said first processed signals at said first input, an input signal at said other input, and for generating an output signal, at said output; said output signal being one of said plurality of second processed signals and is a difference between said first processed signal received at said first input and the sum of said input signal received at said other input; a plurality of adaptive filter means for generating a plurality of adaptive signals. each of said adaptive filter means for receiving said output signal from one of said plurality of combining means and for generating an adaptive signal in response thereto; and means for supplying each of said plurality of adaptive signals to one of said other input of said plurality of combining means other than the associated one combining means. 21 The system of claim 20 wherein each of said adaptive filter means comprises a tapped delay line 22 An adaptive filter digital signal processor for processing waves from a plurality of sources, said system comprising a plurality of transducer means for receiving waves from said plurality of sources, including echoes and reverberation thereof and for generating a plurality of signals in response thereto, wherein each of said plurality of transducer means receives waves from said plurality of sources including echoes and reverberations thereof, and for generating one of said plurality of signals, first processing means comprising a beamformer for receiving said plurality of signals and for generating a plurality of first processed signals in response thereto, wherein each of said first processed signals represents waves from one source, and a reduced amount of waves from other sources, and second processing means for receiving said plurality of first processed signals and for generating a plurality of second processed signals in response thereto, wherein each of said second processed signals represents waves from only one source 23 The system of claim 22, wherein said first processing means comprises a plurality of delay means, each for receiving one of said plurality of signals and for generating a delayed signal in response thereto, and a plurality of combining means, each for receiving at least one delayed signal and one of said plurality of signals and for combining said received delayed signal and said signal to produce one of said first processed signals 24 The system of claim 22 wherein said second processing means comprises a plurality of combining means, each having a first input, at least one other input and an output, and for generating a difference between said first input and the sum of said other inputs, at an output, each of said combining means for receiving one of said first processed signals at said first input, and a plurality of adaptive filter means for generating a plurality of adaptive signals, each of said adaptive filter means for receiving an output signal from one of said plurality of combining means and generating an adaptive signal in response thereto, and means for supplying each one of said plurality of adaptive signals to said other inputs of said plurality of combining means other than the associated one combining means 25 The system of claims 22, 23, and 24, wherein said first processing means and said second processing means comprise analog circuits 26 The system of claims 22, 23, and 24, wherein said first processing means and said second processing means are a part of a digital signal processor 27 The system of claims 22, 23, and 24, wherein said first processing means and said second processing means are a part of a general purpose computer 28 The system of claims 22, 23, and 24, wherein said first processing means and said second processing means are reconfigurable gate array circuits. 29 The system of claim 22, 23, and 24 further comprising a plurality of third processing means for receiving said plurality of second processed signals and for removing frequency coloration therefrom 30 The system of claim 23 further comprising a plurality of sampling digital converting means, each for receiving a different one of said plurality of signals and for generating a digital signal, said digital signal supplied to said plurality of delay means and to said plurality of combining means, as said signal 31 A method of processing waves from a plurality of sources, comprising receiving said waves, including echoes and reverberations thereof, by a plurality of transducer means, converting said waves, including echoes and reverberations thereof from said plurality of sources, by each of said plurality of transducer means into an electrical signal, thereby generating a plurality of electrical signals; first processing said plurality of electrical signals to generate a plurality of first processed signals, wherein in the absence of echoes and reverberations of said waves from said plurality of sources, each of said first processed signals represents waves from one source, and a reduced amount of waves from other sources, and then secondly processing said plurality of first processed signals to generate a plurality of second processed signals, wherein in the presence of echoes and reverberations of said waves from said plurality of sources, each of said second processed signals represents waves from only one different source 32 The method of claim 31 further comprising the step of filtering each of said second processed signals to generate a plurality of third processed signals 33 The method of claim 31 wherein said first processing step further comprises delaying a different one of said plurality of electrical signals and generating a delayed signal in response thereto; and combining each one of said plurality of electrical signals with a different one of said delayed signal to generate one of said processed signal. 34 The method of claim 31 further comprising the step of sampling and converting each one of said plurality of electrical signals and for supplying same to said plurality of delay means and to said plurality of combining means, as said electrical signal 5 The method of claim 31 wherein said second processing step further comprises subtracting, by a plurality of subtracting means, a different one of said first processed signals from an adaptive signal and generating an output signal, thereby generating a plurality of output signals; adaptively filtering said output signals to generate a plurality of adaptive signals; and supplying each one of said plurality of adaptive signals to a different one of said subtracting means.

Inventors: BHADKAMKAR NEAL ASHOK, NGO JOHN-THOMAS CALDERON, BHADKAMKAR, NEAL, ASHOK, NGO, JOHN-THOMAS, CALDERON
Applicants: INTERVAL RESEARCH CORP, INTERVAL RESEARCH CORPORATION
Application year: 1996
Main classification: H04B3
IPC codes: G10K11, H04B3, H04B15, H04M9, H04R3, H04R25, H04R29, H04S1