def resultForBasicToneExistAtHead(self, runs): contiguousRuns = self.contiguousRuns(runs) result = False for run in contiguousRuns: zoneStart = convertTimeCodeToUnsignedLongLong("00:57:30:00",self.timeCodeSampleRate, self.timeBase) zoneStop = convertTimeCodeToUnsignedLongLong("00:58:31:00",self.timeCodeSampleRate, self.timeBase) runStart = convertUnsignedLongLongToTimeCode(run['start'], self.timeCodeSampleRate, self.timeBase) runStop = convertUnsignedLongLongToTimeCode(run['start']+ (run['length']*self.timeCodeSampleRate), self.timeCodeSampleRate, self.timeBase) runLength = run['length'] if runStart >= zoneStart and runStop <= runStop and runLength >= 54: runsToCheck = runs[runs.index(run):run['length']] runsToCheck = runsToCheck[1:-1] doesRunHaveTheCorrectLevelResultString = self.descriptionForLevelsInRuns(runsToCheck) if doesRunHaveTheCorrectLevelResultString != 'success': return {"status":"fail", "resultString":doesRunHaveTheCorrectLevelResultString} else: return {"status":"pass"} description = "" if len(contiguousRuns) > 0: description = "No proper 1kHz tones were found, only 1kHz tones with the following lengths in seconds: {}.".format(" ".join([str(run['length']) for run in contiguousRuns])) else: description = "No proper 1kHz tones were found." return {"status":"fail", "resultString":description}
def doesRunExistWithInToneZone(self, run): zoneStart = convertTimeCodeToUnsignedLongLong("00:57:30:00",self.timeCodeSampleRate, self.timeBase) zoneStop = convertTimeCodeToUnsignedLongLong("00:58:31:00",self.timeCodeSampleRate, self.timeBase) runStart = run['start'] runStop = run['start']+ (run['length']*self.timeCodeSampleRate) if runStart >= zoneStart and runStop <= zoneStop: return True return False
def doesRunExistWithInSilentZone(self, run): silentZoneStart = convertTimeCodeToUnsignedLongLong("00:58:33:00",self.timeCodeSampleRate, self.timeBase) silentZoneStop = convertTimeCodeToUnsignedLongLong("00:59:57:00",self.timeCodeSampleRate, self.timeBase) runStart = run['start'] runStop = run['start']+ (run['length']*self.timeCodeSampleRate) if runStop > silentZoneStart and runStop <= silentZoneStop: return True return False
def doesRunExistWithInSilentZone(self, run): silentZoneStart = convertTimeCodeToUnsignedLongLong( "00:58:33:00", self.timeCodeSampleRate, self.timeBase) silentZoneStop = convertTimeCodeToUnsignedLongLong( "00:59:57:00", self.timeCodeSampleRate, self.timeBase) runStart = run['start'] runStop = run['start'] + (run['length'] * self.timeCodeSampleRate) if runStop > silentZoneStart and runStop <= silentZoneStop: return True return False
def doesRunExistWithInToneZone(self, run): zoneStart = convertTimeCodeToUnsignedLongLong("00:57:30:00", self.timeCodeSampleRate, self.timeBase) zoneStop = convertTimeCodeToUnsignedLongLong("00:58:31:00", self.timeCodeSampleRate, self.timeBase) runStart = run['start'] runStop = run['start'] + (run['length'] * self.timeCodeSampleRate) if runStart >= zoneStart and runStop <= zoneStop: return True return False
def resultForBasicToneExistAtHead(self, runs): contiguousRuns = self.contiguousRuns(runs) result = False for run in contiguousRuns: zoneStart = convertTimeCodeToUnsignedLongLong( "00:57:30:00", self.timeCodeSampleRate, self.timeBase) zoneStop = convertTimeCodeToUnsignedLongLong( "00:58:31:00", self.timeCodeSampleRate, self.timeBase) runStart = convertUnsignedLongLongToTimeCode( run['start'], self.timeCodeSampleRate, self.timeBase) runStop = convertUnsignedLongLongToTimeCode( run['start'] + (run['length'] * self.timeCodeSampleRate), self.timeCodeSampleRate, self.timeBase) runLength = run['length'] if runStart >= zoneStart and runStop <= runStop and runLength >= 54: runsToCheck = runs[runs.index(run):run['length']] runsToCheck = runsToCheck[1:-1] doesRunHaveTheCorrectLevelResultString = self.descriptionForLevelsInRuns( runsToCheck) if doesRunHaveTheCorrectLevelResultString != 'success': return { "status": "fail", "resultString": doesRunHaveTheCorrectLevelResultString } else: return {"status": "pass"} description = "" if len(contiguousRuns) > 0: description = "No proper 1kHz tones were found, only 1kHz tones with the following lengths in seconds: {}.".format( " ".join([str(run['length']) for run in contiguousRuns])) else: description = "No proper 1kHz tones were found." return {"status": "fail", "resultString": description}
def analyzeTwoPopInEighths(filePath): if not os.path.exists(filePath): return {"status":"fail", "resultString":"file doesn't exist", "warningString":""} wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: return {"status":"fail", "resultString":"file is not a wavefile"} dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() timeCodeSampleRate = int(math.ceil(sampleRate * 1.001)) byteWidth = wavefile.numberOfBytesPerSample() numberOfChannels = wavefile.numberOfChannels() data_size = int(math.ceil(sampleRate * 1.001))/24 #1 second of audio dataStartPosOffset = 0 normalizedTimeStamp = wavefile.timestamp # currentPositionInFile = 0 dataLengthInSamples = dataLength / (numberOfChannels * byteWidth) # print "dataStartPosOffset",dataStartPosOffset toneStartTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("00:57:30:00", timeCodeSampleRate, 24) popSafeStartTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("00:59:57:00", timeCodeSampleRate, 24) hourOneTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("01:00:00:00", timeCodeSampleRate, 24) # print "normalizedTimeStamp",normalizedTimeStamp # print "toneStartTimeStamp",toneStartTimeStamp #assume file starts at 00:57:30:00, in the case that the file doesn't have a bext extension #also gets into an issue of what to favor, bext over regn? I assume that the encoders user bext #as you couldn't reliably expect a regn chunk if normalizedTimeStamp == 0 or (normalizedTimeStamp % (timeCodeSampleRate * 60 * 60 * 24) == 0): normalizedTimeStamp = toneStartTimeStamp #we're going to read 3 seconds total secondsInSamplesToRead = 3 * timeCodeSampleRate # print "secondsInSamplesToRead",secondsInSamplesToRead #make sure that the timestamp starts on the second, otherwise normalize the timestamp normalizedTimestampOffset = wavefile.timestamp % timeCodeSampleRate if normalizedTimestampOffset > 0: dataStartPosOffset += (timeCodeSampleRate - normalizedTimestampOffset) * byteWidth * numberOfChannels normalizedTimeStamp = wavefile.timestamp + (timeCodeSampleRate - normalizedTimestampOffset) # print "(timeCodeSampleRate - normalizedTimestampOffset)", (timeCodeSampleRate - normalizedTimestampOffset) # print "normalizedTimestampOffset", normalizedTimestampOffset # print "dataStartPosOffset", dataStartPosOffset # print "normalizedTimeStamp", normalizedTimeStamp if normalizedTimeStamp > popSafeStartTimeStamp: # print 'if wavefile.timestamp > toneStartTimeStamp:' return {"status":"fail", "resultString":"timecode start exceeds pop location","warningString":""} if dataLengthInSamples < (hourOneTimeStamp - toneStartTimeStamp): return {"status":"fail", "resultString":"the file is too short", "warningString":""} if normalizedTimeStamp < popSafeStartTimeStamp: #seek to start time to analyze sampleDifference = (popSafeStartTimeStamp - normalizedTimeStamp) currentPositionInFile = sampleDifference + normalizedTimeStamp dataStartPosOffset += (sampleDifference * byteWidth * numberOfChannels) #lets only look at the 3 seconds of the file from 00:59:57:00 to 01:00:00:00 sizeToRead = secondsInSamplesToRead * byteWidth * numberOfChannels sizeToRead = sizeToRead if dataLength > sizeToRead else dataLength #this scans the head to make sure there is no signal in the head up to a sixteenth of frame before the pop headResult = preScanHead(filePath, data_size, dataStartPos, dataStartPosOffset, byteWidth, numberOfChannels, sampleRate) #this scans the tail to make sure there is no signal in the tail after an eighth of a frame after the pop nextByteOffset = (data_size * 25 * byteWidth * numberOfChannels) #seek 25 frames from the initial start which would be 59:58:01 tailResult = preScanTail(filePath, data_size, dataStartPos, (dataStartPosOffset + nextByteOffset), byteWidth, numberOfChannels, sampleRate) overallResult = {"status":"pass", "resultString":""} suppressSuperfluousWarnings = False if headResult['status'] == 'fail': overallResult['status'] = 'fail' overallResult["resultString"] += headResult["resultString"] if tailResult['status'] == 'fail': overallResult['status'] = 'fail' overallResult["resultString"] += tailResult["resultString"] if overallResult['status'] == 'pass': overallResult["resultString"] = "Pop area contains no discernable problems." twoPopCounter = TwoPopCounterAlt() twoPopCounter.timeCodeSampleRate = timeCodeSampleRate twoPopCounter.timeBase = 24 with open(filePath, 'rb') as f: f.seek(dataStartPos + dataStartPosOffset) dataToReadChunkSize = data_size*byteWidth*numberOfChannels dataRemaining = sizeToRead while dataRemaining > 0: if dataRemaining > dataToReadChunkSize: data = f.read(dataToReadChunkSize) else: data = f.read(dataRemaining) dataRemaining -= len(data) for channel in range(0, numberOfChannels): subdata = "" for x in range(channel*byteWidth,len(data),byteWidth*numberOfChannels): subdata += (data[x] + data[x+1] + data[x+2]) analysis = ultimateFreqAndPowerForData(subdata, byteWidth, sampleRate) twoPopCounter.addAnalysisForChannelAndTimeStamp(analysis, channel, currentPositionInFile) currentPositionInFile += data_size twoPopResult = twoPopCounter.result() #likely that the pop is off as we are checking an area of up to a sixteenth of frame prior to the pop and area an eighth of a frame #after the pop if overallResult['status'] == 'fail' and twoPopResult['status'] == 'pass': twoPopResult['status'] = 'fail' twoPopResult['resultString'] = "Check your pop as it is likely off. " + overallResult['resultString'] if overallResult['status'] == 'fail' and twoPopResult['status'] == 'fail' and twoPopResult['foundPop'] == 'pass': twoPopResult['status'] = 'fail' twoPopResult['resultString'] = "Check your pop as it is likely off. " + overallResult['resultString'] popIntegrityResult = {"status":"pass", "resultString":""} if overallResult['status'] == 'pass' and twoPopResult['status'] == 'pass' and twoPopResult['foundPop'] == 'pass': #lets make sure the pop actually starts consists of a frame nextByteOffset = (data_size * 23 * byteWidth * numberOfChannels) #seek 23 frames from the initial start which would be 59:57:23 popIntegrityResult = scanPop(filePath, data_size, dataStartPos, (dataStartPosOffset + nextByteOffset), byteWidth, numberOfChannels, sampleRate) if popIntegrityResult['status'] == 'fail': twoPopResult['status'] = 'fail' twoPopResult['resultString'] = popIntegrityResult['resultString'] return twoPopResult
def analyzeTwoPopAlt(filePath): if not os.path.exists(filePath): return {"status":"fail", "resultString":"file doesn't exist", "warningString":""} wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: return {"status":"fail", "resultString":"file is not a wavefile"} dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() timeCodeSampleRate = int(math.ceil(sampleRate * 1.001)) byteWidth = wavefile.numberOfBytesPerSample() numberOfChannels = wavefile.numberOfChannels() data_size = int(math.ceil(sampleRate * 1.001))/24 #1 second of audio dataStartPosOffset = 0 normalizedTimeStamp = wavefile.timestamp # currentPositionInFile = 0 dataLengthInSamples = dataLength / (numberOfChannels * byteWidth) # print "dataStartPosOffset",dataStartPosOffset toneStartTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("00:57:30:00", timeCodeSampleRate, 24) popSafeStartTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("00:59:57:00", timeCodeSampleRate, 24) hourOneTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("01:00:00:00", timeCodeSampleRate, 24) # print "normalizedTimeStamp",normalizedTimeStamp # print "toneStartTimeStamp",toneStartTimeStamp #assume file starts at 00:57:30:00, in the case that the file doesn't have a bext extension #also gets into an issue of what to favor, bext over regn? I assume that the encoders user bext #as you couldn't reliably expect a regn chunk if normalizedTimeStamp == 0: normalizedTimeStamp = toneStartTimeStamp #we're going to read 3 seconds total secondsInSamplesToRead = 3 * timeCodeSampleRate # print "secondsInSamplesToRead",secondsInSamplesToRead #make sure that the timestamp starts on the second, otherwise normalize the timestamp normalizedTimestampOffset = wavefile.timestamp % timeCodeSampleRate if normalizedTimestampOffset > 0: dataStartPosOffset += (timeCodeSampleRate - normalizedTimestampOffset) * byteWidth * numberOfChannels normalizedTimeStamp = wavefile.timestamp + (timeCodeSampleRate - normalizedTimestampOffset) # print "(timeCodeSampleRate - normalizedTimestampOffset)", (timeCodeSampleRate - normalizedTimestampOffset) # print "normalizedTimestampOffset", normalizedTimestampOffset # print "dataStartPosOffset", dataStartPosOffset # print "normalizedTimeStamp", normalizedTimeStamp if normalizedTimeStamp > popSafeStartTimeStamp: # print 'if wavefile.timestamp > toneStartTimeStamp:' return {"status":"fail", "resultString":"timecode start exceeds pop location","warningString":""} if dataLengthInSamples < (hourOneTimeStamp - toneStartTimeStamp): return {"status":"fail", "resultString":"the file is too short", "warningString":""} if normalizedTimeStamp < popSafeStartTimeStamp: # print 'if wavefile.timestamp < toneStartTimeStamp:' sampleDifference = (popSafeStartTimeStamp - normalizedTimeStamp) currentPositionInFile = sampleDifference + normalizedTimeStamp dataStartPosOffset += (sampleDifference * byteWidth * numberOfChannels) #lets only look at the 3 seconds of the file from 00:59:57:00 to 01:00:00:00 sizeToRead = secondsInSamplesToRead * byteWidth * numberOfChannels sizeToRead = sizeToRead if dataLength > sizeToRead else dataLength # print "sizeToRead",sizeToRead with open(filePath, 'rb') as f: f.seek(dataStartPos + dataStartPosOffset) dataToReadChunkSize = data_size*byteWidth*numberOfChannels dataRemaining = sizeToRead twoPopCounter = TwoPopCounterAlt() twoPopCounter.timeCodeSampleRate = timeCodeSampleRate twoPopCounter.timeBase = 24 while dataRemaining > 0: if dataRemaining > dataToReadChunkSize: data = f.read(dataToReadChunkSize) else: data = f.read(dataRemaining) dataRemaining -= len(data) for channel in range(0, numberOfChannels): subdata = "" for x in range(channel*byteWidth,len(data),byteWidth*numberOfChannels): subdata += (data[x] + data[x+1] + data[x+2]) analysis = ultimateFreqAndPowerForData(subdata, byteWidth, sampleRate) twoPopCounter.addAnalysisForChannelAndTimeStamp(analysis, channel, currentPositionInFile) currentPositionInFile += data_size return twoPopCounter.result()
def analyzeHeadAlt(filePath): if os.path.exists(filePath): wavefile = PCWaveFile(filePath) if wavefile.isValidWaveFile() != True: return {"status":"fail", "resultString":"file is not a wavefile"} dataStartPos = wavefile.getDataChunk()["chunkPosition"] dataLength = wavefile.getDataChunk()["chunkSize"] sampleRate = wavefile.numberOfSamplesPerSecond() timeCodeSampleRate = int(math.ceil(sampleRate * 1.001)) byteWidth = wavefile.numberOfBytesPerSample() numberOfChannels = wavefile.numberOfChannels() data_size = int(math.ceil(sampleRate * 1.001)) #1 second of audio dataLengthInSamples = dataLength / (numberOfChannels * byteWidth) dataStartPosOffset = 0 normalizedTimeStamp = wavefile.timestamp # # print "dataStartPosOffset",dataStartPosOffset toneStartTimeStamp = pctimecode.convertTimeCodeToUnsignedLongLong("00:57:30:00", timeCodeSampleRate, 24) # print "normalizedTimeStamp",normalizedTimeStamp # print "toneStartTimeStamp",toneStartTimeStamp #assume file starts at 00:57:30:00, in the case that the file doesn't have a bext extension #also gets into an issue of what to favor, bext over regn? I assume that the encoders user bext #as you couldn't reliably expect a regn chunk if normalizedTimeStamp == 0 or (normalizedTimeStamp % (timeCodeSampleRate * 60 * 60 * 24) == 0) : normalizedTimeStamp = toneStartTimeStamp #the head length should be 150 seconds secondsInSamplesToRead = 150 * timeCodeSampleRate # print "secondsInSamplesToRead",secondsInSamplesToRead if secondsInSamplesToRead > dataLengthInSamples: return {"status":"fail", "resultString":"the file is too short", "warningString":""} #make sure that the timestamp starts on the second, otherwise normalize the timestamp normalizedTimestampOffset = wavefile.timestamp % timeCodeSampleRate if normalizedTimestampOffset > 0: dataStartPosOffset += (timeCodeSampleRate - normalizedTimestampOffset) * byteWidth * numberOfChannels normalizedTimeStamp = wavefile.timestamp + (timeCodeSampleRate - normalizedTimestampOffset) # print "(timeCodeSampleRate - normalizedTimestampOffset)", (timeCodeSampleRate - normalizedTimestampOffset) # print "normalizedTimestampOffset", normalizedTimestampOffset # print "dataStartPosOffset", dataStartPosOffset # print "normalizedTimeStamp", normalizedTimeStamp if normalizedTimeStamp > toneStartTimeStamp: # print 'if wavefile.timestamp > toneStartTimeStamp:' secondsInSamplesToRead -= (normalizedTimeStamp - toneStartTimeStamp) if normalizedTimeStamp < toneStartTimeStamp: # print 'if wavefile.timestamp < toneStartTimeStamp:' secondsInSamplesToRead += (toneStartTimeStamp - normalizedTimeStamp) #lets only look at the first 150 seconds of the file sizeToRead = secondsInSamplesToRead * byteWidth * numberOfChannels sizeToRead = sizeToRead if dataLength > sizeToRead else dataLength second = 0 with open(filePath, 'rb') as f: startTime = datetime.datetime.now() dataStartPos += dataStartPosOffset f.seek(dataStartPos) dataToReadChunkSize = timeCodeSampleRate*byteWidth*numberOfChannels dataRemaining = sizeToRead counterDict = {} for channel in range(0, numberOfChannels): counterDict[str(channel)] = ToneCounterAlt() while dataRemaining > 0: if dataRemaining > dataToReadChunkSize: data = f.read(dataToReadChunkSize) else: data = f.read(dataRemaining) dataRemaining -= len(data) currentPositionInFile = normalizedTimeStamp + (second * data_size) # print currentPositionInFile, pctimecode.convertUnsignedLongLongToTimeCode(currentPositionInFile, 48048, 24) for channel in range(0, numberOfChannels): subdata = "" for x in range(channel*byteWidth,len(data),byteWidth*numberOfChannels): subdata += (data[x] + data[x+1] + data[x+2]) result = highestAndNextHighestFreqAndPowerForData(subdata, byteWidth, sampleRate) toneCounter = counterDict[str(channel)] toneCounter.addAnalysis({ "currentTimeStamp":currentPositionInFile, "timeCodeSampleRate":timeCodeSampleRate, "freqs":result, "RMSForInputData":calculateRMSForData(subdata, byteWidth)}) second += 1 #Questions to answer 1) Does it have at least 60 secs of tone 2) Does it start at head 3) Does it have a Pop 4) Does it have other tones? toneCounterResult = ToneCounterResultAlt(timeCodeSampleRate, 24) return toneCounterResult.result(counterDict) else: return {"status":"fail", "resultString":"file doesn't exist","warningString":""}
def doesToneRunStartAtCorrectTime(self, run): #165765600 at 48048 (basically 23.98 @ 48kHz) is 57:30:00 if run["start"] == convertTimeCodeToUnsignedLongLong("00:57:30:00",self.timeCodeSampleRate, 24): return True return False