def G_Lpe(IR, nthOct, minFreq, maxFreq, IREndManualCut=None): """ Calculate the energy level from the room impulsive response. Reference: Christensen, C. L.; Rindel, J. H. APPLYING IN-SITU RECALIBRATION FOR SOUND STRENGTH MEASUREMENTS IN AUDITORIA. :param IR: one channel impulsive response :type IR: ImpulsiveResponse :param nthOct: number of fractions per octave :type nthOct: int :param minFreq: analysis inferior frequency limit :type minFreq: float :param maxFreq: analysis superior frequency limit :type maxFreq: float :return: Analysis object with the calculated parameter :rtype: Analysis """ # Code snippet to guarantee that generated object name is # the declared at global scope # for frame, line in traceback.walk_stack(None): for framenline in traceback.walk_stack(None): # varnames = frame.f_code.co_varnames varnames = framenline[0].f_code.co_varnames if varnames == (): break # creation_file, creation_line, creation_function, \ # creation_text = \ extracted_text = \ traceback.extract_stack(framenline[0], 1)[0] # traceback.extract_stack(frame, 1)[0] # creation_name = creation_text.split("=")[0].strip() creation_name = extracted_text[3].split("=")[0].strip() # firstChNum = IR.systemSignal.channels.mapping[0] # if not IR.systemSignal.channels[firstChNum].calibCheck: # raise ValueError("'IR' must be a calibrated ImpulsiveResponse") if isinstance(IR, SignalObj): SigObj = cp.copy(IR) elif isinstance(IR, ImpulsiveResponse): SigObj = cp.copy(IR.systemSignal) else: raise TypeError("'IR' must be an ImpulsiveResponse or SignalObj.") # Cutting the IR if IREndManualCut is not None: SigObj.crop(0, IREndManualCut) timeSignal, _ = _circular_time_shift(SigObj.timeSignal[:,0]) # Bands filtering # hSignal = SignalObj(SigObj.timeSignal[:,0], hSignal = SignalObj(timeSignal, SigObj.lengthDomain, SigObj.samplingRate) hSignal = _filter(signal=hSignal, nthOct=nthOct, minFreq=minFreq, maxFreq=maxFreq) bands = FOF(nthOct=nthOct, freqRange=[minFreq,maxFreq])[:,1] Lpe = [] for chIndex in range(hSignal.numChannels): Lpe.append( 10*np.log10(np.trapz(y=hSignal.timeSignal[:,chIndex]**2/(2e-5**2), x=hSignal.timeVector))) LpeAnal = Analysis(anType='mixed', nthOct=nthOct, minBand=float(bands[0]), maxBand=float(bands[-1]), data=Lpe, comment='h**2 energy level') LpeAnal.creation_name = creation_name return LpeAnal
def G_Lps(IR, nthOct, minFreq, maxFreq): # TODO: Fix documentation format """G_Lps Calculates the recalibration level, for both in-situ and reverberation chamber. Lps is applied for G calculation. During the recalibration: source height and mic height must be >= 1 [m], while the distance between source and mic must be <= 1 [m]. The distances must be the same for in-situ and reverberation chamber measurements. Reference: Christensen, C. L.; Rindel, J. H. APPLYING IN-SITU RECALIBRATION FOR SOUND STRENGTH MEASUREMENTS IN AUDITORIA. :param IR: one channel impulsive response :type IR: ImpulsiveResponse :param nthOct: number of fractions per octave :type nthOct: int :param minFreq: analysis inferior frequency limit :type minFreq: float :param maxFreq: analysis superior frequency limit :type maxFreq: float :return: Analysis object with the calculated parameter :rtype: Analysis """ # Code snippet to guarantee that generated object name is # the declared at global scope # for frame, line in traceback.walk_stack(None): for framenline in traceback.walk_stack(None): # varnames = frame.f_code.co_varnames varnames = framenline[0].f_code.co_varnames if varnames == (): break # creation_file, creation_line, creation_function, \ # creation_text = \ extracted_text = \ traceback.extract_stack(framenline[0], 1)[0] # traceback.extract_stack(frame, 1)[0] # creation_name = creation_text.split("=")[0].strip() creation_name = extracted_text[3].split("=")[0].strip() # firstChNum = IR.systemSignal.channels.mapping[0] # if not IR.systemSignal.channels[firstChNum].calibCheck: # raise ValueError("'IR' must be a calibrated ImpulsiveResponse") if isinstance(IR, SignalObj): SigObj = IR elif isinstance(IR, ImpulsiveResponse): SigObj = IR.systemSignal else: raise TypeError("'IR' must be an ImpulsiveResponse or SignalObj.") # Windowing the IR # dBtoOnSet = 20 # dBIR = 10*np.log10((SigObj.timeSignal[:,0]**2)/((2e-5)**2)) # windowStart = np.where(dBIR > (max(dBIR) - dBtoOnSet))[0][0] broadBandTimeSignal = cp.copy(SigObj.timeSignal[:,0]) broadBandTimeSignalNoStart, sampleShift = \ _circular_time_shift(broadBandTimeSignal) windowLength = 0.0032 # [s] windowEnd = int(windowLength*SigObj.samplingRate) hSignal = SignalObj(broadBandTimeSignalNoStart[:windowEnd], # hSignal = SignalObj(timeSignal, SigObj.lengthDomain, SigObj.samplingRate) hSignal = _filter(signal=hSignal, nthOct=nthOct, minFreq=minFreq, maxFreq=maxFreq) bands = FOF(nthOct=nthOct, freqRange=[minFreq,maxFreq])[:,1] Lps = [] for chIndex in range(hSignal.numChannels): timeSignal = cp.copy(hSignal.timeSignal[:,chIndex]) # timeSignalNoStart, sampleShift = _circular_time_shift(timeSignal) # windowLength = 0.0032 # [s] # windowEnd = int(windowLength*SigObj.samplingRate) Lps.append( # 10*np.log10(np.trapz(y=timeSignalNoStart[:windowEnd]**2/(2e-5**2), 10*np.log10(np.trapz(y=timeSignal**2/(2e-5**2), # x=hSignal.timeVector[sampleShift:sampleShift+windowEnd]))) x=hSignal.timeVector))) LpsAnal = Analysis(anType='mixed', nthOct=nthOct, minBand=float(bands[0]), maxBand=float(bands[-1]), data=Lps, comment='Source recalibration method IR') LpsAnal.creation_name = creation_name LpsAnal.windowLimits = ((sampleShift)/SigObj.samplingRate, (sampleShift+windowEnd)/SigObj.samplingRate) # Plot IR cutting # fig = plt.figure(figsize=(10, 5)) # ax = fig.add_axes([0.08, 0.15, 0.75, 0.8], polar=False, # projection='rectilinear', xscale='linear') # ax.plot(SigObj.timeVector, 10*np.log10(SigObj.timeSignal**2/2e-5**2)) # ax.axvline(x=(sampleShift)/SigObj.samplingRate, linewidth=4, color='k') # ax.axvline(x=(sampleShift+windowEnd)/SigObj.samplingRate, linewidth=4, color='k') # ax.set_xlim([(sampleShift-100)/SigObj.samplingRate, (sampleShift+windowEnd+100)/SigObj.samplingRate]) return LpsAnal