Пример #1
0
    def __init__(self, parent, sharedGLWidget, logger=PrintLogger()):
        super().__init__(parent)

        self.logger = logger
        self.audiobuffer = None

        self.setObjectName("Spectrum_Widget")
        self.gridLayout = QtWidgets.QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        self.PlotZoneSpect = SpectrumPlotWidget(self, sharedGLWidget,
                                                self.logger)
        self.PlotZoneSpect.setObjectName("PlotZoneSpect")
        self.gridLayout.addWidget(self.PlotZoneSpect, 0, 0, 1, 1)

        # initialize the class instance that will do the fft
        self.proc = audioproc(self.logger)

        self.maxfreq = DEFAULT_MAXFREQ
        self.proc.set_maxfreq(self.maxfreq)
        self.minfreq = DEFAULT_MINFREQ
        self.fft_size = 2**DEFAULT_FFT_SIZE * 32
        self.proc.set_fftsize(self.fft_size)
        self.spec_min = DEFAULT_SPEC_MIN
        self.spec_max = DEFAULT_SPEC_MAX
        self.weighting = DEFAULT_WEIGHTING
        self.dual_channels = False
        self.response_time = DEFAULT_RESPONSE_TIME

        self.update_weighting()
        self.freq = self.proc.get_freq_scale()

        self.old_index = 0
        self.overlap = 3. / 4.

        self.update_display_buffers()

        # set kernel and parameters for the smoothing filter
        self.setresponsetime(self.response_time)

        self.PlotZoneSpect.setlogfreqscale()  #DEFAULT_FREQ_SCALE = 1 #log10
        self.PlotZoneSpect.setfreqrange(self.minfreq, self.maxfreq)
        self.PlotZoneSpect.setspecrange(self.spec_min, self.spec_max)
        self.PlotZoneSpect.setweighting(self.weighting)
        self.PlotZoneSpect.set_peaks_enabled(True)
        self.PlotZoneSpect.set_baseline_displayUnits(0.)
        self.PlotZoneSpect.setShowFreqLabel(DEFAULT_SHOW_FREQ_LABELS)

        # initialize the settings dialog
        self.settings_dialog = Spectrum_Settings_Dialog(self, self.logger)
Пример #2
0
    def __init__(self, parent, logger=PrintLogger()):
        super().__init__(parent)

        self.logger = logger

        self.setObjectName(self.name)
        self.gridLayout = QtWidgets.QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        self.PlotZoneSpect = SpectrumPlotWidget(self, self.logger)
        self.PlotZoneSpect.setObjectName("PlotZoneSpect")
        self.gridLayout.addWidget(self.PlotZoneSpect, 0, 0, 1, 1)

        # initialize the class instance that will do the fft
        self.proc = audioproc(self.logger)

        self.maxfreq = DEFAULT_MAXFREQ
        self.proc.set_maxfreq(self.maxfreq)
        self.minfreq = DEFAULT_MINFREQ
        self.fft_size = 2 ** DEFAULT_FFT_SIZE * 32

        self.proc.set_fftsize(self.fft_size)
        self.spec_min = DEFAULT_SPEC_MIN
        self.spec_max = DEFAULT_SPEC_MAX
        self.weighting = DEFAULT_WEIGHTING
        self.dual_channels = False
        self.response_time = DEFAULT_RESPONSE_TIME
        self.spectrum_type = "Power"  # DEFAULT_SPECTRUM_TYPE = 2
        self.is_dB = True  # DEFAULT_INTENSITY_SCALE = 0

        self.update_weighting()
        self.freq = self.proc.get_freq_scale()

        self.overlap = 3. / 4.
        self.data_buffer = RingBuffer(1, 4 * self.fft_size)
        self.smoothing_buffer = RingBuffer(1, self.fft_size*self.overlap)


        self.update_display_buffers()

        # set kernel and parameters for the smoothing filter
        self.setresponsetime(self.response_time)

        self.PlotZoneSpect.setlogfreqscale()  # DEFAULT_FREQ_SCALE = 1 #log10
        self.PlotZoneSpect.setfreqrange(self.minfreq, self.maxfreq)
        self.PlotZoneSpect.setspecrange(self.spec_min, self.spec_max)
        self.PlotZoneSpect.setweighting(self.weighting)
        self.PlotZoneSpect.set_peaks_enabled(False)
        self.PlotZoneSpect.set_baseline_displayUnits(0.)
        self.PlotZoneSpect.setShowFreqLabel(DEFAULT_SHOW_FREQ_LABELS)

        # initialize the settings dialog
        self.settings_dialog = Spectrum_Settings_Dialog(self, self.logger)
Пример #3
0
class Spectrum_Widget(QtWidgets.QWidget):
    def __init__(self, parent, logger=PrintLogger()):
        super().__init__(parent)

        self.logger = logger
        self.audiobuffer = None

        self.setObjectName("Spectrum_Widget")
        self.gridLayout = QtWidgets.QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        self.PlotZoneSpect = SpectrumPlotWidget(self, self.logger)
        self.PlotZoneSpect.setObjectName("PlotZoneSpect")
        self.gridLayout.addWidget(self.PlotZoneSpect, 0, 0, 1, 1)

        # initialize the class instance that will do the fft
        self.proc = audioproc(self.logger)

        self.maxfreq = DEFAULT_MAXFREQ
        self.proc.set_maxfreq(self.maxfreq)
        self.minfreq = DEFAULT_MINFREQ
        self.fft_size = 2**DEFAULT_FFT_SIZE * 32
        self.proc.set_fftsize(self.fft_size)
        self.spec_min = DEFAULT_SPEC_MIN
        self.spec_max = DEFAULT_SPEC_MAX
        self.weighting = DEFAULT_WEIGHTING
        self.dual_channels = False
        self.response_time = DEFAULT_RESPONSE_TIME

        self.update_weighting()
        self.freq = self.proc.get_freq_scale()

        self.old_index = 0
        self.overlap = 3. / 4.

        self.update_display_buffers()

        # set kernel and parameters for the smoothing filter
        self.setresponsetime(self.response_time)

        self.PlotZoneSpect.setlogfreqscale()  # DEFAULT_FREQ_SCALE = 1 #log10
        self.PlotZoneSpect.setfreqrange(self.minfreq, self.maxfreq)
        self.PlotZoneSpect.setspecrange(self.spec_min, self.spec_max)
        self.PlotZoneSpect.setweighting(self.weighting)
        self.PlotZoneSpect.set_peaks_enabled(True)
        self.PlotZoneSpect.set_baseline_displayUnits(0.)
        self.PlotZoneSpect.setShowFreqLabel(DEFAULT_SHOW_FREQ_LABELS)

        # initialize the settings dialog
        self.settings_dialog = Spectrum_Settings_Dialog(self, self.logger)

    # method
    def set_buffer(self, buffer):
        self.audiobuffer = buffer
        self.old_index = self.audiobuffer.ringbuffer.offset

    def log_spectrogram(self, sp):
        # Note: implementing the log10 of the array in Cython did not bring
        # any speedup.
        # Idea: Instead of computing the log of the data, I could pre-compute
        # a list of values associated with the colormap, and then do a search...
        epsilon = 1e-30
        return 10. * log10(sp + epsilon)

    def handle_new_data(self, floatdata):
        # we need to maintain an index of where we are in the buffer
        index = self.audiobuffer.ringbuffer.offset

        available = index - self.old_index

        if available < 0:
            # ringbuffer must have grown or something...
            available = 0
            self.old_index = index

        # if we have enough data to add a frequency column in the time-frequency plane, compute it
        needed = self.fft_size * (1. - self.overlap)
        realizable = int(floor(available / needed))

        if realizable > 0:
            sp1n = zeros((len(self.freq), realizable), dtype=float64)
            sp2n = zeros((len(self.freq), realizable), dtype=float64)

            for i in range(realizable):
                floatdata = self.audiobuffer.data_indexed(
                    self.old_index, self.fft_size)

                # first channel
                # FFT transform
                sp1n[:, i] = self.proc.analyzelive(floatdata[0, :])

                if self.dual_channels and floatdata.shape[0] > 1:
                    # second channel for comparison
                    sp2n[:, i] = self.proc.analyzelive(floatdata[1, :])

                self.old_index += int(needed)

            # compute the widget data
            sp1 = pyx_exp_smoothed_value_numpy(self.kernel, self.alpha, sp1n,
                                               self.dispbuffers1)
            sp2 = pyx_exp_smoothed_value_numpy(self.kernel, self.alpha, sp2n,
                                               self.dispbuffers2)
            # store result for next computation
            self.dispbuffers1 = sp1
            self.dispbuffers2 = sp2

            sp1.shape = self.freq.shape
            sp2.shape = self.freq.shape
            self.w.shape = self.freq.shape

            if self.dual_channels and floatdata.shape[0] > 1:
                dB_spectrogram = self.log_spectrogram(
                    sp2) - self.log_spectrogram(sp1)
            else:
                dB_spectrogram = self.log_spectrogram(sp1) + self.w

            # the log operation and the weighting could be deffered
            # to the post-weedening !

            i = argmax(dB_spectrogram)
            fmax = self.freq[i]

            self.PlotZoneSpect.setdata(self.freq, dB_spectrogram, fmax)

    # method
    def canvasUpdate(self):
        self.PlotZoneSpect.update()

    def pause(self):
        self.PlotZoneSpect.pause()

    def restart(self):
        self.PlotZoneSpect.restart()

    def setresponsetime(self, response_time):
        # time = SMOOTH_DISPLAY_TIMER_PERIOD_MS/1000. #DISPLAY
        # time = 0.025 #IMPULSE setting for a sound level meter
        # time = 0.125 #FAST setting for a sound level meter
        # time = 1. #SLOW setting for a sound level meter
        self.response_time = response_time

        # an exponential smoothing filter is a simple IIR filter
        # s_i = alpha*x_i + (1-alpha)*s_{i-1}
        # we compute alpha so that the N most recent samples represent 100*w percent of the output
        w = 0.65
        delta_n = self.fft_size * (1. - self.overlap)
        n = self.response_time * SAMPLING_RATE / delta_n
        N = 2 * 4096
        self.alpha = 1. - (1. - w)**(1. / (n + 1))
        self.kernel = self.compute_kernel(self.alpha, N)

    def compute_kernel(self, alpha, N):
        kernel = (1. - alpha)**arange(N - 1, -1, -1)
        return kernel

    def update_display_buffers(self):
        self.dispbuffers1 = zeros(len(self.freq))
        self.dispbuffers2 = zeros(len(self.freq))

    def setminfreq(self, minfreq):
        self.setMinMaxFreq(minfreq, self.maxfreq)

    def setmaxfreq(self, maxfreq):
        self.setMinMaxFreq(self.minfreq, maxfreq)

    def setMinMaxFreq(self, minfreq, maxfreq):
        self.minfreq = minfreq
        self.maxfreq = maxfreq

        realmin = min(self.minfreq, self.maxfreq)
        realmax = max(self.minfreq, self.maxfreq)

        self.proc.set_maxfreq(realmax)

        self.freq = self.proc.get_freq_scale()
        self.update_display_buffers()
        self.update_weighting()
        # reset kernel and parameters for the smoothing filter
        self.setresponsetime(self.response_time)

        self.PlotZoneSpect.setfreqrange(realmin, realmax)

    def setfftsize(self, fft_size):
        self.fft_size = fft_size
        self.proc.set_fftsize(self.fft_size)
        self.freq = self.proc.get_freq_scale()
        self.update_display_buffers()
        self.update_weighting()
        # reset kernel and parameters for the smoothing filter
        self.setresponsetime(self.response_time)

    def setmin(self, value):
        self.spec_min = value
        self.PlotZoneSpect.setspecrange(self.spec_min, self.spec_max)

    def setmax(self, value):
        self.spec_max = value
        self.PlotZoneSpect.setspecrange(self.spec_min, self.spec_max)

    def setweighting(self, weighting):
        self.weighting = weighting
        self.PlotZoneSpect.setweighting(weighting)
        self.update_weighting()

    def update_weighting(self):
        A, B, C = self.proc.get_freq_weighting()
        if self.weighting is 0:
            self.w = zeros(A.shape)
        elif self.weighting is 1:
            self.w = A
        elif self.weighting is 2:
            self.w = B
        else:
            self.w = C

        self.w.shape = (1, self.w.size)

    def setdualchannels(self, dual_enabled):
        self.dual_channels = dual_enabled
        if dual_enabled:
            self.PlotZoneSpect.set_peaks_enabled(False)
            self.PlotZoneSpect.set_baseline_dataUnits(0.)
        else:
            self.PlotZoneSpect.set_peaks_enabled(True)
            self.PlotZoneSpect.set_baseline_displayUnits(0.)

    def setShowFreqLabel(self, showFreqLabel):
        self.PlotZoneSpect.setShowFreqLabel(showFreqLabel)

    def settings_called(self, checked):
        self.settings_dialog.show()

    def saveState(self, settings):
        self.settings_dialog.saveState(settings)

    def restoreState(self, settings):
        self.settings_dialog.restoreState(settings)
Пример #4
0
class Spectrum_Widget(QtWidgets.QWidget):

    def __init__(self, parent, logger=PrintLogger()):
        super().__init__(parent)

        self.logger = logger
        self.audiobuffer = None

        self.setObjectName("Spectrum_Widget")
        self.gridLayout = QtWidgets.QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        self.PlotZoneSpect = SpectrumPlotWidget(self, self.logger)
        self.PlotZoneSpect.setObjectName("PlotZoneSpect")
        self.gridLayout.addWidget(self.PlotZoneSpect, 0, 0, 1, 1)

        # initialize the class instance that will do the fft
        self.proc = audioproc(self.logger)

        self.maxfreq = DEFAULT_MAXFREQ
        self.proc.set_maxfreq(self.maxfreq)
        self.minfreq = DEFAULT_MINFREQ
        self.fft_size = 2 ** DEFAULT_FFT_SIZE * 32
        self.proc.set_fftsize(self.fft_size)
        self.spec_min = DEFAULT_SPEC_MIN
        self.spec_max = DEFAULT_SPEC_MAX
        self.weighting = DEFAULT_WEIGHTING
        self.dual_channels = False
        self.response_time = DEFAULT_RESPONSE_TIME

        self.update_weighting()
        self.freq = self.proc.get_freq_scale()

        self.old_index = 0
        self.overlap = 3. / 4.

        self.update_display_buffers()

        # set kernel and parameters for the smoothing filter
        self.setresponsetime(self.response_time)

        self.PlotZoneSpect.setlogfreqscale()  # DEFAULT_FREQ_SCALE = 1 #log10
        self.PlotZoneSpect.setfreqrange(self.minfreq, self.maxfreq)
        self.PlotZoneSpect.setspecrange(self.spec_min, self.spec_max)
        self.PlotZoneSpect.setweighting(self.weighting)
        self.PlotZoneSpect.set_peaks_enabled(True)
        self.PlotZoneSpect.set_baseline_displayUnits(0.)
        self.PlotZoneSpect.setShowFreqLabel(DEFAULT_SHOW_FREQ_LABELS)

        # initialize the settings dialog
        self.settings_dialog = Spectrum_Settings_Dialog(self, self.logger)

    # method
    def set_buffer(self, buffer):
        self.audiobuffer = buffer
        self.old_index = self.audiobuffer.ringbuffer.offset

    def log_spectrogram(self, sp):
        # Note: implementing the log10 of the array in Cython did not bring
        # any speedup.
        # Idea: Instead of computing the log of the data, I could pre-compute
        # a list of values associated with the colormap, and then do a search...
        epsilon = 1e-30
        return 10. * log10(sp + epsilon)

    def handle_new_data(self, floatdata):
        # we need to maintain an index of where we are in the buffer
        index = self.audiobuffer.ringbuffer.offset

        available = index - self.old_index

        if available < 0:
            # ringbuffer must have grown or something...
            available = 0
            self.old_index = index

        # if we have enough data to add a frequency column in the time-frequency plane, compute it
        needed = self.fft_size * (1. - self.overlap)
        realizable = int(floor(available / needed))

        if realizable > 0:
            sp1n = zeros((len(self.freq), realizable), dtype=float64)
            sp2n = zeros((len(self.freq), realizable), dtype=float64)

            for i in range(realizable):
                floatdata = self.audiobuffer.data_indexed(self.old_index, self.fft_size)

                # first channel
                # FFT transform
                sp1n[:, i] = self.proc.analyzelive(floatdata[0, :])

                if self.dual_channels and floatdata.shape[0] > 1:
                    # second channel for comparison
                    sp2n[:, i] = self.proc.analyzelive(floatdata[1, :])

                self.old_index += int(needed)

            # compute the widget data
            sp1 = pyx_exp_smoothed_value_numpy(self.kernel, self.alpha, sp1n, self.dispbuffers1)
            sp2 = pyx_exp_smoothed_value_numpy(self.kernel, self.alpha, sp2n, self.dispbuffers2)
            # store result for next computation
            self.dispbuffers1 = sp1
            self.dispbuffers2 = sp2

            sp1.shape = self.freq.shape
            sp2.shape = self.freq.shape
            self.w.shape = self.freq.shape

            if self.dual_channels and floatdata.shape[0] > 1:
                dB_spectrogram = self.log_spectrogram(sp2) - self.log_spectrogram(sp1)
            else:
                dB_spectrogram = self.log_spectrogram(sp1) + self.w

            # the log operation and the weighting could be deffered
            # to the post-weedening !

            i = argmax(dB_spectrogram)
            fmax = self.freq[i]

            self.PlotZoneSpect.setdata(self.freq, dB_spectrogram, fmax)

    # method
    def canvasUpdate(self):
        if not self.isVisible():
            return

    def pause(self):
        self.PlotZoneSpect.pause()

    def restart(self):
        self.PlotZoneSpect.restart()

    def setresponsetime(self, response_time):
        # time = SMOOTH_DISPLAY_TIMER_PERIOD_MS/1000. #DISPLAY
        # time = 0.025 #IMPULSE setting for a sound level meter
        # time = 0.125 #FAST setting for a sound level meter
        # time = 1. #SLOW setting for a sound level meter
        self.response_time = response_time

        # an exponential smoothing filter is a simple IIR filter
        # s_i = alpha*x_i + (1-alpha)*s_{i-1}
        # we compute alpha so that the N most recent samples represent 100*w percent of the output
        w = 0.65
        delta_n = self.fft_size * (1. - self.overlap)
        n = self.response_time * SAMPLING_RATE / delta_n
        N = 2 * 4096
        self.alpha = 1. - (1. - w) ** (1. / (n + 1))
        self.kernel = self.compute_kernel(self.alpha, N)

    def compute_kernel(self, alpha, N):
        kernel = (1. - alpha) ** arange(N - 1, -1, -1)
        return kernel

    def update_display_buffers(self):
        self.dispbuffers1 = zeros(len(self.freq))
        self.dispbuffers2 = zeros(len(self.freq))

    def setminfreq(self, minfreq):
        self.setMinMaxFreq(minfreq, self.maxfreq)

    def setmaxfreq(self, maxfreq):
        self.setMinMaxFreq(self.minfreq, maxfreq)

    def setMinMaxFreq(self, minfreq, maxfreq):
        self.minfreq = minfreq
        self.maxfreq = maxfreq

        realmin = min(self.minfreq, self.maxfreq)
        realmax = max(self.minfreq, self.maxfreq)

        self.proc.set_maxfreq(realmax)

        self.freq = self.proc.get_freq_scale()
        self.update_display_buffers()
        self.update_weighting()
        # reset kernel and parameters for the smoothing filter
        self.setresponsetime(self.response_time)

        self.PlotZoneSpect.setfreqrange(realmin, realmax)

    def setfftsize(self, fft_size):
        self.fft_size = fft_size
        self.proc.set_fftsize(self.fft_size)
        self.freq = self.proc.get_freq_scale()
        self.update_display_buffers()
        self.update_weighting()
        # reset kernel and parameters for the smoothing filter
        self.setresponsetime(self.response_time)

    def setmin(self, value):
        self.spec_min = value
        self.PlotZoneSpect.setspecrange(self.spec_min, self.spec_max)

    def setmax(self, value):
        self.spec_max = value
        self.PlotZoneSpect.setspecrange(self.spec_min, self.spec_max)

    def setweighting(self, weighting):
        self.weighting = weighting
        self.PlotZoneSpect.setweighting(weighting)
        self.update_weighting()

    def update_weighting(self):
        A, B, C = self.proc.get_freq_weighting()
        if self.weighting is 0:
            self.w = zeros(A.shape)
        elif self.weighting is 1:
            self.w = A
        elif self.weighting is 2:
            self.w = B
        else:
            self.w = C

        self.w.shape = (1, self.w.size)

    def setdualchannels(self, dual_enabled):
        self.dual_channels = dual_enabled
        if dual_enabled:
            self.PlotZoneSpect.set_peaks_enabled(False)
            self.PlotZoneSpect.set_baseline_dataUnits(0.)
        else:
            self.PlotZoneSpect.set_peaks_enabled(True)
            self.PlotZoneSpect.set_baseline_displayUnits(0.)

    def setShowFreqLabel(self, showFreqLabel):
        self.PlotZoneSpect.setShowFreqLabel(showFreqLabel)

    def settings_called(self, checked):
        self.settings_dialog.show()

    def saveState(self, settings):
        self.settings_dialog.saveState(settings)

    def restoreState(self, settings):
        self.settings_dialog.restoreState(settings)