Exemple #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)
Exemple #2
0
    def __init__(self, parent, logger=None):
        QtGui.QWidget.__init__(self, parent)

        # store the logger instance
        if logger is None:
            self.logger = parent.parent.logger
        else:
            self.logger = logger

        self.audiobuffer = None

        self.setObjectName("Spectrum_Widget")
        self.gridLayout = QtGui.QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        #self.PlotZoneSpect = SpectPlot(self, self.logger)
        self.PlotZoneSpect = GLPlotWidget(self, self.logger)
        self.PlotZoneSpect.setObjectName("PlotZoneSpect")
        self.gridLayout.addWidget(self.PlotZoneSpect, 0, 0, 1, 1)

        self.setStyleSheet(STYLESHEET)

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

        self.maxfreq = DEFAULT_MAXFREQ
        self.minfreq = DEFAULT_MINFREQ
        self.fft_size = 2**DEFAULT_FFT_SIZE * 32
        self.spec_min = DEFAULT_SPEC_MIN
        self.spec_max = DEFAULT_SPEC_MAX
        self.weighting = DEFAULT_WEIGHTING
        self.dual_channels = False

        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.)

        # initialize the settings dialog
        self.settings_dialog = Spectrum_Settings_Dialog(self, self.logger)
Exemple #3
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)
Exemple #4
0
	def __init__(self, parent, sharedGLWidget, logger = PrintLogger()):
		QtGui.QWidget.__init__(self, parent)

		self.logger = logger
		self.audiobuffer = None

		self.setObjectName("Spectrum_Widget")
		self.gridLayout = QtGui.QGridLayout(self)
		self.gridLayout.setObjectName("gridLayout")
		#self.PlotZoneSpect = SpectPlot(self, self.logger)
		self.PlotZoneSpect = GLPlotWidget(self, sharedGLWidget, self.logger)
		self.PlotZoneSpect.setObjectName("PlotZoneSpect")
		self.gridLayout.addWidget(self.PlotZoneSpect, 0, 0, 1, 1)

		self.setStyleSheet(STYLESHEET)
		
		# 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)
Exemple #5
0
	def __init__(self, parent, logger = None):
		QtGui.QWidget.__init__(self, parent)

		# store the logger instance
		if logger is None:
		    self.logger = parent.parent.logger
		else:
		    self.logger = logger

		self.audiobuffer = None

		self.setObjectName("Spectrum_Widget")
		self.gridLayout = QtGui.QGridLayout(self)
		self.gridLayout.setObjectName("gridLayout")
		#self.PlotZoneSpect = SpectPlot(self, self.logger)
  		self.PlotZoneSpect = GLPlotWidget(self, self.logger)
		self.PlotZoneSpect.setObjectName("PlotZoneSpect")
		self.gridLayout.addWidget(self.PlotZoneSpect, 0, 0, 1, 1)

		self.setStyleSheet(STYLESHEET)
		
		# 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.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)
Exemple #6
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)
Exemple #7
0
class Spectrum_Widget(QtGui.QWidget):
	def __init__(self, parent, logger = None):
		QtGui.QWidget.__init__(self, parent)

		# store the logger instance
		if logger is None:
		    self.logger = parent.parent.logger
		else:
		    self.logger = logger

		self.audiobuffer = None

		self.setObjectName("Spectrum_Widget")
		self.gridLayout = QtGui.QGridLayout(self)
		self.gridLayout.setObjectName("gridLayout")
		#self.PlotZoneSpect = SpectPlot(self, self.logger)
  		self.PlotZoneSpect = GLPlotWidget(self, self.logger)
		self.PlotZoneSpect.setObjectName("PlotZoneSpect")
		self.gridLayout.addWidget(self.PlotZoneSpect, 0, 0, 1, 1)

		self.setStyleSheet(STYLESHEET)
		
		# 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.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

	# method
	def update(self):
		if not self.isVisible():
		    return
		
		floatdata = self.audiobuffer.data(self.fft_size)

		# first channel
		sp1 = self.proc.analyzelive(floatdata[0,:])

		if self.dual_channels and floatdata.shape[0] > 1:
			# second channel for comparison
			sp2, freq, A, B, C  = self.proc.analyzelive(floatdata[1,:])

			floatdata_delayed = self.audiobuffer.data_delayed(self.fft_size)
			sp1  = self.proc.analyzelive(floatdata_delayed[0,:])

		#sp, freq = self.proc.analyzelive_cochlear(floatdata, 50, minfreq, maxfreq)
		# scale the db spectrum from [- spec_range db ... 0 db] > [0..1]
		#print freq[len(freq)/6], A[len(freq)/6]
		epsilon = 1e-30
		
		freq = self.proc.get_freq_scale()
		A, B, C = self.proc.get_freq_weighting()

		if self.weighting is 0:
			w = 0.
		elif self.weighting is 1:
			w = A
		elif self.weighting is 2:
			w = B
		else:
			w = C

	           # the log operation and the weighting could be deffered
	           # to the post-weedening !		
		if self.dual_channels and floatdata.shape[0] > 1:
			db_spectrogram = 10*log10(sp2 + epsilon) - 10*log10(sp1 + epsilon)
		else:
			db_spectrogram = 10*log10(sp1 + epsilon) + w

		i = argmax(db_spectrogram)
		fmax = freq[i]
		self.PlotZoneSpect.setdata(freq, db_spectrogram, fmax)

	def setminfreq(self, freq):
		self.minfreq = freq
		self.PlotZoneSpect.setfreqrange(self.minfreq, self.maxfreq)

	def setmaxfreq(self, freq):
		self.maxfreq = freq
  		self.proc.set_maxfreq(self.maxfreq)
		self.PlotZoneSpect.setfreqrange(self.minfreq, self.maxfreq)

	def setfftsize(self, fft_size):
		self.fft_size = fft_size
		self.proc.set_fftsize(self.fft_size)

	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)

	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)
Exemple #8
0
class Spectrum_Widget(QtGui.QWidget):
    def __init__(self, parent, logger=None):
        QtGui.QWidget.__init__(self, parent)

        # store the logger instance
        if logger is None:
            self.logger = parent.parent.logger
        else:
            self.logger = logger

        self.audiobuffer = None

        self.setObjectName("Spectrum_Widget")
        self.gridLayout = QtGui.QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        #self.PlotZoneSpect = SpectPlot(self, self.logger)
        self.PlotZoneSpect = GLPlotWidget(self, self.logger)
        self.PlotZoneSpect.setObjectName("PlotZoneSpect")
        self.gridLayout.addWidget(self.PlotZoneSpect, 0, 0, 1, 1)

        self.setStyleSheet(STYLESHEET)

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

        self.maxfreq = DEFAULT_MAXFREQ
        self.minfreq = DEFAULT_MINFREQ
        self.fft_size = 2**DEFAULT_FFT_SIZE * 32
        self.spec_min = DEFAULT_SPEC_MIN
        self.spec_max = DEFAULT_SPEC_MAX
        self.weighting = DEFAULT_WEIGHTING
        self.dual_channels = False

        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.)

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

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

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

        floatdata = self.audiobuffer.data(self.fft_size)

        # first channel
        sp1, freq, A, B, C = self.proc.analyzelive(floatdata[0, :],
                                                   self.fft_size, self.maxfreq)

        if self.dual_channels and floatdata.shape[0] > 1:
            # second channel for comparison
            sp2, freq, A, B, C = self.proc.analyzelive(floatdata[1, :],
                                                       self.fft_size,
                                                       self.maxfreq)

            floatdata_delayed = self.audiobuffer.data_delayed(self.fft_size)
            sp1, freq, A, B, C = self.proc.analyzelive(floatdata_delayed[0, :],
                                                       self.fft_size,
                                                       self.maxfreq)

        #sp, freq = self.proc.analyzelive_cochlear(floatdata, 50, minfreq, maxfreq)
        # scale the db spectrum from [- spec_range db ... 0 db] > [0..1]
        #print freq[len(freq)/6], A[len(freq)/6]
        epsilon = 1e-30

        if self.weighting is 0:
            w = 0.
        elif self.weighting is 1:
            w = A
        elif self.weighting is 2:
            w = B
        else:
            w = C

    # the log operation and the weighting could be deffered
    # to the post-weedening !
        if self.dual_channels and floatdata.shape[0] > 1:
            db_spectrogram = 20 * log10(sp2 + epsilon) - 20 * log10(sp1 +
                                                                    epsilon)
        else:
            db_spectrogram = 20 * log10(sp1 + epsilon) + w

        self.PlotZoneSpect.setdata(freq, db_spectrogram)

    def setminfreq(self, freq):
        self.minfreq = freq
        self.PlotZoneSpect.setfreqrange(self.minfreq, self.maxfreq)

    def setmaxfreq(self, freq):
        self.maxfreq = freq
        self.PlotZoneSpect.setfreqrange(self.minfreq, self.maxfreq)

    def setfftsize(self, fft_size):
        self.fft_size = fft_size

    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)

    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 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)
Exemple #9
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)