def __init__(self, N=None, taps=None, fs=96000, repeats=2, B=(1, 0, 0), A=(1, 0, 0)): """N is the order of the MLS, taps are preferably selected from the mlstaps dictionary, like >>> taps=TAPS[N][0] B and A are emphasis filter coefficients. The filter used as emphasis must be a minimum phase filter. This means that all the poles and the zeroes are withing the unit circle. We can then invert the filter to apply de-emphasis. The filters.biquads.RBJ class can be used to generate a suitable emphasis filter. """ assert repeats > 1, "at least two sequences are needed, (repeats=2)" _MLS_base.__init__(self, N=N, taps=taps) Audio.__init__(self, fs=fs, initialdata=self.get_full_sequence(repeats=repeats)) self.repeats = repeats self._length_impresp = self.L / self.fs self._filter_emphasis = Filter(B=B, A=A, fs=self.fs) self._filter_deemphasis = Filter(B=A, A=B, fs=self.fs) # inverse filter assert self._filter_emphasis.is_minimum_phase(), \ "The emphasis filter must be minimum phase, i.e. possible to invert"
def __init__(self, N=None, taps=None, fs=96000, repeats=2, B=(1, 0, 0), A=(1, 0, 0)): """N is the order of the MLS, taps are preferably selected from the mlstaps dictionary, like >>> taps=TAPS[N][0] B and A are emphasis filter coefficients. The filter used as emphasis must be a minimum phase filter. This means that all the poles and the zeroes are withing the unit circle. We can then invert the filter to apply de-emphasis. The filters.biquads.RBJ class can be used to generate a suitable emphasis filter. """ assert repeats > 1, "at least two sequences are needed, (repeats=2)" _MLS_base.__init__(self, N=N, taps=taps) Audio.__init__(self, fs=fs, initialdata=self.get_full_sequence(repeats=repeats)) self.repeats = repeats self._length_impresp = self.L/self.fs self._filter_emphasis = Filter(B=B, A=A, fs=self.fs) self._filter_deemphasis = Filter(B=A, A=B, fs=self.fs) # inverse filter assert self._filter_emphasis.is_minimum_phase(), \ "The emphasis filter must be minimum phase, i.e. possible to invert"
class MLS(_MLS_base, Audio): """This class is a mixture of the MLS base class and the Audio class. The MLS data is the audio samples in the Audio class. Because we also know about sample rate here we can apply emphasis and de-emphasis on the samples. When plotting the FFT of the impulse response remember to use a rectangular window. This is perfectly valid since the MLS is cyclic by nature and will wrap around. This class is limited to one channel of audio. Creating a multichannel MLS signal is outside the scope of this class. It can easily be done by creating multiple instances and then extracting the audio samples and constructing a new Audio instance with all channels appended. To extract the impulse response we then need to keep track of which channel is paired with which MLS since they should preferably be using different taps to minimise cross talk. """ def __init__(self, N=None, taps=None, fs=96000, repeats=2, B=(1, 0, 0), A=(1, 0, 0)): """N is the order of the MLS, taps are preferably selected from the mlstaps dictionary, like >>> taps=TAPS[N][0] B and A are emphasis filter coefficients. The filter used as emphasis must be a minimum phase filter. This means that all the poles and the zeroes are withing the unit circle. We can then invert the filter to apply de-emphasis. The filters.biquads.RBJ class can be used to generate a suitable emphasis filter. """ assert repeats > 1, "at least two sequences are needed, (repeats=2)" _MLS_base.__init__(self, N=N, taps=taps) Audio.__init__(self, fs=fs, initialdata=self.get_full_sequence(repeats=repeats)) self.repeats = repeats self._length_impresp = self.L / self.fs self._filter_emphasis = Filter(B=B, A=A, fs=self.fs) self._filter_deemphasis = Filter(B=A, A=B, fs=self.fs) # inverse filter assert self._filter_emphasis.is_minimum_phase(), \ "The emphasis filter must be minimum phase, i.e. possible to invert" def __repr__(self): B, A = self._filter_emphasis.get_coefficients() s = 'MLS(N=%i, taps=%s, fs=%r, repeats=%i, B=%s, A=%s)' \ %(self.N, tuple(self.taps), self.fs, self.repeats, tuple(B), tuple(A)) return s def __str__(self): B, A = self._filter_emphasis.get_coefficients() mls_string = _MLS_base.__str__(self) mls_string = "\n".join(mls_string.splitlines()[2:-1]) s = Audio.__str__(self) s += '%s\n' % mls_string s += 'repeats : %i\n' % self.repeats s += 'len(impulse) : %.3f [s]\n' % self._length_impresp s += 'emphasis filt. B : %s\n' % str(B) s += 'emphasis filt. A : %s\n' % str(A) return s def apply_emphasis(self): """Apply emphasis by filtering the whole audio signal. If high freqencies are boosted noise will be suppressed. If low frequencies are boosted we will get better signal to noise ratio in the lower area of the frequency response. """ self._logger.debug("Applying emphasis filter, in place") self.samples = self._filter_emphasis.filter_samples(self.samples) def apply_deemphasis(self, x): """Undo the emphasis filter by filtering the signal with the inverse of the emphasis filter. """ self._logger.debug("Applying de-emphasis filter") deemphasis_x = self._filter_deemphasis.filter_samples(x) return deemphasis_x def get_impulse(self, x): """Extract the impulse response. Returns an Audio instance. """ imp = _MLS_base.get_impulse(self, x) y = Audio(fs=self.fs, initialdata=imp) return y
class MLS(_MLS_base, Audio): """This class is a mixture of the MLS base class and the Audio class. The MLS data is the audio samples in the Audio class. Because we also know about sample rate here we can apply emphasis and de-emphasis on the samples. When plotting the FFT of the impulse response remember to use a rectangular window. This is perfectly valid since the MLS is cyclic by nature and will wrap around. This class is limited to one channel of audio. Creating a multichannel MLS signal is outside the scope of this class. It can easily be done by creating multiple instances and then extracting the audio samples and constructing a new Audio instance with all channels appended. To extract the impulse response we then need to keep track of which channel is paired with which MLS since they should preferably be using different taps to minimise cross talk. """ def __init__(self, N=None, taps=None, fs=96000, repeats=2, B=(1, 0, 0), A=(1, 0, 0)): """N is the order of the MLS, taps are preferably selected from the mlstaps dictionary, like >>> taps=TAPS[N][0] B and A are emphasis filter coefficients. The filter used as emphasis must be a minimum phase filter. This means that all the poles and the zeroes are withing the unit circle. We can then invert the filter to apply de-emphasis. The filters.biquads.RBJ class can be used to generate a suitable emphasis filter. """ assert repeats > 1, "at least two sequences are needed, (repeats=2)" _MLS_base.__init__(self, N=N, taps=taps) Audio.__init__(self, fs=fs, initialdata=self.get_full_sequence(repeats=repeats)) self.repeats = repeats self._length_impresp = self.L/self.fs self._filter_emphasis = Filter(B=B, A=A, fs=self.fs) self._filter_deemphasis = Filter(B=A, A=B, fs=self.fs) # inverse filter assert self._filter_emphasis.is_minimum_phase(), \ "The emphasis filter must be minimum phase, i.e. possible to invert" def __repr__(self): B, A = self._filter_emphasis.get_coefficients() s = 'MLS(N=%i, taps=%s, fs=%r, repeats=%i, B=%s, A=%s)' \ %(self.N, tuple(self.taps), self.fs, self.repeats, tuple(B), tuple(A)) return s def __str__(self): B, A = self._filter_emphasis.get_coefficients() mls_string = _MLS_base.__str__(self) mls_string = "\n".join(mls_string.splitlines()[2:-1]) s = Audio.__str__(self) s += '%s\n' %mls_string s += 'repeats : %i\n' %self.repeats s += 'len(impulse) : %.3f [s]\n' %self._length_impresp s += 'emphasis filt. B : %s\n' %str(B) s += 'emphasis filt. A : %s\n' %str(A) return s def apply_emphasis(self): """Apply emphasis by filtering the whole audio signal. If high freqencies are boosted noise will be suppressed. If low frequencies are boosted we will get better signal to noise ratio in the lower area of the frequency response. """ self._logger.debug("Applying emphasis filter, in place") self.samples = self._filter_emphasis.filter_samples(self.samples) def apply_deemphasis(self, x): """Undo the emphasis filter by filtering the signal with the inverse of the emphasis filter. """ self._logger.debug("Applying de-emphasis filter") deemphasis_x = self._filter_deemphasis.filter_samples(x) return deemphasis_x def get_impulse(self, x): """Extract the impulse response. Returns an Audio instance. """ imp = _MLS_base.get_impulse(self, x) y = Audio(fs=self.fs, initialdata=imp) return y