Beispiel #1
0
    def initUI(self):
        aCfg = DRCConfig()
        self.uibuilder = Gtk.Builder()
        self.uibuilder.add_from_file(
            DependsWrapperImpl.find_plugin_file(self.parent, "DRCUI.glade"))
        self.dlg = self.uibuilder.get_object("DRCDlg")
        self.dlg.connect("close", self.on_close)
        audioFileFilter = Gtk.FileFilter()
        audioFileFilter.add_pattern("*.wav")
        audioFileFilter.add_pattern("*.pcm")
        audioFileFilter.add_pattern("*.raw")
        self.filechooserbtn = self.uibuilder.get_object(
            "drcfilterchooserbutton")
        self.filechooserbtn.set_filter(audioFileFilter)
        if os.path.isfile(aCfg.filterFile):
            self.filechooserbtn.set_filename(aCfg.filterFile)
        else:
            self.filechooserbtn.set_current_folder(self.getFilterResultsDir())

        self.filechooserbtn.connect("file-set", self.on_file_selected)
        self.entrySweepDuration = self.uibuilder.get_object(
            "entrySweepDuration")
        self.entrySweepDuration.set_text(str(aCfg.sweepDuration))

        self.progressbarInputVolume = self.uibuilder.get_object(
            "progressbarInputVolume")

        self.alsaPlayHardwareCombo = self.uibuilder.get_object("comboOutput")
        self.alsaRecHardwareCombo = self.uibuilder.get_object("comboRecord")
        self.comboSampleRate = self.uibuilder.get_object("comboSampleRate")

        self.execMeasureBtn = self.uibuilder.get_object("buttonMeassure")
        self.execMeasureBtn.connect("clicked", self.on_execMeasure)

        self.alsaDevices = AlsaDevices()
        alsaTools.fillComboFromDeviceList(self.alsaPlayHardwareCombo,
                                self.alsaDevices.alsaPlayDevs,
                                aCfg.playHardwareIndex)
        alsaTools.fillComboFromDeviceList(self.alsaRecHardwareCombo,
                                self.alsaDevices.alsaRecDevs,
                                aCfg.recHardwareIndex)
        self.alsaRecHardwareCombo.connect("changed", self.on_recDeviceChanged)
        self.comboInputChanel = self.uibuilder.get_object("comboInputChanel")
        self.comboInputChanel.set_active(aCfg.recHardwareChannelIndex)
        # fill the number of input channels
        self.updateRecDeviceInfo()
        self.comboInputChanel.connect("changed", self.on_InputChanelChanged)

        calcDRCBtn = self.uibuilder.get_object("buttonCalculateFilter")
        calcDRCBtn.connect("clicked", self.on_calculateDRC)

        slider = self.uibuilder.get_object("scaleSweepAmplitude")
        slider.set_range(0.1, 1)
        slider.set_value_pos(Gtk.PositionType.TOP)
        self.sweep_level = aCfg.recordGain
        slider.set_value(self.sweep_level)
        slider.connect("value_changed", self.slider_changed)

        apply_closeBtn = self.uibuilder.get_object("apply_closeBtn")
        apply_closeBtn.connect("clicked", self.on_apply_settings)

        cancel_closeBtn = self.uibuilder.get_object("cancelButton")
        cancel_closeBtn.connect("clicked", self.on_Cancel)

        self.buttonSetImpRespFile = self.uibuilder.get_object(
            "buttonSetImpRespFile")

        self.buttonSetImpRespFile.connect("clicked", self.on_setImpRespFiles)

        self.comboDRC = self.uibuilder.get_object("combo_drc_type")
        self.cfgDRCButton = self.uibuilder.get_object("cfgDRCButton")
        self.cfgDRCButton.connect("clicked", self.on_cfgDRC)
        self.comboDRC.append_text("DRC")
        self.comboDRC.append_text("PORC")
        self.comboDRC.set_active(0)
        self.comboDRC.connect("changed", self.on_DRCTypeChanged)
        self.on_DRCTypeChanged(self.comboDRC)
        self.drcCfgDlg = DRCCfgDlg(self.parent)
        self.porcCfgDlg = PORCCfgDlg(self.parent)
        self.channelSelDlg = ChanelSelDlg(self.parent)
        self.impRespDlg = ImpRespDlg(self, self.getMeasureResultsDir())
        self.targetCurveDlg = TargetCurveDlg(self.parent)

        self.exec_2ChannelMeasure = self.uibuilder.get_object(
            "checkbutton_2ChannelMeasure")
        self.exec_2ChannelMeasure.set_sensitive(True)

        self.spinbutton_NumChannels = self.uibuilder.get_object(
            "spinbutton_NumChannels")

        self.notebook = self.uibuilder.get_object("notebook1")
        self.volumeUpdateBlocked = False
        self.mode = None
        self.inputVolumeUpdate = InputVolumeProcess(
            self.progressbarInputVolume)
        self.comboboxFIRFilterMode = self.uibuilder.get_object(
            "comboboxFIRFilterMode")
        self.comboboxFIRFilterMode.set_active(aCfg.FIRFilterMode)
        self.comboboxFIRFilterMode.connect("changed",
            self.on_FIRFilterModeChanged)

        self.uibuilder.get_object("buttonTargetCurve").connect("clicked",
            self.on_EditTargetCurve)
Beispiel #2
0
class DRCDlg:
    def initUI(self):
        aCfg = DRCConfig()
        self.uibuilder = Gtk.Builder()
        self.uibuilder.add_from_file(
            DependsWrapperImpl.find_plugin_file(self.parent, "DRCUI.glade"))
        self.dlg = self.uibuilder.get_object("DRCDlg")
        self.dlg.connect("close", self.on_close)
        audioFileFilter = Gtk.FileFilter()
        audioFileFilter.add_pattern("*.wav")
        audioFileFilter.add_pattern("*.pcm")
        audioFileFilter.add_pattern("*.raw")
        self.filechooserbtn = self.uibuilder.get_object(
            "drcfilterchooserbutton")
        self.filechooserbtn.set_filter(audioFileFilter)
        if os.path.isfile(aCfg.filterFile):
            self.filechooserbtn.set_filename(aCfg.filterFile)
        else:
            self.filechooserbtn.set_current_folder(self.getFilterResultsDir())

        self.filechooserbtn.connect("file-set", self.on_file_selected)
        self.entrySweepDuration = self.uibuilder.get_object(
            "entrySweepDuration")
        self.entrySweepDuration.set_text(str(aCfg.sweepDuration))

        self.progressbarInputVolume = self.uibuilder.get_object(
            "progressbarInputVolume")

        self.alsaPlayHardwareCombo = self.uibuilder.get_object("comboOutput")
        self.alsaRecHardwareCombo = self.uibuilder.get_object("comboRecord")
        self.comboSampleRate = self.uibuilder.get_object("comboSampleRate")

        self.execMeasureBtn = self.uibuilder.get_object("buttonMeassure")
        self.execMeasureBtn.connect("clicked", self.on_execMeasure)

        self.alsaDevices = AlsaDevices()
        alsaTools.fillComboFromDeviceList(self.alsaPlayHardwareCombo,
                                self.alsaDevices.alsaPlayDevs,
                                aCfg.playHardwareIndex)
        alsaTools.fillComboFromDeviceList(self.alsaRecHardwareCombo,
                                self.alsaDevices.alsaRecDevs,
                                aCfg.recHardwareIndex)
        self.alsaRecHardwareCombo.connect("changed", self.on_recDeviceChanged)
        self.comboInputChanel = self.uibuilder.get_object("comboInputChanel")
        self.comboInputChanel.set_active(aCfg.recHardwareChannelIndex)
        # fill the number of input channels
        self.updateRecDeviceInfo()
        self.comboInputChanel.connect("changed", self.on_InputChanelChanged)

        calcDRCBtn = self.uibuilder.get_object("buttonCalculateFilter")
        calcDRCBtn.connect("clicked", self.on_calculateDRC)

        slider = self.uibuilder.get_object("scaleSweepAmplitude")
        slider.set_range(0.1, 1)
        slider.set_value_pos(Gtk.PositionType.TOP)
        self.sweep_level = aCfg.recordGain
        slider.set_value(self.sweep_level)
        slider.connect("value_changed", self.slider_changed)

        apply_closeBtn = self.uibuilder.get_object("apply_closeBtn")
        apply_closeBtn.connect("clicked", self.on_apply_settings)

        cancel_closeBtn = self.uibuilder.get_object("cancelButton")
        cancel_closeBtn.connect("clicked", self.on_Cancel)

        self.buttonSetImpRespFile = self.uibuilder.get_object(
            "buttonSetImpRespFile")

        self.buttonSetImpRespFile.connect("clicked", self.on_setImpRespFiles)

        self.comboDRC = self.uibuilder.get_object("combo_drc_type")
        self.cfgDRCButton = self.uibuilder.get_object("cfgDRCButton")
        self.cfgDRCButton.connect("clicked", self.on_cfgDRC)
        self.comboDRC.append_text("DRC")
        self.comboDRC.append_text("PORC")
        self.comboDRC.set_active(0)
        self.comboDRC.connect("changed", self.on_DRCTypeChanged)
        self.on_DRCTypeChanged(self.comboDRC)
        self.drcCfgDlg = DRCCfgDlg(self.parent)
        self.porcCfgDlg = PORCCfgDlg(self.parent)
        self.channelSelDlg = ChanelSelDlg(self.parent)
        self.impRespDlg = ImpRespDlg(self, self.getMeasureResultsDir())
        self.targetCurveDlg = TargetCurveDlg(self.parent)

        self.exec_2ChannelMeasure = self.uibuilder.get_object(
            "checkbutton_2ChannelMeasure")
        self.exec_2ChannelMeasure.set_sensitive(True)

        self.spinbutton_NumChannels = self.uibuilder.get_object(
            "spinbutton_NumChannels")

        self.notebook = self.uibuilder.get_object("notebook1")
        self.volumeUpdateBlocked = False
        self.mode = None
        self.inputVolumeUpdate = InputVolumeProcess(
            self.progressbarInputVolume)
        self.comboboxFIRFilterMode = self.uibuilder.get_object(
            "comboboxFIRFilterMode")
        self.comboboxFIRFilterMode.set_active(aCfg.FIRFilterMode)
        self.comboboxFIRFilterMode.connect("changed",
            self.on_FIRFilterModeChanged)

        self.uibuilder.get_object("buttonTargetCurve").connect("clicked",
            self.on_EditTargetCurve)

    def __init__(self, parent):
        self.parent = parent

    def on_EditTargetCurve(self, button):
        impRespFile = self.impRespDlg.getImpRespFiles()[0].fileName
        self.targetCurveDlg.setImpRespFile(impRespFile)
        self.targetCurveDlg.run()

    def startInputVolumeUpdate(self, channel=None):
        if channel is None:
            channel = self.comboInputChanel.get_active_text()
        if not self.volumeUpdateBlocked:
            self.inputVolumeUpdate.start(self.getAlsaRecordHardwareString(),
                                         channel, self.mode)

    def on_setImpRespFiles(self, button):
        self.impRespDlg.run()

    def on_InputChanelChanged(self, combo):
        self.startInputVolumeUpdate(combo.get_active_text())

    def getAlsaPlayHardwareString(self):
        alsHardwareSelIndex = self.alsaPlayHardwareCombo.get_active()
        alsaPlayHw="hw:0,0"
        if len(self.alsaDevices.alsaPlayDevs) > alsHardwareSelIndex:
            alsaPlayHw = self.alsaDevices.alsaPlayDevs[alsHardwareSelIndex].alsaHW
        else:
            print( "getAlsaPlayHardwareString:!!!!no recording device found!!!! : ", numAlsaRecDev, alsHardwareSelIndex )

        return alsaPlayHw

    def getAlsaRecordHardwareString(self):
        alsHardwareSelIndex = int(self.alsaRecHardwareCombo.get_active())
        alsaRecHw="hw:0,0"
        numAlsaRecDev = int(len(self.alsaDevices.alsaRecDevs))
        if numAlsaRecDev > alsHardwareSelIndex:
            alsaRecHw = self.alsaDevices.alsaRecDevs[alsHardwareSelIndex].alsaHW
        else:
            print( "getAlsaRecordHardwareString:!!!!no recording device found!!!! : ", numAlsaRecDev, alsHardwareSelIndex )
        return alsaRecHw

    def updateRecDeviceInfo(self):
        self.comboInputChanel.remove_all()
        self.volumeUpdateBlocked = True
        alsHardwareSelIndex = self.alsaRecHardwareCombo.get_active()
        currAlsaDev = "hw:0,0"
        if len(self.alsaDevices.alsaRecDevs) > alsHardwareSelIndex:
            currAlsaDev = self.alsaDevices.alsaRecDevs[alsHardwareSelIndex]
            currAlsaDev.loadDeviceInfo()
            for chanel in range(0, currAlsaDev.MaxChannel):
                self.comboInputChanel.append_text(str(chanel+1))

            self.comboInputChanel.set_active(0)
            self.comboSampleRate.remove_all()
            all_rates = [44100,48000,96000,192000]
            for rate in all_rates:
                if rate >= currAlsaDev.MinRate and rate <=  currAlsaDev.MaxRate:
                    self.comboSampleRate.append_text(str(rate))
            self.comboSampleRate.set_active(0)
            self.volumeUpdateBlocked = False
        else:
            print( "!!!!updateRecDeviceInfo:no recording device found!!!! : ", numAlsaRecDev, alsHardwareSelIndex )


    def on_recDeviceChanged(self, combo):
        self.updateRecDeviceInfo()

    def on_cfgDRC(self, button):
        drcMethod = self.comboDRC.get_active_text()
        if drcMethod == "DRC":
            self.drcCfgDlg.run()
        else:
            self.porcCfgDlg.run()

    def on_DRCTypeChanged(self, combo):
        drcMethod = combo.get_active_text()
        if drcMethod == "DRC":
            self.cfgDRCButton.set_label("configure DRC")
        else:
            self.cfgDRCButton.set_label("configure PORC")
            drcScript = [DependsWrapperImpl.find_plugin_file(self.parent, "calcFilterDRC")]
            pluginPath = os.path.dirname(os.path.abspath(drcScript[0]))
            porcTargetCurve = pluginPath + "/porc/data/tact30f.txt"
            if not os.path.exists(porcTargetCurve):
                print("installing PORC")
                installScript = DependsWrapperImpl.find_plugin_file(self.parent, 
                                                    "installPORC.sh")
                pluginPath = os.path.dirname(installScript)
                porcInstCommand = "xterm -e " + installScript + " " + \
                                  pluginPath
                subprocess.call(porcInstCommand, shell=True)

    def slider_changed(self, hscale):
        self.sweep_level = hscale.get_value()

    def set_filter(self):
        DrcFilename = self.filechooserbtn.get_filename()
        self.parent.updateFilter(DrcFilename)

    def on_file_selected(self, widget):
        filterFile = widget.get_filename()
        if os.path.isfile(filterFile):
            self.saveSettings()

    def saveSettings(self):
        aCfg = DRCConfig()
        aCfg.filterFile = self.filechooserbtn.get_filename()
        aCfg.recordGain = self.sweep_level
        aCfg.sweepDuration = int(self.entrySweepDuration.get_text())
        aCfg.FIRFilterMode = self.comboboxFIRFilterMode.get_active()
        aCfg.playHardwareIndex = self.alsaPlayHardwareCombo.get_active()
        aCfg.recHardwareIndex = self.alsaRecHardwareCombo.get_active()
        aCfg.recHardwareChannelIndex = self.comboInputChanel.get_active()
        fileExt = os.path.splitext(aCfg.filterFile)[-1]
        print(("ext = " + fileExt))
        if fileExt != ".wav":
            if self.channelSelDlg.run() == Gtk.ResponseType.OK:
                aCfg.numFilterChanels = self.channelSelDlg.getNumChannels()
        aCfg.save()

    def on_apply_settings(self, some_param):
        self.saveSettings()
        self.dlg.set_visible(False)

    def updateBruteFIRCfg(self, enable):
        updateBruteFIRScript = [DependsWrapperImpl.find_plugin_file(self.parent, "updateBruteFIRCfg")]
        if enable is True:
            self.comboboxFIRFilterMode.set_active(2)
            updateBruteFIRScript.append(self.getAlsaPlayHardwareString())
            updateBruteFIRScript.append(self.filechooserbtn.get_filename())
        print('create bruteFIRConfig and start/install bruteFIR')
        updateBruteFIRCommand = "xterm -e " + " ".join(updateBruteFIRScript)
        subprocess.call(updateBruteFIRCommand, shell=True)

    def on_applyFilterBruteFIR(self):
        self.updateBruteFIRCfg(True)
        self.saveSettings()
        self.set_filter()

    def on_applyFilterGST(self):
        self.comboboxFIRFilterMode.set_active(1)
        self.saveSettings()
        self.set_filter()
        self.updateBruteFIRCfg(False)

    def disableFiltering(self):
        self.comboboxFIRFilterMode.set_active(0)
        self.saveSettings()
        self.set_filter()
        self.updateBruteFIRCfg(False)

    def on_FIRFilterModeChanged(self, some_param):
        FIRFilterMode = self.comboboxFIRFilterMode.get_active()
        if FIRFilterMode is 0:
            self.disableFiltering()
        elif FIRFilterMode is 1:
            self.on_applyFilterGST()
        else:
            self.on_applyFilterBruteFIR()

    def getMeasureResultsDir(self):
        cachedir = RB.user_cache_dir() + "/DRC"
        measureResultsDir = cachedir + "/MeasureResults"
        if not os.path.exists(measureResultsDir):
            os.makedirs(measureResultsDir)
        return measureResultsDir

    def on_execMeasure(self, param):
        self.inputVolumeUpdate.stop()

        # TODO: make the measure script output the volume and parse from
        # there during measurement
        scriptName = DependsWrapperImpl.find_plugin_file(self.parent, "measure1Channel")
        #create new folder for this complete measurement
        strResultsDir = self.getMeasureResultsDir() + "/" +\
                        datetime.datetime.now().strftime("%Y%m%d%H%M%S_") + \
                        str(self.entrySweepDuration.get_text())
        os.makedirs(strResultsDir)
        raw_sweep_file_base_name = "/tmp/msrawsweep.pcm"
        raw_sweep_recorded_base_name = "/tmp/msrecsweep0.pcm"
        evalDlg = MeasureQADlg(self.parent, raw_sweep_file_base_name,
                           raw_sweep_recorded_base_name, self.sweep_level)
        iterLoopMeasure = 0
        acquiredImpResFiles = []
        while(True):
            impOutputFile = strResultsDir + "/" + str(iterLoopMeasure) + ".wav"
            # execute measure script to generate filters
            commandLine = [scriptName, str(self.sweep_level),
                       self.getAlsaRecordHardwareString(),
                       self.getAlsaPlayHardwareString(),
                       "10",
                       "22050",
                       str(self.entrySweepDuration.get_text()),
                       impOutputFile,
                       self.comboInputChanel.get_active_text(),
                       str(self.exec_2ChannelMeasure.get_active()),
                       str(int(self.spinbutton_NumChannels.get_value())),
                       str(self.comboSampleRate.get_active_text())]
            p = subprocess.Popen(commandLine, 0, None, None, subprocess.PIPE,
                             subprocess.PIPE)
            (out, err) = p.communicate()
            print(("output from measure script : " + str(out) + " error : "
                + str(None)))
            # quality check:sweep file and measured result
            evalDlg.setImpRespFileName(impOutputFile)
            evalDlg.run()
            iterLoopMeasure += 1
            if evalDlg.Result == MeasureQARetVal.Reject:
                continue
            acquiredImpResFiles.append(evalDlg.impRespFile)
            if evalDlg.Result == MeasureQARetVal.Done:
                break
        self.impRespDlg.removeAll()
        self.impRespDlg.setFiles(acquiredImpResFiles)
        self.notebook.next_page()

    def changeCfgParamDRC(self, bufferStr, changeArray):
        newBuff = bufferStr
        for i in range(0, len(changeArray)):
            changeParams = changeArray[i]
            searchStr = changeParams[0] + " = "
            paramStart = bufferStr.find(searchStr)
            if paramStart > -1:
                paramEnd = bufferStr.find("\n", paramStart)
                if paramEnd > -1:
                    newBuff = bufferStr[0:paramStart + len(searchStr)] + \
                              changeParams[1] + bufferStr[
                                                paramEnd:len(bufferStr)]
            bufferStr = newBuff
        return newBuff

    def getTmpCfgDir(self):
        cachedir = RB.user_cache_dir() + "/DRC"
        tmpCfgDir = cachedir + "/TmpDRCCfg"
        if not os.path.exists(tmpCfgDir):
            os.makedirs(tmpCfgDir)
        return tmpCfgDir

    def prepareDRC(self, impRespFile, filterResultFile, targetCurveFile):
        drcScript = [DependsWrapperImpl.find_plugin_file(self.parent, "calcFilterDRC")]
        drcCfgFileName = os.path.basename(self.drcCfgDlg.getBaseCfg())
        print(("drcCfgBaseName : " + drcCfgFileName))
        drcCfgSrcFile = self.drcCfgDlg.getBaseCfg()
        drcCfgDestFile = self.getTmpCfgDir() + "/" + drcCfgFileName
        drcScript.append(drcCfgDestFile)
        print(("drcCfgDestFile : " + drcCfgDestFile))
        # update filter file
        srcDrcCfgFile = open(drcCfgSrcFile, "r")
        srcData = srcDrcCfgFile.read()
        micCalFile = self.drcCfgDlg.getMicCalibrationFile()
        normMethod = self.drcCfgDlg.getNormMethod()
        changeCfgFileArray = [["BCInFile", impRespFile],
                              ["PSPointsFile",
                                targetCurveFile],
                              ["PSNormType", normMethod]
                             ]
        if micCalFile is not None:
            changeCfgFileArray.append(["MCFilterType", "M"])
            changeCfgFileArray.append(["MCPointsFile", micCalFile])
        else:
            changeCfgFileArray.append(["MCFilterType", "N"])
        destData = self.changeCfgParamDRC(srcData, changeCfgFileArray)
        destDrcCfgFile = open(drcCfgDestFile, "w")
        destDrcCfgFile.write(destData)
        destDrcCfgFile.close()
        return drcScript

    def showMsgBox(self, msg):
        dlg = Gtk.MessageDialog(self.dlg, Gtk.DialogFlags.MODAL,
                                Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE,
                                msg)
        dlg.run()
        dlg.destroy()

    def getFilterResultsDir(self):
        cachedir = RB.user_cache_dir() + "/DRC"
        filterResultsDir = cachedir + "/DRCFilters"
        if not os.path.exists(filterResultsDir):
            print(
                ("DRC cache dir does not exist : creating -> " +
                filterResultsDir))
            os.makedirs(filterResultsDir)
        return filterResultsDir

    def getSampleShift(self, distanceInCentimeter):
        return int((1.2849 * distanceInCentimeter) + 0.5)

    def calculateAvgImpResponse(self, files):
        projectDir = os.path.dirname(os.path.abspath(files[0].fileName))
        impOutputFile = projectDir + "/impOutputFile"\
                + datetime.datetime.now().strftime("%Y%m%d%H%M%S_") + "avg.wav"
        maxValueStartOffset = 32768
        maxValueEndOffset = 32768
        avgImpulseLength = maxValueEndOffset + maxValueStartOffset
        #loop over all impulse responses for all chanels and
        #calculate average response
        result = DRCFileTool.WaveParams()
        avgData = []
        for currFileInfo in files:
            params = DRCFileTool.LoadWaveFile(currFileInfo.fileName)
            result = DRCFileTool.WaveParams(params.numChannels)
            for chanel in range(0, params.numChannels):
                if len(avgData) <= chanel:
                    arr = [float(0.0)] * avgImpulseLength
                    avgData.append(arr)
                impulseStart = params.maxSampleValuePos[chanel] - \
                        maxValueStartOffset + self.getSampleShift(
                            currFileInfo.centerDistanceInCentimeter)
                print(("impulseStart:", impulseStart))
                for index in range(0, avgImpulseLength):
                    avgData[chanel][index] += float(params.data[chanel][
                        impulseStart + index] *
                            currFileInfo.weightingFactor)
                    #print(("avgData[chanel][index] : ",
                    #    avgData[chanel][index],
                    #    params.data[chanel][impulseStart + index]))
        #write the avg result to the result
        result.data = avgData
        print(("numChans Avg :", params.numChannels, result.numChannels,
            impOutputFile))
        DRCFileTool.WriteWaveFile(result, impOutputFile)
        return impOutputFile

    def on_calculateDRC(self, param):
        drcMethod = self.comboDRC.get_active_text()
        drcScript = [DependsWrapperImpl.find_plugin_file(self.parent, "calcFilterDRC")]
        pluginPath = os.path.dirname(os.path.abspath(drcScript[0]))
        filterResultFile = self.getFilterResultsDir() + "/Filter" + str(
            drcMethod) + datetime.datetime.now().strftime(
            "%Y%m%d%H%M%S") + ".wav"
        impRespFiles = self.impRespDlg.getImpRespFiles()
        #get number of channels from impRespFiles and loop over
        numChannels = DRCFileTool.getNumChannels(impRespFiles[0].fileName)
        #go through all impRespFiles, average them and pass the
        #result to the impRespFile
        avgImpRespFile = self.calculateAvgImpResponse(impRespFiles)
        soxMergeCall = ["sox", "-M"]
        channelFilterFile = ""
        for currChannel in range(0, numChannels):
            channelFilterFile = "/tmp/filter" + str(currChannel) + ".wav"
            soxMergeCall.append(channelFilterFile)
            #get target curve filename per channel
            targetCurveFileName = self.targetCurveDlg.getTargetCurveFileName(
                currChannel)
            if avgImpRespFile is None:
                self.showMsgBox("no file loaded")
                return
            if drcMethod == "DRC":
                drcScript = self.prepareDRC(avgImpRespFile, channelFilterFile,
                    targetCurveFileName)
                drcScript.append(avgImpRespFile)
                drcScript.append(channelFilterFile)
                drcScript.append(str(currChannel))
            elif drcMethod == "PORC":
                drcScript = [DependsWrapperImpl.find_plugin_file(self.parent, "calcFilterPORC")]
                porcCommand = pluginPath + "/porc/porc.py"
                if not os.path.isfile(porcCommand):
                    self.showMsgBox(
                        "porc.py not found. Please download from github and "
                        "install in the DRC plugin subfolder 'porc'")
                    return
                drcScript.append(porcCommand)
                drcScript.append(avgImpRespFile)
                drcScript.append(channelFilterFile)
                drcScript.append(str(currChannel))
                drcScript.append(targetCurveFileName)
                if self.porcCfgDlg.getMixedPhaseEnabled():
                    drcScript.append("--mixed")
            print(("drc command line: " + str(drcScript)))
            p = subprocess.Popen(drcScript, 0, None, None, subprocess.PIPE,
                                 subprocess.PIPE)
            (out, err) = p.communicate()
            print(("output from filter calculate script : " + str(out)))
        #use sox to merge all results to one filter file
        soxMergeCall.append(filterResultFile)
        p = subprocess.Popen(soxMergeCall, 0, None, None, subprocess.PIPE,
            subprocess.PIPE)
        print(("output from sox filter merge : " + str(out)))
        self.filechooserbtn.set_filename(filterResultFile)
        self.set_filter()
        self.notebook.next_page()

    def on_close(self, shell):
        print("closing ui")
        self.inputVolumeUpdate.stop()
        self.dlg.set_visible(False)
        return True

    def show_ui(self, shell, state, dummy):
        print("showing UI")
        self.initUI()
        self.startInputVolumeUpdate()
        if shell is None:
            self.dlg.run()
        else:
            self.dlg.show_all()
            self.dlg.present()
        self.inputVolumeUpdate.stop()
        print("done showing UI")

    def on_destroy(self, widget, data):
        self.on_close(None)
        return True

    def on_Cancel(self, some_param):
        self.dlg.set_visible(False)
        self.inputVolumeUpdate.stop()
Beispiel #3
0
class DRCDlg:
    def initUI(self):
        aCfg = DRCConfig()
        self.uibuilder = Gtk.Builder()
        self.uibuilder.add_from_file(
            DependsWrapperImpl.find_plugin_file(self.parent, "DRCUI.glade"))
        self.dlg = self.uibuilder.get_object("DRCDlg")
        self.dlg.connect("close", self.on_close)
        audioFileFilter = Gtk.FileFilter()
        audioFileFilter.add_pattern("*.wav")
        audioFileFilter.add_pattern("*.pcm")
        audioFileFilter.add_pattern("*.raw")
        self.filechooserbtn = self.uibuilder.get_object(
            "drcfilterchooserbutton")
        self.filechooserbtn.set_filter(audioFileFilter)
        if os.path.isfile(aCfg.filterFile):
            self.filechooserbtn.set_filename(aCfg.filterFile)
        else:
            self.filechooserbtn.set_current_folder(self.getFilterResultsDir())

        self.filechooserbtn.connect("file-set", self.on_file_selected)
        self.entrySweepDuration = self.uibuilder.get_object(
            "entrySweepDuration")
        self.entrySweepDuration.set_text(str(aCfg.sweepDuration))

        self.progressbarInputVolume = self.uibuilder.get_object(
            "progressbarInputVolume")

        self.alsaPlayHardwareCombo = self.uibuilder.get_object("comboOutput")
        self.alsaRecHardwareCombo = self.uibuilder.get_object("comboRecord")
        self.comboSampleRate = self.uibuilder.get_object("comboSampleRate")

        self.execMeasureBtn = self.uibuilder.get_object("buttonMeassure")
        self.execMeasureBtn.connect("clicked", self.on_execMeasure)

        self.alsaDevices = AlsaDevices()
        alsaTools.fillComboFromDeviceList(self.alsaPlayHardwareCombo,
                                          self.alsaDevices.alsaPlayDevs,
                                          aCfg.playHardwareIndex)
        alsaTools.fillComboFromDeviceList(self.alsaRecHardwareCombo,
                                          self.alsaDevices.alsaRecDevs,
                                          aCfg.recHardwareIndex)
        self.alsaRecHardwareCombo.connect("changed", self.on_recDeviceChanged)
        self.comboInputChanel = self.uibuilder.get_object("comboInputChanel")
        self.comboInputChanel.set_active(aCfg.recHardwareChannelIndex)
        # fill the number of input channels
        self.updateRecDeviceInfo()
        self.comboInputChanel.connect("changed", self.on_InputChanelChanged)

        calcDRCBtn = self.uibuilder.get_object("buttonCalculateFilter")
        calcDRCBtn.connect("clicked", self.on_calculateDRC)

        slider = self.uibuilder.get_object("scaleSweepAmplitude")
        slider.set_range(0.1, 1)
        slider.set_value_pos(Gtk.PositionType.TOP)
        self.sweep_level = aCfg.recordGain
        slider.set_value(self.sweep_level)
        slider.connect("value_changed", self.slider_changed)

        apply_closeBtn = self.uibuilder.get_object("apply_closeBtn")
        apply_closeBtn.connect("clicked", self.on_apply_settings)

        cancel_closeBtn = self.uibuilder.get_object("cancelButton")
        cancel_closeBtn.connect("clicked", self.on_Cancel)

        self.buttonSetImpRespFile = self.uibuilder.get_object(
            "buttonSetImpRespFile")

        self.buttonSetImpRespFile.connect("clicked", self.on_setImpRespFiles)

        self.comboDRC = self.uibuilder.get_object("combo_drc_type")
        self.cfgDRCButton = self.uibuilder.get_object("cfgDRCButton")
        self.cfgDRCButton.connect("clicked", self.on_cfgDRC)
        self.comboDRC.append_text("DRC")
        self.comboDRC.append_text("PORC")
        self.comboDRC.set_active(0)
        self.comboDRC.connect("changed", self.on_DRCTypeChanged)
        self.on_DRCTypeChanged(self.comboDRC)
        self.drcCfgDlg = DRCCfgDlg(self.parent)
        self.porcCfgDlg = PORCCfgDlg(self.parent)
        self.channelSelDlg = ChanelSelDlg(self.parent)
        self.impRespDlg = ImpRespDlg(self, self.getMeasureResultsDir())
        self.targetCurveDlg = TargetCurveDlg(self.parent)

        self.exec_2ChannelMeasure = self.uibuilder.get_object(
            "checkbutton_2ChannelMeasure")
        self.exec_2ChannelMeasure.set_sensitive(True)

        self.spinbutton_NumChannels = self.uibuilder.get_object(
            "spinbutton_NumChannels")

        self.notebook = self.uibuilder.get_object("notebook1")
        self.volumeUpdateBlocked = False
        self.mode = None
        self.inputVolumeUpdate = InputVolumeProcess(
            self.progressbarInputVolume)
        self.comboboxFIRFilterMode = self.uibuilder.get_object(
            "comboboxFIRFilterMode")
        self.comboboxFIRFilterMode.set_active(aCfg.FIRFilterMode)
        self.comboboxFIRFilterMode.connect("changed",
                                           self.on_FIRFilterModeChanged)

        self.uibuilder.get_object("buttonTargetCurve").connect(
            "clicked", self.on_EditTargetCurve)

    def __init__(self, parent):
        self.parent = parent

    def on_EditTargetCurve(self, button):
        impRespFile = self.impRespDlg.getImpRespFiles()[0].fileName
        self.targetCurveDlg.setImpRespFile(impRespFile)
        self.targetCurveDlg.run()

    def startInputVolumeUpdate(self, channel=None):
        if channel is None:
            channel = self.comboInputChanel.get_active_text()
        if not self.volumeUpdateBlocked:
            self.inputVolumeUpdate.start(self.getAlsaRecordHardwareString(),
                                         channel, self.mode)

    def on_setImpRespFiles(self, button):
        self.impRespDlg.run()

    def on_InputChanelChanged(self, combo):
        self.startInputVolumeUpdate(combo.get_active_text())

    def getAlsaPlayHardwareString(self):
        alsHardwareSelIndex = self.alsaPlayHardwareCombo.get_active()
        alsaPlayHw = "hw:0,0"
        if len(self.alsaDevices.alsaPlayDevs) > alsHardwareSelIndex:
            alsaPlayHw = self.alsaDevices.alsaPlayDevs[
                alsHardwareSelIndex].alsaHW
        else:
            print(
                "getAlsaPlayHardwareString:!!!!no recording device found!!!! : ",
                numAlsaRecDev, alsHardwareSelIndex)

        return alsaPlayHw

    def getAlsaRecordHardwareString(self):
        alsHardwareSelIndex = int(self.alsaRecHardwareCombo.get_active())
        alsaRecHw = "hw:0,0"
        numAlsaRecDev = int(len(self.alsaDevices.alsaRecDevs))
        if numAlsaRecDev > alsHardwareSelIndex:
            alsaRecHw = self.alsaDevices.alsaRecDevs[
                alsHardwareSelIndex].alsaHW
        else:
            print(
                "getAlsaRecordHardwareString:!!!!no recording device found!!!! : ",
                numAlsaRecDev, alsHardwareSelIndex)
        return alsaRecHw

    def updateRecDeviceInfo(self):
        self.comboInputChanel.remove_all()
        self.volumeUpdateBlocked = True
        alsHardwareSelIndex = self.alsaRecHardwareCombo.get_active()
        currAlsaDev = "hw:0,0"
        if len(self.alsaDevices.alsaRecDevs) > alsHardwareSelIndex:
            currAlsaDev = self.alsaDevices.alsaRecDevs[alsHardwareSelIndex]
            currAlsaDev.loadDeviceInfo()
            for chanel in range(0, currAlsaDev.MaxChannel):
                self.comboInputChanel.append_text(str(chanel + 1))

            self.comboInputChanel.set_active(0)
            self.comboSampleRate.remove_all()
            all_rates = [44100, 48000, 96000, 192000]
            for rate in all_rates:
                if rate >= currAlsaDev.MinRate and rate <= currAlsaDev.MaxRate:
                    self.comboSampleRate.append_text(str(rate))
            self.comboSampleRate.set_active(0)
            self.volumeUpdateBlocked = False
        else:
            print("!!!!updateRecDeviceInfo:no recording device found!!!! : ",
                  numAlsaRecDev, alsHardwareSelIndex)

    def on_recDeviceChanged(self, combo):
        self.updateRecDeviceInfo()

    def on_cfgDRC(self, button):
        drcMethod = self.comboDRC.get_active_text()
        if drcMethod == "DRC":
            self.drcCfgDlg.run()
        else:
            self.porcCfgDlg.run()

    def on_DRCTypeChanged(self, combo):
        drcMethod = combo.get_active_text()
        if drcMethod == "DRC":
            self.cfgDRCButton.set_label("configure DRC")
        else:
            self.cfgDRCButton.set_label("configure PORC")
            drcScript = [
                DependsWrapperImpl.find_plugin_file(self.parent,
                                                    "calcFilterDRC")
            ]
            pluginPath = os.path.dirname(os.path.abspath(drcScript[0]))
            porcTargetCurve = pluginPath + "/porc/data/tact30f.txt"
            if not os.path.exists(porcTargetCurve):
                print("installing PORC")
                installScript = DependsWrapperImpl.find_plugin_file(
                    self.parent, "installPORC.sh")
                pluginPath = os.path.dirname(installScript)
                porcInstCommand = "xterm -e " + installScript + " " + \
                                  pluginPath
                subprocess.call(porcInstCommand, shell=True)

    def slider_changed(self, hscale):
        self.sweep_level = hscale.get_value()

    def set_filter(self):
        DrcFilename = self.filechooserbtn.get_filename()
        self.parent.updateFilter(DrcFilename)

    def on_file_selected(self, widget):
        filterFile = widget.get_filename()
        if os.path.isfile(filterFile):
            self.saveSettings()

    def saveSettings(self):
        aCfg = DRCConfig()
        aCfg.filterFile = self.filechooserbtn.get_filename()
        aCfg.recordGain = self.sweep_level
        aCfg.sweepDuration = int(self.entrySweepDuration.get_text())
        aCfg.FIRFilterMode = self.comboboxFIRFilterMode.get_active()
        aCfg.playHardwareIndex = self.alsaPlayHardwareCombo.get_active()
        aCfg.recHardwareIndex = self.alsaRecHardwareCombo.get_active()
        aCfg.recHardwareChannelIndex = self.comboInputChanel.get_active()
        fileExt = os.path.splitext(aCfg.filterFile)[-1]
        print(("ext = " + fileExt))
        if fileExt != ".wav":
            if self.channelSelDlg.run() == Gtk.ResponseType.OK:
                aCfg.numFilterChanels = self.channelSelDlg.getNumChannels()
        aCfg.save()

    def on_apply_settings(self, some_param):
        self.saveSettings()
        self.dlg.set_visible(False)

    def updateBruteFIRCfg(self, enable):
        updateBruteFIRScript = [
            DependsWrapperImpl.find_plugin_file(self.parent,
                                                "updateBruteFIRCfg")
        ]
        if enable is True:
            self.comboboxFIRFilterMode.set_active(2)
            updateBruteFIRScript.append(self.getAlsaPlayHardwareString())
            updateBruteFIRScript.append(self.filechooserbtn.get_filename())
        print('create bruteFIRConfig and start/install bruteFIR')
        updateBruteFIRCommand = "xterm -e " + " ".join(updateBruteFIRScript)
        subprocess.call(updateBruteFIRCommand, shell=True)

    def on_applyFilterBruteFIR(self):
        self.updateBruteFIRCfg(True)
        self.saveSettings()
        self.set_filter()

    def on_applyFilterGST(self):
        self.comboboxFIRFilterMode.set_active(1)
        self.saveSettings()
        self.set_filter()
        self.updateBruteFIRCfg(False)

    def disableFiltering(self):
        self.comboboxFIRFilterMode.set_active(0)
        self.saveSettings()
        self.set_filter()
        self.updateBruteFIRCfg(False)

    def on_FIRFilterModeChanged(self, some_param):
        FIRFilterMode = self.comboboxFIRFilterMode.get_active()
        if FIRFilterMode is 0:
            self.disableFiltering()
        elif FIRFilterMode is 1:
            self.on_applyFilterGST()
        else:
            self.on_applyFilterBruteFIR()

    def getMeasureResultsDir(self):
        cachedir = RB.user_cache_dir() + "/DRC"
        measureResultsDir = cachedir + "/MeasureResults"
        if not os.path.exists(measureResultsDir):
            os.makedirs(measureResultsDir)
        return measureResultsDir

    def on_execMeasure(self, param):
        self.inputVolumeUpdate.stop()

        # TODO: make the measure script output the volume and parse from
        # there during measurement
        scriptName = DependsWrapperImpl.find_plugin_file(
            self.parent, "measure1Channel")
        #create new folder for this complete measurement
        strResultsDir = self.getMeasureResultsDir() + "/" +\
                        datetime.datetime.now().strftime("%Y%m%d%H%M%S_") + \
                        str(self.entrySweepDuration.get_text())
        os.makedirs(strResultsDir)
        raw_sweep_file_base_name = "/tmp/msrawsweep.pcm"
        raw_sweep_recorded_base_name = "/tmp/msrecsweep0.pcm"
        evalDlg = MeasureQADlg(self.parent, raw_sweep_file_base_name,
                               raw_sweep_recorded_base_name, self.sweep_level)
        iterLoopMeasure = 0
        acquiredImpResFiles = []
        while (True):
            impOutputFile = strResultsDir + "/" + str(iterLoopMeasure) + ".wav"
            # execute measure script to generate filters
            commandLine = [
                scriptName,
                str(self.sweep_level),
                self.getAlsaRecordHardwareString(),
                self.getAlsaPlayHardwareString(), "10", "22050",
                str(self.entrySweepDuration.get_text()), impOutputFile,
                self.comboInputChanel.get_active_text(),
                str(self.exec_2ChannelMeasure.get_active()),
                str(int(self.spinbutton_NumChannels.get_value())),
                str(self.comboSampleRate.get_active_text())
            ]
            p = subprocess.Popen(commandLine, 0, None, None, subprocess.PIPE,
                                 subprocess.PIPE)
            (out, err) = p.communicate()
            print(("output from measure script : " + str(out) + " error : " +
                   str(None)))
            # quality check:sweep file and measured result
            evalDlg.setImpRespFileName(impOutputFile)
            evalDlg.run()
            iterLoopMeasure += 1
            if evalDlg.Result == MeasureQARetVal.Reject:
                continue
            acquiredImpResFiles.append(evalDlg.impRespFile)
            if evalDlg.Result == MeasureQARetVal.Done:
                break
        self.impRespDlg.removeAll()
        self.impRespDlg.setFiles(acquiredImpResFiles)
        self.notebook.next_page()

    def changeCfgParamDRC(self, bufferStr, changeArray):
        newBuff = bufferStr
        for i in range(0, len(changeArray)):
            changeParams = changeArray[i]
            searchStr = changeParams[0] + " = "
            paramStart = bufferStr.find(searchStr)
            if paramStart > -1:
                paramEnd = bufferStr.find("\n", paramStart)
                if paramEnd > -1:
                    newBuff = bufferStr[0:paramStart + len(searchStr)] + \
                              changeParams[1] + bufferStr[
                                                paramEnd:len(bufferStr)]
            bufferStr = newBuff
        return newBuff

    def getTmpCfgDir(self):
        cachedir = RB.user_cache_dir() + "/DRC"
        tmpCfgDir = cachedir + "/TmpDRCCfg"
        if not os.path.exists(tmpCfgDir):
            os.makedirs(tmpCfgDir)
        return tmpCfgDir

    def prepareDRC(self, impRespFile, filterResultFile, targetCurveFile):
        drcScript = [
            DependsWrapperImpl.find_plugin_file(self.parent, "calcFilterDRC")
        ]
        drcCfgFileName = os.path.basename(self.drcCfgDlg.getBaseCfg())
        print(("drcCfgBaseName : " + drcCfgFileName))
        drcCfgSrcFile = self.drcCfgDlg.getBaseCfg()
        drcCfgDestFile = self.getTmpCfgDir() + "/" + drcCfgFileName
        drcScript.append(drcCfgDestFile)
        print(("drcCfgDestFile : " + drcCfgDestFile))
        # update filter file
        srcDrcCfgFile = open(drcCfgSrcFile, "r")
        srcData = srcDrcCfgFile.read()
        micCalFile = self.drcCfgDlg.getMicCalibrationFile()
        normMethod = self.drcCfgDlg.getNormMethod()
        changeCfgFileArray = [["BCInFile", impRespFile],
                              ["PSPointsFile", targetCurveFile],
                              ["PSNormType", normMethod]]
        if micCalFile is not None:
            changeCfgFileArray.append(["MCFilterType", "M"])
            changeCfgFileArray.append(["MCPointsFile", micCalFile])
        else:
            changeCfgFileArray.append(["MCFilterType", "N"])
        destData = self.changeCfgParamDRC(srcData, changeCfgFileArray)
        destDrcCfgFile = open(drcCfgDestFile, "w")
        destDrcCfgFile.write(destData)
        destDrcCfgFile.close()
        return drcScript

    def showMsgBox(self, msg):
        dlg = Gtk.MessageDialog(self.dlg, Gtk.DialogFlags.MODAL,
                                Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE,
                                msg)
        dlg.run()
        dlg.destroy()

    def getFilterResultsDir(self):
        cachedir = RB.user_cache_dir() + "/DRC"
        filterResultsDir = cachedir + "/DRCFilters"
        if not os.path.exists(filterResultsDir):
            print(("DRC cache dir does not exist : creating -> " +
                   filterResultsDir))
            os.makedirs(filterResultsDir)
        return filterResultsDir

    def getSampleShift(self, distanceInCentimeter):
        return int((1.2849 * distanceInCentimeter) + 0.5)

    def calculateAvgImpResponse(self, files):
        projectDir = os.path.dirname(os.path.abspath(files[0].fileName))
        impOutputFile = projectDir + "/impOutputFile"\
                + datetime.datetime.now().strftime("%Y%m%d%H%M%S_") + "avg.wav"
        maxValueStartOffset = 32768
        maxValueEndOffset = 32768
        avgImpulseLength = maxValueEndOffset + maxValueStartOffset
        #loop over all impulse responses for all chanels and
        #calculate average response
        result = DRCFileTool.WaveParams()
        avgData = []
        for currFileInfo in files:
            params = DRCFileTool.LoadWaveFile(currFileInfo.fileName)
            result = DRCFileTool.WaveParams(params.numChannels)
            for chanel in range(0, params.numChannels):
                if len(avgData) <= chanel:
                    arr = [float(0.0)] * avgImpulseLength
                    avgData.append(arr)
                impulseStart = params.maxSampleValuePos[chanel] - \
                        maxValueStartOffset + self.getSampleShift(
                            currFileInfo.centerDistanceInCentimeter)
                print(("impulseStart:", impulseStart))
                for index in range(0, avgImpulseLength):
                    avgData[chanel][index] += float(
                        params.data[chanel][impulseStart + index] *
                        currFileInfo.weightingFactor)
                    #print(("avgData[chanel][index] : ",
                    #    avgData[chanel][index],
                    #    params.data[chanel][impulseStart + index]))
        #write the avg result to the result
        result.data = avgData
        print(("numChans Avg :", params.numChannels, result.numChannels,
               impOutputFile))
        DRCFileTool.WriteWaveFile(result, impOutputFile)
        return impOutputFile

    def on_calculateDRC(self, param):
        drcMethod = self.comboDRC.get_active_text()
        drcScript = [
            DependsWrapperImpl.find_plugin_file(self.parent, "calcFilterDRC")
        ]
        pluginPath = os.path.dirname(os.path.abspath(drcScript[0]))
        filterResultFile = self.getFilterResultsDir() + "/Filter" + str(
            drcMethod) + datetime.datetime.now().strftime(
                "%Y%m%d%H%M%S") + ".wav"
        impRespFiles = self.impRespDlg.getImpRespFiles()
        #get number of channels from impRespFiles and loop over
        numChannels = DRCFileTool.getNumChannels(impRespFiles[0].fileName)
        #go through all impRespFiles, average them and pass the
        #result to the impRespFile
        avgImpRespFile = self.calculateAvgImpResponse(impRespFiles)
        soxMergeCall = ["sox", "-M"]
        channelFilterFile = ""
        for currChannel in range(0, numChannels):
            channelFilterFile = "/tmp/filter" + str(currChannel) + ".wav"
            soxMergeCall.append(channelFilterFile)
            #get target curve filename per channel
            targetCurveFileName = self.targetCurveDlg.getTargetCurveFileName(
                currChannel)
            if avgImpRespFile is None:
                self.showMsgBox("no file loaded")
                return
            if drcMethod == "DRC":
                drcScript = self.prepareDRC(avgImpRespFile, channelFilterFile,
                                            targetCurveFileName)
                drcScript.append(avgImpRespFile)
                drcScript.append(channelFilterFile)
                drcScript.append(str(currChannel))
            elif drcMethod == "PORC":
                drcScript = [
                    DependsWrapperImpl.find_plugin_file(
                        self.parent, "calcFilterPORC")
                ]
                porcCommand = pluginPath + "/porc/porc.py"
                if not os.path.isfile(porcCommand):
                    self.showMsgBox(
                        "porc.py not found. Please download from github and "
                        "install in the DRC plugin subfolder 'porc'")
                    return
                drcScript.append(porcCommand)
                drcScript.append(avgImpRespFile)
                drcScript.append(channelFilterFile)
                drcScript.append(str(currChannel))
                drcScript.append(targetCurveFileName)
                if self.porcCfgDlg.getMixedPhaseEnabled():
                    drcScript.append("--mixed")
            print(("drc command line: " + str(drcScript)))
            p = subprocess.Popen(drcScript, 0, None, None, subprocess.PIPE,
                                 subprocess.PIPE)
            (out, err) = p.communicate()
            print(("output from filter calculate script : " + str(out)))
        #use sox to merge all results to one filter file
        soxMergeCall.append(filterResultFile)
        p = subprocess.Popen(soxMergeCall, 0, None, None, subprocess.PIPE,
                             subprocess.PIPE)
        print(("output from sox filter merge : " + str(out)))
        self.filechooserbtn.set_filename(filterResultFile)
        self.set_filter()
        self.notebook.next_page()

    def on_close(self, shell):
        print("closing ui")
        self.inputVolumeUpdate.stop()
        self.dlg.set_visible(False)
        return True

    def show_ui(self, shell, state, dummy):
        print("showing UI")
        self.initUI()
        self.startInputVolumeUpdate()
        if shell is None:
            self.dlg.run()
        else:
            self.dlg.show_all()
            self.dlg.present()
        self.inputVolumeUpdate.stop()
        print("done showing UI")

    def on_destroy(self, widget, data):
        self.on_close(None)
        return True

    def on_Cancel(self, some_param):
        self.dlg.set_visible(False)
        self.inputVolumeUpdate.stop()
Beispiel #4
0
    def initUI(self):
        aCfg = DRCConfig()
        self.uibuilder = Gtk.Builder()
        self.uibuilder.add_from_file(
            DependsWrapperImpl.find_plugin_file(self.parent, "DRCUI.glade"))
        self.dlg = self.uibuilder.get_object("DRCDlg")
        self.dlg.connect("close", self.on_close)
        audioFileFilter = Gtk.FileFilter()
        audioFileFilter.add_pattern("*.wav")
        audioFileFilter.add_pattern("*.pcm")
        audioFileFilter.add_pattern("*.raw")
        self.filechooserbtn = self.uibuilder.get_object(
            "drcfilterchooserbutton")
        self.filechooserbtn.set_filter(audioFileFilter)
        if os.path.isfile(aCfg.filterFile):
            self.filechooserbtn.set_filename(aCfg.filterFile)
        else:
            self.filechooserbtn.set_current_folder(self.getFilterResultsDir())

        self.filechooserbtn.connect("file-set", self.on_file_selected)
        self.entrySweepDuration = self.uibuilder.get_object(
            "entrySweepDuration")
        self.entrySweepDuration.set_text(str(aCfg.sweepDuration))

        self.progressbarInputVolume = self.uibuilder.get_object(
            "progressbarInputVolume")

        self.alsaPlayHardwareCombo = self.uibuilder.get_object("comboOutput")
        self.alsaRecHardwareCombo = self.uibuilder.get_object("comboRecord")
        self.comboSampleRate = self.uibuilder.get_object("comboSampleRate")

        self.execMeasureBtn = self.uibuilder.get_object("buttonMeassure")
        self.execMeasureBtn.connect("clicked", self.on_execMeasure)

        self.alsaDevices = AlsaDevices()
        alsaTools.fillComboFromDeviceList(self.alsaPlayHardwareCombo,
                                          self.alsaDevices.alsaPlayDevs,
                                          aCfg.playHardwareIndex)
        alsaTools.fillComboFromDeviceList(self.alsaRecHardwareCombo,
                                          self.alsaDevices.alsaRecDevs,
                                          aCfg.recHardwareIndex)
        self.alsaRecHardwareCombo.connect("changed", self.on_recDeviceChanged)
        self.comboInputChanel = self.uibuilder.get_object("comboInputChanel")
        self.comboInputChanel.set_active(aCfg.recHardwareChannelIndex)
        # fill the number of input channels
        self.updateRecDeviceInfo()
        self.comboInputChanel.connect("changed", self.on_InputChanelChanged)

        calcDRCBtn = self.uibuilder.get_object("buttonCalculateFilter")
        calcDRCBtn.connect("clicked", self.on_calculateDRC)

        slider = self.uibuilder.get_object("scaleSweepAmplitude")
        slider.set_range(0.1, 1)
        slider.set_value_pos(Gtk.PositionType.TOP)
        self.sweep_level = aCfg.recordGain
        slider.set_value(self.sweep_level)
        slider.connect("value_changed", self.slider_changed)

        apply_closeBtn = self.uibuilder.get_object("apply_closeBtn")
        apply_closeBtn.connect("clicked", self.on_apply_settings)

        cancel_closeBtn = self.uibuilder.get_object("cancelButton")
        cancel_closeBtn.connect("clicked", self.on_Cancel)

        self.buttonSetImpRespFile = self.uibuilder.get_object(
            "buttonSetImpRespFile")

        self.buttonSetImpRespFile.connect("clicked", self.on_setImpRespFiles)

        self.comboDRC = self.uibuilder.get_object("combo_drc_type")
        self.cfgDRCButton = self.uibuilder.get_object("cfgDRCButton")
        self.cfgDRCButton.connect("clicked", self.on_cfgDRC)
        self.comboDRC.append_text("DRC")
        self.comboDRC.append_text("PORC")
        self.comboDRC.set_active(0)
        self.comboDRC.connect("changed", self.on_DRCTypeChanged)
        self.on_DRCTypeChanged(self.comboDRC)
        self.drcCfgDlg = DRCCfgDlg(self.parent)
        self.porcCfgDlg = PORCCfgDlg(self.parent)
        self.channelSelDlg = ChanelSelDlg(self.parent)
        self.impRespDlg = ImpRespDlg(self, self.getMeasureResultsDir())
        self.targetCurveDlg = TargetCurveDlg(self.parent)

        self.exec_2ChannelMeasure = self.uibuilder.get_object(
            "checkbutton_2ChannelMeasure")
        self.exec_2ChannelMeasure.set_sensitive(True)

        self.spinbutton_NumChannels = self.uibuilder.get_object(
            "spinbutton_NumChannels")

        self.notebook = self.uibuilder.get_object("notebook1")
        self.volumeUpdateBlocked = False
        self.mode = None
        self.inputVolumeUpdate = InputVolumeProcess(
            self.progressbarInputVolume)
        self.comboboxFIRFilterMode = self.uibuilder.get_object(
            "comboboxFIRFilterMode")
        self.comboboxFIRFilterMode.set_active(aCfg.FIRFilterMode)
        self.comboboxFIRFilterMode.connect("changed",
                                           self.on_FIRFilterModeChanged)

        self.uibuilder.get_object("buttonTargetCurve").connect(
            "clicked", self.on_EditTargetCurve)
Beispiel #5
0
class DRCDlg:
    def initUI(self):
        aCfg = DRCConfig()
        self.uibuilder = Gtk.Builder()
        self.uibuilder.add_from_file(
            rb.find_plugin_file(self.parent, "DRCUI.glade"))
        self.dlg = self.uibuilder.get_object("DRCDlg")
        self.dlg.connect("close", self.on_close)
        audioFileFilter = Gtk.FileFilter()
        audioFileFilter.add_pattern("*.wav")
        audioFileFilter.add_pattern("*.pcm")
        audioFileFilter.add_pattern("*.raw")
        self.filechooserbtn = self.uibuilder.get_object(
            "drcfilterchooserbutton")
        self.filechooserbtn.set_filter(audioFileFilter)
        if os.path.isfile(aCfg.filterFile):
            self.filechooserbtn.set_filename(aCfg.filterFile)
        else:
            self.filechooserbtn.set_current_folder(self.getFilterResultsDir())

        self.filechooserbtn.connect("file-set", self.on_file_selected)
        self.entrySweepDuration = self.uibuilder.get_object(
            "entrySweepDuration")
        self.entrySweepDuration.set_text(str(aCfg.sweepDuration))

        self.progressbarInputVolume = self.uibuilder.get_object(
            "progressbarInputVolume")

        self.alsaPlayHardwareCombo = self.uibuilder.get_object("comboOutput")
        self.alsaRecHardwareCombo = self.uibuilder.get_object("comboRecord")

        self.execMeasureBtn = self.uibuilder.get_object("buttonMeassure")
        self.execMeasureBtn.connect("clicked", self.on_execMeasure)

        self.alsaPlayHardwareList = alsaTools.getDeviceListFromAlsaOutput(
            "aplay")
        self.alsaRecHardwareList = alsaTools.getDeviceListFromAlsaOutput(
            "arecord")
        alsaTools.fillComboFromDeviceList(self.alsaPlayHardwareCombo,
                                self.alsaPlayHardwareList,
                                aCfg.playHardwareIndex)
        alsaTools.fillComboFromDeviceList(self.alsaRecHardwareCombo,
                                self.alsaRecHardwareList,
                                aCfg.recHardwareIndex)
        self.alsaRecHardwareCombo.connect("changed", self.on_recDeviceChanged)
        self.comboInputChanel = self.uibuilder.get_object("comboInputChanel")
        self.comboInputChanel.set_active(aCfg.recHardwareChannelIndex)
        # fill the number of input channels
        self.updateRecDeviceInfo()
        self.comboInputChanel.connect("changed", self.on_InputChanelChanged)

        calcDRCBtn = self.uibuilder.get_object("buttonCalculateFilter")
        calcDRCBtn.connect("clicked", self.on_calculateDRC)

        slider = self.uibuilder.get_object("scaleSweepAmplitude")
        slider.set_range(0.1, 1)
        slider.set_value_pos(Gtk.PositionType.TOP)
        self.sweep_level = aCfg.recordGain
        slider.set_value(self.sweep_level)
        slider.connect("value_changed", self.slider_changed)

        apply_closeBtn = self.uibuilder.get_object("apply_closeBtn")
        apply_closeBtn.connect("clicked", self.on_apply_settings)

        cancel_closeBtn = self.uibuilder.get_object("cancelButton")
        cancel_closeBtn.connect("clicked", self.on_Cancel)

        self.buttonSetImpRespFile = self.uibuilder.get_object(
            "buttonSetImpRespFile")

        self.buttonSetImpRespFile.connect("clicked", self.on_setImpRespFiles)

        self.filechooserbuttonTargetCurve = self.uibuilder.get_object(
            "filechooserbuttonTargetCurve")
        self.filechooserbuttonTargetCurve.set_current_folder(
            "/usr/share/drc/target/44.1 kHz")
        self.comboDRC = self.uibuilder.get_object("combo_drc_type")
        # TODO: check availibility of PORC & DRC and fill combo accordingly
        self.cfgDRCButton = self.uibuilder.get_object("cfgDRCButton")
        self.cfgDRCButton.connect("clicked", self.on_cfgDRC)
        self.comboDRC.append_text("DRC")
        self.comboDRC.append_text("PORC")
        self.comboDRC.set_active(0)
        self.comboDRC.connect("changed", self.on_DRCTypeChanged)
        self.on_DRCTypeChanged(self.comboDRC)
        self.drcCfgDlg = DRCCfgDlg(self.parent)
        self.porcCfgDlg = PORCCfgDlg(self.parent)
        self.channelSelDlg = ChanelSelDlg(self.parent)
        self.impRespDlg = ImpRespDlg(self.parent, self.getMeasureResultsDir())

        self.uibuilder.get_object("buttonEditTargetCurve").connect("clicked",
                                                self.on_editTargetCurve)

        self.exec_2ChannelMeasure = self.uibuilder.get_object(
            "checkbutton_2ChannelMeasure")
        self.exec_2ChannelMeasure.set_sensitive(True)

        self.notebook = self.uibuilder.get_object("notebook1")
        self.volumeUpdateBlocked = False
        self.mode = None
        self.inputVolumeUpdate = InputVolumeProcess(
            self.progressbarInputVolume)
        self.comboboxFIRFilterMode = self.uibuilder.get_object(
            "comboboxFIRFilterMode")
        self.comboboxFIRFilterMode.set_active(aCfg.FIRFilterMode)
        self.comboboxFIRFilterMode.connect("changed",
            self.on_FIRFilterModeChanged)

    def __init__(self, parent):
        self.parent = parent

    def on_editTargetCurve(self, widget):
        editDlg = EQControl(self.filechooserbuttonTargetCurve.get_filename(),
                            self.parent)
        if editDlg.run() == Gtk.ResponseType.OK:
            self.filechooserbuttonTargetCurve.set_filename(
                editDlg.getTargetCurveFile())

    def startInputVolumeUpdate(self, channel=None):
        if channel is None:
            channel = self.comboInputChanel.get_active_text()
        if not self.volumeUpdateBlocked:
            self.inputVolumeUpdate.start(self.getAlsaRecordHardwareString(),
                                         channel, self.mode)

    def on_setImpRespFiles(self, button):
        self.impRespDlg.run()

    def on_InputChanelChanged(self, combo):
        self.startInputVolumeUpdate(combo.get_active_text())

    def updateRecDeviceInfo(self):
        self.volumeUpdateBlocked = True
        recDeviceInfo = self.getRecordingDeviceInfo()
        if recDeviceInfo is None:
            return
        self.comboInputChanel.remove_all()
        # TODO: at the moment just 32 bit recording is supported. Maybe
        # check if other bitdepths make sense too
        self.mode = "S32_LE"
        if "S32_LE" in recDeviceInfo[1]:
            self.execMeasureBtn.set_sensitive(True)
        else:
            if len(recDeviceInfo[1]) < 1:
                print("no mode extracted : assuming S16_LE in that case")
                self.mode = "S16_LE"
            else:
                self.mode = recDeviceInfo[1][0]
            self.showMsgBox(
                "Recording device does not support 32 bit recording(S32_LE)")
            self.execMeasureBtn.set_sensitive(False)
        start = 0
        end = int(recDeviceInfo[0][0])
        if len(recDeviceInfo[0]) > 1:
            start = max(int(recDeviceInfo[0][0]) - 1, 0)
            end = int(recDeviceInfo[0][1])
        for chanel in range(start, end):
            self.comboInputChanel.append_text(str(chanel + 1))
        self.volumeUpdateBlocked = False
        self.comboInputChanel.set_active(0)
        return self.mode

    def on_recDeviceChanged(self, combo):
        self.updateRecDeviceInfo()

    def on_cfgDRC(self, button):
        drcMethod = self.comboDRC.get_active_text()
        if drcMethod == "DRC":
            self.drcCfgDlg.run()
        else:
            self.porcCfgDlg.run()

    def on_DRCTypeChanged(self, combo):
        drcMethod = combo.get_active_text()
        if drcMethod == "DRC":
            self.cfgDRCButton.set_label("configure DRC")
            self.filechooserbuttonTargetCurve.set_filename(
                "/usr/share/drc/target/44.1 kHz/bk-44.1.txt")
        else:
            self.cfgDRCButton.set_label("configure PORC")
            drcScript = [rb.find_plugin_file(self.parent, "calcFilterDRC")]
            pluginPath = os.path.dirname(os.path.abspath(drcScript[0]))
            porcTargetCurve = pluginPath + "/porc/data/tact30f.txt"
            if not os.path.exists(porcTargetCurve):
                print("installing PORC")
                installScript = rb.find_plugin_file(self.parent,
                                                    "installPORC.sh")
                pluginPath = os.path.dirname(installScript)
                porcInstCommand = "xterm -e " + installScript + " " + \
                                  pluginPath
                subprocess.call(porcInstCommand, shell=True)
            self.filechooserbuttonTargetCurve.set_filename()

    def slider_changed(self, hscale):
        self.sweep_level = hscale.get_value()

    def set_filter(self):
        DrcFilename = self.filechooserbtn.get_filename()
        self.parent.updateFilter(DrcFilename)

    def on_file_selected(self, widget):
        filterFile = widget.get_filename()
        if os.path.isfile(filterFile):
            self.saveSettings()

    def saveSettings(self):
        aCfg = DRCConfig()
        aCfg.filterFile = self.filechooserbtn.get_filename()
        aCfg.recordGain = self.sweep_level
        aCfg.sweepDuration = int(self.entrySweepDuration.get_text())
        aCfg.FIRFilterMode = self.comboboxFIRFilterMode.get_active()
        aCfg.playHardwareIndex = self.alsaPlayHardwareCombo.get_active()
        aCfg.recHardwareIndex = self.alsaRecHardwareCombo.get_active()
        aCfg.recHardwareChannelIndex = self.comboInputChanel.get_active()
        fileExt = os.path.splitext(aCfg.filterFile)[-1]
        print(("ext = " + fileExt))
        if fileExt != ".wav":
            if self.channelSelDlg.run() == Gtk.ResponseType.OK:
                aCfg.numFilterChanels = self.channelSelDlg.getNumChannels()
        aCfg.save()

    def on_apply_settings(self, some_param):
        self.saveSettings()
        self.dlg.set_visible(False)

    def updateBruteFIRCfg(self, enable):
        updateBruteFIRScript = [rb.find_plugin_file(self.parent,
                "updateBruteFIRCfg")]
        if enable is True:
            self.comboboxFIRFilterMode.set_active(2)
            updateBruteFIRScript.append(self.getAlsaPlayHardwareString())
            updateBruteFIRScript.append(self.filechooserbtn.get_filename())
        print('create bruteFIRConfig and start/install bruteFIR')
        p = subprocess.Popen(updateBruteFIRScript, 0, None, None,
            subprocess.PIPE, subprocess.PIPE)
        (out, err) = p.communicate()
        print(("output from bruteFIR update script : " + str(out)))

    def on_applyFilterBruteFIR(self):
        self.updateBruteFIRCfg(True)
        self.saveSettings()
        self.set_filter()
        self.checkbuttonEnableFiltering.set_active(True)

    def on_applyFilterGST(self):
        self.comboboxFIRFilterMode.set_active(1)
        self.saveSettings()
        self.set_filter()
        self.updateBruteFIRCfg(False)
        self.checkbuttonEnableFiltering.set_active(True)

    def disableFiltering(self):
        self.comboboxFIRFilterMode.set_active(0)
        self.saveSettings()
        self.set_filter()
        self.updateBruteFIRCfg(False)

    def on_FIRFilterModeChanged(self, some_param):
        FIRFilterMode = self.comboboxFIRFilterMode.get_active()
        if FIRFilterMode is 0:
            self.disableFiltering()
        elif FIRFilterMode is 1:
            self.on_applyFilterGST()
        else:
            self.on_applyFilterBruteFIR()

    def getRecordingDeviceInfo(self):
        try:
            params = ['arecord', '-D', self.getAlsaRecordHardwareString(),
                      '--dump-hw-params', '-d 1']
            print(("executing: " + str(params)))
            p = subprocess.Popen(params, 0, None, None, subprocess.PIPE,
                                 subprocess.PIPE)
            (out, err) = p.communicate()
            print(("hw infos : err : " + str(err) + " out : " + str(out)))
            # I rely on channels as it seems to be not translated
            pattern = re.compile("CHANNELS:\s\[?(\d{1,2})\s?(\d{1,2})?\]?",
                                 re.MULTILINE)
            numChanels = pattern.findall(str(err))
            # workaround to remove empty match in case of just single number
            # because I was not clever enough to have a clean
            # conditional regex...
            if len(numChanels[0]) > 1 and not numChanels[0][1]:
                print("only channel number present -> truncate")
                numChanels = [numChanels[0][0]]
            else:
                numChanels = [numChanels[0][0], numChanels[0][1]]
            pattern = re.compile("(\D\d+_\w*)", re.MULTILINE)
            supportedModes = pattern.findall(str(err))

            print(("numChannels : " + str(numChanels)))
            print(("supportedModes : " + str(supportedModes)))
            print(("No. supported Modes : " + str(len(supportedModes))))
            return [numChanels, supportedModes]
        except Exception as inst:
            print((
                'failed to get rec hardware info...',
                sys.exc_info()[0], type(inst), inst))
        return None

    def getAlsaPlayHardwareString(self):
        if len(self.alsaPlayHardwareList) < 1:
            print("no sound hardware detected")
            return
        alsHardwareSelIndex = self.alsaPlayHardwareCombo.get_active()
        alsaDevicePlayback = "hw:" + str(
            self.alsaPlayHardwareList[alsHardwareSelIndex][0]) + "," + str(
            self.alsaPlayHardwareList[alsHardwareSelIndex][2])
        print(("alsa output device : " + alsaDevicePlayback))
        return alsaDevicePlayback

    def getAlsaRecordHardwareString(self):
        if len(self.alsaRecHardwareList) < 1:
            print("no sound hardware detected")
            return
        alsHardwareSelIndex = self.alsaRecHardwareCombo.get_active()
        alsaDeviceRec = "hw:" + str(
            self.alsaRecHardwareList[alsHardwareSelIndex][0]) + "," + str(
            self.alsaRecHardwareList[alsHardwareSelIndex][2])
        print(("alsa input device : " + alsaDeviceRec))
        return alsaDeviceRec

    def getMeasureResultsDir(self):
        cachedir = RB.user_cache_dir() + "/DRC"
        measureResultsDir = cachedir + "/MeasureResults"
        if not os.path.exists(measureResultsDir):
            os.makedirs(measureResultsDir)
        return measureResultsDir

    def on_execMeasure(self, param):
        self.inputVolumeUpdate.stop()

        # TODO: make the measure script output the volume and parse from
        # there during measurement
        scriptName = rb.find_plugin_file(self.parent, "measure1Channel")
        #create new folder for this complete measurement
        strResultsDir = self.getMeasureResultsDir() + "/" +\
                        datetime.datetime.now().strftime("%Y%m%d%H%M%S_") + \
                        str(self.entrySweepDuration.get_text())
        os.makedirs(strResultsDir)
        strResultSuffix = ""
        if self.exec_2ChannelMeasure.get_active():
            strResultSuffix = "l"
        raw_sweep_file_base_name = "/tmp/msrawsweep.pcm"
        raw_sweep_recorded_base_name = "/tmp/msrecsweep" +\
            strResultSuffix + ".pcm"
        evalDlg = MeasureQADlg(self.parent, raw_sweep_file_base_name,
                           raw_sweep_recorded_base_name, self.sweep_level)
        iterLoopMeasure = 0
        acquiredImpResFiles = []
        while(True):
            impOutputFile = strResultsDir + "/" + str(iterLoopMeasure) + ".wav"
            # execute measure script to generate filters
            commandLine = [scriptName, str(self.sweep_level),
                       self.getAlsaRecordHardwareString(),
                       self.getAlsaPlayHardwareString(),
                       "10",
                       "21000",
                       str(self.entrySweepDuration.get_text()),
                       impOutputFile,
                       self.comboInputChanel.get_active_text(),
                       str(self.exec_2ChannelMeasure.get_active())]
            p = subprocess.Popen(commandLine, 0, None, None, subprocess.PIPE,
                             subprocess.PIPE)
            (out, err) = p.communicate()
            print(("output from measure script : " + str(out) + " error : "
                + str(None)))
            # quality check:sweep file and measured result
            evalDlg.setImpRespFileName(impOutputFile)
            evalDlg.run()
            iterLoopMeasure += 1
            if evalDlg.Result == MeasureQARetVal.Reject:
                continue
            acquiredImpResFiles.append(evalDlg.impRespFile)
            if evalDlg.Result == MeasureQARetVal.Done:
                break
        self.impRespDlg.setFiles(acquiredImpResFiles)
        self.notebook.next_page()

    def changeCfgParamDRC(self, bufferStr, changeArray):
        newBuff = bufferStr
        for i in range(0, len(changeArray)):
            changeParams = changeArray[i]
            searchStr = changeParams[0] + " = "
            paramStart = bufferStr.find(searchStr)
            if paramStart > -1:
                paramEnd = bufferStr.find("\n", paramStart)
                if paramEnd > -1:
                    newBuff = bufferStr[0:paramStart + len(searchStr)] + \
                              changeParams[1] + bufferStr[
                                                paramEnd:len(bufferStr)]
            bufferStr = newBuff
        return newBuff

    def getTmpCfgDir(self):
        cachedir = RB.user_cache_dir() + "/DRC"
        tmpCfgDir = cachedir + "/TmpDRCCfg"
        if not os.path.exists(tmpCfgDir):
            os.makedirs(tmpCfgDir)
        return tmpCfgDir

    def prepareDRC(self, impRespFile, filterResultFile):
        drcScript = [rb.find_plugin_file(self.parent, "calcFilterDRC")]
        drcCfgFileName = os.path.basename(self.drcCfgDlg.getBaseCfg())
        print(("drcCfgBaseName : " + drcCfgFileName))
        drcCfgSrcFile = self.drcCfgDlg.getBaseCfg()
        drcCfgDestFile = self.getTmpCfgDir() + "/" + drcCfgFileName
        drcScript.append(drcCfgDestFile)
        print(("drcCfgDestFile : " + drcCfgDestFile))
        # update filter file
        srcDrcCfgFile = open(drcCfgSrcFile, "r")
        srcData = srcDrcCfgFile.read()
        micCalFile = self.drcCfgDlg.getMicCalibrationFile()
        normMethod = self.drcCfgDlg.getNormMethod()
        changeCfgFileArray = [["BCInFile", impRespFile],
                              ["PSPointsFile",
                            self.filechooserbuttonTargetCurve.get_filename()],
                              ["PSNormType", normMethod]
                             ]
        if micCalFile is not None:
            changeCfgFileArray.append(["MCFilterType", "M"])
            changeCfgFileArray.append(["MCPointsFile", micCalFile])
        else:
            changeCfgFileArray.append(["MCFilterType", "N"])
        destData = self.changeCfgParamDRC(srcData, changeCfgFileArray)
        destDrcCfgFile = open(drcCfgDestFile, "w")
        destDrcCfgFile.write(destData)
        destDrcCfgFile.close()
        return drcScript

    def showMsgBox(self, msg):
        dlg = Gtk.MessageDialog(self.dlg, Gtk.DialogFlags.MODAL,
                                Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE,
                                msg)
        dlg.run()
        dlg.destroy()

    def getFilterResultsDir(self):
        cachedir = RB.user_cache_dir() + "/DRC"
        filterResultsDir = cachedir + "/DRCFilters"
        if not os.path.exists(filterResultsDir):
            print(
                ("DRC cache dir does not exist : creating -> " +
                filterResultsDir))
            os.makedirs(filterResultsDir)
        return filterResultsDir

    def getSampleShift(self, distanceInCentimeter):
        return int((1.2849 * distanceInCentimeter) + 0.5)

    def calculateAvgImpResponse(self, files):
        projectDir = os.path.dirname(os.path.abspath(files[0].fileName))
        impOutputFile = projectDir + "/impOutputFile"\
                + datetime.datetime.now().strftime("%Y%m%d%H%M%S_") + "avg.wav"
        maxValueStartOffset = 100
        maxValueEndOffset = 20000
        avgImpulseLength = maxValueEndOffset + maxValueStartOffset
        #loop over all impulse responses for all chanels and
        #calculate average response
        result = DRCFileTool.WaveParams()
        avgData = []
        for currFileInfo in files:
            params = DRCFileTool.LoadWaveFile(currFileInfo.fileName)
            result = DRCFileTool.WaveParams(params.numChannels)
            for chanel in range(0, params.numChannels):
                if len(avgData) <= chanel:
                    arr = [float(0.0)] * avgImpulseLength
                    avgData.append(arr)
                impulseStart = params.maxSampleValuePos[chanel] - \
                        maxValueStartOffset + self.getSampleShift(
                            currFileInfo.centerDistanceInCentimeter)
                print(("impulseStart:", impulseStart))
                for index in range(0, avgImpulseLength):
                    avgData[chanel][index] += float(params.data[chanel][
                        impulseStart + index] *
                            currFileInfo.weightingFactor)
                    #print(("avgData[chanel][index] : ",
                    #    avgData[chanel][index],
                    #    params.data[chanel][impulseStart + index]))
        #write the avg result to the result
        result.data = avgData
        print(("numChans Avg :", params.numChannels, result.numChannels,
            impOutputFile))
        DRCFileTool.WriteWaveFile(result, impOutputFile)
        return impOutputFile

    def on_calculateDRC(self, param):
        drcMethod = self.comboDRC.get_active_text()
        drcScript = [rb.find_plugin_file(self.parent, "calcFilterDRC")]
        pluginPath = os.path.dirname(os.path.abspath(drcScript[0]))
        filterResultFile = self.getFilterResultsDir() + "/Filter" + str(
            drcMethod) + datetime.datetime.now().strftime(
            "%Y%m%d%H%M%S") + ".wav"
        impRespFiles = self.impRespDlg.getImpRespFiles()
        #go through all impRespFiles, average them and pass the
        #result to the impRespFile
        avgImpRespFile = self.calculateAvgImpResponse(impRespFiles)
        if avgImpRespFile is None:
            self.showMsgBox("no file loaded")
            return
        if drcMethod == "DRC":
            drcScript = self.prepareDRC(avgImpRespFile, filterResultFile)
        elif drcMethod == "PORC":
            drcScript = [rb.find_plugin_file(self.parent, "calcFilterPORC")]
            porcCommand = pluginPath + "/porc/porc.py"
            if not os.path.isfile(porcCommand):
                self.showMsgBox(
                    "porc.py not found. Please download from github and "
                    "install in the DRC plugin subfolder 'porc'")
                return
            drcScript.append(porcCommand)
            if self.porcCfgDlg.getMixedPhaseEnabled():
                drcScript.append("--mixed")
            drcScript.append(self.filechooserbuttonTargetCurve.get_filename())
        # execute measure script to generate filters
        # last 2 parameters for all scripts allways impulse response and
        # result filter
        drcScript.append(avgImpRespFile)
        drcScript.append(filterResultFile)
        print(("drc command line: " + str(drcScript)))
        p = subprocess.Popen(drcScript, 0, None, None, subprocess.PIPE,
                             subprocess.PIPE)
        (out, err) = p.communicate()
        print((")output from filter calculate script : " + str(out)))
        self.filechooserbtn.set_filename(filterResultFile)
        self.set_filter()
        self.notebook.next_page()

    def on_close(self, shell):
        print("closing ui")
        self.inputVolumeUpdate.stop()
        self.dlg.set_visible(False)
        return True

    def show_ui(self, shell, state, dummy):
        print("showing UI")
        self.initUI()
        self.startInputVolumeUpdate()
        self.dlg.show_all()
        self.dlg.present()
        self.inputVolumeUpdate.stop()
        print("done showing UI")

    def on_destroy(self, widget, data):
        self.on_close(None)
        return True

    def on_Cancel(self, some_param):
        self.dlg.set_visible(False)
        self.inputVolumeUpdate.stop()