Example #1
0
class LongLevelWidget(QtWidgets.QWidget):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setObjectName("LongLevels_Widget")

        self.setObjectName("Scope_Widget")
        self.gridLayout = QtWidgets.QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        self.PlotZoneUp = TimePlot(self)
        self.PlotZoneUp.setObjectName("PlotZoneUp")
        self.PlotZoneUp.setverticaltitle("Level (dB FS RMS)")
        self.PlotZoneUp.sethorizontaltitle("Time (sec)")
        self.PlotZoneUp.setTrackerFormatter(lambda x, y: "%.3g sec, %.3g" % (x, y))

        self.level_min = DEFAULT_LEVEL_MIN
        self.level_max = DEFAULT_LEVEL_MAX
        self.PlotZoneUp.setverticalrange(self.level_min, self.level_max)

        self.gridLayout.addWidget(self.PlotZoneUp, 0, 0, 1, 1)

        self.audiobuffer = None

        # initialize the settings dialog
        self.settings_dialog = LongLevels_Settings_Dialog(self)

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

        self.level = None  # 1e-30
        self.level_rms = -200.

        self.two_channels = False

        self.i = 0

        self.old_index = 0

        #Set the initial timespan and response time
        self.length_seconds = DEFAULT_MAXTIME
        self.setresptime(DEFAULT_RESPONSE_TIME)

        # ringbuffer for the subsampled data
        self.ringbuffer = RingBuffer()

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

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

        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 = int(2**self.Ndec)
        realizable = int(np.floor(available / needed))

        if realizable > 0:
            for i in range(realizable):
                floatdata = self.audiobuffer.data_indexed(self.old_index, needed)

                # first channel
                y0 = floatdata[0, :]

                y0_squared = y0**2

                # subsample
                y0_squared_dec = self.subsampler.push(y0_squared)

                self.level, self.zf = pyx_lfilter_float64_1D(self.b, self.a, y0_squared_dec, self.zf)

                self.level_rms = 10. * np.log10(max(self.level, 1e-150))

                l = np.array([self.level_rms])
                l.shape = (1, 1)

                self.ringbuffer.push(l)

                self.old_index += needed

            self.time = np.arange(self.length_samples) / self.subsampled_sampling_rate

            levels = self.ringbuffer.data(self.length_samples)

            self.PlotZoneUp.setdata(self.time/1., levels[0, :])

    # method
    def canvasUpdate(self):
        # nothing to do here
        return

    def setmin(self, value):
        self.level_min = value
        self.PlotZoneUp.setverticalrange(self.level_min, self.level_max)

    def setmax(self, value):
        self.level_max = value
        self.PlotZoneUp.setverticalrange(self.level_min, self.level_max)

    def setduration(self, value):
        self.length_seconds = value
        self.length_samples = int(self.length_seconds * self.subsampled_sampling_rate)
        self.PlotZoneUp.settimerange(0., self.length_seconds)

    def setresptime(self, value):
        self.response_time = value
        # how many times we should decimate to end up with 100 points in the kernel
        self.Ndec = int(max(0, np.floor((np.log2(self.response_time * SAMPLING_RATE/100.)))))

        Ngauss = 4
        self.b = np.array(gauss(10*Ngauss+1, 2.*Ngauss))
        self.a = np.zeros(self.b.shape)
        self.a[0] = 1.
        self.zf = np.zeros(max(len(self.b), len(self.a)) - 1)

        self.subsampled_sampling_rate = SAMPLING_RATE / 2 ** (self.Ndec)
        self.subsampler = Subsampler(self.Ndec)

        if self.length_seconds: 
            self.setduration(self.length_seconds)

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

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

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